Main.cpp 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  1. //__________________________ Banshee Project - A modern game development toolkit _________________________________//
  2. //_____________________________________ www.banshee-project.com __________________________________________________//
  3. //________________________ Copyright (c) 2014 Marko Pintera. All rights reserved. ________________________________//
  4. #include <windows.h>
  5. #include "BsApplication.h"
  6. #include "BsImporter.h"
  7. #include "BsGpuProgramImportOptions.h"
  8. #include "BsTextureImportOptions.h"
  9. #include "BsMaterial.h"
  10. #include "BsShader.h"
  11. #include "BsTechnique.h"
  12. #include "BsPass.h"
  13. #include "BsCoreThreadAccessor.h"
  14. #include "BsApplication.h"
  15. #include "BsVirtualInput.h"
  16. #include "BsCamera.h"
  17. #include "BsRenderable.h"
  18. #include "BsGUIWidget.h"
  19. #include "BsGUIArea.h"
  20. #include "BsGUILayoutX.h"
  21. #include "BsGUILayoutY.h"
  22. #include "BsGUISpace.h"
  23. #include "BsGUILabel.h"
  24. #include "BsGUIButton.h"
  25. #include "BsGUIListBox.h"
  26. #include "BsBuiltinResources.h"
  27. #include "BsRTTIType.h"
  28. #include "BsHString.h"
  29. #include "BsRenderWindow.h"
  30. #include "BsSceneObject.h"
  31. #include "BsCoreThread.h"
  32. #include "BsProfilerOverlay.h"
  33. #include "BsRenderer.h"
  34. #include "BsResources.h"
  35. #include "CameraFlyer.h"
  36. namespace BansheeEngine
  37. {
  38. UINT32 windowResWidth = 1280;
  39. UINT32 windowResHeight = 720;
  40. /**
  41. * Imports all of our assets and prepares GameObject that handle the example logic.
  42. */
  43. void setUpExample();
  44. /**
  45. * Import mesh/texture/GPU programs used by the example.
  46. */
  47. void importAssets(HMesh& model, HTexture& texture, HGpuProgram& fragmentGPUProg, HGpuProgram& vertexGPUProg);
  48. /**
  49. * Create a material used by our example model.
  50. */
  51. HMaterial createMaterial(const HTexture& texture, const HGpuProgram& vertexGPUProg, const HGpuProgram& fragmentGPUProg);
  52. /**
  53. * Set up example scene objects.
  54. */
  55. void setUp3DScene(const HMesh& mesh, const HMaterial& material);
  56. /**
  57. * Set up example GUI.
  58. */
  59. void setUpGUI();
  60. /**
  61. * Set up input configuration and callbacks.
  62. */
  63. void setUpInput();
  64. /**
  65. * Toggles the primary window between full-screen and windowed mode.
  66. */
  67. void toggleFullscreen();
  68. /**
  69. * Called whenever the main render window is resized.
  70. */
  71. void renderWindowResized();
  72. /**
  73. * Called when the selected video mode changes in the video mode list box.
  74. */
  75. void videoModeChanged(UINT32 idx);
  76. /**
  77. * Triggered whenever a virtual button is released.
  78. */
  79. void buttonUp(const VirtualButton& button, UINT32 deviceIdx);
  80. }
  81. using namespace BansheeEngine;
  82. /**
  83. * Main entry point into the application.
  84. */
  85. int CALLBACK WinMain(
  86. _In_ HINSTANCE hInstance,
  87. _In_ HINSTANCE hPrevInstance,
  88. _In_ LPSTR lpCmdLine,
  89. _In_ int nCmdShow
  90. )
  91. {
  92. // Descriptor used for initializing the primary application window.
  93. RENDER_WINDOW_DESC renderWindowDesc;
  94. renderWindowDesc.videoMode = VideoMode(windowResWidth, windowResHeight);
  95. renderWindowDesc.title = "Banshee Example App";
  96. renderWindowDesc.fullscreen = false;
  97. // Initializes the application with primary window defined as above and DirectX 11 render system.
  98. // You may use other render systems than DirectX 11, however this example for simplicity only uses DirectX 11.
  99. // If you wanted other render systems you would need to create separate shaders for them and import them
  100. // along with (or replace) the DX11 ones.
  101. Application::startUp(renderWindowDesc, RenderSystemPlugin::DX11);
  102. // Imports all of ours assets and prepares GameObject that handle the example logic.
  103. setUpExample();
  104. // Runs the main loop that does most of the work. This method will exit when user closes the main
  105. // window or exits in some other way.
  106. Application::instance().runMainLoop();
  107. Application::shutDown();
  108. return 0;
  109. }
  110. namespace BansheeEngine
  111. {
  112. Path exampleModelPath = "..\\..\\Data\\Examples\\Dragon.fbx";
  113. Path exampleTexturePath = "..\\..\\Data\\Examples\\Dragon.tga";
  114. Path exampleFragmentShaderPath = "..\\..\\Data\\Examples\\example_fs.gpuprog";
  115. Path exampleVertexShaderPath = "..\\..\\Data\\Examples\\example_vs.gpuprog";
  116. GUIButton* toggleFullscreenButton = nullptr;
  117. bool fullscreen = false;
  118. const VideoMode* selectedVideoMode = nullptr;
  119. Vector<const VideoMode*> videoModes;
  120. HCamera sceneCamera;
  121. HProfilerOverlay profilerOverlay;
  122. VirtualButton toggleCPUProfilerBtn;
  123. VirtualButton toggleGPUProfilerBtn;
  124. bool cpuProfilerActive = false;
  125. bool gpuProfilerActive = false;
  126. void setUpExample()
  127. {
  128. HMesh exampleModel;
  129. HTexture exampleTexture;
  130. HGpuProgram exampleFragmentGPUProg;
  131. HGpuProgram exampleVertexGPUProg;
  132. importAssets(exampleModel, exampleTexture, exampleFragmentGPUProg, exampleVertexGPUProg);
  133. HMaterial exampleMaterial = createMaterial(exampleTexture, exampleVertexGPUProg, exampleFragmentGPUProg);
  134. setUp3DScene(exampleModel, exampleMaterial);
  135. setUpGUI();
  136. setUpInput();
  137. }
  138. void importAssets(HMesh& model, HTexture& texture, HGpuProgram& fragmentGPUProg, HGpuProgram& vertexGPUProg)
  139. {
  140. // Import mesh, texture and shader from the disk. In a normal application you would want to save the imported assets
  141. // so next time the application is ran you can just load them directly. This can be done with Resources::save/load.
  142. // Import an FBX mesh.
  143. model = Importer::instance().import<Mesh>(exampleModelPath);
  144. // When importing you may specify optional import options that control how is the asset imported.
  145. ImportOptionsPtr textureImportOptions = Importer::instance().createImportOptions(exampleTexturePath);
  146. // rtti_is_of_type checks if the import options are of valid type, in case the provided path is pointing to a non-texture resource.
  147. // This is similar to dynamic_cast but uses Banshee internal RTTI system for type checking.
  148. if (rtti_is_of_type<TextureImportOptions>(textureImportOptions))
  149. {
  150. TextureImportOptions* importOptions = static_cast<TextureImportOptions*>(textureImportOptions.get());
  151. // We want maximum number of mipmaps to be generated
  152. importOptions->setGenerateMipmaps(true);
  153. }
  154. // Import texture with specified import options
  155. texture = Importer::instance().import<Texture>(exampleTexturePath, textureImportOptions);
  156. // Create import options for fragment GPU program
  157. ImportOptionsPtr gpuProgImportOptions = Importer::instance().createImportOptions(exampleFragmentShaderPath);
  158. if (rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
  159. {
  160. GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
  161. // Name of the entry function in the GPU program
  162. importOptions->setEntryPoint("ps_main");
  163. // Language the GPU program is written in. Can only be hlsl for DX11
  164. importOptions->setLanguage("hlsl");
  165. // GPU program profile specifying what feature-set the shader code uses.
  166. importOptions->setProfile(GPP_PS_4_0);
  167. // Type of the shader.
  168. importOptions->setType(GPT_FRAGMENT_PROGRAM);
  169. }
  170. // Import fragment GPU program
  171. fragmentGPUProg = Importer::instance().import<GpuProgram>(exampleFragmentShaderPath, gpuProgImportOptions);
  172. // Create import options for vertex GPU program. Similar as above.
  173. gpuProgImportOptions = Importer::instance().createImportOptions(exampleVertexShaderPath);
  174. if (rtti_is_of_type<GpuProgramImportOptions>(gpuProgImportOptions))
  175. {
  176. GpuProgramImportOptions* importOptions = static_cast<GpuProgramImportOptions*>(gpuProgImportOptions.get());
  177. importOptions->setEntryPoint("vs_main");
  178. importOptions->setLanguage("hlsl");
  179. importOptions->setProfile(GPP_VS_4_0);
  180. importOptions->setType(GPT_VERTEX_PROGRAM);
  181. }
  182. // Import vertex GPU program
  183. vertexGPUProg = Importer::instance().import<GpuProgram>(exampleVertexShaderPath, gpuProgImportOptions);
  184. }
  185. HMaterial createMaterial(const HTexture& texture, const HGpuProgram& vertexGPUProg, const HGpuProgram& fragmentGPUProg)
  186. {
  187. /************************************************************************/
  188. /* CREATE SHADER */
  189. /************************************************************************/
  190. // Create a shader that references our vertex and fragment GPU programs, and set
  191. // up shader input parameters.
  192. ShaderPtr exampleShader = Shader::create("ExampleShader");
  193. // Set up shader parameters and renderer semantics.
  194. // Renderer semantics allow our renderer to automatically populate certain shader parameters (e.g. a world view projection matrix).
  195. // These semantics are purely optional and depend on the renderer used. Certain renderers expect certain semantics to be set up
  196. // otherwise they will not render the objects. You always have the option to populate all the parameters manually, but in this example
  197. // we go with the semantics route as it allows for a "set up and forget" approach.
  198. // Add a world view projection matrix parameter, which will be populated by the renderer.
  199. // We map our shader parameter name to the actual GPU program variable, both being "matWorldViewProj" in this case.
  200. exampleShader->addParameter("matWorldViewProj", "matWorldViewProj", GPDT_MATRIX_4X4, RPS_WorldViewProjTfrm);
  201. // Add a sampler and a texture semantic that we will populate manually.
  202. exampleShader->addParameter("samp", "samp", GPOT_SAMPLER2D);
  203. exampleShader->addParameter("tex", "tex", GPOT_TEXTURE2D);
  204. // Our GPU programs use parameter blocks (constant buffers in DX11 lingo). Here we notify the renderer
  205. // that this particular parameter block contains object-specific data (like the world view projection parameter
  206. // we defined above).
  207. exampleShader->setParamBlockAttribs("PerObject", true, GPBU_DYNAMIC, RBS_PerObject);
  208. /************************************************************************/
  209. /* CREATE MATERIAL */
  210. /************************************************************************/
  211. // Create a shader technique. Shader can have many different techniques and the renderer will automatically
  212. // use the most appropriate technique depending on the active renderer and render system. e.g. you can have different
  213. // techniques using HLSL9, HLSL11 and GLSL GPU programs for DirectX 9, DirectX 11 and OpenGL render systems respectively.
  214. TechniquePtr technique = exampleShader->addTechnique(RenderSystemDX11, RendererDefault);
  215. // Add a new pass to the technique. Each technique can have multiple passes that allow you to render the same
  216. // object multiple times using different GPU programs.
  217. PassPtr pass = technique->addPass();
  218. pass->setVertexProgram(vertexGPUProg);
  219. pass->setFragmentProgram(fragmentGPUProg);
  220. // And finally create a material with the newly created shader
  221. HMaterial exampleMaterial = Material::create(exampleShader);
  222. // And set the texture to be used by the "tex" shader parameter. We leave the "samp"
  223. // parameter at its defaults.
  224. exampleMaterial->setTexture("tex", texture);
  225. return exampleMaterial;
  226. }
  227. void setUp3DScene(const HMesh& mesh, const HMaterial& material)
  228. {
  229. /************************************************************************/
  230. /* SCENE OBJECT */
  231. /************************************************************************/
  232. // Now we create a scene object that has a position, orientation, scale and optionally
  233. // components to govern its logic. In this particular case we are creating a SceneObject
  234. // with a Renderable component which will render a mesh at the position of the scene object
  235. // with the provided material.
  236. // Create new scene object at (0, 0, 0)
  237. HSceneObject dragonSO = SceneObject::create("Dragon");
  238. // Attach the Renderable component and hook up the mesh we imported earlier,
  239. // and the material we created in the previous section.
  240. HRenderable renderable = dragonSO->addComponent<Renderable>();
  241. renderable->setMesh(mesh);
  242. renderable->setMaterial(material);
  243. /************************************************************************/
  244. /* CAMERA */
  245. /************************************************************************/
  246. // In order something to render on screen we need at least one camera.
  247. // Like before, we create a new scene object at (0, 0, 0).
  248. HSceneObject sceneCameraSO = SceneObject::create("SceneCamera");
  249. // Get the primary render window we need for creating the camera. Additionally
  250. // hook up a callback so we are notified when user resizes the window.
  251. RenderWindowPtr window = gApplication().getPrimaryWindow();
  252. window->onResized.connect(&renderWindowResized);
  253. // Add a Camera component that will output whatever it sees into that window
  254. // (You could also use a render texture or another window you created).
  255. sceneCamera = sceneCameraSO->addComponent<Camera>(window);
  256. // Set up camera component properties
  257. // Priority determines in what order are cameras rendered in case multiple cameras render to the same render target.
  258. // We raise the priority slightly because later in code we have defined a GUI camera that we want to render second.
  259. sceneCamera->setPriority(1);
  260. // Set closest distance that is visible. Anything below that is clipped.
  261. sceneCamera->setNearClipDistance(5);
  262. // Set aspect ratio depending on the current resolution
  263. sceneCamera->setAspectRatio(windowResWidth / (float)windowResHeight);
  264. // Add a CameraFlyer component that allows us to move the camera. See CameraFlyer for more information.
  265. sceneCameraSO->addComponent<CameraFlyer>();
  266. // Position and orient the camera scene object
  267. sceneCameraSO->setPosition(Vector3(-130.0f, 140.0f, 650.0f));
  268. sceneCameraSO->lookAt(Vector3(0, 0, 0));
  269. }
  270. void setUpInput()
  271. {
  272. // Register input configuration
  273. // Banshee allows you to use VirtualInput system which will map input device buttons
  274. // and axes to arbitrary names, which allows you to change input buttons without affecting
  275. // the code that uses it, since the code is only aware of the virtual names.
  276. // If you want more direct input, see Input class.
  277. auto inputConfig = VirtualInput::instance().getConfiguration();
  278. // Camera controls for buttons (digital 0-1 input, e.g. keyboard or gamepad button)
  279. inputConfig->registerButton("Forward", BC_W);
  280. inputConfig->registerButton("Back", BC_S);
  281. inputConfig->registerButton("Left", BC_A);
  282. inputConfig->registerButton("Right", BC_D);
  283. inputConfig->registerButton("Forward", BC_UP);
  284. inputConfig->registerButton("Back", BC_BACK);
  285. inputConfig->registerButton("Left", BC_LEFT);
  286. inputConfig->registerButton("Right", BC_RIGHT);
  287. inputConfig->registerButton("FastMove", BC_LSHIFT);
  288. inputConfig->registerButton("RotateCam", BC_MOUSE_RIGHT);
  289. // Camera controls for axes (analog input, e.g. mouse or gamepad thumbstick)
  290. // These return values in [-1.0, 1.0] range.
  291. inputConfig->registerAxis("Horizontal", VIRTUAL_AXIS_DESC((UINT32)InputAxis::MouseX));
  292. inputConfig->registerAxis("Vertical", VIRTUAL_AXIS_DESC((UINT32)InputAxis::MouseY));
  293. // Controls that toggle the profiler overlays
  294. inputConfig->registerButton("CPUProfilerOverlay", BC_F1);
  295. inputConfig->registerButton("GPUProfilerOverlay", BC_F2);
  296. // Cache the profiler overlay buttons so when a button is pressed we can quickly
  297. // use these to determine its the one we want
  298. toggleCPUProfilerBtn = VirtualButton("CPUProfilerOverlay");
  299. toggleGPUProfilerBtn = VirtualButton("GPUProfilerOverlay");
  300. // Hook up a callback that gets triggered whenever a virtual button is released
  301. VirtualInput::instance().onButtonUp.connect(&buttonUp);
  302. }
  303. void setUpGUI()
  304. {
  305. // Create a scene object that will contain GUI components
  306. HSceneObject guiSO = SceneObject::create("Example");
  307. // Get the primary render window we need for creating the camera.
  308. RenderWindowPtr window = gApplication().getPrimaryWindow();
  309. // First we want another camera that is responsible for rendering GUI
  310. HCamera guiCamera = guiSO->addComponent<Camera>(window);
  311. // Set up GUI camera properties.
  312. // We don't care about aspect ratio for GUI camera.
  313. guiCamera->setAspectRatio(1.0f);
  314. // This camera should ignore any Renderable objects in the scene
  315. guiCamera->setIgnoreSceneRenderables(true);
  316. // Don't clear this camera as that would clear anything the main camera has rendered.
  317. guiCamera->getViewport()->setRequiresClear(false, false, false);
  318. // Add a GUIWidget, the top-level GUI component, parent to all GUI elements. GUI widgets
  319. // require you to specify a viewport that they will output rendered GUI elements to.
  320. HGUIWidget gui = guiSO->addComponent<GUIWidget>(guiCamera->getViewport().get());
  321. // Depth allows you to control how is a GUI widget rendered in relation to other widgets
  322. // Lower depth means the widget will be rendered in front of those with higher. In this case we just
  323. // make the depth mid-range as there are no other widgets.
  324. gui->setDepth(128);
  325. // GUI skin defines how are all child elements of the GUI widget renderered. It contains all their styles
  326. // and default layout properties. We use the default skin that comes built into Banshee.
  327. gui->setSkin(BuiltinResources::instance().getGUISkin());
  328. // Create a GUI area that is used for displaying messages about toggling profiler overlays.
  329. // This area will stretch the entire surface of its parent widget, even if the widget is resized.
  330. GUIArea* bottomArea = GUIArea::createStretchedXY(*gui, 0, 0, 0, 0);
  331. // Add a vertical layout that will automatically position any child elements top to bottom.
  332. GUILayout& bottomLayout = bottomArea->getLayout().addLayoutY();
  333. // Add a flexible space that fills up any remaining area in the layout, making the two labels above be aligned
  334. // to the bottom of the GUI widget (and the screen).
  335. bottomLayout.addFlexibleSpace();
  336. // Add a couple of labels to the layout with the needed messages. Labels expect a HString object that
  337. // maps into a string table and allows for easily localization.
  338. bottomLayout.addElement(GUILabel::create(HString(L"Press F1 to toggle CPU profiler overlay")));
  339. bottomLayout.addElement(GUILabel::create(HString(L"Press F2 to toggle GPU profiler overlay")));
  340. // Create a GUI area that is used for displaying resolution and fullscreen options.
  341. GUIArea* rightArea = GUIArea::createStretchedXY(*gui, 30, 30, 30, 30);
  342. // We want all the GUI elements be right aligned, so we add a flexible space first.
  343. rightArea->getLayout().addFlexibleSpace();
  344. // And we want the elements to be vertically placed, top to bottom
  345. GUILayout& rightLayout = rightArea->getLayout().addLayoutY();
  346. // Add a button that will trigger a callback when clicked
  347. toggleFullscreenButton = GUIButton::create(HString(L"Toggle fullscreen"));
  348. toggleFullscreenButton->onClick.connect(&toggleFullscreen);
  349. rightLayout.addElement(toggleFullscreenButton);
  350. // Add a profiler overlay object that is resposible for displaying CPU and GPU profiling GUI
  351. profilerOverlay = guiSO->addComponent<ProfilerOverlay>(guiCamera->getViewport());
  352. // Set up video mode list box
  353. // First get a list of output devices
  354. const VideoModeInfo& videoModeInfo = RenderSystem::instance().getVideoModeInfo();
  355. // Get video mode info for the primary monitor
  356. const VideoOutputInfo& primaryMonitorInfo = videoModeInfo.getOutputInfo(0);
  357. // Make the current desktop mode the default video mode
  358. selectedVideoMode = &primaryMonitorInfo.getDesktopVideoMode();
  359. // Create list box elements for each available video mode
  360. UINT32 numVideoModes = primaryMonitorInfo.getNumVideoModes();
  361. Vector<HString> videoModeLabels(numVideoModes);
  362. UINT32 selectedVideoModeIdx = 0;
  363. for (UINT32 i = 0; i < numVideoModes; i++)
  364. {
  365. const VideoMode& curVideoMode = primaryMonitorInfo.getVideoMode(i);
  366. HString videoModeLabel(L"{0} x {1} at {2}Hz");
  367. videoModeLabel.setParameter(0, toWString(curVideoMode.getWidth()));
  368. videoModeLabel.setParameter(1, toWString(curVideoMode.getHeight()));
  369. videoModeLabel.setParameter(2, toWString(Math::roundToInt(curVideoMode.getRefreshRate())));
  370. videoModeLabels[i] = videoModeLabel;
  371. videoModes.push_back(&curVideoMode);
  372. if (curVideoMode == *selectedVideoMode)
  373. selectedVideoModeIdx = i;
  374. }
  375. // Create the list box
  376. GUIListBox* videoModeListBox = GUIListBox::create(videoModeLabels);
  377. rightLayout.addElement(videoModeListBox);
  378. // Select the default (desktop) video mode
  379. videoModeListBox->selectElement(selectedVideoModeIdx);
  380. // Set up a callback to be notified when video mode changes
  381. videoModeListBox->onSelectionChanged.connect(&videoModeChanged);
  382. }
  383. void toggleFullscreen()
  384. {
  385. RenderWindowPtr window = gApplication().getPrimaryWindow();
  386. // In order to toggle between full-screen and windowed mode we need to use a CoreAccessor.
  387. // Banshee is a multi-threaded engine and when you need to communicate between simulation and
  388. // core thread you will use a CoreAccessor. Calling a core accessor method will essentially
  389. // queue the method to be executed later. Since RenderWindow is a core object you need to use
  390. // CoreAccessor to modify and access it from simulation thread, except where noted otherwise.
  391. // Classes where it is not clear if they are to be used on the core or simulation thread have
  392. // it noted in their documentation. e.g. RenderWindow::setWindowed method is marked as "Core only".
  393. // Additional asserts are normally in place for debug builds which make it harder for you to accidentally
  394. // call something from the wrong thread.
  395. if (fullscreen)
  396. {
  397. gCoreAccessor().setWindowed(window, windowResWidth, windowResHeight);
  398. }
  399. else
  400. {
  401. gCoreAccessor().setFullscreen(window, *selectedVideoMode);
  402. }
  403. fullscreen = !fullscreen;
  404. }
  405. void renderWindowResized()
  406. {
  407. RenderWindowPtr window = gApplication().getPrimaryWindow();
  408. if (!fullscreen)
  409. {
  410. windowResWidth = window->getWidth();
  411. windowResHeight = window->getHeight();
  412. }
  413. sceneCamera->setAspectRatio(window->getWidth() / (float)window->getHeight());
  414. }
  415. void videoModeChanged(UINT32 idx)
  416. {
  417. selectedVideoMode = videoModes[idx];
  418. if (fullscreen)
  419. {
  420. RenderWindowPtr window = gApplication().getPrimaryWindow();
  421. gCoreAccessor().setFullscreen(window, *selectedVideoMode);
  422. }
  423. }
  424. void buttonUp(const VirtualButton& button, UINT32 deviceIdx)
  425. {
  426. // Check if the pressed button is one of the either buttons we defined
  427. // in "setUpExample", and toggle profiler overlays accordingly.
  428. // Device index is ignored for now, as it is assumed the user is using a single keyboard,
  429. // but if you wanted support for multiple gamepads you would check deviceIdx.
  430. if (button == toggleCPUProfilerBtn)
  431. {
  432. if (cpuProfilerActive)
  433. {
  434. profilerOverlay->hide();
  435. cpuProfilerActive = false;
  436. }
  437. else
  438. {
  439. profilerOverlay->show(ProfilerOverlayType::CPUSamples);
  440. cpuProfilerActive = true;
  441. gpuProfilerActive = false;
  442. }
  443. }
  444. else if (button == toggleGPUProfilerBtn)
  445. {
  446. if (gpuProfilerActive)
  447. {
  448. profilerOverlay->hide();
  449. gpuProfilerActive = false;
  450. }
  451. else
  452. {
  453. profilerOverlay->show(ProfilerOverlayType::GPUSamples);
  454. gpuProfilerActive = true;
  455. cpuProfilerActive = false;
  456. }
  457. }
  458. }
  459. }