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