1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#pragma once
4
5#include "BsCorePrerequisites.h"
6#include "Utility/BsModule.h"
7#include "RenderAPI/BsRenderWindow.h"
8#include "Utility/BsEvent.h"
9
10namespace bs
11{
12 /** @addtogroup Application-Core
13 * @{
14 */
15
16 /** Structure containing parameters for starting the application. */
17 struct BS_SCRIPT_EXPORT(m:Application,pl:true,api:bsf) START_UP_DESC
18 {
19 String renderAPI; /**< Name of the render system plugin to use. */
20 String renderer; /**< Name of the renderer plugin to use. */
21 String physics; /**< Name of physics plugin to use. */
22 String audio; /**< Name of the audio plugin to use. */
23 String input; /**< Name of the input plugin to use. */
24
25 /**
26 * True if physics cooking library should be loaded. Cooking is useful for creating collision meshes during
27 * development type, but might be unnecessary in the final application. When turned off you can save on space by
28 * not shipping the cooking library.
29 */
30 bool physicsCooking = true;
31
32 RENDER_WINDOW_DESC primaryWindowDesc; /**< Describes the window to create during start-up. */
33
34 Vector<String> importers; /**< A list of importer plugins to load. */
35 };
36
37 /**
38 * Represents the primary entry point for the core systems. Handles start-up, shutdown, primary loop and allows you to
39 * load and unload plugins.
40 *
41 * @note Sim thread only.
42 */
43 class BS_CORE_EXPORT CoreApplication : public Module<CoreApplication>
44 {
45 public:
46 CoreApplication(START_UP_DESC desc);
47 virtual ~CoreApplication();
48
49 /**
50 * Executes the main loop. This will update your components and modules, queue objects for rendering and run
51 * the simulation. Usually called immediately after startUp().
52 *
53 * This will run infinitely until stopMainLoop is called (usually from another thread or internally).
54 */
55 void runMainLoop();
56
57 /** Stops the (infinite) main loop from running. The loop will complete its current cycle before stopping. */
58 void stopMainLoop();
59
60 /** Changes the maximum FPS the application is allowed to run in. Zero means unlimited. */
61 void setFPSLimit(UINT32 limit);
62
63 /**
64 * Issues a request for the application to close. Application may choose to ignore the request depending on the
65 * circumstances and the implementation.
66 */
67 virtual void quitRequested();
68
69 /** Returns the main window that was created on application start-up. */
70 SPtr<RenderWindow> getPrimaryWindow() const { return mPrimaryWindow; }
71
72 /**
73 * Returns the id of the simulation thread.
74 *
75 * @note Thread safe.
76 */
77 ThreadId getSimThreadId() const { return mSimThreadId; }
78
79 /** Returns true if the application is running in an editor, false if standalone. */
80 virtual bool isEditor() const { return false; }
81
82 /**
83 * Loads a plugin.
84 *
85 * @param[in] pluginName Name of the plugin to load, without extension.
86 * @param[out] library Specify as not null to receive a reference to the loaded library.
87 * @param[in] passThrough Optional parameter that will be passed to the loadPlugin function.
88 * @return Value returned from the plugin start-up method.
89 */
90 void* loadPlugin(const String& pluginName, DynLib** library = nullptr, void* passThrough = nullptr);
91
92 /** Unloads a previously loaded plugin. */
93 void unloadPlugin(DynLib* library);
94
95 protected:
96 /** @copydoc Module::onStartUp */
97 void onStartUp() override;
98
99 /** Called for each iteration of the main loop. Called before any game objects or plugins are updated. */
100 virtual void preUpdate();
101
102 /** Called for each iteration of the main loop. Called after all game objects and plugins are updated. */
103 virtual void postUpdate();
104
105 /** Called during the fixed update of the main loop. Called after preUpdate and before postUpdate. */
106 virtual void fixedUpdate();
107
108 /** Initializes the renderer specified during construction. Called during initialization. */
109 virtual void startUpRenderer();
110
111 /** Returns a handler that is used for resolving shader include file paths. */
112 virtual SPtr<IShaderIncludeHandler> getShaderIncludeHandler() const;
113
114 private:
115 /** Called when the frame finishes rendering. */
116 void frameRenderingFinishedCallback();
117
118 /** Called by the core thread to begin profiling. */
119 void beginCoreProfiling();
120
121 /** Called by the core thread to end profiling. */
122 void endCoreProfiling();
123
124 protected:
125 typedef void(*UpdatePluginFunc)();
126
127 SPtr<RenderWindow> mPrimaryWindow;
128 START_UP_DESC mStartUpDesc;
129
130 // Frame limiting
131 UINT64 mFrameStep = 16666; // 60 times a second in microseconds
132 UINT64 mLastFrameTime = 0; // Microseconds
133
134 DynLib* mRendererPlugin;
135
136 Map<DynLib*, UpdatePluginFunc> mPluginUpdateFunctions;
137
138 bool mIsFrameRenderingFinished;
139 Mutex mFrameRenderingFinishedMutex;
140 Signal mFrameRenderingFinishedCondition;
141 ThreadId mSimThreadId;
142
143 volatile bool mRunMainLoop;
144
145 };
146
147 /** Provides easy access to CoreApplication. */
148 BS_CORE_EXPORT CoreApplication& gCoreApplication();
149
150 /** @} */
151}
152