Urho3DPlayer.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. //
  2. // Copyright (c) 2008-2016 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/IO/FileSystem.h>
  29. #include <Urho3D/IO/Log.h>
  30. #ifdef URHO3D_LUA
  31. #include <Urho3D/LuaScript/LuaScript.h>
  32. #endif
  33. #include <Urho3D/Resource/ResourceCache.h>
  34. #include <Urho3D/Resource/ResourceEvents.h>
  35. #include "Urho3DPlayer.h"
  36. #include <Urho3D/DebugNew.h>
  37. URHO3D_DEFINE_APPLICATION_MAIN(Urho3DPlayer);
  38. Urho3DPlayer::Urho3DPlayer(Context* context) :
  39. Application(context)
  40. {
  41. }
  42. void Urho3DPlayer::Setup()
  43. {
  44. // Web platform depends on the resource system to read any data files. Skip parsing the command line file now
  45. // and try later when the resource system is live
  46. #ifndef __EMSCRIPTEN__
  47. // Read command line from a file if no arguments given. This is primarily intended for mobile platforms.
  48. // Note that the command file name uses a hardcoded path that does not utilize the resource system
  49. // properly (including resource path prefix), as the resource system is not yet initialized at this point
  50. FileSystem* filesystem = GetSubsystem<FileSystem>();
  51. const String commandFileName = filesystem->GetProgramDir() + "Data/CommandLine.txt";
  52. if (GetArguments().Empty() && filesystem->FileExists(commandFileName))
  53. {
  54. SharedPtr<File> commandFile(new File(context_, commandFileName));
  55. String commandLine = commandFile->ReadLine();
  56. commandFile->Close();
  57. ParseArguments(commandLine, false);
  58. // Reparse engine startup parameters now
  59. engineParameters_ = Engine::ParseParameters(GetArguments());
  60. }
  61. // Check for script file name from the arguments
  62. GetScriptFileName();
  63. // Show usage if not found
  64. if (scriptFileName_.Empty())
  65. {
  66. ErrorExit("Usage: Urho3DPlayer <scriptfile> [options]\n\n"
  67. "The script file should implement the function void Start() for initializing the "
  68. "application and subscribing to all necessary events, such as the frame update.\n"
  69. #ifndef WIN32
  70. "\nCommand line options:\n"
  71. "-x <res> Horizontal resolution\n"
  72. "-y <res> Vertical resolution\n"
  73. "-m <level> Enable hardware multisampling\n"
  74. "-v Enable vertical sync\n"
  75. "-t Enable triple buffering\n"
  76. "-w Start in windowed mode\n"
  77. "-s Enable resizing when in windowed mode\n"
  78. "-hd Enable high DPI, only supported by Apple platforms (OSX, iOS, and tvOS)\n"
  79. "-q Enable quiet mode which does not log to standard output stream\n"
  80. "-b <length> Sound buffer length in milliseconds\n"
  81. "-r <freq> Sound mixing frequency in Hz\n"
  82. "-p <paths> Resource path(s) to use, separated by semicolons\n"
  83. "-ap <paths> Autoload resource path(s) to use, seperated by semicolons\n"
  84. "-log <level> Change the log level, valid 'level' values are 'debug', 'info', 'warning', 'error'\n"
  85. "-ds <file> Dump used shader variations to a file for precaching\n"
  86. "-mq <level> Material quality level, default 2 (high)\n"
  87. "-tq <level> Texture quality level, default 2 (high)\n"
  88. "-tf <level> Texture filter mode, default 2 (trilinear)\n"
  89. "-af <level> Texture anisotropy level, default 4. Also sets anisotropic filter mode\n"
  90. "-gl2 Force OpenGL 2 use even if OpenGL 3 is available\n"
  91. "-flushgpu Flush GPU command queue each frame. Effective only on Direct3D\n"
  92. "-borderless Borderless window mode\n"
  93. "-headless Headless mode. No application window will be created\n"
  94. "-landscape Use landscape orientations (iOS only, default)\n"
  95. "-portrait Use portrait orientations (iOS only)\n"
  96. "-prepass Use light pre-pass rendering\n"
  97. "-deferred Use deferred rendering\n"
  98. "-renderpath <name> Use the named renderpath (must enter full resource name)\n"
  99. "-lqshadows Use low-quality (1-sample) shadow filtering\n"
  100. "-noshadows Disable shadow rendering\n"
  101. "-nolimit Disable frame limiter\n"
  102. "-nothreads Disable worker threads\n"
  103. "-nosound Disable sound output\n"
  104. "-noip Disable sound mixing interpolation\n"
  105. "-touch Touch emulation on desktop platform\n"
  106. #endif
  107. );
  108. }
  109. else
  110. {
  111. // Use the script file name as the base name for the log file
  112. engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("urho3d", "logs") + GetFileNameAndExtension(scriptFileName_) + ".log";
  113. }
  114. #else
  115. // On Web platform setup a default windowed resolution similar to the executable samples
  116. engineParameters_["FullScreen"] = false;
  117. #endif
  118. // Construct a search path to find the resource prefix with two entries:
  119. // 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
  120. // 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
  121. if (!engineParameters_.Contains("ResourcePrefixPaths"))
  122. engineParameters_["ResourcePrefixPaths"] = ";../share/Resources;../share/Urho3D/Resources";
  123. }
  124. void Urho3DPlayer::Start()
  125. {
  126. // Reattempt reading the command line now on Web platform
  127. #ifdef __EMSCRIPTEN__
  128. if (GetArguments().Empty())
  129. {
  130. SharedPtr<File> commandFile = GetSubsystem<ResourceCache>()->GetFile("CommandLine.txt", false);
  131. if (commandFile)
  132. {
  133. String commandLine = commandFile->ReadLine();
  134. commandFile->Close();
  135. ParseArguments(commandLine, false);
  136. }
  137. }
  138. GetScriptFileName();
  139. if (scriptFileName_.Empty())
  140. {
  141. ErrorExit("Script file name not specified; cannot proceed");
  142. return;
  143. }
  144. #endif
  145. String extension = GetExtension(scriptFileName_);
  146. if (extension != ".lua" && extension != ".luc")
  147. {
  148. #ifdef URHO3D_ANGELSCRIPT
  149. // Instantiate and register the AngelScript subsystem
  150. context_->RegisterSubsystem(new Script(context_));
  151. // Hold a shared pointer to the script file to make sure it is not unloaded during runtime
  152. scriptFile_ = GetSubsystem<ResourceCache>()->GetResource<ScriptFile>(scriptFileName_);
  153. /// \hack If we are running the editor, also instantiate Lua subsystem to enable editing Lua ScriptInstances
  154. #ifdef URHO3D_LUA
  155. if (scriptFileName_.Contains("Editor.as", false))
  156. context_->RegisterSubsystem(new LuaScript(context_));
  157. #endif
  158. // If script loading is successful, proceed to main loop
  159. if (scriptFile_ && scriptFile_->Execute("void Start()"))
  160. {
  161. // Subscribe to script's reload event to allow live-reload of the application
  162. SubscribeToEvent(scriptFile_, E_RELOADSTARTED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadStarted));
  163. SubscribeToEvent(scriptFile_, E_RELOADFINISHED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFinished));
  164. SubscribeToEvent(scriptFile_, E_RELOADFAILED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFailed));
  165. return;
  166. }
  167. #else
  168. ErrorExit("AngelScript is not enabled!");
  169. return;
  170. #endif
  171. }
  172. else
  173. {
  174. #ifdef URHO3D_LUA
  175. // Instantiate and register the Lua script subsystem
  176. LuaScript* luaScript = new LuaScript(context_);
  177. context_->RegisterSubsystem(luaScript);
  178. // If script loading is successful, proceed to main loop
  179. if (luaScript->ExecuteFile(scriptFileName_))
  180. {
  181. luaScript->ExecuteFunction("Start");
  182. return;
  183. }
  184. #else
  185. ErrorExit("Lua is not enabled!");
  186. return;
  187. #endif
  188. }
  189. // The script was not successfully loaded. Show the last error message and do not run the main loop
  190. ErrorExit();
  191. }
  192. void Urho3DPlayer::Stop()
  193. {
  194. #ifdef URHO3D_ANGELSCRIPT
  195. if (scriptFile_)
  196. {
  197. // Execute the optional stop function
  198. if (scriptFile_->GetFunction("void Stop()"))
  199. scriptFile_->Execute("void Stop()");
  200. }
  201. #else
  202. if (false)
  203. {
  204. }
  205. #endif
  206. #ifdef URHO3D_LUA
  207. else
  208. {
  209. LuaScript* luaScript = GetSubsystem<LuaScript>();
  210. if (luaScript && luaScript->GetFunction("Stop", true))
  211. luaScript->ExecuteFunction("Stop");
  212. }
  213. #endif
  214. }
  215. void Urho3DPlayer::HandleScriptReloadStarted(StringHash eventType, VariantMap& eventData)
  216. {
  217. #ifdef URHO3D_ANGELSCRIPT
  218. if (scriptFile_->GetFunction("void Stop()"))
  219. scriptFile_->Execute("void Stop()");
  220. #endif
  221. }
  222. void Urho3DPlayer::HandleScriptReloadFinished(StringHash eventType, VariantMap& eventData)
  223. {
  224. #ifdef URHO3D_ANGELSCRIPT
  225. // Restart the script application after reload
  226. if (!scriptFile_->Execute("void Start()"))
  227. {
  228. scriptFile_.Reset();
  229. ErrorExit();
  230. }
  231. #endif
  232. }
  233. void Urho3DPlayer::HandleScriptReloadFailed(StringHash eventType, VariantMap& eventData)
  234. {
  235. #ifdef URHO3D_ANGELSCRIPT
  236. scriptFile_.Reset();
  237. ErrorExit();
  238. #endif
  239. }
  240. void Urho3DPlayer::GetScriptFileName()
  241. {
  242. const Vector<String>& arguments = GetArguments();
  243. if (arguments.Size() && arguments[0][0] != '-')
  244. scriptFileName_ = GetInternalPath(arguments[0]);
  245. }