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);