Leviathan  0.8.0.0
Leviathan game engine
Leviathan::Engine Class Reference

The main class of the Leviathan Game Engine. More...

#include <Engine.h>

+ Inheritance diagram for Leviathan::Engine:

Public Member Functions

DLLEXPORT Engine (LeviathanApplication *owner)
 
DLLEXPORT ~Engine ()
 
DLLEXPORT bool Init (AppDef *definition, NETWORKED_TYPE ntype, NetworkInterface *packethandler)
 
DLLEXPORT void Release (bool forced=false)
 
DLLEXPORT void PreRelease ()
 Sets objects ready to be released. More...
 
DLLEXPORT bool HasPreReleaseBeenDone () const
 Checks if PreRelease is done and Release can be called. More...
 
DLLEXPORT SecondDuration GetTimeSinceLastTick () const
 Calculates how long has elapsed since the last tick. More...
 
DLLEXPORT void MessagePump ()
 Processes queued messages from SDL and CEF. More...
 
DLLEXPORT float Update ()
 Runs an update cycle (tick and rendering if needed) More...
 
DLLEXPORT void PreFirstTick ()
 Called by Application before the first Update call. More...
 
DLLEXPORT int GetWindowOpenCount ()
 
DLLEXPORT void ClearTimers ()
 Clears physical timers. More...
 
DLLEXPORT void MarkQuit ()
 Marks the owning application to quit. More...
 
DLLEXPORT void Invoke (const std::function< void()> &function)
 Runs function on the main thread before the next tick. More...
 
DLLEXPORT void RunOnMainThread (const std::function< void()> &function)
 Runs the function now if on the main thread otherwise calls Invoke. More...
 
DLLEXPORT bool IsOnMainThread () const
 Returns true if called on the main thread. More...
 
DLLEXPORT void AssertIfNotMainThread () const
 Asserts if not called on the main thread. More...
 
DLLEXPORT bool PassCommandLine (int argcount, char *args[])
 
DLLEXPORT std::shared_ptr< GameWorldCreateWorld (Window *owningwindow, int worldtype, const std::shared_ptr< PhysicsMaterialManager > &physicsMaterials, const WorldNetworkSettings &networking, int overrideid=-1)
 Creates a GameWorld for placing entities into. More...
 
DLLEXPORT void DestroyWorld (const std::shared_ptr< GameWorld > &world)
 Releases a GameWorld. More...
 
DLLEXPORT WindowOpenNewWindow ()
 Opens a new window. More...
 
DLLEXPORT bool CloseWindow (Window *window)
 Closes a window. More...
 
DLLEXPORT WindowGetWindowEntity ()
 Returns the main window. More...
 
DLLEXPORT void ReportClosedWindow (Window *windowentity)
 Removes an closed window from the engine. More...
 
DLLEXPORT bool IsValidWindow (Window *window) const
 
DLLEXPORT void SaveScreenShot ()
 
DLLEXPORT void OpenEditorWindow (Window *useexistingwindow=nullptr)
 Opens an Editor::Editor window. More...
 
DLLEXPORT void FocusOrOpenEditor ()
 Focuses the first editor or opens an editor if none are open. More...
 
GraphicsGetGraphics ()
 
bool IsInGraphicalMode () const
 
EventHandlerGetEventHandler ()
 
RenderingStatisticsGetRenderingStatistics ()
 
ScriptConsoleGetScriptConsole ()
 
FileSystemGetFileSystem ()
 
AppDefGetDefinition ()
 
LeviathanApplicationGetOwningApplication ()
 
NetworkHandlerGetNetworkHandler ()
 
ThreadingManagerGetThreadingManager ()
 
SoundDeviceGetSoundDevice ()
 
ResourceRefreshHandlerGetResourceRefreshHandler ()
 
RemoteConsoleGetRemoteConsole ()
 
RandomGetRandom ()
 
GameModuleLoaderGetGameModuleLoader ()
 
ScriptExecutorGetScriptExecutor ()
 
DLLEXPORT WindowGetWindowFromSDLID (uint32_t sdlid)
 
bool GetNoGui ()
 
void SetNoGUI ()
 
- Public Member Functions inherited from Leviathan::ThreadSafeGeneric< MutexType >
DLLEXPORT ThreadSafeGeneric ()
 
DLLEXPORT ~ThreadSafeGeneric ()
 
FORCE_INLINE void VerifyLock (RecursiveLock &guard) const
 
FORCE_INLINE void VerifyLock (Lock &lockit) const
 

Static Public Member Functions

static DLLEXPORT EngineGetEngine ()
 
static DLLEXPORT EngineGet ()
 

Protected Member Functions

DLLEXPORT void Tick (float elapsed)
 
DLLEXPORT void RenderFrame (float elapsed)
 
DLLEXPORT void ProcessInvokes ()
 Handles InvokeQueue. More...
 
void PostLoad ()
 
DLLEXPORT void ExecuteCommandLine ()
 
void _NotifyThreadsRegisterOgre ()
 
bool _ReceiveConsoleInput (const std::string &command)
 Console input comes through this. More...
 
void _RunQueuedConsoleCommands ()
 Runs all commands in QueuedConsoleCommands. More...
 

Protected Attributes

AppDefDefine = nullptr
 
RenderingStatisticsRenderTimer = nullptr
 
GraphicsGraph = nullptr
 
WindowGraphicalEntity1 = nullptr
 
std::vector< Window * > AdditionalGraphicalEntities
 
SoundDeviceSound = nullptr
 
DataStoreMainstore = nullptr
 
EventHandlerMainEvents = nullptr
 
ScriptExecutorMainScript = nullptr
 
ScriptConsoleMainConsole = nullptr
 
FileSystemMainFileHandler = nullptr
 
RandomMainRandom = nullptr
 
OutOfMemoryHandlerOutOMemory = nullptr
 
NetworkHandler_NetworkHandler = nullptr
 
ThreadingManager_ThreadingManager = nullptr
 
RemoteConsole_RemoteConsole = nullptr
 
ResourceRefreshHandler_ResourceRefreshHandler = nullptr
 
std::unique_ptr< ConsoleInput_ConsoleInput
 
std::unique_ptr< GameModuleLoader_GameModuleLoader
 
std::vector< std::unique_ptr< Editor::Editor > > OpenedEditors
 
IDFactoryIDDefaultInstance = nullptr
 
LeviathanApplicationOwner = nullptr
 
std::vector< std::shared_ptr< GameWorld > > GameWorlds
 List of current worlds. More...
 
std::mutex GameWorldsLock
 Mutex that is locked when changing the worlds. More...
 
std::mutex NetworkHandlerLock
 Mutex that is locked while NetworkHandler is used. More...
 
TimePoint LastTickTime
 Time when last ticked, used to track elapsed time. More...
 
int FrameLimit = -1
 Max FPS. More...
 
int FrameCount = 0
 
int TickCount = 0
 
int TickTime = 0
 
bool PreReleaseDone = false
 Set when PreRelease is called and Tick has happened. More...
 
bool PreReleaseWaiting = false
 
bool NoGui = false
 
bool NoLeap = false
 
bool NoSTDInput = false
 
bool IsClient = false
 Set to true when initialized as a client. More...
 
bool PreReleaseCompleted = false
 
RecursiveMutex InvokeLock
 
std::list< std::function< void()> > InvokeQueue
 
std::vector< std::unique_ptr< std::string > > PassedCommands
 
std::vector< std::unique_ptr< std::string > > QueuedConsoleCommands
 Stores console commands that came from the command line. More...
 
std::vector< std::unique_ptr< Editor::Importer > > QueuedImports
 Queued importers from command line parsing. More...
 
- Protected Attributes inherited from Leviathan::ThreadSafeGeneric< MutexType >
MutexType ObjectsLock
 

Static Protected Attributes

static DLLEXPORT Engineinstance = nullptr
 

Additional Inherited Members

- Public Types inherited from Leviathan::ThreadSafeGeneric< MutexType >
using LockT = typename LockTypeResolver< MutexType >::LType
 

Detailed Description

The main class of the Leviathan Game Engine.

Allocates a lot of classes and performs almost all startup operations.

Note
Only some operations are thread safe
Todo:
Reduce the amount of logging and mention thread safety on methods that ARE thread safe and add note to assume that everything else isn't

Definition at line 37 of file Engine.h.

Constructor & Destructor Documentation

◆ Engine()

DLLEXPORT Engine::Engine ( LeviathanApplication owner)

Definition at line 63 of file Engine.cpp.

63  : Owner(owner)
64 {
65  // This makes sure that uninitialized engine will have at least some last frame time //
67 
68  instance = this;
69 }
TimePoint LastTickTime
Time when last ticked, used to track elapsed time.
Definition: Engine.h:345
static DLLEXPORT TimePoint GetCurrentTimePoint()
static DLLEXPORT Engine * instance
Definition: Engine.h:388
LeviathanApplication * Owner
Definition: Engine.h:333

◆ ~Engine()

DLLEXPORT Engine::~Engine ( )

Definition at line 71 of file Engine.cpp.

72 {
73  if(instance == this)
74  instance = nullptr;
75 
76  _ConsoleInput.reset();
77 }
std::unique_ptr< ConsoleInput > _ConsoleInput
Definition: Engine.h:323
static DLLEXPORT Engine * instance
Definition: Engine.h:388

Member Function Documentation

◆ _NotifyThreadsRegisterOgre()

void Engine::_NotifyThreadsRegisterOgre ( )
protected

Function called by first instance of Window class after creating a window to not error when registering threads to work with Ogre

Todo:
Rename this

Definition at line 1266 of file Engine.cpp.

1267 {
1268  if(NoGui)
1269  return;
1270 
1271  // Register threads to use graphical objects //
1273 }
DLLEXPORT void MakeThreadsWorkWithOgre()
Makes the threads work with Ogre.
ThreadingManager * _ThreadingManager
Definition: Engine.h:319

◆ _ReceiveConsoleInput()

bool Engine::_ReceiveConsoleInput ( const std::string &  command)
protected

Console input comes through this.

Definition at line 1550 of file Engine.cpp.

1551 {
1552  Invoke([=]() {
1553  if(MainConsole) {
1554 
1555  MainConsole->RunConsoleCommand(command);
1556 
1557  } else {
1558 
1559  LOG_WARNING("No console handler attached, cannot run command");
1560  }
1561  });
1562 
1563  // Listening thread quits if PreReleaseWaiting is true
1564  return PreReleaseWaiting;
1565 }
DLLEXPORT void Invoke(const std::function< void()> &function)
Runs function on the main thread before the next tick.
Definition: Engine.cpp:1169
ScriptConsole * MainConsole
Definition: Engine.h:314
bool PreReleaseWaiting
Definition: Engine.h:358
#define LOG_WARNING(x)
Definition: Define.h:91
DLLEXPORT int RunConsoleCommand(std::string cmd)
Definition: Console.cpp:49

◆ _RunQueuedConsoleCommands()

void Engine::_RunQueuedConsoleCommands ( )
protected

Runs all commands in QueuedConsoleCommands.

Definition at line 1526 of file Engine.cpp.

1527 {
1528  if(QueuedConsoleCommands.empty())
1529  return;
1530 
1531  if(!MainConsole) {
1532 
1533  LOG_FATAL("Engine: MainConsole has not been created before running command line "
1534  "passed commands");
1535  return;
1536  }
1537 
1538  LOG_INFO("Engine: Running PostStartup command line. Commands: " +
1540 
1541  for(auto& command : QueuedConsoleCommands) {
1542 
1543  LOG_INFO("Engine: Running \"" + *command + "\"");
1544  MainConsole->RunConsoleCommand(*command);
1545  }
1546 
1547  QueuedConsoleCommands.clear();
1548 }
#define LOG_INFO(x)
Definition: Define.h:90
#define LOG_FATAL(x)
Definition: Define.h:94
ScriptConsole * MainConsole
Definition: Engine.h:314
DLLEXPORT int RunConsoleCommand(std::string cmd)
Definition: Console.cpp:49
static std::string ToString(const T &val)
Definition: Convert.h:72
std::vector< std::unique_ptr< std::string > > QueuedConsoleCommands
Stores console commands that came from the command line.
Definition: Engine.h:383

◆ AssertIfNotMainThread()

DLLEXPORT void Leviathan::Engine::AssertIfNotMainThread ( ) const
inline

Asserts if not called on the main thread.

Definition at line 111 of file Engine.h.

112  {
114  IsOnMainThread(), "Function not called on main thread (AssertIfNotMainThread)");
115  }
DLLEXPORT bool IsOnMainThread() const
Returns true if called on the main thread.
Definition: Engine.cpp:91
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100

◆ ClearTimers()

DLLEXPORT void Engine::ClearTimers ( )

Clears physical timers.

Definition at line 1256 of file Engine.cpp.

1257 {
1259 
1260  Lock lock(GameWorldsLock);
1261 
1262  for(auto iter = GameWorlds.begin(); iter != GameWorlds.end(); ++iter) {
1263  }
1264 }
TimePoint LastTickTime
Time when last ticked, used to track elapsed time.
Definition: Engine.h:345
static DLLEXPORT TimePoint GetCurrentTimePoint()
std::mutex GameWorldsLock
Mutex that is locked when changing the worlds.
Definition: Engine.h:339
std::vector< std::shared_ptr< GameWorld > > GameWorlds
List of current worlds.
Definition: Engine.h:336
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18

◆ CloseWindow()

DLLEXPORT bool Engine::CloseWindow ( Window window)

Closes a window.

Note
Due to Ogre related issues the window isn't actually closed before shutting down completely
Returns
True if closed. False if window was invalid

This is a wrapper for ReportClosedWindow

Definition at line 1094 of file Engine.cpp.

1095 {
1096  if(!window)
1097  return false;
1098 
1099  if(IsValidWindow(window)) {
1100 
1101  ReportClosedWindow(window);
1102  return true;
1103  } else {
1104  return false;
1105  }
1106 }
DLLEXPORT void ReportClosedWindow(Window *windowentity)
Removes an closed window from the engine.
Definition: Engine.cpp:1108
DLLEXPORT bool IsValidWindow(Window *window) const
Definition: Engine.cpp:1054

◆ CreateWorld()

DLLEXPORT std::shared_ptr< GameWorld > Engine::CreateWorld ( Window owningwindow,
int  worldtype,
const std::shared_ptr< PhysicsMaterialManager > &  physicsMaterials,
const WorldNetworkSettings networking,
int  overrideid = -1 
)

Creates a GameWorld for placing entities into.

Note
To actually move the world camera you need to use Leviathan::ObjectLoader::LoadCamera to create a camera entity
Parameters
worldtypeIs the type of the world to be created. This is passed to the game's registered world factory. Types over 1024 are reserved for inbuilt types and are needed for example things like the editor
physicsMaterialsThe physical materials used for the world. This must be non-null if physics is wanted for this world. This is here in order to allow inbuilt worlds to have custom materials
overrideidSet to >= 0 if this is a clientside world and must have the specific id

Definition at line 1202 of file Engine.cpp.

1205 {
1206  std::shared_ptr<GameWorld> world;
1207  if(worldtype >= 1024) {
1208  // Standard world types
1210  static_cast<INBUILT_WORLD_TYPE>(worldtype), physicsMaterials, overrideid);
1211  } else {
1212  world =
1213  GameWorldFactory::Get()->CreateNewWorld(worldtype, physicsMaterials, overrideid);
1214  }
1215 
1216  if(!world) {
1217 
1218  LOG_ERROR("Engine: CreateWorld: factory failed to create a world of type: " +
1219  std::to_string(worldtype));
1220  return nullptr;
1221  }
1222 
1223  world->Init(networking, NoGui ? nullptr : Graph);
1224 
1225  if(owningwindow)
1226  owningwindow->LinkObjects(world);
1227 
1228  Lock lock(GameWorldsLock);
1229 
1230  GameWorlds.push_back(world);
1231  return GameWorlds.back();
1232 }
#define LOG_ERROR(x)
Definition: Define.h:92
static DLLEXPORT GameWorldFactory * Get()
DLLEXPORT bool Init(const WorldNetworkSettings &network, Graphics *graphics)
Creates resources for the world to work.
Definition: GameWorld.cpp:95
DLLEXPORT void LinkObjects(std::shared_ptr< GameWorld > world)
This function also updates the camera aspect ratio.
Definition: Window.cpp:266
std::mutex GameWorldsLock
Mutex that is locked when changing the worlds.
Definition: Engine.h:339
virtual DLLEXPORT std::shared_ptr< GameWorld > CreateNewWorld(int worldtype, const std::shared_ptr< PhysicsMaterialManager > &physicsMaterials, int overrideid=-1)
Creates a new world that can be used.
Graphics * Graph
Definition: Engine.h:305
std::vector< std::shared_ptr< GameWorld > > GameWorlds
List of current worlds.
Definition: Engine.h:336
static std::shared_ptr< GameWorld > CreateNewWorld(INBUILT_WORLD_TYPE worldtype, const std::shared_ptr< PhysicsMaterialManager > &physicsMaterials, int overrideid=-1)
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18

◆ DestroyWorld()

DLLEXPORT void Engine::DestroyWorld ( const std::shared_ptr< GameWorld > &  world)

Releases a GameWorld.

Parameters
worldThe world to destroy. This is taken as a const reference to allow shared_ptrs of derived types to be passed here. Make sure to call world.reset() afterwards to release the reference.
Postcondition
The World will have been released and removed from Engine's internal list and when all other holders of the pointer release it will be deleted

Definition at line 1234 of file Engine.cpp.

1235 {
1236  if(!world)
1237  return;
1238 
1239  // Release the world first //
1240  world->Release();
1241 
1242  // Then delete it //
1243  Lock lock(GameWorldsLock);
1244 
1245  auto end = GameWorlds.end();
1246  for(auto iter = GameWorlds.begin(); iter != end; ++iter) {
1247 
1248  if((*iter).get() == world.get()) {
1249 
1250  GameWorlds.erase(iter);
1251  return;
1252  }
1253  }
1254 }
DLLEXPORT void Release()
Release resources.
Definition: GameWorld.cpp:122
std::mutex GameWorldsLock
Mutex that is locked when changing the worlds.
Definition: Engine.h:339
std::vector< std::shared_ptr< GameWorld > > GameWorlds
List of current worlds.
Definition: Engine.h:336
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18

◆ ExecuteCommandLine()

DLLEXPORT void Engine::ExecuteCommandLine ( )
protected

Runs the normal commands passed by the PassCommandLine function // Ran automatically after Init

Definition at line 1438 of file Engine.cpp.

1439 {
1440  StringIterator itr;
1441 
1442  // TODO: this does nothing
1443  // Iterate over the commands and process them //
1444  for(size_t i = 0; i < PassedCommands.size(); i++) {
1445 
1446  itr.ReInit(PassedCommands[i].get());
1447  // Skip the preceding '-'s //
1448  itr.SkipCharacters('-');
1449 
1450  // Get the command //
1451  auto firstpart = itr.GetUntilNextCharacterOrAll<string>(':');
1452 
1453  // Execute the wanted command //
1454  if(StringOperations::CompareInsensitive<string>(*firstpart, "RemoteConsole")) {
1455 
1456  // Get the next command //
1457  auto commandpart = itr.GetUntilNextCharacterOrAll<string>(L':');
1458 
1459  if(*commandpart == "CloseIfNone") {
1460  // Set the command //
1462  Logger::Get()->Info("Engine will close when no active/waiting remote console "
1463  "sessions");
1464 
1465  } else if(*commandpart == "OpenTo") {
1466  // Get the to part //
1467  auto topart = itr.GetStringInQuotes<string>(QUOTETYPE_BOTH);
1468 
1469  int token = 0;
1470 
1471  auto numberpart = itr.GetNextNumber<string>(DECIMALSEPARATORTYPE_NONE);
1472 
1473  if(numberpart->size() == 0) {
1474 
1475  Logger::Get()->Warning("Engine: ExecuteCommandLine: RemoteConsole: "
1476  "no token number provided");
1477  continue;
1478  }
1479  // Convert to a real number. Maybe we could see if the token is
1480  // complex enough here, but that isn't necessary
1481  token = Convert::StringTo<int>(*numberpart);
1482 
1483  if(token == 0) {
1484  // Invalid number? //
1485  Logger::Get()->Warning("Engine: ExecuteCommandLine: RemoteConsole: "
1486  "couldn't parse token number, " +
1487  *numberpart);
1488  continue;
1489  }
1490 
1491  // Create a connection (or potentially use an existing one) //
1492  shared_ptr<Connection> tmpconnection =
1494 
1495  // Tell remote console to open a command to it //
1496  if(tmpconnection) {
1497 
1498  _RemoteConsole->OfferConnectionTo(tmpconnection, "AutoOpen", token);
1499 
1500  } else {
1501  // Something funky happened... //
1502  Logger::Get()->Warning("Engine: ExecuteCommandLine: RemoteConsole: "
1503  "couldn't open connection to " +
1504  *topart + ", couldn't resolve address");
1505  }
1506 
1507  } else {
1508  // Unknown command //
1509  Logger::Get()->Warning("Engine: ExecuteCommandLine: unknown RemoteConsole "
1510  "command: " +
1511  *commandpart +
1512  ", whole argument: " + *PassedCommands[i]);
1513  }
1514  }
1515  }
1516 
1517 
1518  PassedCommands.clear();
1519 
1520  // Now we can set some things that require command line arguments //
1521  // _RemoteConsole might be NULL //
1522  if(_RemoteConsole)
1524 }
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
NetworkHandler * _NetworkHandler
Definition: Engine.h:318
DLLEXPORT void ReInit(std::unique_ptr< StringDataIterator > &&iterator)
Changes the current iterator to the new iterator and goes to the beginning.
std::unique_ptr< RStrType > GetStringInQuotes(QUOTETYPE quotes, int specialflags=0)
Gets the next string in quotes.
std::vector< std::unique_ptr< std::string > > PassedCommands
Definition: Engine.h:380
std::unique_ptr< RStrType > GetUntilNextCharacterOrAll(int charactertolookfor, int specialflags=0)
Gets characters until a character or all remaining characters.
DLLEXPORT void SetCloseIfNoRemoteConsole(bool state)
Sets the remote console to close the game if there are no connections.
DLLEXPORT void Warning(const std::string &data) override
Definition: Logger.cpp:190
Iterator class for getting parts of a string.
DLLEXPORT std::shared_ptr< Connection > OpenConnectionTo(const std::string &targetaddress)
Opens a new connection to the provided address.
void SkipCharacters(int chartoskip, int additionalflag=0, int specialflags=0)
Skips until chartoskip doesn't match the current character.
RemoteConsole * _RemoteConsole
Definition: Engine.h:320
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
std::unique_ptr< RStrType > GetNextNumber(DECIMALSEPARATORTYPE decimal, int specialflags=0)
Gets the next number.
DLLEXPORT void OfferConnectionTo(std::shared_ptr< Connection > connectiontouse, const std::string &connectionname, int token)
Does everything needed to allow the client on the connection to connect to us.
void SetAllowClose()
Called by Engine after command line has been processed.

◆ FocusOrOpenEditor()

DLLEXPORT void Engine::FocusOrOpenEditor ( )

Focuses the first editor or opens an editor if none are open.

Todo:
Closed editors need to report that they are closed in order to open one again

Definition at line 1152 of file Engine.cpp.

1153 {
1154  if(OpenedEditors.empty()) {
1155 
1156  OpenEditorWindow();
1157  return;
1158  }
1159 
1160  OpenedEditors.front()->BringToFront();
1161 }
DLLEXPORT void OpenEditorWindow(Window *useexistingwindow=nullptr)
Opens an Editor::Editor window.
Definition: Engine.cpp:1133
std::vector< std::unique_ptr< Editor::Editor > > OpenedEditors
Definition: Engine.h:325

◆ Get()

DLLEXPORT Engine * Engine::Get ( )
static

Definition at line 86 of file Engine.cpp.

87 {
88  return instance;
89 }
static DLLEXPORT Engine * instance
Definition: Engine.h:388

◆ GetDefinition()

AppDef* Leviathan::Engine::GetDefinition ( )
inline

Definition at line 211 of file Engine.h.

212  {
213  return Define;
214  }
AppDef * Define
Definition: Engine.h:302

◆ GetEngine()

Engine * Engine::GetEngine ( )
static

Definition at line 81 of file Engine.cpp.

82 {
83  return instance;
84 }
static DLLEXPORT Engine * instance
Definition: Engine.h:388

◆ GetEventHandler()

EventHandler* Leviathan::Engine::GetEventHandler ( )
inline

Definition at line 195 of file Engine.h.

196  {
197  return MainEvents;
198  }
EventHandler * MainEvents
Definition: Engine.h:312

◆ GetFileSystem()

FileSystem* Leviathan::Engine::GetFileSystem ( )
inline

Definition at line 207 of file Engine.h.

208  {
209  return MainFileHandler;
210  }
FileSystem * MainFileHandler
Definition: Engine.h:315

◆ GetGameModuleLoader()

GameModuleLoader* Leviathan::Engine::GetGameModuleLoader ( )
inline

Definition at line 243 of file Engine.h.

244  {
245  return _GameModuleLoader.get();
246  }
std::unique_ptr< GameModuleLoader > _GameModuleLoader
Definition: Engine.h:324

◆ GetGraphics()

Graphics* Leviathan::Engine::GetGraphics ( )
inline

Definition at line 185 of file Engine.h.

186  {
187  return Graph;
188  }
Graphics * Graph
Definition: Engine.h:305

◆ GetNetworkHandler()

NetworkHandler* Leviathan::Engine::GetNetworkHandler ( )
inline

Definition at line 219 of file Engine.h.

220  {
221  return _NetworkHandler;
222  }
NetworkHandler * _NetworkHandler
Definition: Engine.h:318

◆ GetNoGui()

bool Leviathan::Engine::GetNoGui ( )
inline

Definition at line 261 of file Engine.h.

262  {
263  return NoGui;
264  }

◆ GetOwningApplication()

LeviathanApplication* Leviathan::Engine::GetOwningApplication ( )
inline

Definition at line 215 of file Engine.h.

216  {
217  return Owner;
218  }
LeviathanApplication * Owner
Definition: Engine.h:333

◆ GetRandom()

Random* Leviathan::Engine::GetRandom ( )
inline

Definition at line 239 of file Engine.h.

240  {
241  return MainRandom;
242  }
Random * MainRandom
Definition: Engine.h:316

◆ GetRemoteConsole()

RemoteConsole* Leviathan::Engine::GetRemoteConsole ( )
inline

Definition at line 235 of file Engine.h.

236  {
237  return _RemoteConsole;
238  }
RemoteConsole * _RemoteConsole
Definition: Engine.h:320

◆ GetRenderingStatistics()

RenderingStatistics* Leviathan::Engine::GetRenderingStatistics ( )
inline

Definition at line 199 of file Engine.h.

200  {
201  return RenderTimer;
202  }
RenderingStatistics * RenderTimer
Definition: Engine.h:304

◆ GetResourceRefreshHandler()

ResourceRefreshHandler* Leviathan::Engine::GetResourceRefreshHandler ( )
inline

Definition at line 231 of file Engine.h.

232  {
234  }
ResourceRefreshHandler * _ResourceRefreshHandler
Definition: Engine.h:321

◆ GetScriptConsole()

ScriptConsole* Leviathan::Engine::GetScriptConsole ( )
inline

Definition at line 203 of file Engine.h.

204  {
205  return MainConsole;
206  }
ScriptConsole * MainConsole
Definition: Engine.h:314

◆ GetScriptExecutor()

ScriptExecutor* Leviathan::Engine::GetScriptExecutor ( )
inline

Definition at line 247 of file Engine.h.

248  {
249  return MainScript;
250  }
ScriptExecutor * MainScript
Definition: Engine.h:313

◆ GetSoundDevice()

SoundDevice* Leviathan::Engine::GetSoundDevice ( )
inline

Definition at line 227 of file Engine.h.

228  {
229  return Sound;
230  }
SoundDevice * Sound
Definition: Engine.h:310

◆ GetThreadingManager()

ThreadingManager* Leviathan::Engine::GetThreadingManager ( )
inline

Definition at line 223 of file Engine.h.

224  {
225  return _ThreadingManager;
226  }
ThreadingManager * _ThreadingManager
Definition: Engine.h:319

◆ GetTimeSinceLastTick()

DLLEXPORT SecondDuration Engine::GetTimeSinceLastTick ( ) const

Calculates how long has elapsed since the last tick.

Returns
The time in milliseconds

Definition at line 1275 of file Engine.cpp.

1276 {
1278 }
TimePoint LastTickTime
Time when last ticked, used to track elapsed time.
Definition: Engine.h:345
static DLLEXPORT TimePoint GetCurrentTimePoint()

◆ GetWindowEntity()

DLLEXPORT Window* Leviathan::Engine::GetWindowEntity ( )
inline

Returns the main window.

Definition at line 162 of file Engine.h.

163  {
164  return GraphicalEntity1;
165  }
Window * GraphicalEntity1
Definition: Engine.h:307

◆ GetWindowFromSDLID()

DLLEXPORT Window * Engine::GetWindowFromSDLID ( uint32_t  sdlid)

Definition at line 806 of file Engine.cpp.

807 {
808  if(GraphicalEntity1 && GraphicalEntity1->GetSDLID() == sdlid) {
809  return GraphicalEntity1;
810  }
811 
812  for(auto iter = AdditionalGraphicalEntities.begin();
813  iter != AdditionalGraphicalEntities.end(); ++iter) {
814  if((*iter)->GetSDLID() == sdlid) {
815 
816  return *iter;
817  }
818  }
819 
820  return nullptr;
821 }
Window * GraphicalEntity1
Definition: Engine.h:307
DLLEXPORT uint32_t GetSDLID() const
Definition: Window.cpp:906
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308

◆ GetWindowOpenCount()

DLLEXPORT int Engine::GetWindowOpenCount ( )

Definition at line 1033 of file Engine.cpp.

1034 {
1035  int openwindows = 0;
1036 
1037  // If we are in text only mode always return 1 //
1038  if(NoGui)
1039  return 1;
1040 
1041  // TODO: should there be an IsOpen method?
1042  if(GraphicalEntity1)
1043  openwindows++;
1044 
1045  for(size_t i = 0; i < AdditionalGraphicalEntities.size(); i++) {
1046 
1048  openwindows++;
1049  }
1050 
1051  return openwindows;
1052 }
Window * GraphicalEntity1
Definition: Engine.h:307
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308

◆ HasPreReleaseBeenDone()

DLLEXPORT bool Leviathan::Engine::HasPreReleaseBeenDone ( ) const
inline

Checks if PreRelease is done and Release can be called.

Precondition
PreRelease is called

Definition at line 60 of file Engine.h.

61  {
62  return PreReleaseDone;
63  }
bool PreReleaseDone
Set when PreRelease is called and Tick has happened.
Definition: Engine.h:354

◆ Init()

DLLEXPORT bool Engine::Init ( AppDef definition,
NETWORKED_TYPE  ntype,
NetworkInterface packethandler 
)

Definition at line 96 of file Engine.cpp.

98 {
99  GUARD_LOCK();
100 
102 
103  // Get the time, for monitoring how long loading takes //
104  auto InitStartTime = Time::GetTimeMs64();
105 
106  // Store parameters //
107  Define = definition;
108 
109  IsClient = ntype == NETWORKED_TYPE::Client;
110 
111  // Create all the things //
112 
114 
116 
117  // Create threading facilities //
119  if(!_ThreadingManager->Init()) {
120 
121  Logger::Get()->Error("Engine: Init: cannot start threading");
122  return false;
123  }
124 
125  // Create the randomizer //
126  MainRandom = new Random((int)InitStartTime);
128 
129  // Console might be the first thing we want //
130  if(!NoSTDInput) {
131 
132  _ConsoleInput = std::make_unique<ConsoleInput>();
133 
134  if(!_ConsoleInput->Init(
135  std::bind(&Engine::_ReceiveConsoleInput, this, std::placeholders::_1),
136  NoGui ? true : false)) {
137  Logger::Get()->Error("Engine: Init: failed to read stdin, perhaps pass --nocin");
138  return false;
139  }
140  }
141 
142  if(NoGui) {
143 
144  // Tell window title //
145  Logger::Get()->Write(
146  "// ----------- " + Define->GetWindowDetails().Title + " ----------- //");
147  }
148 
149 
150  // We could immediately receive a remote console request so this should be
151  // ready when networking is started
153 
154  // We want to send a request to the master server as soon as possible //
155  {
156  Lock lock(NetworkHandlerLock);
157 
158  _NetworkHandler = new NetworkHandler(ntype, packethandler);
159 
161  }
162 
163  // These should be fine to be threaded //
164 
165  // File change listener //
167  if(!_ResourceRefreshHandler->Init()) {
168 
169  Logger::Get()->Error("Engine: Init: cannot start resource monitor");
170  return false;
171  }
172 
173  // Data storage //
174  Mainstore = new DataStore(true);
175  if(!Mainstore) {
176 
177  Logger::Get()->Error("Engine: Init: failed to create main data store");
178  return false;
179  }
180 
181  // Search data folder for files //
182  MainFileHandler = new FileSystem();
183  if(!MainFileHandler) {
184 
185  Logger::Get()->Error("Engine: Init: failed to create FileSystem");
186  return false;
187  }
188 
189  if(!MainFileHandler->Init(Logger::Get())) {
190 
191  Logger::Get()->Error("Engine: Init: failed to init FileSystem");
192  return false;
193  }
194 
195  // File parsing //
197 
198  // Main program wide event dispatcher //
199  MainEvents = new EventHandler();
200  if(!MainEvents) {
201 
202  Logger::Get()->Error("Engine: Init: failed to create MainEvents");
203  return false;
204  }
205 
206  if(!MainEvents->Init()) {
207 
208  Logger::Get()->Error("Engine: Init: failed to init MainEvents");
209  return false;
210  }
211 
212  // Check is threading properly started //
213  if(!_ThreadingManager->CheckInit()) {
214 
215  Logger::Get()->Error("Engine: Init: threading start failed");
216  return false;
217  }
218 
219  // create script interface before renderer //
220  std::promise<bool> ScriptInterfaceResult;
221 
222  // Ref is OK to use since this task finishes before this function //
223  _ThreadingManager->QueueTask(std::make_shared<QueuedTask>(std::bind<void>(
224  [](std::promise<bool>& returnvalue, Engine* engine) -> void {
225  try {
226  engine->MainScript = new ScriptExecutor();
227  } catch(const Exception&) {
228 
229  Logger::Get()->Error("Engine: Init: failed to create ScriptInterface");
230  returnvalue.set_value(false);
231  return;
232  }
233 
234  // create console after script engine //
235  engine->MainConsole = new ScriptConsole();
236  if(!engine->MainConsole) {
237 
238  Logger::Get()->Error("Engine: Init: failed to create ScriptConsole");
239  returnvalue.set_value(false);
240  return;
241  }
242 
243  if(!engine->MainConsole->Init(engine->MainScript)) {
244 
245  Logger::Get()->Error("Engine: Init: failed to initialize Console, "
246  "continuing anyway");
247  }
248 
249  engine->_GameModuleLoader = std::make_unique<GameModuleLoader>();
250  engine->_GameModuleLoader->Init();
251 
252  if(!engine->NoGui) {
253  // measuring //
254  engine->RenderTimer = new RenderingStatistics();
255  if(!engine->RenderTimer) {
256  Logger::Get()->Error("Engine: Init: failed to create RenderingStatistics");
257 
258  returnvalue.set_value(false);
259  return;
260  }
261  }
262 
263  returnvalue.set_value(true);
264  },
265  std::ref(ScriptInterfaceResult), this)));
266 
267  // Check if we don't want a window //
268  if(NoGui) {
269 
270  Logger::Get()->Info("Engine: Init: starting in console mode "
271  "(won't allocate graphical objects) ");
272 
273  if(!_ConsoleInput->IsAttachedToConsole()) {
274 
275  Logger::Get()->Error(
276  "Engine: Init: in nogui mode and no input terminal connected, "
277  "quitting");
278  return false;
279  }
280 
282 
283  } else {
284 
285  ObjectFileProcessor::LoadValueFromNamedVars<int>(
286  Define->GetValues(), "MaxFPS", FrameLimit, 144, Logger::Get(), "Graphics: Init:");
287 
288  Graph = new Graphics();
289  }
290 
291  // We need to wait for all current tasks to finish //
293 
294  // Check return values //
295  if(!ScriptInterfaceResult.get_future().get()) {
296 
297  Logger::Get()->Error("Engine: Init: one or more queued tasks failed");
298  return false;
299  }
300 
301  // We can queue some more tasks //
302  // create leap controller //
303 #ifdef LEVIATHAN_USES_LEAP
304 
305  // Disable leap if in non-gui mode //
306  if(NoGui)
307  NoLeap = true;
308 
309  std::thread leapinitthread;
310  if(!NoLeap) {
311 
312  Logger::Get()->Info("Engine: will try to create Leap motion connection");
313 
314  // Seems that std::threads are joinable when constructed with default constructor
315  leapinitthread = std::thread(std::bind<void>(
316  [](Engine* engine) -> void {
317  engine->LeapData = new LeapManager(engine);
318  if(!engine->LeapData) {
319  Logger::Get()->Error("Engine: Init: failed to create LeapManager");
320  return;
321  }
322  // try here just in case //
323  try {
324  if(!engine->LeapData->Init()) {
325 
326  Logger::Get()->Info(
327  "Engine: Init: No Leap controller found, not using one");
328  }
329  } catch(...) {
330  // threw something //
331  Logger::Get()->Error(
332  "Engine: Init: Leap threw something, even without leap "
333  "this shouldn't happen; continuing anyway");
334  }
335  },
336  this));
337  }
338 #endif
339 
340 
341  // sound device //
342  if(!NoGui) {
343  Sound = new SoundDevice();
344 
345  if(!Sound) {
346  Logger::Get()->Error("Engine: Init: failed to create Sound");
347  return false;
348  }
349 
350  if(!Sound->Init()) {
351 
352  Logger::Get()->Error(
353  "Engine: Init: failed to init SoundDevice. Continuing anyway");
354  }
355  }
356 
357  if(!NoGui) {
358  if(!Graph) {
359 
360  Logger::Get()->Error("Engine: Init: failed to create instance of Graphics");
361  return false;
362  }
363 
364  // call init //
365  if(!Graph->Init(definition)) {
366  Logger::Get()->Error("Failed to init Engine, Init graphics failed! Aborting");
367  return false;
368  }
369 
370  // Create window //
371  GraphicalEntity1 = new Window(Graph, definition);
372  }
373 
374 #ifdef LEVIATHAN_USES_LEAP
375  // We can probably assume here that leap creation has stalled if the thread is running //
376  if(!NoLeap) {
377 
378  auto start = WantedClockType::now();
379 
380  while(leapinitthread.joinable()) {
381 
382  auto elapsed = WantedClockType::now() - start;
383 
384  if(elapsed > std::chrono::milliseconds(150)) {
385 
386  Logger::Get()->Warning("LeapController creation would have stalled the game!");
387  Logger::Get()->Write("TODO: allow increasing wait period");
388  leapinitthread.detach();
389  break;
390  }
391 
392  std::this_thread::sleep_for(std::chrono::milliseconds(5));
393  }
394  }
395 #endif
396 
397  const auto timeNow = Time::GetTimeMs64();
398 
399  LOG_INFO("Engine init took " + Convert::ToString(timeNow - InitStartTime) + " ms");
400 
401  PostLoad();
402 
403  const auto timeAfterPostLoad = Time::GetTimeMs64();
404 
405  if(timeAfterPostLoad - timeNow > 5)
406  LOG_INFO("PostLoad took " + Convert::ToString(timeAfterPostLoad - timeNow) + " ms");
407 
408 
409  return true;
410 }
ScriptExecutor * MainScript
Definition: Engine.h:313
virtual DLLEXPORT bool Init()
Sets up the work queue.
DLLEXPORT bool Init(AppDef *appdef)
Definition: Graphics.cpp:167
DLLEXPORT void Write(const std::string &data) override
Definition: Logger.cpp:113
#define LOG_INFO(x)
Definition: Define.h:90
RenderingStatistics * RenderTimer
Definition: Engine.h:304
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
DLLEXPORT void QueueTask(std::shared_ptr< QueuedTask > task)
Adds a task to the queue.
AppDef * Define
Definition: Engine.h:302
Random number generator based on Mersenne Twister.
Definition: Random.h:15
Manages loading the audio library and provides some helpers.
Definition: SoundDevice.h:15
DataStore * Mainstore
Definition: Engine.h:311
Allows object to register for events that can be fired from anywhere.
Definition: EventHandler.h:15
constexpr auto THREAD_MAGIC
Definition: Engine.cpp:58
DLLEXPORT MasterServerInformation & GetMasterServerInfo()
Definition: AppDefine.h:97
IDFactory * IDDefaultInstance
Definition: Engine.h:332
NetworkHandler * _NetworkHandler
Definition: Engine.h:318
ScriptConsole * MainConsole
Definition: Engine.h:314
Class for indexing and searching game data directory.
Definition: FileSystem.h:65
OutOfMemoryHandler * OutOMemory
Definition: Engine.h:317
Handles ScriptModule creation and AngelScript code execution.
DLLEXPORT void WaitForAllTasksToFinish()
Blocks until all queued tasks are finished.
bool _ReceiveConsoleInput(const std::string &command)
Console input comes through this.
Definition: Engine.cpp:1550
Window * GraphicalEntity1
Definition: Engine.h:307
DLLEXPORT bool Init(AppDef *definition, NETWORKED_TYPE ntype, NetworkInterface *packethandler)
Definition: Engine.cpp:96
std::unique_ptr< ConsoleInput > _ConsoleInput
Definition: Engine.h:323
DLLEXPORT WindowDataDetails & GetWindowDetails()
Definition: AppDefine.h:93
The main class of the Leviathan Game Engine.
Definition: Engine.h:37
Base class for all exceptions thrown by Leviathan.
Definition: Exceptions.h:10
static thread_local int MainThreadMagic
Used to detect when accessed from main thread.
Definition: Engine.cpp:57
static DLLEXPORT int64_t GetTimeMs64()
DLLEXPORT bool Init()
DLLEXPORT bool Init(ScriptExecutor *MainScript)
Definition: Console.cpp:27
DLLEXPORT void SetAsMain()
Definition: Random.cpp:144
DLLEXPORT NamedVars * GetValues()
Definition: AppDefine.cpp:40
DLLEXPORT void Warning(const std::string &data) override
Definition: Logger.cpp:190
Manages delayed execution of functions through use of QueuedTask and subclasses.
Allows various resource loaders to get notified when the file on disk changes.
ThreadingManager * _ThreadingManager
Definition: Engine.h:319
DLLEXPORT bool Init(LErrorReporter *errorreport)
Runs the indexing and sorting.
Definition: FileSystem.cpp:91
DLLEXPORT bool Init(bool simulatesound=false)
Definition: SoundDevice.cpp:71
RemoteConsole * _RemoteConsole
Definition: Engine.h:320
static DLLEXPORT void Initialize()
SoundDevice * Sound
Definition: Engine.h:310
static std::string ToString(const T &val)
Definition: Convert.h:72
virtual DLLEXPORT bool CheckInit()
Checks has Init worked.
std::mutex NetworkHandlerLock
Mutex that is locked while NetworkHandler is used.
Definition: Engine.h:342
ResourceRefreshHandler * _ResourceRefreshHandler
Definition: Engine.h:321
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
FileSystem * MainFileHandler
Definition: Engine.h:315
Random * MainRandom
Definition: Engine.h:316
Class used to handle remote server commands and receiving messages.
Definition: RemoteConsole.h:45
constexpr auto DEFAULT_HEADLESS_MAX_UPDATES_PER_SECOND
Max "FPS" in headless mode.
Definition: Define.h:22
int FrameLimit
Max FPS.
Definition: Engine.h:348
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
Graphics * Graph
Definition: Engine.h:305
Handles everything related to connections.
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
std::unique_ptr< GameModuleLoader > _GameModuleLoader
Definition: Engine.h:324
bool IsClient
Set to true when initialized as a client.
Definition: Engine.h:369
virtual DLLEXPORT bool Init(const MasterServerInformation &info)
EventHandler * MainEvents
Definition: Engine.h:312

◆ Invoke()

DLLEXPORT void Engine::Invoke ( const std::function< void()> &  function)

Runs function on the main thread before the next tick.

This is provided to be able to

Note
This maybe called after preshutdown has started before final tick. This means that some objects may no longer be valid so check the result of any Get functions called in the invoke
Todo:
Write a wrapper file that can be used for invoking without having to include this huge file

Definition at line 1169 of file Engine.cpp.

1170 {
1171  RecursiveLock lock(InvokeLock);
1172  InvokeQueue.push_back(function);
1173 }
std::lock_guard< std::recursive_mutex > RecursiveLock
Definition: ThreadSafe.h:19
std::list< std::function< void()> > InvokeQueue
Definition: Engine.h:376
RecursiveMutex InvokeLock
Definition: Engine.h:375

◆ IsInGraphicalMode()

bool Leviathan::Engine::IsInGraphicalMode ( ) const
inline

Definition at line 190 of file Engine.h.

191  {
192  return !NoGui;
193  }

◆ IsOnMainThread()

DLLEXPORT bool Engine::IsOnMainThread ( ) const

Returns true if called on the main thread.

Definition at line 91 of file Engine.cpp.

92 {
93  return MainThreadMagic == THREAD_MAGIC;
94 }
constexpr auto THREAD_MAGIC
Definition: Engine.cpp:58
static thread_local int MainThreadMagic
Used to detect when accessed from main thread.
Definition: Engine.cpp:57

◆ IsValidWindow()

DLLEXPORT bool Engine::IsValidWindow ( Window window) const
Returns
True if window is a valid open Window

Definition at line 1054 of file Engine.cpp.

1055 {
1056  if(window == GraphicalEntity1) {
1057  return true;
1058  }
1059 
1060  for(Window* openWindow : AdditionalGraphicalEntities) {
1061  if(openWindow == window) {
1062  return true;
1063  }
1064  }
1065 
1066  return false;
1067 }
Window * GraphicalEntity1
Definition: Engine.h:307
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308

◆ MarkQuit()

DLLEXPORT void Engine::MarkQuit ( )

Marks the owning application to quit.

Definition at line 1163 of file Engine.cpp.

1164 {
1165  if(Owner)
1166  Owner->MarkAsClosing();
1167 }
DLLEXPORT void MarkAsClosing()
Thread safely marks the game to close sometime.
LeviathanApplication * Owner
Definition: Engine.h:333

◆ MessagePump()

DLLEXPORT void Engine::MessagePump ( )

Processes queued messages from SDL and CEF.

Definition at line 620 of file Engine.cpp.

621 {
622  // CEF events (Also on windows as multi_threaded_message_loop makes rendering harder)
624 
625  SDL_Event event;
626  while(SDL_PollEvent(&event)) {
627 
628  switch(event.type) {
629  case SDL_QUIT:
630  LOG_INFO("SDL_QUIT received, marked as closing");
631  MarkQuit();
632  break;
633 
634  case SDL_KEYDOWN: {
635  Window* win = GetWindowFromSDLID(event.key.windowID);
636 
637  if(win) {
638 
639  // LOG_WRITE("SDL_KEYDOWN: " + Convert::ToString(event.key.keysym.sym));
640 
641  // Core engine functionality keys
642  switch(event.key.keysym.sym) {
643  case SDLK_F10: {
644  // Editor key pressed
645  LOG_INFO("Editor key pressed");
647  break;
648  }
649  default: win->InjectKeyDown(event);
650  }
651  }
652  break;
653  }
654  case SDL_KEYUP: {
655  Window* win = GetWindowFromSDLID(event.key.windowID);
656 
657  if(win) {
658 
659  // LOG_WRITE("SDL_KEYUP: " + Convert::ToString(event.key.keysym.sym));
660  win->InjectKeyUp(event);
661  }
662 
663  break;
664  }
665  case SDL_TEXTINPUT: {
666  Window* win = GetWindowFromSDLID(event.text.windowID);
667 
668  if(win) {
669 
670  const auto text = std::string(event.text.text);
671 
672  // LOG_WRITE("TextInput: " + text);
673 
674  std::vector<uint32_t> codepoints;
675 
677  std::begin(text), std::end(text), std::back_inserter(codepoints));
678 
679  // LOG_WRITE("Codepoints(" + Convert::ToString(codepoints.size()) + "): ");
680  // for(auto codepoint : codepoints)
681  // LOG_WRITE(" " + Convert::ToString(codepoint));
682  for(auto codepoint : codepoints) {
683 
684  win->InjectCodePoint(event);
685  }
686  }
687 
688  break;
689  }
690  // TODO: implement this
691  // case SDL_TEXTEDITING: (https://wiki.libsdl.org/Tutorials/TextInput)
692  case SDL_MOUSEBUTTONDOWN: {
693  Window* win = GetWindowFromSDLID(event.button.windowID);
694 
695  if(win)
696  win->InjectMouseButtonDown(event);
697 
698  break;
699  }
700 
701  case SDL_MOUSEBUTTONUP: {
702  Window* win = GetWindowFromSDLID(event.button.windowID);
703 
704  if(win)
705  win->InjectMouseButtonUp(event);
706 
707  break;
708  }
709 
710  case SDL_MOUSEMOTION: {
711  Window* win = GetWindowFromSDLID(event.motion.windowID);
712 
713  if(win)
714  win->InjectMouseMove(event);
715 
716  break;
717  }
718 
719  case SDL_MOUSEWHEEL: {
720  Window* win = GetWindowFromSDLID(event.motion.windowID);
721 
722  if(win)
723  win->InjectMouseWheel(event);
724 
725  break;
726  }
727 
728  case SDL_WINDOWEVENT: {
729  switch(event.window.event) {
730 
731  case SDL_WINDOWEVENT_RESIZED: {
732  Window* win = GetWindowFromSDLID(event.window.windowID);
733 
734  if(win) {
735 
736  int32_t width, height;
737  win->GetSize(width, height);
738 
739  LOG_INFO("SDL window resize: " + Convert::ToString(width) + "x" +
740  Convert::ToString(height));
741 
742  win->OnResize(width, height);
743  }
744 
745  break;
746  }
747  case SDL_WINDOWEVENT_CLOSE: {
748  LOG_INFO("SDL window close");
749 
750  Window* win = GetWindowFromSDLID(event.window.windowID);
751 
752  // Detect closed windows //
753  if(win == GraphicalEntity1) {
754  // Window closed //
756  }
757 
758  for(size_t i = 0; i < AdditionalGraphicalEntities.size(); i++) {
759  if(AdditionalGraphicalEntities[i] == win) {
760 
762  break;
763  }
764  }
765 
766  break;
767  }
768  case SDL_WINDOWEVENT_FOCUS_GAINED: {
769  Window* win = GetWindowFromSDLID(event.window.windowID);
770 
771  if(win)
772  win->OnFocusChange(true);
773 
774  break;
775  }
776  case SDL_WINDOWEVENT_FOCUS_LOST: {
777  Window* win = GetWindowFromSDLID(event.window.windowID);
778 
779  if(win)
780  win->OnFocusChange(false);
781 
782  break;
783  }
784  }
785  }
786  }
787  }
788 
789  // CEF needs to be let handle the keyboard events now to make sure that they can be
790  // dispatched to further on listeners
792 
793  // Reset input states //
794  if(GraphicalEntity1) {
795 
796  // TODO: fix initial mouse position being incorrect
798  }
799 
800  for(auto iter = AdditionalGraphicalEntities.begin();
801  iter != AdditionalGraphicalEntities.end(); ++iter) {
802  (*iter)->InputEnd();
803  }
804 }
DLLEXPORT void MarkQuit()
Marks the owning application to quit.
Definition: Engine.cpp:1163
DLLEXPORT void GetSize(int32_t &width, int32_t &height) const
Definition: Window.cpp:896
u32bit_iterator utf8to32(octet_iterator start, octet_iterator end, u32bit_iterator result)
Definition: checked.h:258
#define LOG_INFO(x)
Definition: Define.h:90
DLLEXPORT void OnFocusChange(bool focused)
Definition: Window.cpp:328
DLLEXPORT void InjectMouseButtonUp(const SDL_Event &event)
Definition: Window.cpp:1171
DLLEXPORT void OnResize(int width, int height)
Definition: Window.cpp:312
DLLEXPORT void InjectKeyDown(const SDL_Event &event)
Definition: Window.cpp:1204
Window * GraphicalEntity1
Definition: Engine.h:307
DLLEXPORT void InjectMouseMove(const SDL_Event &event)
Definition: Window.cpp:1099
DLLEXPORT void ReportClosedWindow(Window *windowentity)
Removes an closed window from the engine.
Definition: Engine.cpp:1108
DLLEXPORT void FocusOrOpenEditor()
Focuses the first editor or opens an editor if none are open.
Definition: Engine.cpp:1152
DLLEXPORT void InputEnd()
Translates a client space coordinate to screen coordinate.
Definition: Window.cpp:1042
DLLEXPORT void InjectKeyUp(const SDL_Event &event)
Definition: Window.cpp:1236
DLLEXPORT Window * GetWindowFromSDLID(uint32_t sdlid)
Definition: Engine.cpp:806
static std::string ToString(const T &val)
Definition: Convert.h:72
DLLEXPORT void InjectMouseButtonDown(const SDL_Event &event)
Definition: Window.cpp:1154
DLLEXPORT void InjectCodePoint(const SDL_Event &event)
Injects text.
Definition: Window.cpp:1188
DLLEXPORT void InjectMouseWheel(const SDL_Event &event)
Definition: Window.cpp:1121
static DLLEXPORT void DoCEFMessageLoopWork()
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308

◆ OpenEditorWindow()

DLLEXPORT void Engine::OpenEditorWindow ( Window useexistingwindow = nullptr)

Opens an Editor::Editor window.

Todo:
Exit fullscreen mode if main window is in fullscreen mode

Definition at line 1133 of file Engine.cpp.

1134 {
1136 
1137  if(useexistingwindow && !IsValidWindow(useexistingwindow)) {
1138 
1139  LOG_WARNING("Engine: OpenEditorWindow: invalid window given, defaulting to opening a "
1140  "new window");
1141  useexistingwindow = nullptr;
1142  }
1143 
1144  if(!useexistingwindow) {
1145  useexistingwindow = OpenNewWindow();
1146  }
1147 
1148 
1149  OpenedEditors.emplace_back(std::make_unique<Editor::Editor>(useexistingwindow, this));
1150 }
#define LOG_WARNING(x)
Definition: Define.h:91
DLLEXPORT bool IsValidWindow(Window *window) const
Definition: Engine.cpp:1054
std::vector< std::unique_ptr< Editor::Editor > > OpenedEditors
Definition: Engine.h:325
DLLEXPORT Window * OpenNewWindow()
Opens a new window.
Definition: Engine.cpp:1069
DLLEXPORT void AssertIfNotMainThread() const
Asserts if not called on the main thread.
Definition: Engine.h:111

◆ OpenNewWindow()

DLLEXPORT Window * Engine::OpenNewWindow ( )

Opens a new window.

Note
The window may become broken if the main window is closed
Todo:
Allow changing the parameters

Definition at line 1069 of file Engine.cpp.

1070 {
1072 
1073  AppDef winparams;
1074 
1076  "Leviathan Window " + std::to_string(++WindowNameCounter), 1280, 720, "no",
1077  // Multiple vsyncs cause issues (or they can cause issues, sometimes it is fine)
1078  /* Define->GetWindowDetails().VSync */ false,
1079  // Opens on same display as the other window
1080  // TODO: open on next display
1082 #ifdef _WIN32
1083  Define->GetWindowDetails().Icon,
1084 #endif
1085  nullptr));
1086 
1087  auto newwindow = std::make_unique<Window>(Graph, &winparams);
1088 
1089  AdditionalGraphicalEntities.push_back(newwindow.get());
1090 
1091  return newwindow.release();
1092 }
AppDef * Define
Definition: Engine.h:302
static std::atomic< int > WindowNameCounter
Used for automatic unique window names.
Definition: Engine.cpp:61
DLLEXPORT WindowDataDetails & GetWindowDetails()
Definition: AppDefine.h:93
DLLEXPORT AppDef & SetWindowDetails(const WindowDataDetails &det)
Definition: AppDefine.h:75
Graphics * Graph
Definition: Engine.h:305
DLLEXPORT void AssertIfNotMainThread() const
Asserts if not called on the main thread.
Definition: Engine.h:111
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308

◆ PassCommandLine()

DLLEXPORT bool Engine::PassCommandLine ( int  argcount,
char *  args[] 
)

Passes the commands and preprocesses them

Also interprets commands like –nogui

Returns
False if invalid command line and the game should quit instantly

Definition at line 1294 of file Engine.cpp.

1295 {
1296  namespace po = boost::program_options;
1297 
1298  std::vector<std::vector<std::string>> import;
1299  std::vector<std::string> cmds;
1300  // TODO: these could probably directly be read into the variables in this class
1301  bool nogui = false;
1302  bool noleap = false;
1303  bool nocin = false;
1304 
1305  bool crash = false;
1306 
1307  po::options_description desc("Engine Options");
1308  // clang-format off
1309  desc.add_options()
1310  ("import", po::value<std::vector<std::string>>()->multitoken(),
1311  "Import assets from source to destination")
1312  ("cmd", po::value<std::vector<std::string>>(&cmds)->multitoken(),
1313  "Run console commands after startup")
1314  ("nogui", po::bool_switch(&nogui), "Disable graphics")
1315  ("nocin", po::bool_switch(&nocin), "Disable stdin reading")
1316  ("noleap", po::bool_switch(&noleap), "Disable Leap Motion")
1317  ("noleap", po::bool_switch(&crash), "Crash for testing purposes")
1318  // We see CEF arguments here, we need to allow them
1319  ("no-sandbox", "CEF option")
1320  ("single-process", "CEF option")
1321  ("disable-gpu", "CEF option")
1322  ;
1323  // clang-format on
1324 
1325  // TODO: allow the game to add extra options here
1326 
1327  po::positional_options_description positional;
1328  positional.add("cmd", -1);
1329 
1330  // This was before added to PassedCommands.push_back(std::move(splitval));
1331  // but it would be better to make those actual flags
1332 
1333  po::variables_map vm;
1334 
1335  try {
1336  // The parsing is done in two steps here to add custom handling for the import option
1337  po::parsed_options parsed_options =
1338  po::command_line_parser(argcount, args).options(desc).positional(positional).run();
1339 
1340 
1341  // Read import option lists
1342  for(const po::option& option : parsed_options.options) {
1343  if(option.string_key == "import")
1344  import.push_back(option.value);
1345  }
1346 
1347  // Finish parsing
1348  po::store(parsed_options, vm);
1349  po::notify(vm);
1350 
1351  } catch(const po::error& e) {
1352  LOG_INFO("Engine: Command line: ");
1353  for(int i = 0; i < argcount; ++i) {
1354 
1355  LOG_WRITE("\t> " + (args[i] ? std::string(args[i]) : std::string()));
1356  }
1357 
1358  LOG_ERROR("Engine: parsing command line failed: " + std::string(e.what()));
1359 
1360  std::stringstream sstream;
1361  desc.print(sstream);
1362 
1363  LOG_WRITE(sstream.str());
1364 
1365  return false;
1366  }
1367 
1368  if(nogui) {
1369  NoGui = true;
1370  LOG_INFO("Engine starting in non-GUI mode");
1371  }
1372 
1373  if(nocin) {
1374  NoSTDInput = true;
1375  LOG_INFO("Engine not listening for terminal commands");
1376  }
1377 
1378  if(noleap) {
1379  NoLeap = true;
1380 
1381 #ifdef LEVIATHAN_USES_LEAP
1382  LOG_INFO("Engine starting with LeapMotion disabled");
1383 #endif
1384  }
1385 
1386  if(crash) {
1387  LOG_INFO("Engine testing crash handling");
1388  // TODO: write a file that disables crash handling
1389  // Make the log say something useful //
1390  Logger::Get()->Save();
1391 
1392  // Test crashing //
1393  TestCrash(12);
1394  }
1395 
1396  // // Coalesce commands
1397  // if(vm.count("console-commands")) {
1398  // }
1399 
1400  for(const std::string& command : cmds) {
1401  if(StringOperations::IsCharacterQuote(command.at(0))) {
1402 
1403  StringIterator itr(command);
1404 
1405  auto withoutquotes = itr.GetStringInQuotes<std::string>(QUOTETYPE_BOTH);
1406 
1407  if(withoutquotes) {
1408 
1409  QueuedConsoleCommands.push_back(std::move(withoutquotes));
1410 
1411  } else {
1412 
1413  LOG_WARNING("Engine: command in quotes is empty");
1414  }
1415 
1416  } else {
1417 
1418  QueuedConsoleCommands.push_back(std::make_unique<std::string>(command));
1419  }
1420  }
1421 
1422  for(const auto& group : import) {
1423 
1424  if(group.size() != 2) {
1425 
1426  LOG_ERROR("Import option needs two parameters, source and destination, parameter "
1427  "count: " +
1428  std::to_string(group.size()));
1429  return false;
1430  }
1431 
1432  QueuedImports.push_back(std::make_unique<Editor::Importer>(group[0], group[1]));
1433  }
1434 
1435  return true;
1436 }
#define LOG_INFO(x)
Definition: Define.h:90
#define LOG_ERROR(x)
Definition: Define.h:92
std::vector< std::unique_ptr< Editor::Importer > > QueuedImports
Queued importers from command line parsing.
Definition: Engine.h:386
#define LOG_WARNING(x)
Definition: Define.h:91
DLLEXPORT void Save()
Definition: Logger.cpp:203
static bool IsCharacterQuote(CharType character)
Iterator class for getting parts of a string.
#define LOG_WRITE(x)
Definition: Define.h:93
std::vector< std::unique_ptr< std::string > > QueuedConsoleCommands
Stores console commands that came from the command line.
Definition: Engine.h:383
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
int TestCrash(int writenum)
Definition: Engine.cpp:1285

◆ PostLoad()

void Engine::PostLoad ( )
protected

Definition at line 412 of file Engine.cpp.

413 {
414  // increase start count //
415  int startcounts = 0;
416 
417  if(Mainstore->GetValueAndConvertTo<int>("StartCount", startcounts)) {
418  // increase //
419  Mainstore->SetValue("StartCount", new VariableBlock(new IntBlock(startcounts + 1)));
420  } else {
421 
422  Mainstore->AddVar(
423  std::make_shared<NamedVariableList>("StartCount", new VariableBlock(1)));
424 
425  // set as persistent //
426  Mainstore->SetPersistance("StartCount", true);
427  }
428 
429  // Makes sure commands don't fail if they use some time stuff
430  ClearTimers();
431 
433 
434  // Run startup command line //
436 
437  // Run queued imports
438  if(!QueuedImports.empty()) {
439  for(const auto& importer : QueuedImports) {
440  try {
441  if(!importer->Run()) {
442 
443  LOG_ERROR("An import operation failed");
444  }
445  } catch(const Exception& e) {
446  LOG_ERROR("An exception happened in importer:");
447  e.PrintToLog();
448  }
449  }
450 
451  QueuedImports.clear();
452  LOG_INFO("Marking as closing after processing imports");
453  MarkQuit();
454  }
455 
456  // Makes the time next tick happens good
457  ClearTimers();
458 }
DLLEXPORT void MarkQuit()
Marks the owning application to quit.
Definition: Engine.cpp:1163
DLLEXPORT void ClearTimers()
Clears physical timers.
Definition: Engine.cpp:1256
bool GetValueAndConvertTo(const std::string &name, T &receiver) const
Definition: DataStore.h:82
#define LOG_INFO(x)
Definition: Define.h:90
#define LOG_ERROR(x)
Definition: Define.h:92
Non-template class for working with all types of DataBlocks.
Definition: DataBlock.h:425
DataStore * Mainstore
Definition: Engine.h:311
std::vector< std::unique_ptr< Editor::Importer > > QueuedImports
Queued importers from command line parsing.
Definition: Engine.h:386
void _RunQueuedConsoleCommands()
Runs all commands in QueuedConsoleCommands.
Definition: Engine.cpp:1526
Base class for all exceptions thrown by Leviathan.
Definition: Exceptions.h:10
DLLEXPORT bool SetValue(const std::string &name, const VariableBlock &value1)
Definition: DataStore.cpp:164
DataBlock< int > IntBlock
Definition: DataBlock.h:382
DLLEXPORT void SetPersistance(unsigned int index, bool toset)
Definition: DataStore.cpp:135
DLLEXPORT void ExecuteCommandLine()
Definition: Engine.cpp:1438
DLLEXPORT void AddVar(std::shared_ptr< NamedVariableList > values)
Definition: DataStore.cpp:208
virtual DLLEXPORT void PrintToLog() const noexcept
Definition: Exceptions.cpp:35

◆ PreFirstTick()

DLLEXPORT void Engine::PreFirstTick ( )

Called by Application before the first Update call.

Definition at line 971 of file Engine.cpp.

972 {
973  GUARD_LOCK();
974 
977 
978  ClearTimers();
979 
980  Logger::Get()->Info("Engine: PreFirstTick: everything fine to start running");
981 }
DLLEXPORT void ClearTimers()
Clears physical timers.
Definition: Engine.cpp:1256
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
DLLEXPORT void NotifyQueuerThread()
Notifies the queuer thread to check task setting.
ThreadingManager * _ThreadingManager
Definition: Engine.h:319
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
#define GUARD_LOCK()
Definition: ThreadSafe.h:111

◆ PreRelease()

DLLEXPORT void Engine::PreRelease ( )

Sets objects ready to be released.

Note
The Tick function must be called after this but before Release

Definition at line 460 of file Engine.cpp.

461 {
462  GUARD_LOCK();
463 
465  return;
466 
467  PreReleaseWaiting = true;
468  // This will stay true until the end of times //
469  PreReleaseCompleted = true;
470 
471  // Stop command handling first //
472  if(_ConsoleInput) {
473 
474  _ConsoleInput->Release(false);
475  Logger::Get()->Info("Successfully stopped command handling");
476  }
477 
478  // Close all editors
479  OpenedEditors.clear();
480 
481  // Automatically destroy input sources //
483 
484  // Then kill the network //
485  {
486  Lock lock(NetworkHandlerLock);
487 
489  }
490 
491  // Let the game release it's resources //
493 
494  // Close remote console //
496 
497  // Close all connections //
498  {
499  Lock lock(NetworkHandlerLock);
500 
502  }
503 
505 
506  // Set worlds to empty //
507  {
508  Lock lock(GameWorldsLock);
509 
510  for(auto iter = GameWorlds.begin(); iter != GameWorlds.end(); ++iter) {
511  // Set all objects to release //
512  (*iter)->MarkForClear();
513  }
514  }
515 
516  // Set tasks to a proper state //
519 
520  Logger::Get()->Info("Engine: prerelease done, waiting for a tick");
521 }
DLLEXPORT void SetDiscardConditionalTasks(bool discard)
Sets the task queuer to discard all conditional tasks.
virtual DLLEXPORT void EnginePreShutdown()
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
NetworkInterface * GetInterface()
Returns interface object. Type depends on AppType.
NetworkHandler * _NetworkHandler
Definition: Engine.h:318
std::unique_ptr< ConsoleInput > _ConsoleInput
Definition: Engine.h:323
bool PreReleaseWaiting
Definition: Engine.h:358
virtual DLLEXPORT void CloseDown()=0
Called when the program is closing.
ThreadingManager * _ThreadingManager
Definition: Engine.h:319
std::vector< std::unique_ptr< Editor::Editor > > OpenedEditors
Definition: Engine.h:325
#define SAFE_RELEASEDEL(x)
Definition: Define.h:141
RemoteConsole * _RemoteConsole
Definition: Engine.h:320
std::mutex NetworkHandlerLock
Mutex that is locked while NetworkHandler is used.
Definition: Engine.h:342
ResourceRefreshHandler * _ResourceRefreshHandler
Definition: Engine.h:321
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT void SetDisallowRepeatingTasks(bool disallow)
Disallows repeating tasks to occur again.
std::mutex GameWorldsLock
Mutex that is locked when changing the worlds.
Definition: Engine.h:339
bool PreReleaseCompleted
Definition: Engine.h:372
#define SAFE_DELETE(x)
Definition: Define.h:149
DLLEXPORT void ReleaseInputHandler()
Destroys the networked input handler and all input objects.
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
std::vector< std::shared_ptr< GameWorld > > GameWorlds
List of current worlds.
Definition: Engine.h:336
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
LeviathanApplication * Owner
Definition: Engine.h:333

◆ ProcessInvokes()

DLLEXPORT void Engine::ProcessInvokes ( )
protected

Handles InvokeQueue.

Definition at line 1175 of file Engine.cpp.

1176 {
1177  RecursiveLock lock(InvokeLock);
1178 
1179  while(!InvokeQueue.empty()) {
1180 
1181  const auto& func = InvokeQueue.front();
1182 
1183  // Recursive mutex allows the invoke to call extra invokes
1184  func();
1185 
1186  InvokeQueue.pop_front();
1187  }
1188 }
std::lock_guard< std::recursive_mutex > RecursiveLock
Definition: ThreadSafe.h:19
std::list< std::function< void()> > InvokeQueue
Definition: Engine.h:376
RecursiveMutex InvokeLock
Definition: Engine.h:375

◆ Release()

void Engine::Release ( bool  forced = false)
Todo:
Add a thread that monitors if the thing gets stuck on a task

Definition at line 523 of file Engine.cpp.

524 {
525  GUARD_LOCK();
526 
527  if(!forced)
528  LEVIATHAN_ASSERT(PreReleaseDone, "PreReleaseDone must be done before actual release!");
529 
530  // Force garbase collection //
531  if(MainScript)
533 
534  // Make windows clear their stored objects //
535  for(size_t i = 0; i < AdditionalGraphicalEntities.size(); i++) {
536 
537  AdditionalGraphicalEntities[i]->UnlinkAll();
538  }
539 
540  // Finally the main window //
541  if(GraphicalEntity1) {
542 
544  }
545 
546  // Destroy worlds //
547  {
548  Lock lock(GameWorldsLock);
549 
550  while(GameWorlds.size()) {
551 
552  GameWorlds[0]->Release();
553  GameWorlds.erase(GameWorlds.begin());
554  }
555  }
556 
557  if(_NetworkHandler)
559 
560  // Wait for tasks to finish //
561  if(!forced)
563 
564  // Destroy windows //
565  for(size_t i = 0; i < AdditionalGraphicalEntities.size(); i++) {
566 
568  }
569 
571 
573 
574 #ifdef LEVIATHAN_USES_LEAP
575  SAFE_RELEASEDEL(LeapData);
576 #endif
577 
578  // Console needs to be released before script release //
580 
581  _GameModuleLoader.reset();
582 
584 
585  // Save at this point (just in case it crashes before exiting) //
586  Logger::Get()->Save();
587 
588 
590 
593 
594  // If graphics aren't unregistered crashing will occur //
596 
597  // Stop threads //
599 
601 
603  // delete randomizer last, for obvious reasons //
605 
608 
609  // clears all running timers that might have accidentally been left running //
611 
612  // safe to delete this here //
614 
616 
617  Logger::Get()->Write("Goodbye cruel world!");
618 }
ScriptExecutor * MainScript
Definition: Engine.h:313
DLLEXPORT void Write(const std::string &data) override
Definition: Logger.cpp:113
DLLEXPORT void ShutdownCache()
Destroys the network cache permanently.
RenderingStatistics * RenderTimer
Definition: Engine.h:304
DataStore * Mainstore
Definition: Engine.h:311
IDFactory * IDDefaultInstance
Definition: Engine.h:332
NetworkHandler * _NetworkHandler
Definition: Engine.h:318
ScriptConsole * MainConsole
Definition: Engine.h:314
OutOfMemoryHandler * OutOMemory
Definition: Engine.h:317
DLLEXPORT void WaitForAllTasksToFinish()
Blocks until all queued tasks are finished.
DLLEXPORT void CollectGarbage()
Does a full garbage collection cycle.
static DLLEXPORT void ClearTimers()
Window * GraphicalEntity1
Definition: Engine.h:307
DLLEXPORT void Save()
Definition: Logger.cpp:203
ThreadingManager * _ThreadingManager
Definition: Engine.h:319
#define SAFE_RELEASEDEL(x)
Definition: Define.h:141
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100
SoundDevice * Sound
Definition: Engine.h:310
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT void UnlinkAll()
Definition: Window.cpp:289
FileSystem * MainFileHandler
Definition: Engine.h:315
std::mutex GameWorldsLock
Mutex that is locked when changing the worlds.
Definition: Engine.h:339
Random * MainRandom
Definition: Engine.h:316
DLLEXPORT void UnregisterGraphics()
Must be called if MakeThreadsWorkWithOgre has been called, BEFORE releasing graphics.
#define SAFE_DELETE(x)
Definition: Define.h:149
Graphics * Graph
Definition: Engine.h:305
bool PreReleaseDone
Set when PreRelease is called and Tick has happened.
Definition: Engine.h:354
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
std::vector< std::shared_ptr< GameWorld > > GameWorlds
List of current worlds.
Definition: Engine.h:336
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
std::unique_ptr< GameModuleLoader > _GameModuleLoader
Definition: Engine.h:324
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308
EventHandler * MainEvents
Definition: Engine.h:312

◆ RenderFrame()

void Engine::RenderFrame ( float  elapsed)
protected

Definition at line 983 of file Engine.cpp.

984 {
985  // We want to totally ignore this if we are in headless mode
986  if(NoGui)
987  return;
988 
989  FrameCount++;
990 
991  // This is needed for the statistics to work correctly but this is no longer used to track
992  // if we can render or not
993  int unused;
995 
996  // advanced statistic start monitoring //
998 
1000 
1001  bool shouldrender = false;
1002 
1003  // Render //
1004  if(GraphicalEntity1 && GraphicalEntity1->Render(elapsed))
1005  shouldrender = true;
1006 
1007  for(size_t i = 0; i < AdditionalGraphicalEntities.size(); i++) {
1008 
1009  if(AdditionalGraphicalEntities[i]->Render(elapsed))
1010  shouldrender = true;
1011  }
1012 
1013  // guard.unlock();
1014  if(shouldrender)
1015  Graph->Frame();
1016 
1017  // guard.lock();
1018 
1019  // advanced statistics frame has ended //
1021 }
Class that represents a statically defined event.
Definition: Event.h:106
DLLEXPORT bool Render(float elapsed)
This function uses the LinkObjects function objects.
Definition: Window.cpp:300
RenderingStatistics * RenderTimer
Definition: Engine.h:304
Window * GraphicalEntity1
Definition: Engine.h:307
DLLEXPORT bool Frame()
Definition: Graphics.cpp:537
DLLEXPORT void CallEvent(Event *event)
Data for EVENT_TYPE_ENGINE_TICK and all others that have only int data.
Definition: Event.h:90
DLLEXPORT bool CanRenderNow(int maxfps, int &TimeSinceLastFrame)
int FrameLimit
Max FPS.
Definition: Engine.h:348
Graphics * Graph
Definition: Engine.h:305
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308
EventHandler * MainEvents
Definition: Engine.h:312

◆ ReportClosedWindow()

DLLEXPORT void Engine::ReportClosedWindow ( Window windowentity)

Removes an closed window from the engine.

Definition at line 1108 of file Engine.cpp.

1109 {
1110  windowentity->UnlinkAll();
1111 
1112  if(GraphicalEntity1 == windowentity) {
1113 
1115  return;
1116  }
1117 
1118  for(size_t i = 0; i < AdditionalGraphicalEntities.size(); i++) {
1119 
1120  if(AdditionalGraphicalEntities[i] == windowentity) {
1121 
1124 
1125  return;
1126  }
1127  }
1128 
1129  // Didn't find the target //
1130  Logger::Get()->Error("Engine: couldn't find closing Window");
1131 }
Window * GraphicalEntity1
Definition: Engine.h:307
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
DLLEXPORT void UnlinkAll()
Definition: Window.cpp:289
#define SAFE_DELETE(x)
Definition: Define.h:149
DLLEXPORT void Error(const std::string &data) override
Definition: Logger.cpp:177
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308

◆ RunOnMainThread()

DLLEXPORT void Engine::RunOnMainThread ( const std::function< void()> &  function)

Runs the function now if on the main thread otherwise calls Invoke.

Definition at line 1190 of file Engine.cpp.

1191 {
1192  if(!IsOnMainThread()) {
1193 
1194  Invoke(function);
1195 
1196  } else {
1197 
1198  function();
1199  }
1200 }
DLLEXPORT bool IsOnMainThread() const
Returns true if called on the main thread.
Definition: Engine.cpp:91
DLLEXPORT void Invoke(const std::function< void()> &function)
Runs function on the main thread before the next tick.
Definition: Engine.cpp:1169

◆ SaveScreenShot()

DLLEXPORT void Engine::SaveScreenShot ( )

Definition at line 1023 of file Engine.cpp.

1024 {
1025  LEVIATHAN_ASSERT(!NoGui, "really shouldn't try to screenshot in text-only mode");
1026  GUARD_LOCK();
1027 
1028  const string fileprefix = MainFileHandler->GetDataFolder() + "Screenshots/Captured_frame_";
1029 
1030  GraphicalEntity1->SaveScreenShot(fileprefix);
1031 }
static DLLEXPORT std::string GetDataFolder()
Definition: FileSystem.cpp:198
Window * GraphicalEntity1
Definition: Engine.h:307
#define LEVIATHAN_ASSERT(x, msg)
Definition: Define.h:100
DLLEXPORT void SaveScreenShot(const std::string &filename)
Definition: Window.cpp:957
FileSystem * MainFileHandler
Definition: Engine.h:315
#define GUARD_LOCK()
Definition: ThreadSafe.h:111

◆ SetNoGUI()

void Leviathan::Engine::SetNoGUI ( )
inline

Definition at line 267 of file Engine.h.

268  {
269  NoGui = true;
270  }

◆ Tick()

void Engine::Tick ( float  elapsed)
protected

Definition at line 895 of file Engine.cpp.

896 {
897  if(PreReleaseWaiting) {
898 
899  PreReleaseWaiting = false;
900  PreReleaseDone = true;
901 
902  Logger::Get()->Info("Engine: performing final release tick");
903 
904  // Call last tick event //
905 
906  return;
907  }
908 
909  TickCount++;
910 
911  // Update input //
912 #ifdef LEVIATHAN_USES_LEAP
913  if(LeapData)
914  LeapData->OnTick(TimePassed);
915 #endif
916 
917  // sound tick //
918  if(Sound)
919  Sound->Tick(elapsed);
920 
921  if(!NoGui) {
922  // update windows //
923  if(GraphicalEntity1)
924  GraphicalEntity1->Tick(elapsed);
925 
926  for(size_t i = 0; i < AdditionalGraphicalEntities.size(); i++) {
927 
928  AdditionalGraphicalEntities[i]->Tick(elapsed);
929  }
930  }
931 
932 
933  // Update worlds //
934  {
935  Lock lock(GameWorldsLock);
936 
937  // This will also update physics //
938  auto end = GameWorlds.end();
939  for(auto iter = GameWorlds.begin(); iter != end; ++iter) {
940 
941  (*iter)->Tick(elapsed);
942  }
943  }
944 
945  // Some dark magic here //
946  if(TickCount % 25 == 0) {
947  // update values
951  // TODO: having the max tick time of the past second, would also be nice
952 
953  if(!NoGui) {
954  // send updated rendering statistics //
956  }
957  }
958 
959  // Update file listeners //
962 
963  // Send the tick event //
964  if(MainEvents)
966 
967  // Call the default app tick //
968  Owner->Tick(elapsed);
969 }
DLLEXPORT void Tick(float elapsed)
Class that represents a statically defined event.
Definition: Event.h:106
RenderingStatistics * RenderTimer
Definition: Engine.h:304
DLLEXPORT void Info(const std::string &data) override
Definition: Logger.cpp:164
DLLEXPORT void CheckFileStatus()
Called by Engine to check are updated files available.
DataStore * Mainstore
Definition: Engine.h:311
DLLEXPORT void Tick(float elapsed)
Called by Engine.
Definition: Window.cpp:294
Window * GraphicalEntity1
Definition: Engine.h:307
bool PreReleaseWaiting
Definition: Engine.h:358
virtual DLLEXPORT void Tick(float elapsed)
SoundDevice * Sound
Definition: Engine.h:310
DLLEXPORT void SetTicksBehind(int value)
Definition: DataStore.cpp:411
DLLEXPORT void CallEvent(Event *event)
ResourceRefreshHandler * _ResourceRefreshHandler
Definition: Engine.h:321
static DLLEXPORT Logger * Get()
Definition: Logger.cpp:106
std::mutex GameWorldsLock
Mutex that is locked when changing the worlds.
Definition: Engine.h:339
DLLEXPORT void ReportStats(DataStore *dstore)
Data for EVENT_TYPE_ENGINE_TICK and all others that have only int data.
Definition: Event.h:90
DLLEXPORT void SetTickTime(int newval)
Definition: DataStore.cpp:405
bool PreReleaseDone
Set when PreRelease is called and Tick has happened.
Definition: Engine.h:354
std::vector< std::shared_ptr< GameWorld > > GameWorlds
List of current worlds.
Definition: Engine.h:336
DLLEXPORT void SetTickCount(int newval)
Definition: DataStore.cpp:399
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
std::vector< Window * > AdditionalGraphicalEntities
Definition: Engine.h:308
EventHandler * MainEvents
Definition: Engine.h:312
LeviathanApplication * Owner
Definition: Engine.h:333

◆ Update()

float Engine::Update ( )

Runs an update cycle (tick and rendering if needed)

Returns
The time in seconds until next update time (this value is used to sleep in Application)

Definition at line 823 of file Engine.cpp.

824 {
825  // Always try to update networking //
826  {
827  Lock lock(NetworkHandlerLock);
828 
829  if(_NetworkHandler)
831  }
832 
833  // And handle invokes //
834  ProcessInvokes();
835 
836  const auto now = Time::GetCurrentTimePoint();
837 
838  GUARD_LOCK();
839 
840  SecondDuration elapsed = now - LastTickTime;
841 
842  if(elapsed.count() <= 0.f) {
843  // Time passed is too short, everything will break if our step is 0, so try again
844  // very shortly
845  LOG_INFO("Trying to run Update before any (detectable) time has passed, skipping");
846  return 0.f;
847  }
848 
849  if(elapsed > SecondDuration(1)) {
850  LOG_ERROR("Game is lagging! Time since last update: " +
851  std::to_string(elapsed.count()) + "s. Capping it at one second.");
852  elapsed = SecondDuration(1);
853  }
854 
855  bool frameLimited = FrameLimit >= 0 && FrameLimit < 1000;
856 
857  PreciseSecondDuration frameInterval;
858 
859  // Update limiter
860  // This is now a much simpler limiter based on needing to have some time elapsed since last
861  // tick
862  if(frameLimited) {
863 
864  frameInterval = PreciseSecondDuration(1.0 / FrameLimit);
865 
866  if(elapsed < frameInterval) {
867  return SecondDuration(frameInterval - elapsed).count();
868  }
869  }
870 
871  // Update should happen
872 
873  LastTickTime = now;
874 
875  // Tick first
876  Tick(elapsed.count());
877 
878  const auto tickDuration = Time::GetCurrentTimePoint() - LastTickTime;
879 
880  TickTime = std::chrono::duration_cast<MillisecondDuration>(tickDuration).count();
881 
882  // And then render (this skips rendering in headless mode)
883  RenderFrame(elapsed.count());
884 
885  if(frameLimited) {
886  return std::max(
887  SecondDuration(LastTickTime - Time::GetCurrentTimePoint() - frameInterval).count(),
888  0.f);
889  } else {
890  // No update rate limit. No sleep should happen before the next update
891  return 0.f;
892  }
893 }
virtual DLLEXPORT void UpdateAllConnections()
#define LOG_INFO(x)
Definition: Define.h:90
#define LOG_ERROR(x)
Definition: Define.h:92
NetworkHandler * _NetworkHandler
Definition: Engine.h:318
DLLEXPORT void RenderFrame(float elapsed)
Definition: Engine.cpp:983
DLLEXPORT void ProcessInvokes()
Handles InvokeQueue.
Definition: Engine.cpp:1175
std::chrono::duration< double, std::ratio< 1 > > PreciseSecondDuration
Definition: TimeIncludes.h:17
TimePoint LastTickTime
Time when last ticked, used to track elapsed time.
Definition: Engine.h:345
DLLEXPORT void Tick(float elapsed)
Definition: Engine.cpp:895
static DLLEXPORT TimePoint GetCurrentTimePoint()
std::mutex NetworkHandlerLock
Mutex that is locked while NetworkHandler is used.
Definition: Engine.h:342
int FrameLimit
Max FPS.
Definition: Engine.h:348
#define GUARD_LOCK()
Definition: ThreadSafe.h:111
std::unique_lock< std::mutex > Lock
Definition: ThreadSafe.h:18
std::chrono::duration< float, std::ratio< 1 > > SecondDuration
Definition: TimeIncludes.h:16

Member Data Documentation

◆ _ConsoleInput

std::unique_ptr<ConsoleInput> Leviathan::Engine::_ConsoleInput
protected

Definition at line 323 of file Engine.h.

◆ _GameModuleLoader

std::unique_ptr<GameModuleLoader> Leviathan::Engine::_GameModuleLoader
protected

Definition at line 324 of file Engine.h.

◆ _NetworkHandler

NetworkHandler* Leviathan::Engine::_NetworkHandler = nullptr
protected

Definition at line 318 of file Engine.h.

◆ _RemoteConsole

RemoteConsole* Leviathan::Engine::_RemoteConsole = nullptr
protected

Definition at line 320 of file Engine.h.

◆ _ResourceRefreshHandler

ResourceRefreshHandler* Leviathan::Engine::_ResourceRefreshHandler = nullptr
protected

Definition at line 321 of file Engine.h.

◆ _ThreadingManager

ThreadingManager* Leviathan::Engine::_ThreadingManager = nullptr
protected

Definition at line 319 of file Engine.h.

◆ AdditionalGraphicalEntities

std::vector<Window*> Leviathan::Engine::AdditionalGraphicalEntities
protected

Definition at line 308 of file Engine.h.

◆ Define

AppDef* Leviathan::Engine::Define = nullptr
protected

Definition at line 302 of file Engine.h.

◆ FrameCount

int Leviathan::Engine::FrameCount = 0
protected

Definition at line 349 of file Engine.h.

◆ FrameLimit

int Leviathan::Engine::FrameLimit = -1
protected

Max FPS.

Definition at line 348 of file Engine.h.

◆ GameWorlds

std::vector<std::shared_ptr<GameWorld> > Leviathan::Engine::GameWorlds
protected

List of current worlds.

Definition at line 336 of file Engine.h.

◆ GameWorldsLock

std::mutex Leviathan::Engine::GameWorldsLock
protected

Mutex that is locked when changing the worlds.

Definition at line 339 of file Engine.h.

◆ Graph

Graphics* Leviathan::Engine::Graph = nullptr
protected

Definition at line 305 of file Engine.h.

◆ GraphicalEntity1

Window* Leviathan::Engine::GraphicalEntity1 = nullptr
protected

Definition at line 307 of file Engine.h.

◆ IDDefaultInstance

IDFactory* Leviathan::Engine::IDDefaultInstance = nullptr
protected

Definition at line 332 of file Engine.h.

◆ instance

DLLEXPORT Engine * Engine::instance = nullptr
staticprotected

Definition at line 388 of file Engine.h.

◆ InvokeLock

RecursiveMutex Leviathan::Engine::InvokeLock
protected

Definition at line 375 of file Engine.h.

◆ InvokeQueue

std::list<std::function<void()> > Leviathan::Engine::InvokeQueue
protected

Definition at line 376 of file Engine.h.

◆ IsClient

bool Leviathan::Engine::IsClient = false
protected

Set to true when initialized as a client.

Used to call client specific events

Definition at line 369 of file Engine.h.

◆ LastTickTime

TimePoint Leviathan::Engine::LastTickTime
protected

Time when last ticked, used to track elapsed time.

Definition at line 345 of file Engine.h.

◆ MainConsole

ScriptConsole* Leviathan::Engine::MainConsole = nullptr
protected

Definition at line 314 of file Engine.h.

◆ MainEvents

EventHandler* Leviathan::Engine::MainEvents = nullptr
protected

Definition at line 312 of file Engine.h.

◆ MainFileHandler

FileSystem* Leviathan::Engine::MainFileHandler = nullptr
protected

Definition at line 315 of file Engine.h.

◆ MainRandom

Random* Leviathan::Engine::MainRandom = nullptr
protected

Definition at line 316 of file Engine.h.

◆ MainScript

ScriptExecutor* Leviathan::Engine::MainScript = nullptr
protected

Definition at line 313 of file Engine.h.

◆ Mainstore

DataStore* Leviathan::Engine::Mainstore = nullptr
protected

Definition at line 311 of file Engine.h.

◆ NetworkHandlerLock

std::mutex Leviathan::Engine::NetworkHandlerLock
protected

Mutex that is locked while NetworkHandler is used.

Definition at line 342 of file Engine.h.

◆ NoGui

bool Leviathan::Engine::NoGui = false
protected
Todo:
Rename to headless

Definition at line 362 of file Engine.h.

◆ NoLeap

bool Leviathan::Engine::NoLeap = false
protected

Definition at line 363 of file Engine.h.

◆ NoSTDInput

bool Leviathan::Engine::NoSTDInput = false
protected

Definition at line 364 of file Engine.h.

◆ OpenedEditors

std::vector<std::unique_ptr<Editor::Editor> > Leviathan::Engine::OpenedEditors
protected

Definition at line 325 of file Engine.h.

◆ OutOMemory

OutOfMemoryHandler* Leviathan::Engine::OutOMemory = nullptr
protected

Definition at line 317 of file Engine.h.

◆ Owner

LeviathanApplication* Leviathan::Engine::Owner = nullptr
protected

Definition at line 333 of file Engine.h.

◆ PassedCommands

std::vector<std::unique_ptr<std::string> > Leviathan::Engine::PassedCommands
protected
Todo:
Remove this, doesn't work now and needs redoing

Definition at line 380 of file Engine.h.

◆ PreReleaseCompleted

bool Leviathan::Engine::PreReleaseCompleted = false
protected

Definition at line 372 of file Engine.h.

◆ PreReleaseDone

bool Leviathan::Engine::PreReleaseDone = false
protected

Set when PreRelease is called and Tick has happened.

Definition at line 354 of file Engine.h.

◆ PreReleaseWaiting

bool Leviathan::Engine::PreReleaseWaiting = false
protected

Set when PreRelease called and waiting for Tick see PreReleaseDone

Definition at line 358 of file Engine.h.

◆ QueuedConsoleCommands

std::vector<std::unique_ptr<std::string> > Leviathan::Engine::QueuedConsoleCommands
protected

Stores console commands that came from the command line.

Definition at line 383 of file Engine.h.

◆ QueuedImports

std::vector<std::unique_ptr<Editor::Importer> > Leviathan::Engine::QueuedImports
protected

Queued importers from command line parsing.

Definition at line 386 of file Engine.h.

◆ RenderTimer

RenderingStatistics* Leviathan::Engine::RenderTimer = nullptr
protected

Definition at line 304 of file Engine.h.

◆ Sound

SoundDevice* Leviathan::Engine::Sound = nullptr
protected

Definition at line 310 of file Engine.h.

◆ TickCount

int Leviathan::Engine::TickCount = 0
protected

Definition at line 350 of file Engine.h.

◆ TickTime

int Leviathan::Engine::TickTime = 0
protected

Definition at line 351 of file Engine.h.


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