Nameless Engine
Loading...
Searching...
No Matches
ne::GameInstance Class Reference

#include <GameInstance.h>

Inheritance diagram for ne::GameInstance:
ne::EditorGameInstance

Public Member Functions

 GameInstance (Window *pGameWindow, GameManager *pGameManager, InputManager *pInputManager)
 
 GameInstance (const GameInstance &)=delete
 
GameInstanceoperator= (const GameInstance &)=delete
 
void addDeferredTask (const std::function< void()> &task) const
 
void addTaskToThreadPool (const std::function< void()> &task) const
 
void createWorld (const std::function< void(const std::optional< Error > &)> &onCreated, size_t iWorldSize=Globals::getDefaultWorldSize())
 
void loadNodeTreeAsWorld (const std::function< void(const std::optional< Error > &)> &onLoaded, const std::filesystem::path &pathToNodeTree, size_t iWorldSize=Globals::getDefaultWorldSize())
 
void queueGarbageCollection (bool bForce, const std::optional< std::function< void()> > &onFinished={})
 
void setGarbageCollectorRunInterval (long long iGcRunIntervalInSec)
 
void executeShaderManagerSelfValidation () const
 
sgc::GcPtr< NodegetWorldRootNode () const
 
float getWorldTimeInSeconds () const
 
size_t getWorldSize () const
 
size_t getTotalSpawnedNodeCount ()
 
size_t getCalledEveryFrameNodeCount ()
 
WindowgetWindow () const
 
CameraManagergetCameraManager () const
 
InputManagergetInputManager () const
 
long long getGarbageCollectorRunIntervalInSec ()
 

Static Public Member Functions

static float getTotalApplicationTimeInSec ()
 

Protected Member Functions

TimercreateTimer (const std::string &sTimerName)
 
void stopAndDisableCreatedTimers ()
 
virtual void onGameStarted ()
 
virtual void onBeforeNewFrame (float timeSincePrevCallInSec)
 
virtual void onKeyboardInput (KeyboardKey key, KeyboardModifiers modifiers, bool bIsPressedDown)
 
virtual void onMouseInput (MouseButton button, KeyboardModifiers modifiers, bool bIsPressedDown)
 
virtual void onMouseMove (double xOffset, double yOffset)
 
virtual void onMouseScrollMove (int iOffset)
 
virtual void onWindowFocusChanged (bool bIsFocused)
 
virtual void onFramebufferSizeChanged (int iWidth, int iHeight)
 
virtual void onWindowClose ()
 
std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, bool)> > > * getActionEventBindings ()
 
std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, float)> > > * getAxisEventBindings ()
 

Private Member Functions

void onInputActionEvent (unsigned int iActionId, KeyboardModifiers modifiers, bool bIsPressedDown)
 
void onInputAxisEvent (unsigned int iAxisEventId, KeyboardModifiers modifiers, float input)
 

Private Attributes

std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, bool)> > > mtxBindedActionEvents
 
std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, float)> > > mtxBindedAxisEvents
 
std::pair< std::recursive_mutex, std::vector< std::unique_ptr< Timer > > > mtxCreatedTimers
 
bool bAllowCreatingTimers = true
 
WindowpGameWindow = nullptr
 
GameManagerpGameManager = nullptr
 
InputManagerpInputManager = nullptr
 

Friends

class GameManager
 

Detailed Description

Main game class, exists while the game window is not closed (i.e. while the game is not closed).

Reacts to user inputs, window events and etc. Owned by Game object.

Constructor & Destructor Documentation

◆ GameInstance()

ne::GameInstance::GameInstance ( Window pGameWindow,
GameManager pGameManager,
InputManager pInputManager 
)

Constructor.

Remarks
There is no need to save window/input manager pointers in derived classes as the base class already saves these pointers and provides getWindow and getInputManager functions.
Parameters
pGameWindowWindow that owns this game instance.
pGameManagerGameManager that owns this game instance.
pInputManagerInput manager of the owner Game object.

Member Function Documentation

◆ addDeferredTask()

void ne::GameInstance::addDeferredTask ( const std::function< void()> &  task) const

Adds a function to be executed on the main thread next time onBeforeNewFrame is called.

Warning
Don't capture gc pointers in std::function, this is not supported and will cause memory leaks/crashes!
If you are using member functions/fields inside of the task you need to make sure that the owner object of these member functions/fields will not be deleted until this task is finished. If you use GameInstance or Node member functions/fields inside of the task and submitting a deferred tasks from the main thread then ignore this warning, they are safe to use in deferred tasks and will not be deleted until the task is finished. If you are submitting a deferred task that operates on a GameInstance/Node from a non main thread then you need to do a few additional checks inside of your deferred task, for example:
// We are on a non-main thread inside of a node:
addDeferredTask([this, iNodeId](){ // capturing `this` to use `Node` (self) functions, also
capturing self ID
// We are inside of a deferred task (on the main thread) and we don't know if the node (`this`)
// was garbage collected or not because we submitted our task from a non-main thread.
// REMEMBER: we can't capture `gc` pointers in `std::function`, this is not supported
// and will cause memory leaks/crashes!
const auto pGameManager = GameManager::get(); // using engine's private class `GameManager`
// `pGameManager` is guaranteed to be valid inside of a deferred task.
// Otherwise, if running this code outside of a deferred task you need to do 2 checks:
// if (pGameManager == nullptr) return;
// if (pGameManager->isBeingDestroyed()) return;
if (!pGameManager->isNodeSpawned(iNodeId)){
// Node was despawned and it may be dangerous to run the callback.
return;
}
// Can safely interact with `this` (self) - we are on the main thread.
});
void addDeferredTask(const std::function< void()> &task) const
Definition: GameInstance.cpp:99
GameManager * pGameManager
Definition: GameInstance.h:525
static GameManager * get()
Definition: GameManager.cpp:305
bool isNodeSpawned(size_t iNodeId)
Definition: GameManager.cpp:604
Remarks
In the task you don't need to check if the game is being destroyed, the engine makes sure all tasks are finished before the game is destroyed.
Parameters
taskFunction to execute.

◆ addTaskToThreadPool()

void ne::GameInstance::addTaskToThreadPool ( const std::function< void()> &  task) const

Adds a function to be executed on the thread pool.

Warning
Don't capture gc pointers in std::function, this is not supported and will cause memory leaks/crashes!
If you are using a member functions/fields inside of the task you need to make sure that the owner object of these member functions/fields will not be deleted until this task is finished.
Remarks
In the task you don't need to check if the game is being destroyed, the engine makes sure all tasks are finished before the game is destroyed.
Parameters
taskFunction to execute.

◆ createTimer()

Timer * ne::GameInstance::createTimer ( const std::string &  sTimerName)
protected

Creates a new timer and saves it inside of this GameInstance.

Warning
Do not free (delete) returned pointer.
Do not use returned pointer outside of this object as the timer is only guaranteed to live while the GameInstance (that created the timer) is living.
Remarks
This function will not work and will log an error if you would try to create a timer inside of the onWindowClose function.
This function exists to add some protection code to not shoot yourself in the foot, such as: GameInstance will automatically stop and disable created timers before onWindowClose is called by using Timer::stop(true) so that you don't have to remember to stop created timers. Moreover, if you are using a callback function for the timer's timeout event it's guaranteed that this callback function will only be called while the object is valid.
There is no removeTimer function but it may appear in the future (although there's really no point in removing a timer so don't care about it).
Parameters
sTimerNameName of this timer (used for logging). Don't add "timer" word to your timer's name as it will be appended in the logs.
Returns
nullptr if something went wrong, otherwise a non-owning pointer to the created timer that is guaranteed to be valid while this object is alive.

◆ createWorld()

void ne::GameInstance::createWorld ( const std::function< void(const std::optional< Error > &)> &  onCreated,
size_t  iWorldSize = Globals::getDefaultWorldSize() 
)

Adds a deferred task (see addDeferredTask) to create a new world that contains only one node - root node.

Warning
If you are holding any gc pointers to nodes in your game instance, make sure you clear them (set to nullptr) before calling this function.
Remarks
Replaces the old world (if existed).
Engine will execute all deferred tasks before changing the world (before destroying all nodes), so even if deferred tasks queue looks like this: ... – create/load world task – call node's member function task – ..., on create/load world task the engine will finish all other tasks and only when deferred tasks queue is empty start to create/load world so you don't need to care about the order of deferred tasks.
Parameters
onCreatedCallback function that will be called on the main thread after the world is created. Contains optional error (if world creation failed) as the only argument. Use GameInstance member functions as callback functions for created worlds, because all nodes and other game objects will be destroyed while the world is changing.
iWorldSizeSize of the new world in game units. Must be power of 2 (128, 256, 512, 1024, 2048, etc.). World size needs to be specified for internal purposes such as Directional Light shadow map size. You don't need to care why we need this information, you only need to know that if you leave world bounds lighting or physics may be incorrect (the editor or engine will warn you if something is leaving world bounds, pay attention to the logs).

◆ executeShaderManagerSelfValidation()

void ne::GameInstance::executeShaderManagerSelfValidation ( ) const

Analyzes the current state to see if any shader-related errors have place (like unused shaders in memory or etc.). Fixes errors and reports them in log.

Remarks
Generally should be called right before you let the player play the game (after all required nodes are spawned).

◆ getActionEventBindings()

std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, bool)> > > * ne::GameInstance::getActionEventBindings ( )
protected

Returns map of action events that this GameInstance is binded to (must be used with mutex). Binded callbacks will be automatically called when an action event is triggered.

Remarks
Note that nodes can also have their input event bindings and you may prefer to bind to input in specific nodes instead of binding to them in GameInstance.
Only events in GameInstance's InputManager (GameInstance::getInputManager) will be considered to trigger events in the node.
Called after onKeyboardInput.

Example:

const unsigned int iForwardActionId = 0;
const auto pMtxActionEvents = getActionEventBindings();
std::scoped_lock guard(pMtxActionEvents->first);
pMtxActionEvents->second[iForwardActionId] = [&](KeyboardModifiers modifiers, bool
bIsPressedDown) {
moveForward(modifiers, bIsPressedDown);
};
std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, bool)> > > * getActionEventBindings()
Definition: GameInstance.cpp:135
Definition: KeyboardKey.hpp:10
Returns
Binded action events.

◆ getAxisEventBindings()

std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, float)> > > * ne::GameInstance::getAxisEventBindings ( )
protected

Returns map of axis events that this GameInstance is binded to (must be used with mutex). Binded callbacks will be automatically called when an axis event is triggered.

Remarks
Note that nodes can also have their input event bindings and you may prefer to bind to input in specific nodes instead of binding to them in GameInstance.
Only events in GameInstance's InputManager (GameInstance::getInputManager) will be considered to trigger events in the node.
Called after onKeyboardInput.

Example:

const auto iForwardAxisEventId = 0;
const auto pMtxAxisEvents = getAxisEventBindings();
std::scoped_lock guard(pMtxAxisEvents->first);
pMtxAxisEvents->second[iForwardAxisEventId] = [&](KeyboardModifiers modifiers, float input) {
moveForward(modifiers, input);
};
std::pair< std::recursive_mutex, std::unordered_map< unsigned int, std::function< void(KeyboardModifiers, float)> > > * getAxisEventBindings()
Definition: GameInstance.cpp:142
Remarks
Input parameter is a value in range [-1.0f; 1.0f] that describes input.
Returns
Binded action events.

◆ getCalledEveryFrameNodeCount()

size_t ne::GameInstance::getCalledEveryFrameNodeCount ( )

Returns the current amount of spawned nodes that are marked as "should be called every frame".

Returns
Amount of spawned nodes that should be called every frame.

◆ getCameraManager()

CameraManager * ne::GameInstance::getCameraManager ( ) const

Returns a reference to the camera manager this game is using.

Returns
A pointer to the camera manager, should not be deleted.

◆ getGarbageCollectorRunIntervalInSec()

long long ne::GameInstance::getGarbageCollectorRunIntervalInSec ( )

Returns the current interval after which we need to run garbage collector again.

Returns
Interval in seconds.

◆ getInputManager()

InputManager * ne::GameInstance::getInputManager ( ) const

Returns a reference to the input manager this game instance is using. Input manager allows binding IDs with multiple input keys that you can receive in onInputActionEvent.

Returns
A pointer to the input manager, should not be deleted.

◆ getTotalApplicationTimeInSec()

float ne::GameInstance::getTotalApplicationTimeInSec ( )
static

Returns the time in seconds that has passed since the very first window was created.

Returns
Time in seconds.

◆ getTotalSpawnedNodeCount()

size_t ne::GameInstance::getTotalSpawnedNodeCount ( )

Returns total amount of currently spawned nodes.

Returns
Total nodes spawned right now.

◆ getWindow()

Window * ne::GameInstance::getWindow ( ) const

Returns a reference to the window this game instance is using.

Returns
A pointer to the window, should not be deleted.

◆ getWorldRootNode()

sgc::GcPtr< Node > ne::GameInstance::getWorldRootNode ( ) const

Returns a pointer to world's root node.

Returns
nullptr if world is not created or was destroyed (see createWorld), otherwise world's root node.

◆ getWorldSize()

size_t ne::GameInstance::getWorldSize ( ) const

Returns world size in game units.

Returns
World size.

◆ getWorldTimeInSeconds()

float ne::GameInstance::getWorldTimeInSeconds ( ) const

Returns time since world creation (in seconds).

Returns
Zero if world is not created (see createWorld), otherwise time since world creation (in seconds).

◆ loadNodeTreeAsWorld()

void ne::GameInstance::loadNodeTreeAsWorld ( const std::function< void(const std::optional< Error > &)> &  onLoaded,
const std::filesystem::path &  pathToNodeTree,
size_t  iWorldSize = Globals::getDefaultWorldSize() 
)

Adds a deferred task (see addDeferredTask) to load and deserialize a node tree to be used as the new world.

Node tree's root node will be used as world's root node.

Warning
If you are holding any gc pointers to nodes in game instance, make sure you set nullptr to them before calling this function.
Remarks
Replaces the old world (if existed).
Engine will execute all deferred tasks before changing the world (before destroying all nodes), so even if deferred tasks queue looks like this: ... – create/load world task – call node's member function task – ..., on create/load world task the engine will finish all other tasks and only when deferred tasks queue is empty start to create/load world so you don't need to care about the order of deferred tasks.
Parameters
onLoadedCallback function that will be called on the main thread after the world is loaded. Contains optional error (if world loading failed) as the only argument. Use GameInstance member functions as callback functions for loaded worlds, because all nodes and other game objects will be destroyed while the world is changing.
pathToNodeTreePath to the file that contains a node tree to load, the ".toml" extension will be automatically added if not specified.
iWorldSizeSize of the world in game units. Must be power of 2 (128, 256, 512, 1024, 2048, etc.). World size needs to be specified for internal purposes such as Directional Light shadow map size. You don't need to care why we need this information, you only need to know that if you leave world bounds lighting or physics may be incorrect (the editor or engine will warn you if something is leaving world bounds, pay attention to the logs).

◆ onBeforeNewFrame()

virtual void ne::GameInstance::onBeforeNewFrame ( float  timeSincePrevCallInSec)
inlineprotectedvirtual

Called before a new frame is rendered.

Remarks
Called before nodes that should be called every frame.
Parameters
timeSincePrevCallInSecTime in seconds that has passed since the last call to this function.

Reimplemented in ne::EditorGameInstance.

◆ onFramebufferSizeChanged()

virtual void ne::GameInstance::onFramebufferSizeChanged ( int  iWidth,
int  iHeight 
)
inlineprotectedvirtual

Called when the framebuffer size was changed.

Parameters
iWidthNew width of the framebuffer (in pixels).
iHeightNew height of the framebuffer (in pixels).

◆ onGameStarted()

virtual void ne::GameInstance::onGameStarted ( )
inlineprotectedvirtual

Called after GameInstance's constructor is finished and created GameInstance object was saved in GameManager (that owns GameInstance).

At this point you can create and interact with the game world and etc.

Reimplemented in ne::EditorGameInstance.

◆ onInputActionEvent()

void ne::GameInstance::onInputActionEvent ( unsigned int  iActionId,
KeyboardModifiers  modifiers,
bool  bIsPressedDown 
)
private

Called when a window that owns this game instance receives user input and the input key exists as an action event in the InputManager. Called after onKeyboardInput.

Parameters
iActionIdUnique ID of the input action event (from input manager).
modifiersKeyboard modifier keys.
bIsPressedDownWhether the key down event occurred or key up.

◆ onInputAxisEvent()

void ne::GameInstance::onInputAxisEvent ( unsigned int  iAxisEventId,
KeyboardModifiers  modifiers,
float  input 
)
private

Called when a window that owns this game instance receives user input and the input key exists as an axis event in the InputManager. Called after onKeyboardInput and after onInputActionEvent.

Parameters
iAxisEventIdUnique ID of the input axis event (from input manager).
modifiersKeyboard modifier keys.
inputA value in range [-1.0f; 1.0f] that describes input.

◆ onKeyboardInput()

virtual void ne::GameInstance::onKeyboardInput ( KeyboardKey  key,
KeyboardModifiers  modifiers,
bool  bIsPressedDown 
)
inlineprotectedvirtual

Called when the window receives keyboard input. Called before onInputActionEvent. Prefer to use onInputActionEvent instead of this function.

Parameters
keyKeyboard key.
modifiersKeyboard modifier keys.
bIsPressedDownWhether the key down event occurred or key up.

◆ onMouseInput()

virtual void ne::GameInstance::onMouseInput ( MouseButton  button,
KeyboardModifiers  modifiers,
bool  bIsPressedDown 
)
inlineprotectedvirtual

Called when the window receives mouse input. Called before onInputActionEvent. Prefer to use onInputActionEvent instead of this function.

Parameters
buttonMouse button.
modifiersKeyboard modifier keys.
bIsPressedDownWhether the button down event occurred or button up.

◆ onMouseMove()

virtual void ne::GameInstance::onMouseMove ( double  xOffset,
double  yOffset 
)
inlineprotectedvirtual

Called when the window received mouse movement.

Parameters
xOffsetMouse X movement delta in pixels (plus if moved to the right, minus if moved to the left).
yOffsetMouse Y movement delta in pixels (plus if moved up, minus if moved down).

◆ onMouseScrollMove()

virtual void ne::GameInstance::onMouseScrollMove ( int  iOffset)
inlineprotectedvirtual

Called when the window receives mouse scroll movement.

Parameters
iOffsetMovement offset.

◆ onWindowClose()

virtual void ne::GameInstance::onWindowClose ( )
inlineprotectedvirtual

Called when the window that owns this game instance was requested to close (no new frames will be rendered).

Prefer to have your destructor logic here, because after this function is finished the world will be destroyed and will be inaccessible (nullptr).

◆ onWindowFocusChanged()

virtual void ne::GameInstance::onWindowFocusChanged ( bool  bIsFocused)
inlineprotectedvirtual

Called when the window focus was changed.

Parameters
bIsFocusedWhether the window has gained or lost the focus.

◆ queueGarbageCollection()

void ne::GameInstance::queueGarbageCollection ( bool  bForce,
const std::optional< std::function< void()> > &  onFinished = {} 
)

Queues a request to run a garbage collection as a deferred task on the main thread using addDeferredTask.

Remarks
Typically you don't need to call this function as garbage collection is executed regularly (see setGarbageCollectorRunInterval) but you can still call it anyway.
Parameters
bForceForce run garbage collection even if the last garbage collection was run not so long ago.
onFinishedOptional callback that will be triggered on the main thread when garbage collection is finished (queued as addDeferredTask).

◆ setGarbageCollectorRunInterval()

void ne::GameInstance::setGarbageCollectorRunInterval ( long long  iGcRunIntervalInSec)

Modifies the interval after which we need to run garbage collector again. The current value can be retrieved using getGarbageCollectorRunIntervalInSec.

Remarks
Interval should be in range [30; 300] seconds (otherwise it will be clamped).
Note that garbage collection will also be executed additionally in some special cases, such as when World is being destructed.
Parameters
iGcRunIntervalInSecInterval in seconds.

◆ stopAndDisableCreatedTimers()

void ne::GameInstance::stopAndDisableCreatedTimers ( )
protected

Called by owner object to stop and disable all created timers, additionally does not allows creating any more timers.

Member Data Documentation

◆ bAllowCreatingTimers

bool ne::GameInstance::bAllowCreatingTimers = true
private

Whether createTimer works or not.

◆ mtxBindedActionEvents

std::pair< std::recursive_mutex, std::unordered_map<unsigned int, std::function<void(KeyboardModifiers, bool)> > > ne::GameInstance::mtxBindedActionEvents
private

Map of action events that this GameInstance is binded to. Must be used with mutex.

◆ mtxBindedAxisEvents

std::pair< std::recursive_mutex, std::unordered_map<unsigned int, std::function<void(KeyboardModifiers, float)> > > ne::GameInstance::mtxBindedAxisEvents
private

Map of axis events that this GameInstance is binded to. Must be used with mutex.

◆ mtxCreatedTimers

std::pair<std::recursive_mutex, std::vector<std::unique_ptr<Timer> > > ne::GameInstance::mtxCreatedTimers
private

Timers creates via createTimer.

Warning
Don't remove/erase timers from this array because in callback validator's deferred task we will use the timer to check its state so we need to make sure that stopped timer will not be deleted while the object exists.

◆ pGameManager

GameManager* ne::GameInstance::pGameManager = nullptr
private

Do not delete. Owner of this object.

◆ pGameWindow

Window* ne::GameInstance::pGameWindow = nullptr
private

Do not delete. Owner of pGameManager object.

◆ pInputManager

InputManager* ne::GameInstance::pInputManager = nullptr
private

Do not delete. Input manager of the pGameManager object.


The documentation for this class was generated from the following files: