Sample.inl 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  1. //
  2. // Copyright (c) 2008-2014 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. #include "Application.h"
  23. #include "Camera.h"
  24. #include "Console.h"
  25. #include "Cursor.h"
  26. #include "DebugHud.h"
  27. #include "Engine.h"
  28. #include "FileSystem.h"
  29. #include "Graphics.h"
  30. #include "Input.h"
  31. #include "InputEvents.h"
  32. #include "Renderer.h"
  33. #include "ResourceCache.h"
  34. #include "Scene.h"
  35. #include "SceneEvents.h"
  36. #include "Sprite.h"
  37. #include "Texture2D.h"
  38. #include "Timer.h"
  39. #include "UI.h"
  40. #include "XMLFile.h"
  41. Sample::Sample(Context* context) :
  42. Application(context),
  43. yaw_(0.0f),
  44. pitch_(0.0f),
  45. touchEnabled_(false),
  46. screenJoystickIndex_(M_MAX_UNSIGNED),
  47. screenJoystickSettingsIndex_(M_MAX_UNSIGNED),
  48. paused_(false)
  49. {
  50. }
  51. void Sample::Setup()
  52. {
  53. // Modify engine startup parameters
  54. engineParameters_["WindowTitle"] = GetTypeName();
  55. engineParameters_["LogName"] = GetSubsystem<FileSystem>()->GetAppPreferencesDir("urho3d", "logs") + GetTypeName() + ".log";
  56. engineParameters_["FullScreen"] = false;
  57. engineParameters_["Headless"] = false;
  58. }
  59. void Sample::Start()
  60. {
  61. if (GetPlatform() == "Android" || GetPlatform() == "iOS")
  62. // On mobile platform, enable touch by adding a screen joystick
  63. InitTouchInput();
  64. else if (GetSubsystem<Input>()->GetNumJoysticks() == 0)
  65. // On desktop platform, do not detect touch when we already got a joystick
  66. SubscribeToEvent(E_TOUCHBEGIN, HANDLER(Sample, HandleTouchBegin));
  67. // Create logo
  68. CreateLogo();
  69. // Set custom window Title & Icon
  70. SetWindowTitleAndIcon();
  71. // Create console and debug HUD
  72. CreateConsoleAndDebugHud();
  73. // Subscribe key down event
  74. SubscribeToEvent(E_KEYDOWN, HANDLER(Sample, HandleKeyDown));
  75. // Subscribe scene update event
  76. SubscribeToEvent(E_SCENEUPDATE, HANDLER(Sample, HandleSceneUpdate));
  77. }
  78. void Sample::InitTouchInput()
  79. {
  80. touchEnabled_ = true;
  81. ResourceCache* cache = GetSubsystem<ResourceCache>();
  82. Input* input = GetSubsystem<Input>();
  83. XMLFile* layout = cache->GetResource<XMLFile>("UI/ScreenJoystick_Samples.xml");
  84. const String& patchString = GetScreenJoystickPatchString();
  85. if (!patchString.Empty())
  86. {
  87. // Patch the screen joystick layout further on demand
  88. SharedPtr<XMLFile> patchFile(new XMLFile(context_));
  89. if (patchFile->FromString(patchString))
  90. layout->Patch(patchFile);
  91. }
  92. screenJoystickIndex_ = input->AddScreenJoystick(layout, cache->GetResource<XMLFile>("UI/DefaultStyle.xml"));
  93. input->SetScreenJoystickVisible(screenJoystickSettingsIndex_, true);
  94. }
  95. void Sample::SetLogoVisible(bool enable)
  96. {
  97. if (logoSprite_)
  98. logoSprite_->SetVisible(enable);
  99. }
  100. void Sample::CreateLogo()
  101. {
  102. // Get logo texture
  103. ResourceCache* cache = GetSubsystem<ResourceCache>();
  104. Texture2D* logoTexture = cache->GetResource<Texture2D>("Textures/LogoLarge.png");
  105. if (!logoTexture)
  106. return;
  107. // Create logo sprite and add to the UI layout
  108. UI* ui = GetSubsystem<UI>();
  109. logoSprite_ = ui->GetRoot()->CreateChild<Sprite>();
  110. // Set logo sprite texture
  111. logoSprite_->SetTexture(logoTexture);
  112. int textureWidth = logoTexture->GetWidth();
  113. int textureHeight = logoTexture->GetHeight();
  114. // Set logo sprite scale
  115. logoSprite_->SetScale(256.0f / textureWidth);
  116. // Set logo sprite size
  117. logoSprite_->SetSize(textureWidth, textureHeight);
  118. // Set logo sprite hot spot
  119. logoSprite_->SetHotSpot(0, textureHeight);
  120. // Set logo sprite alignment
  121. logoSprite_->SetAlignment(HA_LEFT, VA_BOTTOM);
  122. // Make logo not fully opaque to show the scene underneath
  123. logoSprite_->SetOpacity(0.75f);
  124. // Set a low priority for the logo so that other UI elements can be drawn on top
  125. logoSprite_->SetPriority(-100);
  126. }
  127. void Sample::SetWindowTitleAndIcon()
  128. {
  129. ResourceCache* cache = GetSubsystem<ResourceCache>();
  130. Graphics* graphics = GetSubsystem<Graphics>();
  131. Image* icon = cache->GetResource<Image>("Textures/UrhoIcon.png");
  132. graphics->SetWindowIcon(icon);
  133. graphics->SetWindowTitle("Urho3D Sample");
  134. }
  135. void Sample::CreateConsoleAndDebugHud()
  136. {
  137. // Get default style
  138. ResourceCache* cache = GetSubsystem<ResourceCache>();
  139. XMLFile* xmlFile = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
  140. // Create console
  141. Console* console = engine_->CreateConsole();
  142. console->SetDefaultStyle(xmlFile);
  143. console->GetBackground()->SetOpacity(0.8f);
  144. // Create debug HUD.
  145. DebugHud* debugHud = engine_->CreateDebugHud();
  146. debugHud->SetDefaultStyle(xmlFile);
  147. }
  148. void Sample::HandleKeyDown(StringHash eventType, VariantMap& eventData)
  149. {
  150. using namespace KeyDown;
  151. int key = eventData[P_KEY].GetInt();
  152. // Close console (if open) or exit when ESC is pressed
  153. if (key == KEY_ESC)
  154. {
  155. Console* console = GetSubsystem<Console>();
  156. if (console->IsVisible())
  157. console->SetVisible(false);
  158. else
  159. engine_->Exit();
  160. }
  161. // Toggle console with F1
  162. else if (key == KEY_F1)
  163. GetSubsystem<Console>()->Toggle();
  164. // Toggle debug HUD with F2
  165. else if (key == KEY_F2)
  166. GetSubsystem<DebugHud>()->ToggleAll();
  167. // Common rendering quality controls, only when UI has no focused element
  168. else if (!GetSubsystem<UI>()->GetFocusElement())
  169. {
  170. Renderer* renderer = GetSubsystem<Renderer>();
  171. // Preferences / Pause
  172. if (key == KEY_SELECT && touchEnabled_)
  173. {
  174. paused_ = !paused_;
  175. Input* input = GetSubsystem<Input>();
  176. if (screenJoystickSettingsIndex_ == M_MAX_UNSIGNED)
  177. {
  178. // Lazy initialization
  179. ResourceCache* cache = GetSubsystem<ResourceCache>();
  180. screenJoystickSettingsIndex_ = input->AddScreenJoystick(cache->GetResource<XMLFile>("UI/ScreenJoystickSettings_Samples.xml"), cache->GetResource<XMLFile>("UI/DefaultStyle.xml"));
  181. }
  182. else
  183. input->SetScreenJoystickVisible(screenJoystickSettingsIndex_, paused_);
  184. }
  185. // Texture quality
  186. else if (key == '1')
  187. {
  188. int quality = renderer->GetTextureQuality();
  189. ++quality;
  190. if (quality > QUALITY_HIGH)
  191. quality = QUALITY_LOW;
  192. renderer->SetTextureQuality(quality);
  193. }
  194. // Material quality
  195. else if (key == '2')
  196. {
  197. int quality = renderer->GetMaterialQuality();
  198. ++quality;
  199. if (quality > QUALITY_HIGH)
  200. quality = QUALITY_LOW;
  201. renderer->SetMaterialQuality(quality);
  202. }
  203. // Specular lighting
  204. else if (key == '3')
  205. renderer->SetSpecularLighting(!renderer->GetSpecularLighting());
  206. // Shadow rendering
  207. else if (key == '4')
  208. renderer->SetDrawShadows(!renderer->GetDrawShadows());
  209. // Shadow map resolution
  210. else if (key == '5')
  211. {
  212. int shadowMapSize = renderer->GetShadowMapSize();
  213. shadowMapSize *= 2;
  214. if (shadowMapSize > 2048)
  215. shadowMapSize = 512;
  216. renderer->SetShadowMapSize(shadowMapSize);
  217. }
  218. // Shadow depth and filtering quality
  219. else if (key == '6')
  220. {
  221. int quality = renderer->GetShadowQuality();
  222. ++quality;
  223. if (quality > SHADOWQUALITY_HIGH_24BIT)
  224. quality = SHADOWQUALITY_LOW_16BIT;
  225. renderer->SetShadowQuality(quality);
  226. }
  227. // Occlusion culling
  228. else if (key == '7')
  229. {
  230. bool occlusion = renderer->GetMaxOccluderTriangles() > 0;
  231. occlusion = !occlusion;
  232. renderer->SetMaxOccluderTriangles(occlusion ? 5000 : 0);
  233. }
  234. // Instancing
  235. else if (key == '8')
  236. renderer->SetDynamicInstancing(!renderer->GetDynamicInstancing());
  237. // Take screenshot
  238. else if (key == '9')
  239. {
  240. Graphics* graphics = GetSubsystem<Graphics>();
  241. Image screenshot(context_);
  242. graphics->TakeScreenShot(screenshot);
  243. // Here we save in the Data folder with date and time appended
  244. screenshot.SavePNG(GetSubsystem<FileSystem>()->GetProgramDir() + "Data/Screenshot_" +
  245. Time::GetTimeStamp().Replaced(':', '_').Replaced('.', '_').Replaced(' ', '_') + ".png");
  246. }
  247. }
  248. }
  249. void Sample::HandleSceneUpdate(StringHash eventType, VariantMap& eventData)
  250. {
  251. // Move the camera by touch, if the camera node is initialized by descendant sample class
  252. if (touchEnabled_ && cameraNode_)
  253. {
  254. Input* input = GetSubsystem<Input>();
  255. for (unsigned i = 0; i < input->GetNumTouches(); ++i)
  256. {
  257. TouchState* state = input->GetTouch(i);
  258. if (!state->touchedElement_) // Touch on empty space
  259. {
  260. if (state->delta_.x_ ||state->delta_.y_)
  261. {
  262. Camera* camera = cameraNode_->GetComponent<Camera>();
  263. if (!camera)
  264. return;
  265. Graphics* graphics = GetSubsystem<Graphics>();
  266. yaw_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.x_;
  267. pitch_ += TOUCH_SENSITIVITY * camera->GetFov() / graphics->GetHeight() * state->delta_.y_;
  268. // Construct new orientation for the camera scene node from yaw and pitch; roll is fixed to zero
  269. cameraNode_->SetRotation(Quaternion(pitch_, yaw_, 0.0f));
  270. }
  271. else
  272. {
  273. // Move the cursor to the touch position
  274. Cursor* cursor = GetSubsystem<UI>()->GetCursor();
  275. if (cursor && cursor->IsVisible())
  276. cursor->SetPosition(state->position_);
  277. }
  278. }
  279. }
  280. }
  281. }
  282. void Sample::HandleTouchBegin(StringHash eventType, VariantMap& eventData)
  283. {
  284. // On some platforms like Windows the presence of touch input can only be detected dynamically
  285. InitTouchInput();
  286. UnsubscribeFromEvent("TouchBegin");
  287. }