diff --git a/src/xenia/gpu/gl4/premake5.lua b/src/xenia/gpu/gl4/premake5.lua index 435e3542f..f70c1be2b 100644 --- a/src/xenia/gpu/gl4/premake5.lua +++ b/src/xenia/gpu/gl4/premake5.lua @@ -71,9 +71,13 @@ project("xenia-gpu-gl4-trace-viewer") }) filter("platforms:Windows") - debugdir(project_root) - debugargs({ - "--flagfile=scratch/flags.txt", - "2>&1", - "1>scratch/stdout-trace-viewer.txt", - }) + -- Only create the .user file if it doesn't already exist. + local user_file = project_root.."/build/xenia-gpu-gl4-trace-viewer.vcxproj.user" + if not os.isfile(user_file) then + debugdir(project_root) + debugargs({ + "--flagfile=scratch/flags.txt", + "2>&1", + "1>scratch/stdout-trace-viewer.txt", + }) + end diff --git a/src/xenia/gpu/xe-gpu-trace-viewer.vcxproj b/src/xenia/gpu/xe-gpu-trace-viewer.vcxproj deleted file mode 100644 index 6ae53c80a..000000000 --- a/src/xenia/gpu/xe-gpu-trace-viewer.vcxproj +++ /dev/null @@ -1,94 +0,0 @@ - - - - - Checked - x64 - - - Debug - x64 - - - Release - x64 - - - - {21DDCB81-68A3-4AB2-8CB0-C2B051B9FDDC} - Win32Proj - xegputraceviewer - - - - Application - true - v140 - Unicode - - - Application - false - v140 - true - Unicode - - - - - - - - - - - - - - - - - - - - - - - - Level3 - Disabled - _WINDOWS;%(PreprocessorDefinitions) - - - Windows - libgflags.lib;libglew.lib;libimgui.lib;libxenia.lib;%(AdditionalDependencies) - - - - - Level3 - - - _WINDOWS;%(PreprocessorDefinitions) - - - Windows - libgflags.lib;libglew.lib;libimgui.lib;libxenia.lib;%(AdditionalDependencies) - - - - - libgflags.lib;libglew.lib;libimgui.lib;libxenia.lib;%(AdditionalDependencies) - - - - - - - - - - - - - \ No newline at end of file diff --git a/src/xenia/gpu/xe-gpu-trace-viewer.vcxproj.filters b/src/xenia/gpu/xe-gpu-trace-viewer.vcxproj.filters deleted file mode 100644 index f925bf708..000000000 --- a/src/xenia/gpu/xe-gpu-trace-viewer.vcxproj.filters +++ /dev/null @@ -1,30 +0,0 @@ - - - - - {e3dfb6f1-ec4a-4b58-9a57-0d6eeadd01af} - - - {be07fbff-bc38-4314-9ba0-821ae4e46026} - - - {13989fe7-adab-418c-be97-298171bea0ec} - - - {06641461-811b-44ff-be49-f013a39eb662} - - - - - src\xenia\base - - - src\xenia\gpu - - - - - src\xenia\base - - - \ No newline at end of file diff --git a/src/xenia/ui/premake5.lua b/src/xenia/ui/premake5.lua index 43697e222..35f40ef1f 100644 --- a/src/xenia/ui/premake5.lua +++ b/src/xenia/ui/premake5.lua @@ -17,3 +17,41 @@ project("xenia-ui") project_root.."/build_tools/third_party/gflags/src", }) local_platform_files() + +group("demos") +project("xenia-ui-window-demo") + uuid("e0a687e5-d1f4-4c18-b2f7-012c53ec1ee4") + kind("WindowedApp") + language("C++") + links({ + "elemental-forms", + "gflags", + "glew", + "imgui", + "xenia-base", + "xenia-core", + "xenia-ui", + "xenia-ui-gl", + }) + flags({ + "WinMain", -- Use WinMain instead of main. + }) + defines({ + "GLEW_STATIC=1", + "GLEW_MX=1", + }) + includedirs({ + project_root.."/third_party/elemental-forms/src", + project_root.."/build_tools/third_party/gflags/src", + }) + files({ + "window_demo.cc", + "../base/main_"..platform_suffix..".cc", + }) + files({ + project_root.."/third_party/elemental-forms/resources.rc", + }) + resincludedirs({ + project_root, + project_root.."/third_party/elemental-forms", + }) diff --git a/src/xenia/ui/window.cc b/src/xenia/ui/window.cc index 222d5a8f3..d94245014 100644 --- a/src/xenia/ui/window.cc +++ b/src/xenia/ui/window.cc @@ -144,7 +144,7 @@ bool Window::MakeReady() { root_element_->set_background_skin(TBIDC("background")); root_element_->set_rect({0, 0, width(), height()}); - el::util::ShowDebugInfoSettingsForm(root_element_.get()); + // el::util::ShowDebugInfoSettingsForm(root_element_.get()); return true; } diff --git a/src/xenia/ui/window_demo.cc b/src/xenia/ui/window_demo.cc new file mode 100644 index 000000000..abdab998f --- /dev/null +++ b/src/xenia/ui/window_demo.cc @@ -0,0 +1,205 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2015 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include + +#include + +#include "third_party/elemental-forms/src/el/util/debug.h" +#include "third_party/imgui/imgui.h" +#include "xenia/base/clock.h" +#include "xenia/base/logging.h" +#include "xenia/base/main.h" +#include "xenia/base/platform_win.h" +#include "xenia/base/threading.h" +#include "xenia/profiling.h" +#include "xenia/ui/gl/gl_context.h" +#include "xenia/ui/imgui_drawer.h" +#include "xenia/ui/window.h" + +namespace xe { +namespace ui { + +std::unique_ptr imgui_drawer_; + +int window_demo_main(const std::vector& args) { + Profiler::Initialize(); + Profiler::ThreadEnter("main"); + + // Create run loop and the window. + auto loop = ui::Loop::Create(); + auto window = xe::ui::Window::Create(loop.get(), L"xenia-ui-window-demo"); + loop->PostSynchronous([&window]() { + xe::threading::set_name("Win32 Loop"); + xe::Profiler::ThreadEnter("Win32 Loop"); + if (!window->Initialize()) { + FatalError("Failed to initialize main window"); + return; + } + }); + window->on_closed.AddListener([&loop](xe::ui::UIEvent* e) { + loop->Quit(); + XELOGI("User-initiated death!"); + imgui_drawer_.reset(); + exit(1); + }); + loop->on_quit.AddListener([&window](xe::ui::UIEvent* e) { window.reset(); }); + + // Main menu. + auto main_menu = MenuItem::Create(MenuItem::Type::kNormal); + auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File"); + { + file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"&Close", + L"Alt+F4", + [&window]() { window->Close(); })); + } + main_menu->AddChild(std::move(file_menu)); + auto debug_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Debug"); + { + debug_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, + L"Toggle Profiler &Display", L"F3", + []() { Profiler::ToggleDisplay(); })); + debug_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, + L"&Pause/Resume Profiler", L"`", + []() { Profiler::TogglePause(); })); + } + main_menu->AddChild(std::move(debug_menu)); + window->set_main_menu(std::move(main_menu)); + + // Initial size setting, done here so that it knows the menu exists. + window->Resize(1920, 1200); + + // Create the graphics context used for drawing and setup the window. + loop->PostSynchronous([&window]() { + // Create context and give it to the window. + // The window will finish initialization wtih the context (loading + // resources, etc). + auto context = xe::ui::gl::GLContext::Create(window.get()); + window->set_context(std::move(context)); + + // Setup the profiler display. + GraphicsContextLock context_lock(window->context()); + Profiler::set_window(window.get()); + + // Initialize the ImGui renderer we'll use. + imgui_drawer_ = std::make_unique(window.get()); + + // Show the elemental-forms debug UI so we can see it working. + el::util::ShowDebugInfoSettingsForm(window->root_element()); + }); + + window->on_key_char.AddListener([](xe::ui::KeyEvent* e) { + auto& io = ImGui::GetIO(); + if (e->key_code() > 0 && e->key_code() < 0x10000) { + io.AddInputCharacter(e->key_code()); + } + e->set_handled(true); + }); + window->on_key_down.AddListener([](xe::ui::KeyEvent* e) { + auto& io = ImGui::GetIO(); + io.KeysDown[e->key_code()] = true; + switch (e->key_code()) { + case 0x72: { // F3 + Profiler::ToggleDisplay(); + } break; + case 16: { + io.KeyShift = true; + } break; + case 17: { + io.KeyCtrl = true; + } break; + } + }); + window->on_key_up.AddListener([](xe::ui::KeyEvent* e) { + auto& io = ImGui::GetIO(); + io.KeysDown[e->key_code()] = false; + switch (e->key_code()) { + case 16: { + io.KeyShift = false; + } break; + case 17: { + io.KeyCtrl = false; + } break; + } + }); + window->on_mouse_down.AddListener([](xe::ui::MouseEvent* e) { + auto& io = ImGui::GetIO(); + io.MousePos = ImVec2(float(e->x()), float(e->y())); + switch (e->button()) { + case xe::ui::MouseEvent::Button::kLeft: { + io.MouseDown[0] = true; + } break; + case xe::ui::MouseEvent::Button::kRight: { + io.MouseDown[1] = true; + } break; + } + }); + window->on_mouse_move.AddListener([](xe::ui::MouseEvent* e) { + auto& io = ImGui::GetIO(); + io.MousePos = ImVec2(float(e->x()), float(e->y())); + }); + window->on_mouse_up.AddListener([](xe::ui::MouseEvent* e) { + auto& io = ImGui::GetIO(); + io.MousePos = ImVec2(float(e->x()), float(e->y())); + switch (e->button()) { + case xe::ui::MouseEvent::Button::kLeft: { + io.MouseDown[0] = false; + } break; + case xe::ui::MouseEvent::Button::kRight: { + io.MouseDown[1] = false; + } break; + } + }); + window->on_mouse_wheel.AddListener([](xe::ui::MouseEvent* e) { + auto& io = ImGui::GetIO(); + io.MousePos = ImVec2(float(e->x()), float(e->y())); + io.MouseWheel += float(e->dy() / 120.0f); + }); + + window->on_painting.AddListener([&](xe::ui::UIEvent* e) { + auto& io = ImGui::GetIO(); + auto current_tick_count = Clock::QueryHostTickCount(); + static uint64_t last_draw_tick_count = 0; + io.DeltaTime = (current_tick_count - last_draw_tick_count) / + static_cast(Clock::host_tick_frequency()); + last_draw_tick_count = current_tick_count; + + io.DisplaySize = ImVec2(static_cast(window->width()), + static_cast(window->height())); + + ImGui::NewFrame(); + + ImGui::ShowTestWindow(); + ImGui::ShowMetricsWindow(); + + ImGui::Render(); + + // Continuous paint. + window->Invalidate(); + }); + + window->Invalidate(); + + // Wait until we are exited. + loop->AwaitQuit(); + + imgui_drawer_.reset(); + + window.reset(); + loop.reset(); + Profiler::Dump(); + Profiler::Shutdown(); + return 0; +} + +} // namespace ui +} // namespace xe + +DEFINE_ENTRY_POINT(L"xenia-ui-window-demo", L"xenia-ui-window-demo", + xe::ui::window_demo_main);