WindowSettingsDemo.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. //
  2. // Copyright (c) 2008-2020 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 <Urho3D/Core/CoreEvents.h>
  23. #include <Urho3D/Engine/Engine.h>
  24. #include <Urho3D/Graphics/Graphics.h>
  25. #include <Urho3D/Graphics/GraphicsEvents.h>
  26. #include <Urho3D/Graphics/Material.h>
  27. #include <Urho3D/Graphics/Model.h>
  28. #include <Urho3D/Graphics/Octree.h>
  29. #include <Urho3D/Graphics/StaticModel.h>
  30. #include <Urho3D/Graphics/Texture2D.h>
  31. #include <Urho3D/Graphics/Zone.h>
  32. #include <Urho3D/Input/Input.h>
  33. #include <Urho3D/Resource/ResourceCache.h>
  34. #include <Urho3D/UI/Button.h>
  35. #include <Urho3D/UI/CheckBox.h>
  36. #include <Urho3D/UI/DropDownList.h>
  37. #include <Urho3D/UI/LineEdit.h>
  38. #include <Urho3D/UI/Text.h>
  39. #include <Urho3D/UI/ToolTip.h>
  40. #include <Urho3D/UI/UI.h>
  41. #include <Urho3D/UI/UIEvents.h>
  42. #include <Urho3D/UI/Window.h>
  43. #include "WindowSettingsDemo.h"
  44. #include <Urho3D/DebugNew.h>
  45. URHO3D_DEFINE_APPLICATION_MAIN(WindowSettingsDemo)
  46. WindowSettingsDemo::WindowSettingsDemo(Context* context)
  47. : Sample(context)
  48. , uiRoot_(GetSubsystem<UI>()->GetRoot())
  49. {
  50. }
  51. void WindowSettingsDemo::Start()
  52. {
  53. // Execute base class startup
  54. Sample::Start();
  55. // Enable OS cursor
  56. GetSubsystem<Input>()->SetMouseVisible(true);
  57. // Load XML file containing default UI style sheet
  58. auto* cache = GetSubsystem<ResourceCache>();
  59. auto* style = cache->GetResource<XMLFile>("UI/DefaultStyle.xml");
  60. // Set the loaded style as default style
  61. uiRoot_->SetDefaultStyle(style);
  62. // Create window with settings.
  63. InitSettings();
  64. SynchronizeSettings();
  65. SubscribeToEvent(E_SCREENMODE,
  66. [this](StringHash /*eventType*/, const VariantMap& /*eventData*/)
  67. {
  68. SynchronizeSettings();
  69. });
  70. // Set the mouse mode to use in the sample
  71. Sample::InitMouseMode(MM_FREE);
  72. // Create scene
  73. CreateScene();
  74. // Setup viewport
  75. auto* renderer = GetSubsystem<Renderer>();
  76. SharedPtr<Viewport> viewport(new Viewport(context_, scene_, cameraNode_->GetComponent<Camera>()));
  77. renderer->SetViewport(0, viewport);
  78. }
  79. void WindowSettingsDemo::CreateScene()
  80. {
  81. auto* cache = GetSubsystem<ResourceCache>();
  82. scene_ = new Scene(context_);
  83. scene_->CreateComponent<Octree>();
  84. auto* zone = scene_->CreateComponent<Zone>();
  85. zone->SetAmbientColor(Color::WHITE);
  86. // Create 3D object
  87. Node* objectNode = scene_->CreateChild("Object");
  88. objectNode->SetRotation(Quaternion(45.0f, 45.0f, 45.0f));
  89. auto* objectModel = objectNode->CreateComponent<StaticModel>();
  90. objectModel->SetModel(cache->GetResource<Model>("Models/Box.mdl"));
  91. objectModel->SetMaterial(cache->GetResource<Material>("Materials/Stone.xml"));
  92. // Create camera
  93. cameraNode_ = scene_->CreateChild("Camera");
  94. cameraNode_->CreateComponent<Camera>();
  95. cameraNode_->SetPosition(Vector3(0.0f, 0.0f, -4.0f));
  96. // Rotate object
  97. SubscribeToEvent(scene_, E_SCENEUPDATE,
  98. [objectNode](StringHash /*eventType*/, VariantMap& eventData)
  99. {
  100. const float timeStep = eventData[SceneUpdate::P_TIMESTEP].GetFloat();
  101. objectNode->Rotate(Quaternion(0.0f, 20.0f * timeStep, 0.0f), TS_WORLD);
  102. });
  103. }
  104. void WindowSettingsDemo::InitSettings()
  105. {
  106. auto* graphics = GetSubsystem<Graphics>();
  107. // Create the Window and add it to the UI's root node
  108. window_ = uiRoot_->CreateChild<Window>("Window");
  109. // Set Window size and layout settings
  110. window_->SetPosition(128, 128);
  111. window_->SetMinWidth(300);
  112. window_->SetLayout(LM_VERTICAL, 6, IntRect(6, 6, 6, 6));
  113. window_->SetMovable(true);
  114. window_->SetStyleAuto();
  115. // Create the Window title Text
  116. auto* windowTitle = window_->CreateChild<Text>("WindowTitle");
  117. windowTitle->SetText("Window Settings");
  118. windowTitle->SetStyleAuto();
  119. // Create monitor selector
  120. monitorControl_ = window_->CreateChild<DropDownList>("Monitor");
  121. monitorControl_->SetMinHeight(24);
  122. monitorControl_->SetStyleAuto();
  123. for (int i = 0; i < graphics->GetMonitorCount(); ++i)
  124. {
  125. auto text = MakeShared<Text>(context_);
  126. text->SetText(ToString("Monitor %d", i));
  127. text->SetMinWidth(CeilToInt(text->GetRowWidth(0) + 10));
  128. monitorControl_->AddItem(text);
  129. text->SetStyleAuto();
  130. }
  131. // Create resolution selector
  132. resolutionControl_ = window_->CreateChild<DropDownList>("Resolution");
  133. resolutionControl_->SetMinHeight(24);
  134. resolutionControl_->SetStyleAuto();
  135. auto resolutionPlaceholder = MakeShared<Text>(context_);
  136. resolutionPlaceholder->SetText("[Cannot fill list of resolutions]");
  137. resolutionPlaceholder->SetMinWidth(CeilToInt(resolutionPlaceholder->GetRowWidth(0) + 10));
  138. resolutionControl_->AddItem(resolutionPlaceholder);
  139. resolutionPlaceholder->SetStyleAuto();
  140. // Create fullscreen controller
  141. auto* fullscreenFrame = window_->CreateChild<UIElement>("Fullscreen Frame");
  142. fullscreenFrame->SetMinHeight(24);
  143. fullscreenFrame->SetLayout(LM_HORIZONTAL, 6);
  144. fullscreenControl_ = fullscreenFrame->CreateChild<CheckBox>("Fullscreen Control");
  145. fullscreenControl_->SetStyleAuto();
  146. auto* fullscreenText = fullscreenFrame->CreateChild<Text>("Fullscreen Label");
  147. fullscreenText->SetText("Fullscreen");
  148. fullscreenText->SetMinWidth(CeilToInt(fullscreenText->GetRowWidth(0) + 10));
  149. fullscreenText->SetStyleAuto();
  150. // Create borderless controller
  151. auto* borderlessFrame = window_->CreateChild<UIElement>("Borderless Frame");
  152. borderlessFrame->SetMinHeight(24);
  153. borderlessFrame->SetLayout(LM_HORIZONTAL, 6);
  154. borderlessControl_ = borderlessFrame->CreateChild<CheckBox>("Borderless Control");
  155. borderlessControl_->SetStyleAuto();
  156. auto* borderlessText = borderlessFrame->CreateChild<Text>("Borderless Label");
  157. borderlessText->SetText("Borderless");
  158. borderlessText->SetMinWidth(CeilToInt(borderlessText->GetRowWidth(0) + 10));
  159. borderlessText->SetStyleAuto();
  160. // Create resizable controller
  161. auto* resizableFrame = window_->CreateChild<UIElement>("Resizable Frame");
  162. resizableFrame->SetMinHeight(24);
  163. resizableFrame->SetLayout(LM_HORIZONTAL, 6);
  164. resizableControl_ = resizableFrame->CreateChild<CheckBox>("Resizable Control");
  165. resizableControl_->SetStyleAuto();
  166. auto* resizableText = resizableFrame->CreateChild<Text>("Resizable Label");
  167. resizableText->SetText("Resizable");
  168. resizableText->SetMinWidth(CeilToInt(resizableText->GetRowWidth(0) + 10));
  169. resizableText->SetStyleAuto();
  170. // Create resizable controller
  171. auto* vsyncFrame = window_->CreateChild<UIElement>("V-Sync Frame");
  172. vsyncFrame->SetMinHeight(24);
  173. vsyncFrame->SetLayout(LM_HORIZONTAL, 6);
  174. vsyncControl_ = vsyncFrame->CreateChild<CheckBox>("V-Sync Control");
  175. vsyncControl_->SetStyleAuto();
  176. auto* vsyncText = vsyncFrame->CreateChild<Text>("V-Sync Label");
  177. vsyncText->SetText("V-Sync");
  178. vsyncText->SetMinWidth(CeilToInt(vsyncText->GetRowWidth(0) + 10));
  179. vsyncText->SetStyleAuto();
  180. // Create multi-sample controller from 1 (= 2^0) to 16 (= 2^4)
  181. multiSampleControl_ = window_->CreateChild<DropDownList>("Multi-Sample Control");
  182. multiSampleControl_->SetMinHeight(24);
  183. multiSampleControl_->SetStyleAuto();
  184. for (int i = 0; i <= 4; ++i)
  185. {
  186. auto text = MakeShared<Text>(context_);
  187. text->SetText(i == 0 ? "No MSAA" : ToString("MSAA x%d", 1 << i));
  188. text->SetMinWidth(CeilToInt(text->GetRowWidth(0) + 10));
  189. multiSampleControl_->AddItem(text);
  190. text->SetStyleAuto();
  191. }
  192. // Create "Apply" button
  193. auto* applyButton = window_->CreateChild<Button>("Apply");
  194. applyButton->SetLayout(LM_HORIZONTAL, 6, IntRect(6, 6, 6, 6));
  195. applyButton->SetStyleAuto();
  196. auto* applyButtonText = applyButton->CreateChild<Text>("Apply Text");
  197. applyButtonText->SetAlignment(HA_CENTER, VA_CENTER);
  198. applyButtonText->SetText("Apply");
  199. applyButtonText->SetStyleAuto();
  200. applyButton->SetFixedWidth(CeilToInt(applyButtonText->GetRowWidth(0) + 20));
  201. applyButton->SetFixedHeight(30);
  202. // Apply settings when "Apply" button is clicked
  203. SubscribeToEvent(applyButton, E_RELEASED,
  204. [this, graphics](StringHash /*eventType*/, const VariantMap& /*eventData*/)
  205. {
  206. const unsigned monitor = monitorControl_->GetSelection();
  207. if (monitor == M_MAX_UNSIGNED)
  208. return;
  209. const auto& resolutions = graphics->GetResolutions(monitor);
  210. const unsigned selectedResolution = resolutionControl_->GetSelection();
  211. if (selectedResolution >= resolutions.Size())
  212. return;
  213. const bool fullscreen = fullscreenControl_->IsChecked();
  214. const bool borderless = borderlessControl_->IsChecked();
  215. const bool resizable = resizableControl_->IsChecked();
  216. const bool vsync = vsyncControl_->IsChecked();
  217. const unsigned multiSampleSelection = multiSampleControl_->GetSelection();
  218. const int multiSample = multiSampleSelection == M_MAX_UNSIGNED ? 1 : static_cast<int>(1 << multiSampleSelection);
  219. // TODO: Expose these options too?
  220. const bool highDPI = graphics->GetHighDPI();
  221. const bool tripleBuffer = graphics->GetTripleBuffer();
  222. const int width = resolutions[selectedResolution].x_;
  223. const int height = resolutions[selectedResolution].y_;
  224. const int refreshRate = resolutions[selectedResolution].z_;
  225. graphics->SetMode(width, height, fullscreen, borderless, resizable, highDPI, vsync, tripleBuffer, multiSample, monitor, refreshRate);
  226. });
  227. }
  228. void WindowSettingsDemo::SynchronizeSettings()
  229. {
  230. auto* graphics = GetSubsystem<Graphics>();
  231. // Synchronize monitor
  232. const unsigned currentMonitor = graphics->GetMonitor();
  233. monitorControl_->SetSelection(currentMonitor);
  234. // Synchronize resolution list
  235. resolutionControl_->RemoveAllItems();
  236. const auto& resolutions = graphics->GetResolutions(currentMonitor);
  237. for (const IntVector3& resolution : resolutions)
  238. {
  239. auto resolutionEntry = MakeShared<Text>(context_);
  240. resolutionEntry->SetText(ToString("%dx%d, %d Hz", resolution.x_, resolution.y_, resolution.z_));
  241. resolutionEntry->SetMinWidth(CeilToInt(resolutionEntry->GetRowWidth(0) + 10));
  242. resolutionControl_->AddItem(resolutionEntry);
  243. resolutionEntry->SetStyleAuto();
  244. }
  245. // Synchronize selected resolution
  246. const unsigned currentResolution = graphics->FindBestResolutionIndex(currentMonitor,
  247. graphics->GetWidth(), graphics->GetHeight(), graphics->GetRefreshRate());
  248. resolutionControl_->SetSelection(currentResolution);
  249. // Synchronize fullscreen and borderless flags
  250. fullscreenControl_->SetChecked(graphics->GetFullscreen());
  251. borderlessControl_->SetChecked(graphics->GetBorderless());
  252. resizableControl_->SetChecked(graphics->GetResizable());
  253. vsyncControl_->SetChecked(graphics->GetVSync());
  254. // Synchronize MSAA
  255. for (unsigned i = 0; i <= 4; ++i)
  256. {
  257. if (graphics->GetMultiSample() == static_cast<int>(1 << i))
  258. multiSampleControl_->SetSelection(i);
  259. }
  260. }