Urho3DPlayer.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. //
  2. // Copyright (c) 2008-2017 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #ifdef URHO3D_ANGELSCRIPT
  23. #include <Urho3D/AngelScript/ScriptFile.h>
  24. #include <Urho3D/AngelScript/Script.h>
  25. #endif
  26. #include <Urho3D/Core/Main.h>
  27. #include <Urho3D/Engine/Engine.h>
  28. #include <Urho3D/Engine/EngineDefs.h>
  29. #include <Urho3D/IO/FileSystem.h>
  30. #include <Urho3D/IO/Log.h>
  31. #ifdef URHO3D_LUA
  32. #include <Urho3D/LuaScript/LuaScript.h>
  33. #endif
  34. #include <Urho3D/Resource/ResourceCache.h>
  35. #include <Urho3D/Resource/ResourceEvents.h>
  36. #include "Urho3DPlayer.h"
  37. #include <Urho3D/DebugNew.h>
  38. URHO3D_DEFINE_APPLICATION_MAIN(Urho3DPlayer);
  39. Urho3DPlayer::Urho3DPlayer(Context* context) :
  40. Application(context),
  41. commandLineRead_(false)
  42. {
  43. }
  44. void Urho3DPlayer::Setup()
  45. {
  46. // Web platform depends on the resource system to read any data files. Skip parsing the command line file now
  47. // and try later when the resource system is live
  48. #ifndef __EMSCRIPTEN__
  49. // Read command line from a file if no arguments given. This is primarily intended for mobile platforms.
  50. // Note that the command file name uses a hardcoded path that does not utilize the resource system
  51. // properly (including resource path prefix), as the resource system is not yet initialized at this point
  52. auto* filesystem = GetSubsystem<FileSystem>();
  53. const String commandFileName = filesystem->GetProgramDir() + "Data/CommandLine.txt";
  54. if (GetArguments().Empty() && filesystem->FileExists(commandFileName))
  55. {
  56. SharedPtr<File> commandFile(new File(context_, commandFileName));
  57. if (commandFile->IsOpen())
  58. {
  59. commandLineRead_ = true;
  60. String commandLine = commandFile->ReadLine();
  61. commandFile->Close();
  62. ParseArguments(commandLine, false);
  63. // Reparse engine startup parameters now
  64. engineParameters_ = Engine::ParseParameters(GetArguments());
  65. }
  66. }
  67. #endif
  68. // Check for script file name from the arguments
  69. GetScriptFileName();
  70. #ifndef __EMSCRIPTEN__
  71. // Show usage if not found
  72. if ((GetArguments().Size() || commandLineRead_) && scriptFileName_.Empty())
  73. {
  74. ErrorExit("Usage: Urho3DPlayer <scriptfile> [options]\n\n"
  75. "The script file should implement the function void Start() for initializing the "
  76. "application and subscribing to all necessary events, such as the frame update.\n"
  77. #ifndef _WIN32
  78. "\nCommand line options:\n"
  79. "-x <res> Horizontal resolution\n"
  80. "-y <res> Vertical resolution\n"
  81. "-m <level> Enable hardware multisampling\n"
  82. "-v Enable vertical sync\n"
  83. "-t Enable triple buffering\n"
  84. "-w Start in windowed mode\n"
  85. "-s Enable resizing when in windowed mode\n"
  86. "-q Enable quiet mode which does not log to standard output stream\n"
  87. "-b <length> Sound buffer length in milliseconds\n"
  88. "-r <freq> Sound mixing frequency in Hz\n"
  89. "-pp <paths> Resource prefix path(s), separated by semicolons, default to executable path\n"
  90. "The resource prefix paths can also be defined using URHO3D_PREFIX_PATH env - var\n"
  91. "When both are defined, the paths set by -pp takes higher precedence\n"
  92. "-p <paths> Resource path(s) to use, separated by semicolons, default to 'Data;CoreData'\n"
  93. "-pf <files> Resource package file to use, separated by semicolons, default to none\n"
  94. "-ap <paths> Resource autoload path(s), separated by semicolons, default to 'AutoLoad'\n"
  95. "-log <level> Change the log level, valid 'level' values: 'debug', 'info', 'warning', 'error'\n"
  96. "-ds <file> Dump used shader variations to a file for precaching\n"
  97. "-mq <level> Material quality level, default 2 (high)\n"
  98. "-tq <level> Texture quality level, default 2 (high)\n"
  99. "-tf <level> Texture filter mode, default 2 (trilinear)\n"
  100. "-af <level> Texture anisotropy level, default 4. Also sets anisotropic filter mode\n"
  101. "-gl2 Force OpenGL 2 use even if OpenGL 3 is available\n"
  102. "-flushgpu Flush GPU command queue each frame. Effective only on Direct3D\n"
  103. "-borderless Borderless window mode\n"
  104. "-lowdpi Force low DPI mode on Retina display\n"
  105. "-headless Headless mode. No application window will be created\n"
  106. "-landscape Use landscape orientations (iOS only, default)\n"
  107. "-portrait Use portrait orientations (iOS only)\n"
  108. "-monitor <num> Monitor number to use\n"
  109. "-hz <freq> Monitor refresh rate to use\n"
  110. "-prepass Use light pre-pass rendering\n"
  111. "-deferred Use deferred rendering\n"
  112. "-renderpath <name> Use the named renderpath (must enter full resource name)\n"
  113. "-lqshadows Use low-quality (1-sample) shadow filtering\n"
  114. "-noshadows Disable shadow rendering\n"
  115. "-nolimit Disable frame limiter\n"
  116. "-nothreads Disable worker threads\n"
  117. "-nosound Disable sound output\n"
  118. "-noip Disable sound mixing interpolation\n"
  119. "-touch Touch emulation on desktop platform\n"
  120. #endif
  121. );
  122. }
  123. else
  124. {
  125. // Use the script file name as the base name for the log file
  126. engineParameters_[EP_LOG_NAME] = filesystem->GetAppPreferencesDir("urho3d", "logs") + GetFileNameAndExtension(scriptFileName_) + ".log";
  127. }
  128. #else
  129. // On Web platform setup a default windowed resolution similar to the executable samples
  130. engineParameters_[EP_FULL_SCREEN] = false;
  131. #endif
  132. // Construct a search path to find the resource prefix with two entries:
  133. // The first entry is an empty path which will be substituted with program/bin directory -- this entry is for binary when it is still in build tree
  134. // The second and third entries are possible relative paths from the installed program/bin directory to the asset directory -- these entries are for binary when it is in the Urho3D SDK installation location
  135. if (!engineParameters_.Contains(EP_RESOURCE_PREFIX_PATHS))
  136. engineParameters_[EP_RESOURCE_PREFIX_PATHS] = ";../share/Resources;../share/Urho3D/Resources";
  137. }
  138. void Urho3DPlayer::Start()
  139. {
  140. // Reattempt reading the command line from the resource system now if not read before
  141. // Note that the engine can not be reconfigured at this point; only the script name can be specified
  142. if (GetArguments().Empty() && !commandLineRead_)
  143. {
  144. SharedPtr<File> commandFile = GetSubsystem<ResourceCache>()->GetFile("CommandLine.txt", false);
  145. if (commandFile)
  146. {
  147. String commandLine = commandFile->ReadLine();
  148. commandFile->Close();
  149. ParseArguments(commandLine, false);
  150. }
  151. GetScriptFileName();
  152. }
  153. if (scriptFileName_.Empty())
  154. {
  155. ErrorExit("Script file name not specified; cannot proceed");
  156. return;
  157. }
  158. String extension = GetExtension(scriptFileName_);
  159. if (extension != ".lua" && extension != ".luc")
  160. {
  161. #ifdef URHO3D_ANGELSCRIPT
  162. // Instantiate and register the AngelScript subsystem
  163. context_->RegisterSubsystem(new Script(context_));
  164. // Hold a shared pointer to the script file to make sure it is not unloaded during runtime
  165. scriptFile_ = GetSubsystem<ResourceCache>()->GetResource<ScriptFile>(scriptFileName_);
  166. /// \hack If we are running the editor, also instantiate Lua subsystem to enable editing Lua ScriptInstances
  167. #ifdef URHO3D_LUA
  168. if (scriptFileName_.Contains("Editor.as", false))
  169. context_->RegisterSubsystem(new LuaScript(context_));
  170. #endif
  171. // If script loading is successful, proceed to main loop
  172. if (scriptFile_ && scriptFile_->Execute("void Start()"))
  173. {
  174. // Subscribe to script's reload event to allow live-reload of the application
  175. SubscribeToEvent(scriptFile_, E_RELOADSTARTED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadStarted));
  176. SubscribeToEvent(scriptFile_, E_RELOADFINISHED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFinished));
  177. SubscribeToEvent(scriptFile_, E_RELOADFAILED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFailed));
  178. return;
  179. }
  180. #else
  181. ErrorExit("AngelScript is not enabled!");
  182. return;
  183. #endif
  184. }
  185. else
  186. {
  187. #ifdef URHO3D_LUA
  188. // Instantiate and register the Lua script subsystem
  189. auto* luaScript = new LuaScript(context_);
  190. context_->RegisterSubsystem(luaScript);
  191. // If script loading is successful, proceed to main loop
  192. if (luaScript->ExecuteFile(scriptFileName_))
  193. {
  194. luaScript->ExecuteFunction("Start");
  195. return;
  196. }
  197. #else
  198. ErrorExit("Lua is not enabled!");
  199. return;
  200. #endif
  201. }
  202. // The script was not successfully loaded. Show the last error message and do not run the main loop
  203. ErrorExit();
  204. }
  205. void Urho3DPlayer::Stop()
  206. {
  207. #ifdef URHO3D_ANGELSCRIPT
  208. if (scriptFile_)
  209. {
  210. // Execute the optional stop function
  211. if (scriptFile_->GetFunction("void Stop()"))
  212. scriptFile_->Execute("void Stop()");
  213. }
  214. #else
  215. if (false)
  216. {
  217. }
  218. #endif
  219. #ifdef URHO3D_LUA
  220. else
  221. {
  222. auto* luaScript = GetSubsystem<LuaScript>();
  223. if (luaScript && luaScript->GetFunction("Stop", true))
  224. luaScript->ExecuteFunction("Stop");
  225. }
  226. #endif
  227. }
  228. void Urho3DPlayer::HandleScriptReloadStarted(StringHash eventType, VariantMap& eventData)
  229. {
  230. #ifdef URHO3D_ANGELSCRIPT
  231. if (scriptFile_->GetFunction("void Stop()"))
  232. scriptFile_->Execute("void Stop()");
  233. #endif
  234. }
  235. void Urho3DPlayer::HandleScriptReloadFinished(StringHash eventType, VariantMap& eventData)
  236. {
  237. #ifdef URHO3D_ANGELSCRIPT
  238. // Restart the script application after reload
  239. if (!scriptFile_->Execute("void Start()"))
  240. {
  241. scriptFile_.Reset();
  242. ErrorExit();
  243. }
  244. #endif
  245. }
  246. void Urho3DPlayer::HandleScriptReloadFailed(StringHash eventType, VariantMap& eventData)
  247. {
  248. #ifdef URHO3D_ANGELSCRIPT
  249. scriptFile_.Reset();
  250. ErrorExit();
  251. #endif
  252. }
  253. void Urho3DPlayer::GetScriptFileName()
  254. {
  255. const Vector<String>& arguments = GetArguments();
  256. if (arguments.Size() && arguments[0][0] != '-')
  257. scriptFileName_ = GetInternalPath(arguments[0]);
  258. }