Index
-
template<WindowImplementationConcept WindowImplementation = DefaultWindowImplementation, Dispatchable EventDispatcher = Dispatcher, template<typename> typename Renderer = DefaultRendererImplementation>
class Application - #include <application.hxx>
Provides the entry point for any Obscura game or application.
- Template Parameters:
WindowImplementation – The implementation of the window to use. Defaults to DefaultWindowImplementation.
EventDispatcher – The dispatcher to use for the window. Defaults to obscura::Dispatcher.
Public Types
-
using WindowType = Window<WindowImplementation>
Public Functions
-
inline Application()
-
inline void run()
This will start the main loop. This is a blocking call.
-
inline void onTick([[maybe_unused]] const TickEvent &event)
Callback that is triggered with every main loop iteration. This callback updates the window. Don’t call this function manually.
- Parameters:
event – The tick event.
-
inline void stopMainLoop()
This will stop the main loop and hence the application. Can only be called from another thread as the run function is a blocking call.
-
inline auto getWindow() const -> WindowType&
-
inline auto getMainLoop() const -> MainLoop<Dispatcher>&
-
inline auto getWindowEventEmitter() const -> auto&
Private Functions
-
inline void startMainLoop()
Private Members
-
std::unique_ptr<WindowType> window
-
std::unique_ptr<Renderer<WindowType>> renderer
-
std::unique_ptr<typename WindowImplementation::template EventEmitterType<Dispatcher>, typename WindowImplementation::template EventEmitterDeleterType<Dispatcher>> windowEventEmitter
-
MainLoop<Dispatcher> *mainLoop = {nullptr}
-
class ApplicationAlreadyRunningException : public std::exception
Private Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
template<Dispatchable Dispatcher>
class AsyncLoop : public obscura::LoopBase<Dispatcher>
-
class BaseLoggerImpl
- #include <logger_impl.hxx>
Base class for the logger implementation.
A logger should always be a singleton. That is, first create a logger class inheriting from this base class and then create a singleton of that class.
Subclassed by obscura::CoreLoggerImpl, obscura::LoggerImpl
Public Functions
-
void addSink(spdlog::sink_ptr sink)
-
void setLevel(spdlog::level::level_enum level)
Private Members
-
spdlog::logger backend
-
void addSink(spdlog::sink_ptr sink)
-
template<class Child>
class BaseLoopConfig Public Functions
Protected Functions
-
inline void setBaseConfigParameters(LoopConfig &config) const
-
inline void setBaseConfigParameters(LoopConfig &config) const
-
template<class Listener, class EventType, void (Listener::* CallbackPointer)(const EventType&)>
class CallbackWrapper
-
template<EventDefinitionConcept Definition, EventDefinitionConcept... AdditionalDefinitions>
class ConfigurableDispatcher : public obscura::DispatcherBase<Definition> - #include <configurable_dispatcher.hxx>
The class provides an implementation for a dispatcher. It must be configured to be compatible with the event_system that are supposed to be dispatched. For that you must pass event definitions to the template parameters list. A
Definition
must satisfy the EventDefinitionConcept concept.- Template Parameters:
Definition – Class that satisfies EventDefinitionConcept concept
AdditionalDefinitions – Classes that satisfies EventDefinitionConcept concept
Subclassed by obscura::LoopBase< Dispatcher >
Public Functions
-
void dispatch()
Dispatches all enqueued events to the respective listeners.
-
template<class Listener, bool hasFoundMatchedConcept = false>
void registerListener(Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP}) Registers a listener with the dispatcher. The callbacks of the listener will be invoked when dispatch() is called.
- Template Parameters:
Listener – Type of the listener
hasFoundMatchedConcept – Template parameter that indicates if the listener fits any of the configured definitions. The parameter is false by default and should not be manually changed.
- Parameters:
listener – The listener that is registered with the dispatcher. Can be any object as long as it contains at least one of the callback defined via the event definitions. If the listener is not matching any event definition a compile error will be thrown. Each listener can have arbitrarily many supported callbacks.
listenerGroup – The listener group the listener should be registered for. Events can be dispatched to specific listener groups. The default listener listenerGroup is named “default”.
-
template<class Listener>
void unregisterListener(const Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP}) Removes a listener from the register of the dispatcher, i.e., event_system will not be dispatched to the respective listener anymore. Throws an KeyError when the listener could not be removed for the given group.
- Template Parameters:
Listener – Type of the listener.
- Parameters:
listener – Reference to the listener.
-
template<class Listener>
auto isListenerRegistered(const Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP}) -> bool
-
template<EventDefinitionConcept Definition>
class ConfigurableDispatcher<Definition> : public obscura::DispatcherBase<Definition> Public Functions
-
void dispatch()
-
template<class Listener, bool hasFoundMatchedConcept = false>
void registerListener(Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP})
-
template<class Listener>
void unregisterListener(const Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP})
-
template<class Listener>
auto isListenerRegistered(const Listener &listener, const std::string &listenerGroup = std::string{DispatcherBase<Definition>::DEFAULT_LISTENER_GROUP}) -> bool
-
void dispatch()
-
class CoreLogger : public obscura::Singleton<CoreLoggerImpl>
- #include <logging.hxx>
The CoreLogger class is a singleton that provides a logging interface for the core of the library.
Can be used by calling CoreLogger::getInstance().info(“Hello, world!”). However, instead of using this singleton directly, it is recommended to use the
logCoreInfo
,logCoreWarn
,logCoreError
,logCoreDebug
andlogCoreTrace
, since these functions are only called if logging is enabled.
-
class CoreLoggerImpl : public obscura::BaseLoggerImpl
- #include <logger_impl.hxx>
Implementation of the logger for the core.
This class should not be used directly. Instead, use the
CoreLogger
singleton.Public Functions
-
CoreLoggerImpl()
-
CoreLoggerImpl()
-
template<class App>
class DefaultApplicationListener - #include <application.hxx>
A default application listener that will close the window and stop the main loop when the window closed button is pressed. Without registering this listener, the application will not close by using the OS UI.
- Template Parameters:
App – The application type. Should be of type obscura::Application.
Public Functions
-
inline void onWindowClosed([[maybe_unused]] const WindowEvent &event)
-
class Device
-
Private Functions
-
auto setupPhysicalDevice() -> vk::raii::PhysicalDevice
-
auto setupLogicalDevice() -> vk::raii::Device
-
auto findGraphicsQueueFamilyIndex() -> uint32_t
-
auto setupPhysicalDevice() -> vk::raii::PhysicalDevice
-
template<EventDefinitionConcept Definition, class ListenerIdType = uintptr_t>
class DispatcherBase Subclassed by obscura::ConfigurableDispatcher< Definition, AdditionalDefinitions >, obscura::ConfigurableDispatcher< Definition >
Public Functions
-
void enqueue(typename Definition::Event &&event, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP})
Enqueue an event in the dispatcher. The event is passed forward to the respective listener once dispatch() is called.
- Parameters:
event – Can be any event, the dispatcher is configured for. The function only takes event_system that are defined for the dispatcher.
listenerGroup – The group of listeners the event should be dispatched to.
-
void enqueue(const typename Definition::Event &event, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP})
Same as enqueue(Definition::Event&&, const std::string&) but the function takes a const reference of the event.
- Parameters:
event – Can be any event, the dispatcher is configured for. The function only takes event_system that are defined for the dispatcher.
listenerGroup – The group of listeners the event should be dispatched to.
-
void enqueueForAllGroups(typename Definition::Event &&event)
-
void enqueueForAllGroups(const typename Definition::Event &event)
-
inline auto hasListenerForEvent(const typename Definition::Event&, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP}) -> bool
Checks whether a listener was appended that a certain event can be dispatched to.
- Parameters:
event – Any event the dispatcher is configured for.
- Returns:
Whether a listener for an event is appended.
Protected Types
-
using EventQueue = eventpp::EventQueue<std::string, void(const typename Definition::Event&)>
Protected Functions
-
void appendToEventQueue(typename Definition::Event &&event, const std::string &listenerGroup)
Given an event and an event queue, the function checks if the event queue has a listener registered for this event (if not a warning will be logged) and enqueues the event in the queue.
- Parameters:
listenerGroup – Group of listeners the event will be dispatched to.
event – The event of type Definition::Event.
-
void appendToEventQueue(const typename Definition::Event &event, const std::string &listenerGroup)
Same as appendToEventQueue(Definition::Event&&, const std::string&) but with a const reference event.
- Parameters:
listenerGroup – Listener listenerGroup to which the event shall be dispatched.
event – The event of type Definition::Event.
-
void checkIfHasListener(const std::string &listenerGroup)
Checks if a queue has any listener for the given listenerGroup.
- Parameters:
listenerGroup – The listener listenerGroup.
-
template<class Listener>
void appendToListenerQueue(Listener &listener, const std::string &listenerGroup) Append and register a listener with the event queue.
- Template Parameters:
Listener – The listener type.
- Parameters:
listener – The listener object.
listenerGroup – The group the listener should be registered with. Any event dispatched to this group will be forwarded to the listener.
-
template<class Listener>
auto removeFromListenerQueue(const Listener &listener, const std::string &listenerGroup) -> bool
-
template<class Listener>
auto isListenerRegisteredForDefinition(const Listener &listener, const std::string &listenerGroup) -> bool Checks if a listener is already registered with a listenerGroup.
- Template Parameters:
Listener – The listener type.
- Parameters:
listener – The listener object.
listenerGroup – The group the listener is checked to be registered with.
- Returns:
Whether the given listener was registered.
Protected Attributes
-
EventQueue eventQueue = {}
Private Members
-
ListenerRegistry<typename EventQueue::Handle, ListenerIdType> listenerRegistry = {}
-
void enqueue(typename Definition::Event &&event, const std::string &listenerGroup = std::string{DEFAULT_LISTENER_GROUP})
-
class DynamicLoader
Public Functions
-
DynamicLoader()
Private Members
-
vk::DynamicLoader dynamicLoader
-
DynamicLoader()
-
class Event
- #include <event.hxx>
Base class for all event_system.
Subclassed by obscura::KeyEvent< EventCause::MouseClicked >, obscura::KeyEvent< compile_time_cause >, obscura::LoopStoppedEvent, obscura::MouseMovedEvent, obscura::MouseScrolledEvent, obscura::TickEvent, obscura::WindowEvent
Public Functions
-
inline Event(obscura::EventCategory category, obscura::EventCause cause)
-
inline auto getCategory() const -> obscura::EventCategory
-
inline auto getCause() const -> obscura::EventCause
-
inline auto getCode() const
Returns a unique code that is a combination of the event’s category and cause.
- Returns:
The event’s code.
-
inline void setCategory(EventCategory eventCategory)
-
inline void setCause(EventCause eventCause)
-
inline Event(obscura::EventCategory category, obscura::EventCause cause)
-
template<StringLiteral Name, class EventType, template<class Listener> class Callback>
struct EventDefinition -
Public Static Functions
Public Static Attributes
-
static constexpr obscura::EventCategory Category = Event::Category
-
static constexpr obscura::EventCause Cause = Event::Cause
-
template<class Listener>
static constexpr bool hasCallback =requires(Listener& listener, const EventType& event) { Callback<Listener>::call(&listener, event); }
-
static constexpr obscura::EventCategory Category = Event::Category
-
class FPS
Public Functions
-
FPS()
- template<class T> inline explicit requires std::is_convertible_v< T, float > FPS (T fps)
-
template<class TimeUnit>
inline auto framesPerTimeUnit() const -> float
-
inline auto framesPerSecond() const -> float
-
void set(float newFps)
- template<class T> inline requires std::is_convertible_v< T, float > auto operator= (T newFps) -> FPS &
-
operator float() const
-
operator double() const
Public Static Functions
Private Members
-
float fps
-
FPS()
-
class FractionalLoopConfig : public obscura::BaseLoopConfig<FractionalLoopConfig>
Public Functions
-
auto build() const -> LoopConfig
Private Functions
-
explicit FractionalLoopConfig(float fraction)
Private Members
-
float fraction
Friends
- friend class LoopConfig
-
auto build() const -> LoopConfig
-
template<Dispatchable Dispatcher, class Event>
class FrameDelayer Public Functions
-
~FrameDelayer() = default
-
FrameDelayer(const FrameDelayer&) = delete
-
FrameDelayer &operator=(const FrameDelayer&) = delete
-
FrameDelayer(FrameDelayer&&) = delete
-
FrameDelayer &operator=(FrameDelayer&&) = delete
Private Functions
-
inline FrameDelayer(Dispatcher &dispatcher, Event &&event, std::size_t framesToWait)
-
~FrameDelayer() = default
-
template<duration HorizonTimeUnit = std::chrono::seconds>
class FramePacer : public obscura::FrameProfiler<std::chrono::seconds> - #include <frame_pacer.hxx>
Responsible for pacing frames and reaching consisting frame times.
- Template Parameters:
HorizonTimeUnit – See obscura::FrameProfiler for more information.
-
template<duration HorizonTimeUnit = std::chrono::seconds>
class FrameProfiler : public obscura::Timer - #include <frame_profiler.hxx>
Class that profiles frame times. It can be used to receive the FPS or intervals between frames. It is an extension of obscura::Timer.
- Template Parameters:
HorizonTimeUnit – Type of the time horizon for the FPS averaging. In order to measure the FPS it is necessary to provide a time window in which the frame times are averaged. This template parameter specifies the type of that duration.
Public Functions
-
inline explicit FrameProfiler(const HorizonTimeUnit &timePointsHorizon = std::chrono::seconds{2})
The constructor requires the time horizon for the FPS aggregation. Since the FPS measures how many frames there are per second, it must be specified over what time horizon the frames will be counted. A longer time horizon will be less sensible to outliers while a shorter horizon will be make frame time spikes more visible.
- Parameters:
timePointsHorizon – Time horizon for FPS counting. Default: 2 seconds
-
inline void start()
Must be called before measuring any frame times.
-
inline void tick()
Should be called at the beginning of each frame.
-
inline void stop()
Stops the measurement. Calling this function is not required for cleaning up the frame profiler.
-
template<duration TimeUnit>
inline auto getFPS(const TimeUnit &aggregationTimeframe) -> FPS Returns FPS measured over the given aggregation horizon. The given time frame cannot be longer than the specified time horizon in the constructor.
- Template Parameters:
TimeUnit – The time unit for the aggregation time frame.
- Parameters:
aggregationTimeframe – The aggregation time frame.
- Returns:
-
inline auto getDelta() const -> float
- Returns:
Frame time delta in seconds.
-
inline void setReferenceTimePoint()
Creates a reference point from where frame time computations are carried out.
This function should be called at the beginning of any frame time computations in order to guarantee the consistency of consecutive calls to aggregating function. All aggregate computations concerning frame times must have a rolling sample window. That sample window is carried out from either this measuring point or from the current time point. If a reference point is not set the sample window is changing with consecutive calls.
Note that you also have to set createNewReferencePoint to false in any function that requires reference points in order to use this reference point.
Example: tick - tick - sample window start - tick - tick - setReferenceTimePoint point/sample window end
-
inline auto getNumberOfFrameTimes() const -> std::size_t
Returns the number of frames within the time point horizon.
The time point horizon is set in the constructor. A frame is considered within the horizon if it intersects with the horizon.
- Returns:
Number of frames.
-
template<duration TimeUnit>
inline auto getNumberOfFrameTimes(const TimeUnit &withinDuration, bool createNewReferencePoint = true) -> std::size_t Returns the number of frames within the given duration.
A frame is considered within the duration if it intersects with it.
- Template Parameters:
TimeUnit – The time unit for the duration.
- Parameters:
withinDuration – The duration in which frames should be counted.
- Returns:
Number of frames.
-
inline auto getFrameTimes() const -> std::list<TimePoint::duration>
Returns the frame times within the time point horizon.
The time point horizon is set in the constructor. A frame is considered within the horizon if it intersects with the horizon.
- Returns:
List of frame times within the horizon.
-
template<duration FrameTimeUnit, duration CutOffTimeUnit>
inline auto getFrameTimes(const CutOffTimeUnit &withinDuration, bool createNewReferencePoint = true) -> std::list<FrameTimeUnit> Returns the frame times within the given duration.
A frame is considered within the duration if it intersects with it.
- Template Parameters:
TimeUnit – The time unit for the returned frame times.
CutOffTimeUnit – The time unit for the time window.
- Parameters:
withinDuration – The duration in which frames should be counted.
createNewReferencePoint – Whether or not to create a new reference point for the time window. Create a manual reference point if you consecutively call functions with a time window in order to keep a consistent time window.
- Returns:
List of frame times within the given duration.
-
template<duration TimeUnit = TimePoint::duration>
inline auto getCumulativeFrameTimes() const -> TimeUnit Returns the summed up frame times within the time point horizon.
- Template Parameters:
TimeUnit – The time unit for the duration.
- Returns:
Sum of frame times within the horizon.
-
template<duration CutOffTimeUnit, duration TimeUnit = TimePoint::duration>
inline auto getCumulativeFrameTimes(const CutOffTimeUnit &withinDuration, bool createNewReferencePoint = true) -> TimeUnit Returns the summed up frame times within the given duration.
- Template Parameters:
CutOffTimeUnit – The time unit for the time window.
TimeUnit – The time unit for the returned frame times.
- Parameters:
withinDuration – The duration in which frames should be counted.
createNewReferencePoint – Whether or not to create a new reference point for the time window. Create a manual reference point if you consecutively call functions with a time window in order to keep a consistent time window.
- Returns:
Sum of frame times within the given duration.
-
template<duration TimeUnit = TimePoint::duration>
inline auto getDurationSinceLastTick(bool createNewReferencePoint = true) -> TimeUnit Nearly the same as obscura::Timer::getDurationSinceLastTick with the difference that a reference point can be used.
- Template Parameters:
TimeUnit – Type of duration to return.
- Parameters:
createNewReferencePoint – Whether or not to create a new reference point. Set this to false if you have manually created a reference point.
- Returns:
The duration from end/reference point to the last tick.
Private Functions
-
inline void removeTimePointsOutsideOfHorizon()
-
template<Dispatchable Dispatcher>
class GlfwEventEmitter - #include <event_emitter.hxx>
GlfwEventEmitter is a class that emits events from GLFW to the Obscura event system. It is responsible for polling window-related events from GLFW and emitting them to the event system. Don’t construct an object of this class manually. Instead, use the makeEventEmitter function.
- Template Parameters:
Dispatcher – The type of the dispatcher to use.
Public Functions
-
inline explicit GlfwEventEmitter(GLFWwindow *window)
-
inline ~GlfwEventEmitter()
-
GlfwEventEmitter(const GlfwEventEmitter&) = delete
-
GlfwEventEmitter(GlfwEventEmitter&&) = default
-
GlfwEventEmitter &operator=(const GlfwEventEmitter&) = delete
-
GlfwEventEmitter &operator=(GlfwEventEmitter&&) = default
Public Static Functions
-
static inline const glm::vec2 &getLastMousePosition()
-
static inline void setLastMousePosition(const glm::vec2 &newMousePosition)
Private Members
-
GLFWwindow *window
Private Static Functions
-
static inline void pollEvents()
-
template<Dispatchable Dispatcher>
struct GlfwEventEmitterDeleter - #include <event_emitter.hxx>
A deleter for the GlfwEventEmitter class. This is used by the std::shared_ptr to delete the GlfwEventEmitter object.
- Template Parameters:
Dispatcher –
Public Functions
-
inline void operator()(GlfwEventEmitter<Dispatcher> *ptr)
-
class GlfwException : private std::exception
Public Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
class GlfwWindow
Public Types
-
template<Dispatchable Dispatcher>
using EventEmitterType = GlfwEventEmitter<Dispatcher>
-
template<Dispatchable Dispatcher>
using EventEmitterDeleterType = GlfwEventEmitterDeleter<Dispatcher>
Public Functions
-
GlfwWindow()
-
void update()
-
template<Dispatchable Dispatcher>
inline auto makeEventEmitter() -> std::unique_ptr<GlfwEventEmitter<Dispatcher>, GlfwEventEmitterDeleter<Dispatcher>>
-
inline auto getGlfwWindow() const -> GLFWwindow*
Private Static Attributes
-
static bool glfwInitialized = false
-
template<Dispatchable Dispatcher>
-
template<Dispatchable Dispatcher>
class HeadlessEventEmitter - #include <event_emitter.hxx>
HeadlessEventEmitter is a class that can be used to emit events without a window. It is used by the HeadlessWindow to emit events into the Obscura event system. Don’t construct this class directly, but use the makeEventEmitter function instead. Once, an object of this class is you can manually simulate mouse, keyboard and window events.
- Template Parameters:
Dispatcher – The type of the dispatcher to use.
Public Functions
-
inline HeadlessEventEmitter()
-
inline ~HeadlessEventEmitter()
-
HeadlessEventEmitter(const HeadlessEventEmitter&) = delete
-
HeadlessEventEmitter(HeadlessEventEmitter&&) = default
-
HeadlessEventEmitter &operator=(const HeadlessEventEmitter&) = delete
-
HeadlessEventEmitter &operator=(HeadlessEventEmitter&&) = default
-
inline void pressKey(int key)
-
inline void releaseKey(int key)
-
inline void repeatKey(int key)
-
inline void moveMouseFromTo(const glm::vec2 &origin, const glm::vec2 &target, float pixels_per_second, float pollIntervalInSeconds = constant::DEFAULT_MOUSE_MOVE_INTERVAL_IN_SECONDS)
Moves the mouse from origin to target with a given speed.
- Parameters:
origin – Origin position of the mouse.
target – Target position of the mouse.
pixels_per_second – Pixels per second the mouse should move.
pollIntervalInSeconds – Interval in seconds between two mouse move events.
-
inline void clickMouse(const glm::vec2 &position, int key)
-
inline void scrollMouse(float verticalOffset, float horizontalOffset)
Private Functions
-
template<class E, class EventArgs>
inline void processQueue(moodycamel::ConcurrentQueue<EventArgs> *queue)
-
inline void pollEvents()
Private Members
-
template<class Dispatcher>
class HeadlessEventEmitterDeleter Public Functions
-
inline void operator()(HeadlessEventEmitter<Dispatcher> *ptr)
-
inline void operator()(HeadlessEventEmitter<Dispatcher> *ptr)
-
class HeadlessWindow
Public Types
-
template<Dispatchable Dispatcher>
using EventEmitterType = HeadlessEventEmitter<Dispatcher>
-
template<Dispatchable Dispatcher>
using EventEmitterDeleterType = HeadlessEventEmitterDeleter<Dispatcher>
Public Functions
-
HeadlessWindow() = default
-
inline void create([[maybe_unused]] const std::string &title, [[maybe_unused]] std::size_t width, [[maybe_unused]] std::size_t height)
-
template<Dispatchable Dispatcher>
inline auto makeEventEmitter() -> std::unique_ptr<HeadlessEventEmitter<Dispatcher>, HeadlessEventEmitterDeleter<Dispatcher>>
-
inline void update()
-
template<Dispatchable Dispatcher>
-
class Instance
Public Functions
-
Instance()
-
~Instance() = default
-
inline auto getVulkanInternalInstance() const -> const vk::raii::Instance&
Private Functions
-
auto createInstanceCreateInfo(const std::span<const char*> &externallyRequiredExtensions) -> vk::InstanceCreateInfo
-
auto createInstance() const -> vk::raii::Instance
-
auto setupVulkanLayers() -> void
-
auto checkRequiredExtensions() const -> void
-
auto checkRequiredVulkanLayers() const -> void
Private Members
-
std::string applicationName = {constant::DEFAULT_WINDOW_TITLE}
-
vk::raii::Context context
-
vk::ApplicationInfo applicationInfo
-
vk::InstanceCreateInfo instanceCreateInfo
-
vk::raii::Instance instance
-
Instance()
-
template<obscura::EventCause compile_time_cause>
class KeyEvent : public obscura::Event -
Private Members
-
int key
-
int key
-
class ListenerCouldNotBeRemovedException : public std::exception
Public Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
template<class EventQueueHandle, class ListenerIdType = uintptr_t>
class ListenerRegistry - #include <listener_registry.hxx>
Class that implements a container that keeps track of listeners registered with the dispatcher. A ListenerRegistry internally contains a hash map in the format:
- Template Parameters:
ListenerIdType –
EventQueueHandle –
Public Functions
-
template<class Listener>
void registerListener(const Listener &listener, const std::string &listenerGroup, const EventQueueHandle &eventQueueHandle) Add listener to the register.
- Template Parameters:
Listener – Type of the listener.
- Parameters:
listener – Reference to the listener.
listenerGroup – Listener group in which the listener should be registered.
eventQueueHandle – Event queue handle of the listener. When adding a listener to the event queue you should receive some kind of handle with that you can remove the listener from the queue again. This handle must be stored in the registry.
-
template<class Listener>
void unregisterListener(const Listener &listener, const std::string &listenerGroup)
-
template<class Listener>
auto getHandle(const Listener &listener, const std::string &listenerGroup) const -> const EventQueueHandle&
-
template<class Listener>
auto contains(const Listener &listener) const -> bool Checks whether the given listener is registered to any listener group.
- Template Parameters:
Listener – Type of the listener.
- Parameters:
listener – Reference to the listener.
- Returns:
Whether listener is registered to any listener group.
-
template<class Listener>
auto contains(const Listener &listener, const std::string &listenerGroup) const -> bool Checks whether the given is registered to the given listener group.
- Template Parameters:
Listener – Type of the listener.
- Parameters:
listener – Reference to the listener.
listenerGroup – Listener group that is checked for containing the given listener.
- Returns:
Whether the listener is registered to the listener group.
Private Members
-
std::unordered_map<ListenerIdType, std::unordered_map<std::string, EventQueueHandle>> listenerRegistry = {}
Private Static Functions
-
template<class Listener>
static inline auto getListenerId(const Listener &listener) -> ListenerIdType Get the listener id from a listener object. The id is used for checking if a listener is already registered or with which group it is registered.
- Template Parameters:
Listener – The listener type.
- Parameters:
listener – The listener object.
- Returns:
The listener id.
-
class ListenerRegistryFixture : public TestKeyListenerFixture
-
class Logger : public obscura::Singleton<LoggerImpl>
- #include <logging.hxx>
The Logger class is a singleton that provides a logging interface.
Can be used by calling Logger::getInstance().info(“Hello, world!”). However, instead of using this singleton directly, it is recommended to use the
logInfo
,logWarn
,logError
,logDebug
andlogTrace
, since these functions are only called if logging is enabled.
-
class LoggerImpl : public obscura::BaseLoggerImpl
- #include <logger_impl.hxx>
Implementation of the logger for the client.
This class should not be used directly. Instead, use the
Logger
singleton.Public Functions
-
LoggerImpl()
-
LoggerImpl()
-
template<Dispatchable Dispatcher>
class LoopBase : public obscura::ConfigurableDispatcher<TickDefinition, KeyPressedDefinition, MouseMovedDefintion, KeyReleasedDefinition, KeyRepeatedDefinition, WindowClosedDefintion, MouseClickedDefinition, LoopEndDefinition> Subclassed by obscura::MainLoop< obscura::ConfigurableDispatcher >, obscura::AsyncLoop< Dispatcher >, obscura::MainLoop< Dispatcher >, obscura::SyncLoop< Dispatcher, BaseLoop >
Public Functions
-
inline LoopBase()
-
~LoopBase() = default
-
LoopBase(LoopBase<Dispatcher>&&) noexcept = default
-
auto operator=(LoopBase<Dispatcher>&&) noexcept -> LoopBase<Dispatcher>& = default
-
LoopBase(const LoopBase<Dispatcher>&) = delete
-
auto operator=(const LoopBase<Dispatcher>&) -> LoopBase<Dispatcher>& = delete
-
inline void tick()
-
template<class Event, class Duration>
inline void scheduleOnce(Event &&event, const Duration &delay)
-
inline auto getFramePacer() const -> const FramePacer<>&
-
inline void waitForStop()
-
inline LoopBase()
-
class LoopConfig
Subclassed by obscura::LoopSynchronizer< BaseLoop, DependentLoop >
Public Static Functions
-
static auto runAtFractionOfBaseLoop(float fraction) -> FractionalLoopConfig
Protected Attributes
-
bool isTargetingFPS = false
-
bool runsAtFractionOfBaseLoop = false
-
float fractionOfBaseLoop = {}
-
bool hasMinFrameTime = false
-
bool hasMaxFrameTime = false
-
float minFrameTime = {}
-
float maxFrameTime = {}
Private Functions
-
LoopConfig() = default
Friends
- friend class TargetFPSLoopConfig
- friend class FractionalLoopConfig
- friend class BaseLoopConfig
-
static auto runAtFractionOfBaseLoop(float fraction) -> FractionalLoopConfig
-
class LoopDoesNotExistException : public std::exception
Public Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
class LoopIsAlreadyRunningException : public std::exception
Public Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
template<class BaseLoop, class DependentLoop>
class LoopSynchronizer : private obscura::LoopConfig Public Functions
-
inline LoopSynchronizer(BaseLoop &baseLoop, DependentLoop &dependentLoop, LoopConfig config)
-
inline LoopSynchronizer(BaseLoop &baseLoop, DependentLoop &dependentLoop, LoopConfig &&config)
-
inline LoopSynchronizer(BaseLoop &baseLoop, DependentLoop &dependentLoop, LoopConfig config)
-
template<Dispatchable Dispatcher>
class MainLoop : public obscura::LoopBase<Dispatcher>
-
class MouseClickedEvent : public obscura::KeyEvent<EventCause::MouseClicked>
Public Functions
-
MouseClickedEvent(float xPosition, float yPosition, int key)
-
auto getPosition() const -> const glm::vec2&
Private Members
-
glm::vec2 position
-
MouseClickedEvent(float xPosition, float yPosition, int key)
-
class NameAlreadyTakenException : public std::exception
Public Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
template<Dispatchable Dispatcher>
class Scheduler : public obscura::Singleton<SchedulerImpl<Dispatcher>> - #include <scheduler.hxx>
Scheduler is a singleton that manages all the loops in the application. The class inherits from obscura::SchedulerImpl that implements all the main functionalities. In order to use the scheduler, retrieve an instance of the scheduler using obscura::Scheduler::getInstance().
- Template Parameters:
Dispatcher – Type of the dispatcher to be used by the scheduler.
Private Functions
-
inline Scheduler()
-
template<Dispatchable Dispatcher>
class SchedulerImpl Public Functions
-
inline auto getMainLoop() -> MainLoop<Dispatcher>*
-
inline auto getSyncLoop(const std::string &name) -> SyncLoop<Dispatcher, MainLoop<Dispatcher>>*
-
inline auto getAsyncLoop(const std::string &name) -> AsyncLoop<Dispatcher>*
-
inline void startMainLoop()
-
inline void stopMainLoop()
-
inline auto createSyncLoop(const std::string &name, const LoopConfig &config) -> SyncLoop<Dispatcher, MainLoop<Dispatcher>>*
Creates a new synchronous loop and registers it with the scheduler.
- Parameters:
name – Name of the loop. The name is required to schedule event_system on the loop.
config – Config for the loop.
- Returns:
Returns a pointer to the newly created loop.
-
inline auto createAsyncLoop(const std::string &name, const FPS &fps) -> AsyncLoop<Dispatcher>*
Creates a new asynchronous loop and registers it with the scheduler.
- Parameters:
name – Name of the loop. The name is required to schedule event_system on the loop.
fps – FPS of the loop.
- Returns:
Returns a pointer to the newly created loop.
-
template<class Event>
inline void scheduleOnce(Event &&event, const std::string &loopName) Schedules an event on the specified loop.
- Template Parameters:
Event – Type of the event.
- Parameters:
event – Event to be scheduled.
loopName – Name of the loop on which the event is to be scheduled.
-
template<class Event>
inline void scheduleOnce(Event &&event) Schedules an event on the main loop.
- Template Parameters:
Event – Type of the event.
- Parameters:
event – Event to be scheduled.
-
template<class Event, class Duration>
inline void scheduleOnce(Event &&event, const Duration &delay, const std::string &loopName) Schedules an event on the specified loop after a delay.
- Template Parameters:
Event – Type of the event.
Duration – Type of the duration. Usually, a std::chrono::duration.
- Parameters:
event – Event to be scheduled.
delay – Delay after which the event is to be scheduled.
loopName – Name of the loop on which the event is to be scheduled.
-
template<class Event, class Duration>
inline void scheduleOnce(Event &&event, const Duration &delay) Schedules an event on the main loop.
- Template Parameters:
Event – Type of the event.
Duration – Type of the duration. Usually, a std::chrono::duration.
- Parameters:
event – Event to be scheduled.
delay – Delay after which the event is to be scheduled.
-
template<class Listener>
inline void registerListener(Listener &listener, const std::string &loopName)
-
template<class Listener>
inline void registerListener(Listener &listener) Registers a listener with the main loop.
- Template Parameters:
Listener – Type of the listener.
- Parameters:
listener – The listener to be registered.
-
template<class Listener>
inline void unregisterListener(Listener &listener, const std::string &loopName) Unregisters a listener from the specified loop.
- Template Parameters:
Listener – Type of the listener.
- Parameters:
listener – The listener to be unregistered.
loopName – Name of the loop from which the listener is to be unregistered.
Private Members
-
MainLoop<Dispatcher> mainLoop = {}
-
std::unordered_map<std::string, SyncLoop<Dispatcher, MainLoop<Dispatcher>>> syncLoops
-
std::unordered_map<std::string, AsyncLoop<Dispatcher>> asyncLoops
Private Static Attributes
-
static constexpr auto defaultFPS = 30
-
inline auto getMainLoop() -> MainLoop<Dispatcher>*
-
template<class T>
class Singleton Public Functions
-
template<size_t N>
struct StringLiteral - #include <event_definition.hxx>
A class that can be used to pass string literals as template parameters.
- Template Parameters:
N – Number of characters. The template parameter is deduced automatically.
-
template<Dispatchable Dispatcher, Loop BaseLoop>
class SyncLoop : public obscura::LoopBase<Dispatcher> Public Functions
-
inline void run(BaseLoop &newBaseLoop, const LoopConfig &config)
-
inline void stop()
Private Members
-
std::unique_ptr<LoopSynchronizer<BaseLoop, SyncLoop<Dispatcher, BaseLoop>>> synchronizer
-
inline void run(BaseLoop &newBaseLoop, const LoopConfig &config)
-
class TargetFPSLoopConfig : public obscura::BaseLoopConfig<TargetFPSLoopConfig>
Public Functions
-
auto build() const
Friends
- friend class LoopConfig
-
auto build() const
-
class Timer
- #include <timer.hxx>
Class that measures times between tick points.
Subclassed by obscura::FrameProfiler< std::chrono::seconds >, obscura::FrameProfiler< HorizonTimeUnit >
Public Functions
-
Timer() = default
-
void start()
Starts the timer. Must be called before measuring any times. Otherwise, an exception is thrown.
-
void tick()
Creates a tick point that is used to measure intermediate timings.
-
void stop()
Stops the timer. The timing between the start and stop point can be gathered afterward.
-
auto isStarted() const -> bool
-
auto isStopped() const -> bool
-
template<class TimeUnit = TimePoint::duration>
inline auto getDuration() const -> TimeUnit Returns the duration between the stop and start point, if stop was called, or otherwise the duration between the current time point and the start point.
- Template Parameters:
TimeUnit – Type of the duration to return. Usually, std::chrono::duration.
- Returns:
Returns the duration between stop/current point and start point.
-
template<class TimeUnit = TimePoint::duration>
inline auto getDurationSinceLastTick() -> TimeUnit Returns the duration between the stop and last tick point, if stop was called, or otherwise the duration between the current time point and the last tick point.
- Template Parameters:
TimeUnit – Type of the duration to return. Usually, std::chrono::duration.
- Returns:
Returns the duration between stop/current point and last tick point.
Private Functions
-
auto invoked() const -> bool
-
Timer() = default
-
class TimerAlreadyStartedException : public std::exception
Private Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
class TimerAlreadyStoppedException : public std::exception
Private Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
class TimerNotStartedException : public std::exception
Private Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
class TimerNotStoppedException : public std::exception
Private Functions
-
auto what() const noexcept -> const char* override
-
auto what() const noexcept -> const char* override
-
class VulkanInstanceTest : public testing::Test
Private Members
-
obscura::DynamicLoader dynamicLoader
-
obscura::DynamicLoader dynamicLoader
-
template<typename Window>
class VulkanRenderer
-
template<WindowImplementationConcept Implementation = DefaultWindowImplementation>
class Window Public Functions
-
inline explicit Window(const WindowProperties &windowProperties)
-
inline void open(const WindowProperties &newWindowProperties)
-
inline void close()
-
inline void tick()
-
inline auto getImplementation() const -> Implementation&
-
template<Dispatchable Dispatcher>
inline auto makeEventEmitter() Constructs an event emitter for the given dispatcher. As long as the returned event emitter is alive, it will forward events sent to the window to the dispatcher. Destroy this object to stop this behavior. If this isn’t called, windows events cannot be processed.
- Template Parameters:
Dispatcher – The type of the dispatcher to use.
- Returns:
A unique pointer to an event emitter object.
Private Members
-
std::unique_ptr<Implementation> implementation
-
std::unique_ptr<WindowProperties> windowProperties
-
inline explicit Window(const WindowProperties &windowProperties)
-
class WindowEvent : public obscura::Event
Public Functions
-
explicit WindowEvent(const EventCause &cause)
-
explicit WindowEvent(const EventCause &cause)
-
struct WindowProperties
Public Members
-
std::size_t width = constant::DEFAULT_WINDOW_WIDTH
-
std::size_t height = constant::DEFAULT_WINDOW_HEIGHT
-
std::string title = std::string{constant::DEFAULT_WINDOW_TITLE}
-
std::size_t width = constant::DEFAULT_WINDOW_WIDTH
-
namespace obscura
Typedefs
-
using Dispatcher = ConfigurableDispatcher<TickDefinition, KeyPressedDefinition, MouseMovedDefintion, KeyReleasedDefinition, KeyRepeatedDefinition, WindowClosedDefintion, MouseClickedDefinition, LoopEndDefinition>
The Obscura default dispatcher with all predefined event types pre-configured. Use this class if you have no need to define custom event_system.
-
template<class Listener>
using KeyPressedCallback = CallbackWrapper<Listener, KeyPressedEvent, &Listener::onKeyPressed>
-
using KeyPressedDefinition = EventDefinition<"KeyPressedDefinition", KeyPressedEvent, KeyPressedCallback>
-
template<class Listener>
using KeyReleasedCallback = CallbackWrapper<Listener, KeyReleasedEvent, &Listener::onKeyReleased>
-
using KeyReleasedDefinition = EventDefinition<"KeyReleasedDefinition", KeyReleasedEvent, KeyReleasedCallback>
-
template<class Listener>
using KeyRepeatedCallback = CallbackWrapper<Listener, KeyRepeatedEvent, &Listener::onKeyRepeated>
-
using KeyRepeatedDefinition = EventDefinition<"KeyRepeatedDefinition", KeyRepeatedEvent, KeyRepeatedCallback>
-
template<class Listener>
using TickCallback = CallbackWrapper<Listener, TickEvent, &Listener::onTick>
-
using TickDefinition = EventDefinition<"TickDefinition", TickEvent, TickCallback>
-
template<class Listener>
using LoopEndCallback = CallbackWrapper<Listener, LoopStoppedEvent, &Listener::onLoopStop>
-
using LoopEndDefinition = EventDefinition<"LoopEndDefinition", LoopStoppedEvent, LoopEndCallback>
-
template<class Listener>
using MouseMovedCallback = CallbackWrapper<Listener, MouseMovedEvent, &Listener::onMouseMoved>
-
using MouseMovedDefintion = EventDefinition<"MouseMovedDefintion", MouseMovedEvent, MouseMovedCallback>
-
template<class Listener>
using MouseClickedCallback = CallbackWrapper<Listener, MouseClickedEvent, &Listener::onMouseClicked>
-
using MouseClickedDefinition = EventDefinition<"MouseClickedDefinition", MouseClickedEvent, MouseClickedCallback>
-
template<class Listener>
using WindowClosedCallback = CallbackWrapper<Listener, WindowEvent, &Listener::onWindowClosed>
-
using WindowClosedDefintion = EventDefinition<"WindowClosedDefintion", WindowEvent, WindowClosedCallback>
-
using KeyPressedEvent = KeyEvent<EventCause::KeyPressed>
-
using KeyRepeatedEvent = KeyEvent<EventCause::KeyRepeated>
-
using KeyReleasedEvent = KeyEvent<EventCause::KeyReleased>
-
template<typename Window>
using DefaultRendererImplementation = VulkanRenderer<Window>
-
using DefaultWindowImplementation = GlfwWindow
Enums
-
enum class EventCategory
The available event categories for Obscura. SIZE must be at the end of the enum. It is used to determine the number of categories.
Values:
-
enumerator None
-
enumerator Application
-
enumerator KeyInput
-
enumerator ScrollInput
-
enumerator CoordinateInput
-
enumerator Window
-
enumerator SIZE
-
enumerator None
-
enum class EventCause
The available event causes for Obscura.
Values:
-
enumerator None
-
enumerator KeyPressed
-
enumerator KeyReleased
-
enumerator KeyRepeated
-
enumerator WindowClosed
-
enumerator WindowResized
-
enumerator WindowMoved
-
enumerator WindowFocus
-
enumerator WindowLostFocus
-
enumerator MouseMoved
-
enumerator MouseScrolled
-
enumerator MouseClicked
-
enumerator LoopTicked
-
enumerator LoopStopped
-
enumerator Rendered
-
enumerator None
Functions
-
inline constexpr auto eventCode(EventCategory category, EventCause cause) -> std::size_t
Returns a unique code that is a combination of the event’s category and cause.
- Parameters:
category – Category of the event.
cause – Cause of the event.
- Returns:
Unique code for the event.
-
inline auto getCategoryFromCode(std::size_t code) -> EventCategory
Determines and returns the category of an event from its code.
- Parameters:
code – The event’s code.
- Returns:
An event category.
-
inline auto getCauseFromCode(std::size_t code) -> EventCause
Determines and returns the cause of an event from its code.
- Parameters:
code – The event’s code.
- Returns:
An event cause.
-
template<Dispatchable Dispatcher, class Event>
void emitDelayedEvent(Dispatcher &dispatcher, Event &&event, std::size_t emitAfterNFrames)
-
template<typename StringType, typename ...Args>
inline void logCoreInfo(StringType fmt, const Args&... args) Logs an info message.
Should only be used internally by obscura. For logging in the client code, use
logInfo
. The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logCoreWarn(StringType fmt, const Args&... args) Logs a warning message.
Should only be used internally by obscura. For logging in the client code, use
logWarn
. The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logCoreError(StringType fmt, const Args&... args) Logs an error message.
Should only be used internally by obscura. For logging in the client code, use
logError
. The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logCoreDebug(StringType fmt, const Args&... args) Logs a debug message.
Should only be used internally by obscura. For logging in the client code, use
logDebug
. The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logCoreTrace(StringType fmt, const Args&... args) Logs a trace message.
Should only be used internally by obscura. For logging in the client code, use
logTrace
. The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logInfo(StringType fmt, const Args&... args) Logs an info message.
The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.
- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logWarn(StringType fmt, const Args&... args) Logs a warning message.
The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.
- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logError(StringType fmt, const Args&... args) Logs an error message.
The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.
- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logDebug(StringType fmt, const Args&... args) Logs a debug message.
The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.
- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
-
template<typename StringType, typename ...Args>
inline void logTrace(StringType fmt, const Args&... args) Logs a trace message.
The function is only called if logging is enabled. If the pre-processing variable is set to false, the function does not cause any function call overhead.
- Template Parameters:
StringType – The type of the string to log.
Args – The types of the arguments to log.
- Parameters:
fmt – The format string.
args – The arguments to log.
- static VKAPI_ATTR auto VKAPI_CALL debugCallback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *) -> VkBool32
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator<=(const obscura::FPS &lhs, T rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator<=(T lhs, const obscura::FPS &rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator<(const obscura::FPS &lhs, T rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator<(T lhs, const obscura::FPS &rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator==(const obscura::FPS &lhs, T rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator==(T lhs, const obscura::FPS &rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator!=(const obscura::FPS &lhs, T rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator!=(T lhs, const obscura::FPS &rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator>=(const obscura::FPS &lhs, T rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator>=(T lhs, const obscura::FPS &rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator>(const obscura::FPS &lhs, T rhs) -> bool
-
template<class T>
requires std::is_convertible_v<T, float>
auto operator>(T lhs, const obscura::FPS &rhs) -> bool
-
template<Dispatchable Dispatcher>
void keyCallback([[maybe_unused]] GLFWwindow*, int key, [[maybe_unused]] int scancode, int action, [[maybe_unused]] int mods)
-
template<class Dispatcher>
void windowCloseCallback([[maybe_unused]] GLFWwindow*)
-
template<class Dispatcher, class WindowImplementation>
void mouseMovedCallback([[maybe_unused]] GLFWwindow*, double xCoordinate, double yCoordinate)
Variables
- template<class T> concept Dispatchable = requires(T impl) { impl.dispatch(); }
- template<class T> concept Loop = requires(T impl) {impl.tick();impl.scheduleOnce(0);impl.scheduleOnce(0, std::chrono::seconds { 1 });impl.scheduleOnce(0, std::chrono::milliseconds { 1 });impl.scheduleOnce(0, std::chrono::microseconds { 1 });impl.scheduleOnce(0, std::size_t {});{ impl.getFramePacer() } -> std::convertible_to<Timer>;impl.waitForStop();}
-
static const bool loggingEnabled = false
- template<typename Renderer, typename Window> concept RendererImplementationConcept = requires(Renderer renderer, Windowwindow) {Renderer { window };}
- template<class T> concept duration = std::regular<T> && requires(T lhs, T rhs, typename T::rep rep) {typename T::rep;typename T::period;{ lhs + rhs } -> std::same_as<T>;{ lhs - rhs } -> std::same_as<T>;{ lhs* rep } -> std::same_as<T>;{ rep* lhs } -> std::same_as<T>;{ lhs / rep } -> std::same_as<T>;{ lhs / rhs } -> std::same_as<typename T::rep>;{ lhs % rep } -> std::same_as<T>;{ lhs % rhs } -> std::same_as<T>;{ lhs.count() } -> std::same_as<typename T::rep>;}
- template<class T> concept is_smart_ptr = SmartPtr<T>::value
- template<class T> concept WindowImplementationConcept =requires(T impl, const std::string& title, std::size_t width, std::size_t height) {T();{ impl.create(title, width, height) } -> std::same_as<void>;{ impl.update() } -> std::same_as<void>;{ impl.template makeEventEmitter<Dispatcher>() } -> is_smart_ptr;impl.getVulkanExtensions();}
-
using Dispatcher = ConfigurableDispatcher<TickDefinition, KeyPressedDefinition, MouseMovedDefintion, KeyReleasedDefinition, KeyRepeatedDefinition, WindowClosedDefintion, MouseClickedDefinition, LoopEndDefinition>
-
namespace constant
-
namespace std
-
namespace chrono_literals
-
namespace testing
- file CONTRIBUTING_INSTRUCTIONS.md
- file application.hxx
- #include <obscura/core/core.hxx>#include <obscura/event_system/concepts/dispatcher.hxx>#include <obscura/event_system/scheduler/scheduler.hxx>#include <obscura/renderer/renderer.hxx>#include <obscura/renderer/renderer_concept.hxx>#include <obscura/window/window.hxx>#include <obscura/window/window_properties.hxx>
- file application.test.cxx
- #include <chrono>#include <gtest/gtest.h>#include <obscura/obscura.hxx>#include <test_config/config.hxx>#include <thread>
- file core.hxx
- #include <atomic>#include <bit>#include <chrono>#include <concepts>#include <cstddef>#include <format>#include <functional>#include <iostream>#include <list>#include <memory>#include <mutex>#include <numeric>#include <obscura/exceptions/exceptions.hxx>#include <obscura/logging/logging.hxx>#include <optional>#include <set>#include <span>#include <string>#include <thread>#include <tuple>#include <type_traits>#include <unordered_map>#include <vector>
- file dispatcher.hxx
- #include <obscura/event_system/events/event.hxx>
- file dispatcher.hxx
- file loop.hxx
- #include “obscura/core/core.hxx”#include “obscura/timer/timer.hxx”
- file configurable_dispatcher.hxx
- #include “dispatcher_base.hxx”
- file dispatcher.test.cxx
- #include <gtest/gtest.h>#include <obscura/core/core.hxx>#include <obscura/event_system/events/key_events.hxx>#include <obscura/event_system/events/loop_events.hxx>#include <test_config/config.hxx>
Functions
-
TEST(DispatcherNoErrorsTest, DispatcherCanBeConstructed)
-
TEST(DispatcherNoErrorsTest, ListenerCanBeAppended)
-
TEST(DispatcherNoErrorsTest, EventCanBeEnqueued)
-
TEST_F(DispatcherFixture, KeyPressedEventIsDispatched)
-
TEST_F(DispatcherFixture, KeyReleaseEventIsDispatched)
-
TEST_F(DispatcherFixture, MouseMovedEventIsDispatched)
-
TEST_F(DispatcherFixture, KeyPressedEventIsNotDispatchedIfKeyReleasedEventIsEmitted)
-
TEST_F(DispatcherFixture, MultipleEventsAreDispatched)
-
TEST(DispatcherListenerTest, AddressedEventsAreCorrectlyDispatched)
-
TEST(DispatcherListenerTest, ListenersCanBeRemoved)
-
TEST_F(DispatcherFixture, TickListenerIsAddedToDispatcher)
-
TEST_F(DispatcherFixture, MultipleListenersAreRegistered)
-
TEST_F(TestKeyListenerFixture, CallbackWrapperCallsListenerCorrectly)
-
TEST(DispatcherNoErrorsTest, SingleDefinitionDispatcherCanBeConstructed)
-
TEST(DispatcherNoErrorsTest, ListenerCanBeRegisteredWithSingleDefinitionDispatcher)
-
TEST(DispatcherNoErrorsTest, EventCanBeEnqueuedAndDispatchedWithSingleDefinitionDispatcher)
-
TEST(DispatcherNoErrorsTest, DispatcherCanBeConstructed)
- file dispatcher_base.hxx
- #include “listener_registry.hxx”#include “obscura/core/core.hxx”#include <eventpp/eventdispatcher.h>#include <eventpp/eventqueue.h>
- file dispatcher_base.test.cxx
- #include <gtest/gtest.h>#include <obscura/core/core.hxx>
Functions
-
TEST_F(DispatcherBaseFixture, EventCanBeEnqueued)
-
TEST_F(DispatcherBaseFixture, HasListenerForEventReturnsCorrectlyFalse)
-
TEST_F(DispatcherBaseFixture, EventCanBeEnqueued)
- file listener_registry.hxx
- #include “obscura/core/core.hxx”
- file listener_registry.test.cxx
- #include <gtest/gtest.h>#include <obscura/core/core.hxx>#include <test_config/config.hxx>
Functions
-
TEST_F(ListenerRegistryFixture, ListenerCanBeRegistered)
-
TEST_F(ListenerRegistryFixture, ListenerIsNotContainedIfNotAdded)
-
TEST_F(ListenerRegistryFixture, ListenerCanBeRegisteredForMultipleGroups)
-
TEST_F(ListenerRegistryFixture, ExceptionIsThrownIfListenerIsRegisteredTwice)
-
TEST_F(ListenerRegistryFixture, ListenerCanBeUnregistered)
-
TEST_F(ListenerRegistryFixture, ErrorIsThrownIfListenerWithNonExistingGroupIsUnregistered)
-
TEST_F(ListenerRegistryFixture, ErrorIsThrownIfNotRegisteredListenerIsUnregistered)
-
TEST_F(ListenerRegistryFixture, ContainsListenerGroupReturnsTrueIfGroupExists)
-
TEST_F(ListenerRegistryFixture, ContainsListenerGroupReturnsFalseIfGroupDoesNotExist)
-
TEST_F(ListenerRegistryFixture, HandleCanBeReceivedForListener)
-
TEST_F(ListenerRegistryFixture, ListenerGroupsAreCorrectlyReturnedWithMultipleGroups)
-
TEST_F(ListenerRegistryFixture, ListenerCanBeRegistered)
- file event_definition.hxx
- #include <obscura/core/core.hxx>#include <obscura/event_system/events/event.hxx>
Variables
- template<class T> concept EventDefinitionConcept = requires(T definition) {{EventDefinition{ definition } } -> std::same_as<T>;}
- file key_event_definitions.hxx
-
#include <obscura/event_system/events/key_events.hxx>
- file loop_event_definitions.hxx
-
#include <obscura/event_system/events/loop_events.hxx>
- file mouse_event_definitions.hxx
-
#include <obscura/event_system/events/mouse_events.hxx>
- file window_event_defintions.hxx
- file async_loop.hxx
- #include “loop_base.hxx”#include “obscura/event_system/concepts/dispatcher.hxx”
- file loop_base.hxx
- #include “obscura/event_system/concepts/dispatcher.hxx”#include “obscura/timer/frame_pacer.hxx”#include “obscura/timer/sleep.hxx”
- file loop_config.cxx
- file loop_config.hxx
- #include <obscura/timer/fps.hxx>
- file loop_synchronizer.hxx
- #include “loop_config.hxx”#include “obscura/event_system/concepts/dispatcher.hxx”#include “obscura/event_system/events/loop_events.hxx”#include “obscura/timer/timer.hxx”
- file loops.test.cxx
- #include <gtest/gtest.h>#include <obscura/core/core.hxx>#include <obscura/event_system/events/loop_events.hxx>#include <test_config/config.hxx>
- file main_loop.hxx
- #include “loop_base.hxx”#include “obscura/core/core.hxx”#include “obscura/event_system/concepts/dispatcher.hxx”
- file sync_loop.hxx
- #include “loop_base.hxx”#include “loop_synchronizer.hxx”#include “obscura/event_system/concepts/dispatcher.hxx”#include “obscura/event_system/concepts/loop.hxx”
- file event.hxx
- #include “obscura/core/core.hxx”
- file events.test.cxx
- #include <gtest/gtest.h>#include <iostream>#include <obscura/event_system/events/event.hxx>
- file key_events.hxx
- #include “event.hxx”
- file key_events.test.cxx
- #include <gtest/gtest.h>#include <obscura/event_system/events/key_events.hxx>
- file loop_events.cxx
- #include <obscura/event_system/events/loop_events.hxx>#include <utility>
- file loop_events.hxx
- #include “event.hxx”#include “obscura/event_system/concepts/dispatcher.hxx”#include <chrono>
- file mouse_events.cxx
- #include <obscura/event_system/events/mouse_events.hxx>
- file mouse_events.hxx
- #include “event.hxx”#include “key_events.hxx”#include <glm/glm.hpp>
- file mouse_events.test.cxx
- #include <gtest/gtest.h>#include <obscura/event_system/events/mouse_events.hxx>
Functions
-
TEST(MouseMovedEventConstructorTest, MouseMovedEventCanBeConstructed)
-
TEST(MouseMovedEventConstructorTest, OffsetIsCorrect)
-
TEST(MouseMovedEventConstructorTest, PreviousPositionIsCorrect)
-
TEST(MouseMovedEventConstructorTest, CurrentPositionIsCorrect)
-
TEST(MouseMovedEventConstructorTest, CategoryAndCauseAreCorrect)
-
TEST(MouseScrolledEventConstructorTest, MouseScrolledEventCanBeConstructed)
-
TEST(MouseScrolledEventConstructorTest, VerticalOffsetIsCorrect)
-
TEST(MouseScrolledEventConstructorTest, HorizontalOffsetIsCorrect)
-
TEST(MouseScrolledEventConstructorTest, CategoryAndCauseAreCorrect)
-
TEST(MouseMovedEventConstructorTest, MouseMovedEventCanBeConstructed)
- file window_events.cxx
- file window_events.hxx
- #include “event.hxx”
- file delay.hxx
- #include “obscura/event_system/concepts/dispatcher.hxx”#include “obscura/event_system/events/loop_events.hxx”
- file scheduler.hxx
- #include “obscura/core/core.hxx”#include “obscura/event_system/concepts/dispatcher.hxx”#include “obscura/utils/singleton.hxx”
- file scheduler.test.cxx
- #include <gtest/gtest.h>#include <obscura/event_system/scheduler/scheduler.hxx>#include <test_config/config.hxx>
- file exceptions.cxx
- #include <obscura/exceptions/exceptions.hxx>
- file exceptions.hxx
- #include <obscura/core/core.hxx>
- file logger_impl.cxx
- #include <obscura/logging/logger_impl.hxx>#include <spdlog/sinks/stdout_color_sinks.h>
- file logger_impl.hxx
- #include <spdlog/spdlog.h>#include <string>
- file logging.hxx
- #include <obscura/logging/logger_impl.hxx>#include <obscura/logging/logging_levels.hxx>#include <obscura/utils/singleton.hxx>
- file logging_levels.hxx
- file obscura.hxx
- #include <obscura/application/application.hxx>#include <obscura/core/core.hxx>#include <obscura/event_system/events/event.hxx>#include <obscura/event_system/events/key_events.hxx>#include <obscura/event_system/events/loop_events.hxx>#include <obscura/event_system/events/mouse_events.hxx>#include <obscura/event_system/scheduler/scheduler.hxx>#include <obscura/window/window.hxx>
- file renderer.hxx
- #include <obscura/renderer/renderer_concept.hxx>#include <obscura/renderer/vulkan/renderer.hxx>
- file renderer.hxx
- #include <obscura/renderer/renderer_concept.hxx>#include <obscura/renderer/vulkan/device.hxx>#include <obscura/renderer/vulkan/dynamic_loader.hxx>#include <obscura/renderer/vulkan/instance.hxx>
- file renderer_concept.hxx
- file vulkan-init.test.cxx
- #include <gtest/gtest.h>#include <obscura/obscura.hxx>#include <vulkan/vulkan_raii.hpp>
Functions
-
TEST(Renderer, VulkanInit)
-
TEST(Renderer, VulkanInit)
- file device.cxx
- #include <obscura/logging/logging.hxx>#include <obscura/renderer/vulkan/device.hxx>#include <obscura/renderer/vulkan/instance.hxx>
- file device.hxx
- #include <obscura/renderer/vulkan/instance.hxx>#include <vulkan/vulkan_raii.hpp>
- file dynamic_loader.cxx
- #include <obscura/renderer/vulkan/dynamic_loader.hxx>
Variables
- VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
- file dynamic_loader.hxx
- #include <vulkan/vulkan_raii.hpp>
- file instance.cxx
- #include <obscura/logging/logging.hxx>#include <obscura/renderer/vulkan/instance.hxx>#include <vulkan/vulkan_raii.hpp>
- file instance.hxx
- #include <obscura/logging/logging.hxx>#include <obscura/window/window_properties.hxx>#include <span>#include <vulkan/vulkan_raii.hpp>
- file instance.test.cxx
- #include <gtest/gtest.h>#include <obscura/logging/logging.hxx>#include <obscura/renderer/vulkan/dynamic_loader.hxx>#include <obscura/renderer/vulkan/instance.hxx>
Functions
-
TEST_F(VulkanInstanceTest, VulkanInstanceIsSuccessfullyCreated)
-
TEST_F(VulkanInstanceTest, VulkanInstanceRequiresUnknownExtension)
-
TEST_F(VulkanInstanceTest, VulkanInstanceCanBeCreatedTwice)
-
TEST_F(VulkanInstanceTest, VulkanInstanceIsSuccessfullyCreated)
- file renderer.test.cxx
- #include <gtest/gtest.h>#include <obscura/renderer/vulkan/renderer.hxx>
Functions
-
TEST_F(VulkanRendererTest, VulkanRendererIsSuccessfullyCreated)
-
TEST_F(VulkanRendererTest, VulkanRendererCanBeCreatedTwice)
-
TEST_F(VulkanRendererTest, VulkanRendererIsSuccessfullyCreated)
- file duration.hxx
- #include <obscura/core/core.hxx>
- file fps.hxx
- #include <obscura/timer/fps/fps_comp_operators.hxx>#include <obscura/timer/fps/fps_impl.hxx>
- file fps.test.cxx
- #include <gtest/gtest.h>#include <obscura/timer/fps.hxx>
Functions
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromFloat)
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromDouble)
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromInt)
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromUnsignedInt)
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromChar)
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromFrameTime)
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromDurationAndNumberOfFrames)
-
TEST(FPSAssignmentTests, FloatCanBeAssignedToFPSObject)
-
TEST(FPSAssignmentTests, DoubleCanBeAssignedToFPSObject)
-
TEST(FPSAssignmentTests, IntCanBeAssignedToFPSObject)
-
TEST(FPSAssignmentTests, CharCanBeAssignedToFPSObject)
-
TEST(FPSAssignmentTests, UnsignedIntCanBeAssignedToFPSObject)
-
TEST(FPSConversionTests, FPSCanBeConvertedToFrameTime)
-
TEST(FPSConversionTests, FPSCanBeConvertedToMicrosecondsFrameTime)
-
TEST(FPSOperatorTests, LessEqualOperatorWorks)
-
TEST(FPSOperatorTests, LessOperatorWorks)
-
TEST(FPSOperatorTests, EqualOperatorWorks)
-
TEST(FPSOperatorTests, NotEqualOperatorWorks)
-
TEST(FPSOperatorTests, GreaterEqualOperatorWorks)
-
TEST(FPSOperatorTests, GreaterOperatorWorks)
-
TEST(FPSConversionTests, FPSCanBeConvertedToFramesPerSecond)
-
TEST(FPSConversionTests, FPSCanBeConvertedToFramesPerSecondSpecialization)
-
TEST(FPSConversionTests, FPSCanBeConvertedToFramesPerMicrosecond)
-
TEST(FPSConstructionTests, FPSObjectCanBeConstructedFromFloat)
- file fps_comp_operators.hxx
- #include <obscura/core/core.hxx>#include <obscura/timer/fps/fps_impl.hxx>
- file fps_impl.cxx
- #include “fps_impl.hxx”
- file fps_impl.hxx
- #include <obscura/core/core.hxx>
- file frame_pacer.hxx
- #include <obscura/timer/concepts/duration.hxx>#include <obscura/timer/frame_profiler.hxx>#include <obscura/timer/sleep.hxx>
- file frame_pacer.test.cxx
- #include <gtest/gtest.h>#include <obscura/timer/frame_pacer.hxx>
- file frame_profiler.hxx
- #include <obscura/core/core.hxx>#include <obscura/timer/concepts/duration.hxx>#include <obscura/timer/timer.hxx>
- file frame_profiler.test.cxx
- #include <gtest/gtest.h>#include <obscura/timer/frame_profiler.hxx>#include <obscura/timer/sleep.hxx>
Functions
-
TEST(FrameProfilerExceptionTest, ExceptionIsThrownIfTimerIsNotStopped)
-
TEST(FrameProfilerFunctionalityTest, TimerReturnsApproximatelyRightDurationWithTick)
-
TEST(FrameProfilerFunctionalityTest, NumberOfFramesInLastSecondsReturnsCorrectTotal)
-
TEST(FrameProfilerFunctionalityTest, NumberOfFramesInLastSecondsReturnsCorrectTotalWithSleep)
-
TEST(FrameProfilerFunctionalityTest, NumberOfFramesInLastSecondThatExceedOneSecondAreCorrect)
-
TEST(FrameProfilerFunctionalityTest, FrameTimesOfLastSecondAreApproximatelyCorrect)
-
TEST(FrameProfilerFunctionalityTest, FrameTimesOfLastSecondAreCorrectWhenOneFrameTimeLongerThanASecond)
-
TEST(FrameProfilerFunctionalityTest, CumulativeFrameTimeIsCorrect)
-
TEST(FrameProfilerFunctionalityTest, GetLastFrameTimeReturnsCorrectValue)
-
TEST(FrameProfilerFunctionalityTest, GetFPSReturnsCorrectValue)
-
TEST(FrameProfilerFunctionalityTest, GetDeltaReturnsCorrectValue)
-
TEST(FrameProfilerExceptionTest, ExceptionIsThrownIfTimerIsNotStopped)
- file sleep.hxx
- #include <obscura/core/core.hxx>
- file timer.cxx
- #include <obscura/timer/timer.hxx>
- file timer.hxx
- #include <obscura/core/core.hxx>#include <obscura/timer/fps.hxx>
- file timer.test.cxx
- #include <gtest/gtest.h>#include <obscura/timer/frame_pacer.hxx>#include <obscura/timer/timer.hxx>#include <thread>
Functions
-
TEST(TimerExceptionTest, ExceptionIsThrownIfTimerIsNotStarted)
-
TEST(TimerExceptionTest, ExceptionIsThrownIfTimerIsStartedTwice)
-
TEST(TimerExceptionsTest, ExceptionsIsThrownIfTimerIsStoppedTwice)
-
TEST(TimerFunctionalityTest, TimerReturnsApproximatelyRightDuration)
-
TEST(TimerFunctionalityTest, TimerReturnsApproximatelyRightDurationInMilliSeconds)
-
TEST(TimerExceptionTest, ExceptionIsThrownIfTimerIsNotStarted)
- file singleton.hxx
- file window_implementation.hxx
- #include <obscura/core/core.hxx>#include <obscura/event_system/events/key_events.hxx>#include <obscura/event_system/events/mouse_events.hxx>
- file event_emitter.hxx
- #include <GLFW/glfw3.h>#include <obscura/event_system/concepts/dispatcher.hxx>#include <obscura/event_system/scheduler/scheduler.hxx>#include <obscura/logging/logging.hxx>
- file event_emitter.hxx
- #include <concurrentqueue.h>#include <obscura/event_system/concepts/dispatcher.hxx>#include <obscura/event_system/scheduler/scheduler.hxx>#include <obscura/logging/logging.hxx>
- file window.cxx
- #include <obscura/window/glfw/window.hxx>
- file window.cxx
- #include <obscura/window/headless/window.hxx>
- file window.hxx
- #include <GLFW/glfw3.h>#include <obscura/core/core.hxx>#include <obscura/event_system/events/mouse_events.hxx>#include <obscura/window/glfw/event_emitter.hxx>
- file window.hxx
- #include <concurrentqueue.h>#include <glm/glm.hpp>#include <glm/gtx/norm.hpp>#include <obscura/core/core.hxx>#include <obscura/event_system/events/key_events.hxx>#include <obscura/event_system/events/mouse_events.hxx>#include <obscura/timer/frame_pacer.hxx>#include <obscura/window/headless/event_emitter.hxx>
- file window.hxx
- #include <obscura/core/core.hxx>#include <obscura/event_system/concepts/dispatcher.hxx>#include <obscura/window/headless/window.hxx>#include <obscura/window/window_properties.hxx>#include <obscura/window/glfw/window.hxx>
- file window.test.cxx
- #include <gtest/gtest.h>#include <memory>#include <obscura/window/window.hxx>
- file window_properties.cxx
- #include <obscura/window/window_properties.hxx>
- file window_properties.hxx
- #include <obscura/core/core.hxx>
- page md__home_docs_checkouts_readthedocs_org_user_builds_obscura_engine_checkouts_stable_src_CONTRIBUTING_INSTRUCTIONS
Structure should be as follows:
. ├── Target_1 │ ├── SubTarget_1 │ │ └── ... │ ├── SubTarget_2 │ │ └── ... │ └── ... └── Target_2 └── ...
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/application
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/event_system/concepts
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/window/concepts
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/timer/concepts
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/core
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/event_system/dispatcher
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/event_system/event_definitions
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/event_system/event_loops
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/event_system
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/event_system/events
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/exceptions
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/timer/fps
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/window/glfw
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/window/headless
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/logging
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/renderer
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/event_system/scheduler
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/timer
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/utils
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/renderer/vulkan
- dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/stable/src/obscura/window