Index

template<template<typename> typename 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<EventDispatcher, 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>&

Private Functions

inline void startMainLoop()

Private Members

std::unique_ptr<WindowType> window
std::unique_ptr<Renderer<WindowType>> renderer
MainLoop<Dispatcher> *mainLoop = {nullptr}
class ApplicationAlreadyRunningException : public std::exception

Private Functions

auto what() const noexcept -> const char* override
template<Dispatchable Dispatcher>
class AsyncLoop : public obscura::LoopBase<Dispatcher>

Public Functions

inline void run(const FPS &fps)
inline void stop()

Private Members

std::unique_ptr<std::thread> asyncThread
template<class Child>
class BaseLoopConfig

Public Functions

inline auto setMinFrameTime(float newMinFrameTime) -> Child&
inline auto setMaxFrameTime(float newMaxFrameTime) -> Child&

Protected Functions

inline void setBaseConfigParameters(LoopConfig &config) const

Protected Attributes

bool hasMinFrameTime = false
bool hasMaxFrameTime = false
float minFrameTime = 0
float maxFrameTime = 100
template<class Definition, class ...AdditionalDefinitions>
class ConfigurableDispatcher
#include <dispatcher.hxx>

The class provides an implementation for a dispatcher. It must be configured to be compatible with the events that are supposed to be dispatched. For that you must pass event definitions to the template parameters list. A Definition must satisfy the EventDefinition concept.

Template Parameters:
  • Definition – Class that satisfies EventDefinition concept

  • AdditionalDefinitions – Classes that satisfies EventDefinition concept

Subclassed by obscura::LoopBase< Dispatcher >

Public Functions

inline void dispatch()

Dispatches all enqueued events to the respective listeners.

inline void enqueue(typename Definition::Event &&event)

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 events that are defined for the dispatcher.

template<class Address>
inline void enqueue(const Address &address, typename Definition::Event &&event)

Same as enqueue(Definition::Event&&) but additionally requires a listener. Events enqueued with this function will only be dispatched to the given listener.

Template Parameters:

Address – Type of the listener to which the event shall be dispatched.

Parameters:
  • address – Listener to which the event shall be dispatched.

  • event – Can be any event, the dispatcher is configured for. The function only takes events that are defined for the dispatcher.

inline void enqueue(const typename Definition::Event &event)

Same as enqueue(Definition::Event&&) 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 events that are defined for the dispatcher.

template<class Address>
inline void enqueue(const Address &address, const typename Definition::Event &event)

Same as enqueue(const Address&, Definition::Event&&) but the functions takes a const reference of the event.

Template Parameters:

Address – Type of the listener to which the event shall be dispatched.

Parameters:
  • address – Listener to which the event shall be dispatched.

  • event – Can be any event, the dispatcher is configured for. The function only takes events that are defined for the dispatcher.

template<class Listener, bool hasFoundMatchedConcept = false>
inline auto appendListener(Listener &listener) -> std::size_t

Appends a new listener to the register of the dispatcher. Listeners must be added before events can be dispatched to them.

Note

If you want to address an event to a specific listener, appendAddressableListener(Listener&) must be used.

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 fitting a compile error will be thrown. One listener can have arbitrarily many supported callbacks.

Returns:

Returns a handle to the registered listener. This handle must be used to unregister the listener again from the dispatcher.

template<class Listener, bool hasFoundMatchedConcept = false>
inline auto appendAddressableListener(Listener &listener) -> std::size_t

Same as appendListener(Listener&) but listeners registered with this function are only invoked if an event is enqueued with enqueue(const Address&, const Definition::Event&) targeted for the appended listener.

Note

Globally enqueued events are also dispatched to listeners registered with this function.

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 fitting a compile error will be thrown. One listener can have arbitrarily many supported callbacks.

Returns:

Returns a handle to the registered listener. This handle must be used to unregister the listener again from the dispatcher.

template<class Listener>
inline auto removeListener(Listener &listener) -> bool

Removes a listener from the register of the dispatcher, i.e., events will not be dispatched to the respective listener anymore.

Template Parameters:

Listener – Type of the listener.

Parameters:

listener – Reference to the listener.

Returns:

Whether the removal was successful or not.

template<class Listener>
inline auto hasListenerRegistered(const Listener &listener) -> bool
inline auto hasListenerForEvent([[maybe_unused]] const typename Definition::Event &event) -> 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.

Private Types

using EventQueue = eventpp::EventQueue<std::size_t, void(const typename Definition::Event&)>
using Handle = typename EventQueue::Handle

Private Members

EventQueue eventQueue = {}
std::unordered_map<std::size_t, std::list<Handle>> listenerRegistry = {}
template<class Definition>
class ConfigurableDispatcher<Definition>

Public Functions

inline void dispatch()
inline void enqueue(typename Definition::Event &&event)
inline void enqueue(const typename Definition::Event &event)
template<class Address>
inline void enqueue(const Address &address, const typename Definition::Event &event)
template<class Listener, bool hasFoundMatchedConcept = false>
inline auto appendListener(Listener &listener) -> std::size_t
template<class Listener, bool hasFoundMatchedConcept = false>
inline auto appendAddressableListener(Listener &listener) -> std::size_t
template<class Listener>
inline auto removeListener(Listener &listener) -> bool
template<class Listener>
inline auto hasListenerRegistered(const Listener &listener) -> bool
inline auto hasListenerForEvent([[maybe_unused]] const typename Definition::Event &event) -> bool

Private Types

using EventQueue = eventpp::EventQueue<std::size_t, void(const typename Definition::Event&)>

Private Members

EventQueue eventQueue = {}
std::unordered_map<std::size_t, std::list<typename EventQueue::Handle>> listenerRegistry = {}
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 explicit DefaultApplicationListener(App &application)
inline void onWindowClosed([[maybe_unused]] const WindowEvent &event)

Private Members

App &application
class Device

Public Functions

Device(const Instance &instance)
~Device() = default

Private Functions

auto setupPhysicalDevice() -> vk::raii::PhysicalDevice
auto setupLogicalDevice() -> vk::raii::Device
auto findGraphicsQueueFamilyIndex() -> uint32_t

Private Members

const Instance &instance
vk::raii::PhysicalDevice physicalDevice
vk::raii::Device logicalDevice

Private Static Functions

static auto logPhysicalDevices(const vk::raii::PhysicalDevices &physicalDevices) -> void
static auto selectPhysicalDevice(const vk::raii::PhysicalDevices &physicalDevices) -> const vk::raii::PhysicalDevice&
class DynamicLoader

Public Functions

DynamicLoader()

Private Members

vk::DynamicLoader dynamicLoader
class Event
#include <event.hxx>

Base class for all events.

Subclassed by obscura::KeyEvent< EventCause::MouseClicked >, obscura::KeyEvent< compile_time_cause >, 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.

Protected Attributes

obscura::EventCategory category
obscura::EventCause cause
template<class EventType>
struct EventDefinitionBase

Public Types

using Event = EventType
template<Dispatchable Dispatcher = Dispatcher>
class EventEmitter

Public Functions

inline explicit EventEmitter(Dispatcher *dispatcher)
template<class Event>
inline void emit(Event &&event)
template<class Event>
inline void emit(const Event &event)

Private Members

Dispatcher *dispatcher
class FakeWindow

Public Static Functions

static inline constexpr auto getVulkanExtensions()
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 toFrameTime() const -> TimeUnit
template<class TimeUnit>
inline auto framesPerTimeUnit() const -> float
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

template<class TimeUnit>
static inline auto fromFrameTime(TimeUnit &&frameTime) -> FPS
template<class TimeUnit>
static inline auto fromDurationAndNumberOfFrames(TimeUnit duration, std::size_t numberOfFrames) -> FPS

Private Members

float 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
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
inline void onTick([[maybe_unused]] const TickEvent &tickEvent)

Private Functions

inline FrameDelayer(Dispatcher &dispatcher, Event &&event, std::size_t framesToWait)

Private Members

Event event
Dispatcher *dispatcher
std::size_t framesToWait

Friends

template<Dispatchable D, class E>
friend void emitDelayedEvent(D&, E &&event, std::size_t)
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.

Public Functions

inline FramePacer()
inline void sleepRestOfFrameTime(const FPS &fps) const
template<duration TimeUnit>
inline void sleepForSinceLastTick(TimeUnit duration) const
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.

inline auto getFPS() const -> FPS

Returns FPS measured over the time point horizon.

Returns:

FPS

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:

FPS

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 getLastFrameTime() const -> TimeUnit
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()

Private Members

std::list<TimePoint::duration> frameTimes = {}
std::list<TimePoint> tickedTimePoints = {}
TimePoint referencePoint
HorizonTimeUnit timePointsHorizon
class GlfwException : private std::exception

Public Functions

auto what() const noexcept -> const char* override
template<typename Dispatcher>
class GlfwWindow

Public Functions

explicit GlfwWindow(EventEmitter<Dispatcher> *emitter)
void create(const std::string &title, std::size_t width, std::size_t height)
void update()
void pollEvents()
auto getVulkanExtensions() const -> std::span<const char*>

Private Members

std::unique_ptr<GLFWwindow, void (*)(GLFWwindow*)> window
EventEmitter<Dispatcher> *emitter
glm::vec2 lastMousePosition = {0, 0}

Private Static Attributes

static bool glfwInitialized = false

Friends

friend void keyCallback(GLFWwindow *window, int key, int scancode, int action, int mods)
friend void windowCloseCallback(GLFWwindow *window)
friend void mouseMovedCallback(GLFWwindow *window, double xCoordinate, double yCoordinate)
template<Dispatchable Dispatcher = Dispatcher>
class HeadlessWindow

Public Functions

inline explicit HeadlessWindow(EventEmitter<Dispatcher> *emitter)
inline void create([[maybe_unused]] const std::string &title, [[maybe_unused]] std::size_t width, [[maybe_unused]] std::size_t height)
inline void update()
inline void pollEvents()
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_POLL_INTERVAL_IN_SECONDS)
inline void clickMouse(const glm::vec2 &position, int key)
inline void scrollMouse(float verticalOffset, float horizontalOffset)
auto getVulkanExtensions() const -> std::span<const char*>

Private Functions

template<class E, class EventArgs>
inline void processQueue(moodycamel::ConcurrentQueue<EventArgs> *queue)

Private Members

EventEmitter<Dispatcher> *emitter
moodycamel::ConcurrentQueue<std::tuple<int>> keyPressedEvents
moodycamel::ConcurrentQueue<std::tuple<int>> keyReleasedEvents
moodycamel::ConcurrentQueue<std::tuple<int>> keyRepeatedEvents
moodycamel::ConcurrentQueue<std::tuple<float, float, float, float>> movedMouseEvents
moodycamel::ConcurrentQueue<std::tuple<float, float, int>> clickedMouseEvents
moodycamel::ConcurrentQueue<std::tuple<float, float>> scrolledMouseEvents
class Instance

Public Functions

Instance()
Instance(const std::span<const char*> &externallyRequiredExtensions)
~Instance() = default
Instance(const Instance &other) = delete
auto operator=(const Instance &other) -> Instance& = delete
Instance(Instance&&) = delete
auto operator=(Instance&&) -> Instance& = delete
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 setupDebugMessenger() -> std::optional<vk::raii::DebugUtilsMessengerEXT>
auto setupVulkanExtensions(const std::span<const char*> &externallyRequiredExtensions) -> void
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
std::vector<const char*> requiredExtensions
std::vector<const char*> requiredLayers
vk::InstanceCreateInfo instanceCreateInfo
vk::raii::Instance instance
std::optional<vk::raii::DebugUtilsMessengerEXT> debugMessenger

Private Static Functions

static auto queryAvailableVulkanExtensions() -> const std::vector<vk::ExtensionProperties>&
static auto queryAvailableVulkanLayers() -> const std::vector<vk::LayerProperties>&
static auto logAvailableVulkanExtensions() -> void
static auto logAvailableVulkanLayers() -> void
static auto createDebugUtilsMessengerCreateInfoEXT() -> vk::DebugUtilsMessengerCreateInfoEXT

Private Static Attributes

static const bool enableValidationLayers = false
static bool extensionsAlreadyQueried = false
static std::vector<vk::ExtensionProperties> availableExtensions
static bool layersAlreadyQueried = false
static std::vector<vk::LayerProperties> availableLayers
template<obscura::EventCause compile_time_cause>
class KeyEvent : public obscura::Event

Public Functions

inline explicit KeyEvent(int key)
inline auto getKey() const -> int

Private Members

int key
class ListenerCouldNotBeRemovedException : public std::exception

Public Functions

auto what() const noexcept -> const char* override
class Logger

Public Functions

explicit Logger(const std::string &name)
Logger(const std::string &name, spdlog::sink_ptr sink)
void addSink(spdlog::sink_ptr sink)
void setLevel(spdlog::level::level_enum level)
template<typename ...Args>
inline void info(const char *fmt, const Args&... args)
template<typename ...Args>
inline void warn(const char *fmt, const Args&... args)
template<typename ...Args>
inline void error(const char *fmt, const Args&... args)
template<typename ...Args>
inline void debug(const char *fmt, const Args&... args)
template<typename ...Args>
inline void trace(const char *fmt, const Args&... args)

Private Members

spdlog::logger backend
class Logging

Public Functions

Logging()

Public Static Functions

static void init()
static auto getCoreLogger() -> Logger&
static auto getClientLogger() -> Logger&

Private Static Attributes

static bool initialized = false
static std::optional<Logger> coreLogger
static std::optional<Logger> clientLogger
template<Dispatchable Dispatcher>
class LoopBase : public obscura::ConfigurableDispatcher<TickDefinition, KeyPressedDefinition, MouseMovedDefintion, KeyReleasedDefintion, KeyRepeatedDefintion, WindowClosedDefintion, MouseClickedDefinition, LoopEndDefinition>

Subclassed by obscura::MainLoop< obscura::ConfigurableDispatcher >, obscura::AsyncLoop< Dispatcher >, obscura::MainLoop< Dispatcher >, obscura::SyncLoop< Dispatcher, BaseLoop >

Public Functions

inline LoopBase()
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>
inline void scheduleOnce(Event &&event)
template<class Event, class Duration>
inline void scheduleOnce(Event &&event, const Duration &delay)
template<class Event>
inline void scheduleOnce(Event &&event, std::size_t afterNFrames)
inline auto getFramePacer() const -> const FrameProfiler<>&
inline void waitForStop()

Protected Functions

inline void assertIsNotRunning() const
inline void initRun()
inline void tearDownRun()

Protected Attributes

FramePacer framePacer = {}
std::atomic_flag isRunning
std::atomic_flag interruptSignal
class LoopConfig

Subclassed by obscura::LoopSynchronizer< BaseLoop, DependentLoop >

Public Static Functions

static auto targetFPS(const FPS &fps)
static auto runAtFractionOfBaseLoop(float fraction) -> FractionalLoopConfig

Protected Attributes

bool isTargetingFPS = false
FPS fpsTarget
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
class LoopDoesNotExistException : public std::exception

Public Functions

explicit LoopDoesNotExistException(const std::string &name)
auto what() const noexcept -> const char* override

Private Members

std::string message
class LoopIsAlreadyRunningException : public std::exception

Public Functions

auto what() const noexcept -> const char* override
template<class BaseLoop, class DependentLoop>
class LoopSynchronizer : private obscura::LoopConfig

Public Functions

inline explicit LoopSynchronizer(BaseLoop &baseLoop, DependentLoop &dependentLoop, LoopConfig config)
inline explicit LoopSynchronizer(BaseLoop &baseLoop, DependentLoop &dependentLoop, LoopConfig &&config)
inline void onTick([[maybe_unused]] const TickEvent &event)

Private Functions

inline auto shouldTickDependentLoop(const FPS &targetFPS) const -> bool
template<class TimeUnit>
inline auto computeFrameTimeRequiredForTargetFPS(const FPS &targetFPS) const -> TimeUnit
template<class TimeUnit>
inline auto predictDurationToNextBaseTick() const -> TimeUnit
inline auto shouldTickDependentLoop(float fractionOfBaseLoop) const -> bool

Private Members

BaseLoop *baseLoop
DependentLoop *dependentLoop
template<Dispatchable Dispatcher>
class MainLoop : public obscura::LoopBase<Dispatcher>

Public Functions

inline void run(const FPS &fps)
inline void stop()
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
class MouseMovedEvent : public obscura::Event

Public Functions

MouseMovedEvent(float xPosition, float yPosition, float xOffset, float yOffset)
auto getOffset() const -> const glm::vec2&
auto getPreviousPosition() const -> const glm::vec2&
auto getCurrentPosition() const -> glm::vec2

Private Members

glm::vec2 offset
glm::vec2 position
class MouseScrolledEvent : public obscura::Event

Public Functions

MouseScrolledEvent(float verticalOffset, float horizontalOffset)
auto getVerticalOffset() const -> const float&
auto getHorizontalOffset() const -> const float&

Private Members

float verticalOffset
float horizontalOffset
class NameAlreadyTakenException : public std::exception

Public Functions

NameAlreadyTakenException(const std::string &name, const std::string &context)
auto what() const noexcept -> const char* override

Private Members

std::string message
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 events 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 events on the loop.

  • fpsFPS 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:
  • eventEvent 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:

eventEvent 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:
  • eventEvent 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:
  • eventEvent to be scheduled.

  • delay – Delay after which the event is to be scheduled.

template<class Listener>
inline void appendListener(Listener &listener, const std::string &loopName)
template<class Listener>
inline void appendListener(Listener &listener)

Registers a listener with the main loop.

Template Parameters:

Listener – Type of the listener.

Parameters:

listener – The listener to be registered.

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
template<class T>
class Singleton

Public Functions

Singleton(const Singleton&) = delete
void operator=(const Singleton&) = delete

Public Static Functions

static inline auto getInstance() -> T&

Protected Functions

inline Singleton()
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

BaseLoop *baseLoop
std::unique_ptr<LoopSynchronizer<BaseLoop, SyncLoop<Dispatcher, BaseLoop>>> synchronizer
class TargetFPSLoopConfig : public obscura::BaseLoopConfig<TargetFPSLoopConfig>

Public Functions

auto build() const

Private Functions

explicit TargetFPSLoopConfig(const FPS &fps)

Private Members

FPS fpsTarget

Friends

friend class LoopConfig
class TickEvent : public obscura::Event

Public Functions

explicit TickEvent(std::chrono::microseconds durationSinceLastTick)
auto getDurationSinceLastTick() const -> std::chrono::microseconds

Private Members

std::chrono::microseconds durationSinceLastTick
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 getStart() const -> TimePoint
auto getTick() const -> TimePoint
auto getEnd() const -> TimePoint
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.

Protected Attributes

TimePoint startPoint
TimePoint lastTickPoint
TimePoint endPoint
bool started = false
bool stopped = false

Private Functions

auto invoked() const -> bool
class TimerAlreadyStartedException : public std::exception

Private Functions

auto what() const noexcept -> const char* override
class TimerAlreadyStoppedException : public std::exception

Private Functions

auto what() const noexcept -> const char* override
class TimerNotStartedException : public std::exception

Private Functions

auto what() const noexcept -> const char* override
class TimerNotStoppedException : public std::exception

Private Functions

auto what() const noexcept -> const char* override
class VulkanInstanceTest : public testing::Test

Protected Functions

inline void SetUp() override

Private Members

obscura::DynamicLoader dynamicLoader
template<typename Window>
class VulkanRenderer

Public Functions

inline VulkanRenderer(const Window &window)

Private Members

DynamicLoader dynamicLoader
Instance instance
Device device
class VulkanRendererTest : public testing::Test

Protected Functions

inline void SetUp() override
template<Dispatchable Dispatcher = obscura::Dispatcher, template<typename> typename Implementation = DefaultWindowImplementation>
class Window : public obscura::EventEmitter<obscura::Dispatcher>

Public Functions

inline Window(Dispatcher *dispatcher, const WindowProperties &windowProperties)
inline Window(Dispatcher *dispatcher, WindowProperties &&windowProperties)
inline void open(const WindowProperties &newWindowProperties)
inline void close()
inline void tick()
inline auto getWidth() const -> std::size_t
inline auto getHeight() const -> std::size_t
inline auto getImplementation() const -> Implementation<Dispatcher>&
inline auto getVulkanExtensions() const -> std::span<const char*>

Private Members

std::unique_ptr<Implementation<Dispatcher>> implementation
std::unique_ptr<WindowProperties> windowProperties
std::atomic<bool> windowClosed = true
class WindowEvent : public obscura::Event

Public Functions

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}
namespace obscura

Typedefs

using Dispatcher = ConfigurableDispatcher<TickDefinition, KeyPressedDefinition, MouseMovedDefintion, KeyReleasedDefintion, KeyRepeatedDefintion, 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 events.

using KeyPressedEvent = KeyEvent<EventCause::KeyPressed>
using KeyRepeatedEvent = KeyEvent<EventCause::KeyRepeated>
using KeyReleasedEvent = KeyEvent<EventCause::KeyReleased>
template<typename Window>
using DefaultRendererImplementation = VulkanRenderer<Window>
typedef std::chrono::steady_clock Clock
using TimePoint = decltype(Clock::now())
template<class Dispatcher>
using DefaultWindowImplementation = GlfwWindow<Dispatcher>

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
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

Functions

template<class Definition, class Queue>
void appendToEventQueue(typename Definition::Event &&event, Queue &eventQueue)

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.

Template Parameters:
  • Definition – The event definition.

  • Queue – The type of the queue.

Parameters:
  • event – The event of type Definition::Event.

  • eventQueue – The event queue object.

template<class Definition, class Queue>
void appendToEventQueue(const typename Definition::Event &event, Queue &eventQueue)

Same as appendToEventQueue(Definition::Event&&, Queue&) but with a const reference to the event.

Template Parameters:
  • Definition – The event definition.

  • Queue – The type of the queue.

Parameters:
  • event – The event of type Definition::Event.

  • eventQueue – The event queue object.

template<class Definition, class Queue, class Address>
void appendToEventQueue(const Address &address, typename Definition::Event &&event, Queue &eventQueue)

Same as appendToEventQueue(typename Definition::Event&& event, Queue& eventQueue) but addresses the event only to the given listener.

Template Parameters:
  • Definition – The event definition.

  • Queue – The type of the queue.

  • Address – Type of the addressed listener.

Parameters:
  • address – Listener to which the event shall be solely dispatched.

  • event – The event of type Definition::Event.

  • eventQueue – The event queue object.

template<class Definition, class Queue, class Address>
void appendToEventQueue(const Address &address, const typename Definition::Event &event, Queue &eventQueue)

Same as appendToEventQueue(const Address& address, typename Definition::Event&& event, Queue& eventQueue) but with a const reference event.

Template Parameters:
  • Definition – The event definition.

  • Queue – The type of the queue.

  • Address – Type of the addressed listener.

Parameters:
  • address – Listener to which the event shall be solely dispatched.

  • event – The event of type Definition::Event.

  • eventQueue – The event queue object.

template<class Definition, class Queue>
void checkIfHasListener(std::size_t code, const Queue &eventQueue)

Checks if a queue has any listener for the given code.

Template Parameters:
  • Definition – The event definition.

  • Queue – The type of the event queue.

Parameters:
  • code – 0 for generic listeners and <address> (i.e. the pointer address) for addressable listeners

  • eventQueue – The event queue object.

template<class Definition, class Listener, class Queue, class ListenerRegistry>
auto appendToListenerQueue(Listener &listener, Queue &queue, ListenerRegistry &registry)

Register a listener with an event queue.

Template Parameters:
  • Definition – The event definition.

  • Listener – The listener type.

  • Queue – The event queue type.

  • ListenerRegistry – The type of the listener registry. Usually, std::unordered_map<std::size_t, std::list<Handle>>

Parameters:
  • listener – The listener object.

  • queue – The event queue object.

  • registry – The listener registry keeps track of appended listeners and their handles such that they can be removed again.

Returns:

Returns the address of the appended listener casted to size_t.

template<class Definition, class Listener, class Queue, class ListenerRegistry>
auto appendToAddressableListenerQueue(Listener &listener, Queue &queue, ListenerRegistry &registry)

Same as appendToListenerQueue(Listener& listener, Queue& queue, ListenerRegistry& registry) but it will append an addressable listener.

Template Parameters:
  • Definition – The event definition.

  • Listener – The listener type.

  • Queue – The event queue type.

  • ListenerRegistry – The type of the listener registry. Usually, std::unordered_map<std::size_t, std::list<Handle>>

Parameters:
  • listener – The listener object.

  • queue – The event queue object.

  • registry – The listener registry keeps track of appended listeners and their handles such that they can be removed again.

Returns:

Returns the address of the appended listener casted to size_t.

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.

DEFINE_EVENT(KeyPressedDefinition, KeyPressedEvent, EventCategory::KeyInput, EventCause::KeyPressed, onKeyPressed)
DEFINE_EVENT(KeyReleasedDefintion, KeyReleasedEvent, EventCategory::KeyInput, EventCause::KeyReleased, onKeyReleased)
DEFINE_EVENT(KeyRepeatedDefintion, KeyRepeatedEvent, EventCategory::KeyInput, EventCause::KeyRepeated, onKeyRepeated)
DEFINE_EVENT(TickDefinition, TickEvent, EventCategory::Application, EventCause::LoopTicked, onTick)
DEFINE_EVENT(LoopEndDefinition, TickEvent, EventCategory::Application, EventCause::LoopStopped, onLoopStop)
DEFINE_EVENT(MouseMovedDefintion, MouseMovedEvent, EventCategory::CoordinateInput, EventCause::MouseMoved, onMouseMoved)
DEFINE_EVENT(MouseClickedDefinition, MouseClickedEvent, EventCategory::KeyInput, EventCause::MouseClicked, onMouseClicked)
DEFINE_EVENT(WindowClosedDefintion, WindowEvent, EventCategory::Window, EventCause::WindowClosed, onWindowClosed)
static VKAPI_ATTR auto VKAPI_CALL debugCallback (VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData, void *) -> VkBool32
template<Dispatchable Dispatcher, class Event>
void emitDelayedEvent(Dispatcher &dispatcher, Event &&event, std::size_t emitAfterNFrames)
template<class TimePoint>
void preciseSleepUntil(const TimePoint &timePoint)
template<duration TimeUnit>
void preciseSleepFor(const TimeUnit &duration)
template<class Dispatcher>
void keyCallback(GLFWwindow *window, int key, [[maybe_unused]] int scancode, int action, [[maybe_unused]] int mods)
template<class Dispatcher>
void windowCloseCallback(GLFWwindow *window)
template<class Dispatcher>
void mouseMovedCallback(GLFWwindow *window, double xCoordinate, double yCoordinate)

Variables

template<class T> concept Dispatchable  = requires(T impl) {impl.dispatch();}
constexpr std::size_t MAX_CATEGORIES = 100
template<typename Renderer, typename Window> concept RendererImplementationConcept   = requires(Renderer renderer, Windowwindow) {Renderer { window };}
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();}
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, class Dispatcher> concept WindowImplementationConcept  = requires(T impl,const std::string& title,std::size_t width,std::size_t height,EventEmitter<Dispatcher>* emitter) {T(emitter);impl.create(title, width, height);impl.update();impl.pollEvents();}
std::mutex tickMutex
namespace constant

Variables

constexpr std::size_t BULK_SIZE = 32
constexpr float DEFAULT_POLL_INTERVAL_IN_SECONDS = 1e-3
constexpr std::size_t DEFAULT_WINDOW_WIDTH = {1280}
constexpr std::size_t DEFAULT_WINDOW_HEIGHT = {720}
constexpr std::string_view DEFAULT_WINDOW_TITLE = {"Obscura"}
namespace std
namespace chrono_literals
namespace testing
file CONTRIBUTING_INSTRUCTIONS.md
file application.hxx
file application.test.cxx
#include <chrono>
#include <gtest/gtest.h>
#include <test_config/config.hxx>
#include <thread>

Functions

TEST_F(ApplicationFixture, MultipleEventsCanBeDispatched)
TEST_F(ApplicationFixture, MultipleConcurrentEventsCanBeDispatched)
TEST_F(ApplicationFixture, TickEventsAreDispatchedToMainLoop)
file core.hxx
#include <atomic>
#include <chrono>
#include <concepts>
#include <cstddef>
#include <functional>
#include <iostream>
#include <list>
#include <memory>
#include <mutex>
#include <numeric>
#include <optional>
#include <span>
#include <string>
#include <thread>
#include <tuple>
#include <type_traits>
#include <unordered_map>
#include <vector>
file dispatcher.hxx
file dispatcher.hxx
#include <eventpp/eventdispatcher.h>
#include <eventpp/eventqueue.h>
file dispatcher.test.cxx
#include <gtest/gtest.h>
#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)
file emitter.hxx
file event.hxx
file event_definition.hxx

Defines

DEFINE_EVENT(ClassName, EventType, EventCategory, EventCause, callback)

Variables

template<class T, class EventType> concept EventDefinition   = std::is_base_of<EventDefinitionBase<EventType>, T>::value && requires(int* listener) {{ T::getEventCode() } -> std::convertible_to<std::size_t>;{ T::getCallback(listener) } -> std::convertible_to<std::function<void(EventType &&)>>;{ T::template hasCallback<int> } -> std::convertible_to<bool>;}
file key_event_definitions.hxx
file loop_event_definitions.hxx
file mouse_event_definitions.hxx
file window_event_defintions.hxx
file events.test.cxx
#include <gtest/gtest.h>
#include <iostream>

Functions

TEST(EventCategoryAndCauseTest, EventCategoryIntsAreCorrect)
TEST(EventCategoryAndCauseTest, EventCauseIntsAreCorrect)
TEST(EventCategoryAndCauseTest, EventCodeIsCorrect)
TEST(EventCategoryAndCauseTest, EventCodeConversionWorks)
file key_events.hxx
file key_events.test.cxx
#include <gtest/gtest.h>

Functions

TEST(KeyEventConstructorTest, KeyEventCanBeConstructed)
TEST(KeyEventConstructorTest, KeyEventGettersReturnCorrectValues)
TEST(KeyEventConstructorTest, KeyEventHasCorrectCode)
file loop_events.cxx
file loop_events.hxx
#include <chrono>
file loops.test.cxx
#include <gtest/gtest.h>
#include <test_config/config.hxx>

Functions

TEST_F(MainLoopFixture, TickListenerAddedToMainLoopIsRegistered)
TEST_F(MainLoopFixture, TickListenerAddedToMainLoopAcceptsTickEvents)
TEST_F(MainLoopFixture, TickListenerOnSyncLoopShouldOnlyReceiveHalfOfTicks)
TEST_F(MainLoopFixture, AsyncLoopAndMainLoopStopAfterGivenNumberOfTicks)
file mouse_events.cxx
file mouse_events.hxx
#include <glm/glm.hpp>
file mouse_events.test.cxx
#include <gtest/gtest.h>

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)
file window_events.cxx
file window_events.hxx
file exceptions.cxx
file exceptions.hxx
file logging.cxx
#include <spdlog/sinks/stdout_color_sinks.h>
#include <utility>
file logging.hxx
#include <fmtmsg.h>
#include <memory>
#include <optional>
#include <spdlog/spdlog.h>

Defines

OBS_CORE_LOG_INFO(...)
OBS_CORE_LOG_WARN(...)
OBS_CORE_LOG_ERROR(...)
OBS_CORE_LOG_DEBUG(...)
OBS_CORE_LOG_TRACE(...)
OBS_LOG_INFO(...)
OBS_LOG_WARN(...)
OBS_LOG_ERROR(...)
OBS_LOG_TRACE(...)
OBS_LOG_DEBUG(...)
file obscura.hxx
file renderer.hxx
file renderer.hxx
file renderer_concept.hxx
file vulkan-init.test.cxx
#include <gtest/gtest.h>
#include <vulkan/vulkan_raii.hpp>

Functions

TEST(Renderer, VulkanInit)
file device.cxx
file device.hxx
#include <vulkan/vulkan_raii.hpp>
file dynamic_loader.cxx

Variables

VULKAN_HPP_DEFAULT_DISPATCH_LOADER_DYNAMIC_STORAGE
file dynamic_loader.hxx
#include <vulkan/vulkan_raii.hpp>
file instance.cxx
#include <vulkan/vulkan_raii.hpp>
file instance.hxx
#include <span>
#include <vulkan/vulkan_raii.hpp>
file instance.test.cxx
#include <gtest/gtest.h>

Functions

TEST_F(VulkanInstanceTest, VulkanInstanceIsSuccessfullyCreated)
TEST_F(VulkanInstanceTest, VulkanInstanceRequiresUnknownExtension)
TEST_F(VulkanInstanceTest, VulkanInstanceCanBeCreatedTwice)
file renderer.test.cxx
#include <gtest/gtest.h>

Functions

TEST_F(VulkanRendererTest, VulkanRendererIsSuccessfullyCreated)
TEST_F(VulkanRendererTest, VulkanRendererCanBeCreatedTwice)
file async_loop.hxx
file loop.hxx
file delay.hxx
file loop_base.hxx
file loop_config.cxx
file loop_config.hxx
file loop_synchronizer.hxx
file main_loop.hxx
file scheduler.hxx
file scheduler.test.cxx
#include <gtest/gtest.h>
#include <test_config/config.hxx>

Functions

TEST(SingletonTest, SingletonReturnsSamePointer)
TEST(SingletonTest, SchedulerReturnsSameMainLoop)
TEST_F(TestKeyListenerFixture, MainLoopCanBeRetrievedAndEventsCanBeScheduled)
TEST_F(TestKeyListenerFixture, EventsCanBeScheduled)
file singleton.hxx
file sync_loop.hxx
file duration.hxx
file fps.cxx
file fps.hxx

Defines

OBS_FORWARD_DECLARE_FPS_OPERATOR(symbol)
OBS_FRIEND_FPS_OPERATOR(symbol)
OBS_IMPLEMENT_FPS_OPERATOR(symbol)
file fps.test.cxx
#include <gtest/gtest.h>

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)
file frame_pacer.hxx
file frame_pacer.test.cxx
#include <gtest/gtest.h>

Functions

TEST(FramePacerFunctionalityTest, SleepForRestOfFrameTimeWorks)
TEST(FramePacerFunctionalityTest, SleepForSinceLastTickWorks)
file frame_profiler.hxx
file frame_profiler.test.cxx
#include <gtest/gtest.h>

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)
file sleep.hxx
file timer.cxx
file timer.hxx
file timer.test.cxx
#include <gtest/gtest.h>
#include <thread>

Functions

TEST(TimerExceptionTest, ExceptionIsThrownIfTimerIsNotStarted)
TEST(TimerExceptionTest, ExceptionIsThrownIfTimerIsStartedTwice)
TEST(TimerExceptionsTest, ExceptionsIsThrownIfTimerIsStoppedTwice)
TEST(TimerFunctionalityTest, TimerReturnsApproximatelyRightDuration)
TEST(TimerFunctionalityTest, TimerReturnsApproximatelyRightDurationInMilliSeconds)
file window_implementation.hxx
#include <concepts>
file window.cxx
file window.cxx
file window.hxx
#include <GLFW/glfw3.h>
#include <span>
file window.hxx
#include <concurrentqueue.h>
#include <glm/glm.hpp>
#include <glm/gtx/norm.hpp>
#include <span>
file window.hxx
file window.test.cxx
#include <gtest/gtest.h>
#include <memory>

Functions

TEST(WindowCreationTest, WindowIsSuccessfullyCreated)
TEST(WindowCreationTest, WindowIsSuccessfullyCreatedWithRValue)
file window_properties.cxx
file window_properties.hxx
page md__home_docs_checkouts_readthedocs_org_user_builds_obscura_engine_checkouts_v0_4_1_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/v0.4.1/src/obscura/application
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/events/concepts
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/window/concepts
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/timer/concepts
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/scheduler/concepts
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/core
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/events/event_definitions
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/events
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/exceptions
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/window/glfw
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/window/headless
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/logging
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/renderer
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/scheduler
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/scheduler/singleton
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/timer
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/renderer/vulkan
dir /home/docs/checkouts/readthedocs.org/user_builds/obscura-engine/checkouts/v0.4.1/src/obscura/window