Adding menus.

This commit is contained in:
Ben Vanik 2015-06-22 23:30:34 -07:00
parent b9c39d1b33
commit 9441808b40
12 changed files with 210 additions and 67 deletions

View File

@ -34,6 +34,7 @@
<ClCompile Include="src\xenia\base\mapped_memory_win.cc" />
<ClCompile Include="src\xenia\base\math.cc" />
<ClCompile Include="src\xenia\base\memory_generic.cc" />
<ClCompile Include="src\xenia\base\platform_win.cc" />
<ClCompile Include="src\xenia\base\ring_buffer.cc" />
<ClCompile Include="src\xenia\base\string.cc" />
<ClCompile Include="src\xenia\base\string_buffer.cc" />

View File

@ -712,9 +712,6 @@
<ClCompile Include="src\xenia\cpu\backend\x64\x64_code_cache.cc">
<Filter>src\xenia\cpu\backend\x64</Filter>
</ClCompile>
<ClCompile Include="src\xenia\apu\audio_decoder.cc">
<Filter>src\xenia\apu</Filter>
</ClCompile>
<ClCompile Include="src\xenia\base\clock.cc">
<Filter>src\xenia\base</Filter>
</ClCompile>
@ -778,6 +775,9 @@
<ClCompile Include="src\xenia\apu\xma_context.cc">
<Filter>src\xenia\apu</Filter>
</ClCompile>
<ClCompile Include="src\xenia\base\platform_win.cc">
<Filter>src\xenia\base</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="src\xenia\emulator.h">

View File

@ -71,6 +71,8 @@ const char path_separator = '/';
const size_t max_path = 1024; // PATH_MAX
#endif // XE_PLATFORM_WIN32
void LaunchBrowser(const char* url);
} // namespace xe
#endif // XENIA_BASE_PLATFORM_H_

View File

@ -0,0 +1,20 @@
/**
******************************************************************************
* 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 "xenia/base/platform.h"
#include <shellapi.h>
namespace xe {
void LaunchBrowser(const char* url) {
ShellExecuteA(NULL, "open", url, NULL, NULL, SW_SHOWNORMAL);
}
} // namespace xe

View File

@ -129,6 +129,10 @@ void Profiler::OnMouseWheel(int x, int y, int dy) {
MicroProfileMousePosition(x, y, dy);
}
void Profiler::ToggleDisplay() { MicroProfileToggleDisplayMode(); }
void Profiler::TogglePause() { MicroProfileTogglePause(); }
#else
void Profiler::OnMouseDown(bool left_button, bool right_button) {}
@ -139,6 +143,10 @@ void Profiler::OnMouseMove(int x, int y) {}
void Profiler::OnMouseWheel(int x, int y, int dy) {}
void Profiler::ToggleDisplay() {}
void Profiler::TogglePause() {}
#endif // XE_OPTION_PROFILING_UI
void Profiler::set_display(std::unique_ptr<ProfilerDisplay> display) {

View File

@ -176,6 +176,8 @@ class Profiler {
static void OnMouseUp();
static void OnMouseMove(int x, int y);
static void OnMouseWheel(int x, int y, int dy);
static void ToggleDisplay();
static void TogglePause();
// Gets the current display, if any.
static ProfilerDisplay* display() { return display_.get(); }
@ -184,8 +186,6 @@ class Profiler {
// Presents the profiler to the bound display, if any.
static void Present();
// TODO(benvanik): display mode/pause/etc?
private:
static std::unique_ptr<ProfilerDisplay> display_;
};

View File

@ -11,6 +11,7 @@
#include "xenia/base/clock.h"
#include "xenia/base/logging.h"
#include "xenia/base/platform.h"
#include "xenia/base/threading.h"
#include "xenia/gpu/graphics_system.h"
#include "xenia/emulator.h"
@ -19,6 +20,25 @@
namespace xe {
namespace ui {
enum Commands {
IDC_FILE_EXIT,
IDC_CPU_TIME_SCALAR_RESET,
IDC_CPU_TIME_SCALAR_HALF,
IDC_CPU_TIME_SCALAR_DOUBLE,
IDC_CPU_PROFILER_TOGGLE_DISPLAY,
IDC_CPU_PROFILER_TOGGLE_PAUSE,
IDC_GPU_TRACE_FRAME,
IDC_GPU_CLEAR_CACHES,
IDC_WINDOW_FULLSCREEN,
IDC_HELP_WEBSITE,
IDC_HELP_ABOUT,
};
const std::wstring kBaseTitle = L"xenia";
MainWindow::MainWindow(Emulator* emulator)
@ -56,63 +76,116 @@ bool MainWindow::Initialize() {
on_key_down.AddListener([this](KeyEvent& e) {
bool handled = true;
switch (e.key_code()) {
case 0x0D: { // numpad enter
OnCommand(Commands::IDC_CPU_TIME_SCALAR_RESET);
} break;
case 0x6D: { // numpad minus
OnCommand(Commands::IDC_CPU_TIME_SCALAR_HALF);
} break;
case 0x6B: { // numpad plus
OnCommand(Commands::IDC_CPU_TIME_SCALAR_DOUBLE);
} break;
case 0x73: { // VK_F4
emulator()->graphics_system()->RequestFrameTrace();
break;
}
OnCommand(Commands::IDC_GPU_TRACE_FRAME);
} break;
case 0x74: { // VK_F5
emulator()->graphics_system()->ClearCaches();
break;
}
OnCommand(Commands::IDC_GPU_CLEAR_CACHES);
} break;
case 0x7A: { // VK_F11
ToggleFullscreen();
break;
}
OnCommand(Commands::IDC_WINDOW_FULLSCREEN);
} break;
case 0x1B: { // VK_ESCAPE
// Allow users to escape fullscreen (but not enter it)
// Allow users to escape fullscreen (but not enter it).
if (fullscreen_) {
ToggleFullscreen();
}
}
case 0x6D: { // numpad minus
Clock::set_guest_time_scalar(Clock::guest_time_scalar() / 2.0);
UpdateTitle();
break;
}
case 0x6B: { // numpad plus
Clock::set_guest_time_scalar(Clock::guest_time_scalar() * 2.0);
UpdateTitle();
break;
}
case 0x0D: { // numpad enter
Clock::set_guest_time_scalar(1.0);
UpdateTitle();
break;
}
default: {
handled = false;
break;
}
} break;
case 0x70: { // VK_F1
OnCommand(Commands::IDC_HELP_WEBSITE);
} break;
default: { handled = false; } break;
}
e.set_handled(handled);
});
// Main menu
// Main menu.
// FIXME: This code is really messy.
auto file = std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&File");
file->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_FILE_OPEN, L"&Open"));
auto file_menu =
std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&File");
{
file_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_FILE_EXIT, L"E&xit", L"Alt+F4"));
}
main_menu_.AddChild(std::move(file_menu));
main_menu_.AddChild(std::move(file));
// CPU menu.
auto cpu_menu =
std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&CPU");
{
cpu_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_CPU_TIME_SCALAR_RESET,
L"&Reset Time Scalar", L"Numpad Enter"));
cpu_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_CPU_TIME_SCALAR_HALF,
L"Time Scalar /= 2", L"Numpad -"));
cpu_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_CPU_TIME_SCALAR_DOUBLE,
L"Time Scalar *= 2", L"Numpad +"));
}
cpu_menu->AddChild(
std::make_unique<PlatformMenu>(MenuItem::Type::kSeparator));
{
cpu_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_CPU_PROFILER_TOGGLE_DISPLAY,
L"Toggle Profiler &Display", L"Tab"));
cpu_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_CPU_PROFILER_TOGGLE_PAUSE,
L"&Pause/Resume Profiler", L"`"));
}
main_menu_.AddChild(std::move(cpu_menu));
// Window submenu
auto window =
// GPU menu.
auto gpu_menu =
std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&GPU");
{
gpu_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_GPU_TRACE_FRAME, L"&Trace Frame",
L"F4"));
}
gpu_menu->AddChild(
std::make_unique<PlatformMenu>(MenuItem::Type::kSeparator));
{
gpu_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_GPU_CLEAR_CACHES,
L"&Clear Caches", L"F5"));
}
main_menu_.AddChild(std::move(gpu_menu));
// Window menu.
auto window_menu =
std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&Window");
window->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_WINDOW_FULLSCREEN,
L"Fullscreen\tF11"));
{
window_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_WINDOW_FULLSCREEN,
L"&Fullscreen", L"F11"));
}
main_menu_.AddChild(std::move(window_menu));
main_menu_.AddChild(std::move(window));
// Help menu.
auto help_menu =
std::make_unique<PlatformMenu>(MenuItem::Type::kPopup, L"&Help");
{
help_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_HELP_WEBSITE, L"&Website...",
L"F1"));
help_menu->AddChild(std::make_unique<PlatformMenu>(
MenuItem::Type::kString, Commands::IDC_HELP_ABOUT, L"&About..."));
}
main_menu_.AddChild(std::move(help_menu));
SetMenu(&main_menu_);
@ -146,11 +219,46 @@ void MainWindow::OnClose() {
void MainWindow::OnCommand(int id) {
switch (id) {
// TODO: Setup delegates to MenuItems so we don't have to do this
case IDC_FILE_EXIT: {
Close();
} break;
case IDC_CPU_TIME_SCALAR_RESET: {
Clock::set_guest_time_scalar(1.0);
UpdateTitle();
} break;
case IDC_CPU_TIME_SCALAR_HALF: {
Clock::set_guest_time_scalar(Clock::guest_time_scalar() / 2.0);
UpdateTitle();
} break;
case IDC_CPU_TIME_SCALAR_DOUBLE: {
Clock::set_guest_time_scalar(Clock::guest_time_scalar() * 2.0);
UpdateTitle();
} break;
case IDC_CPU_PROFILER_TOGGLE_DISPLAY: {
Profiler::ToggleDisplay();
} break;
case IDC_CPU_PROFILER_TOGGLE_PAUSE: {
Profiler::TogglePause();
} break;
case IDC_GPU_TRACE_FRAME: {
emulator()->graphics_system()->RequestFrameTrace();
} break;
case IDC_GPU_CLEAR_CACHES: {
emulator()->graphics_system()->ClearCaches();
} break;
case IDC_WINDOW_FULLSCREEN: {
ToggleFullscreen();
break;
}
} break;
case IDC_HELP_WEBSITE: {
LaunchBrowser("http://xenia.jp");
} break;
case IDC_HELP_ABOUT: {
LaunchBrowser("http://xenia.jp/about/");
} break;
}
}

View File

@ -50,12 +50,6 @@ class MainWindow : public PlatformWindow {
void OnClose() override;
void OnCommand(int id) override;
enum Commands {
IDC_FILE_OPEN,
IDC_WINDOW_FULLSCREEN,
};
Emulator* emulator_;
PlatformLoop loop_;
PlatformMenu main_menu_;

View File

@ -14,8 +14,9 @@ namespace ui {
MenuItem::MenuItem(Type type) : type_(type), parent_item_(nullptr) {}
MenuItem::MenuItem(Type type, const std::wstring& text)
: type_(type), parent_item_(nullptr), text_(text) {}
MenuItem::MenuItem(Type type, const std::wstring& text,
const std::wstring& hotkey)
: type_(type), parent_item_(nullptr), text_(text), hotkey_(hotkey) {}
MenuItem::~MenuItem() = default;

View File

@ -35,6 +35,7 @@ class MenuItem {
MenuItem* parent_item() const { return parent_item_; }
Type type() { return type_; }
const std::wstring& text() { return text_; }
const std::wstring& hotkey() { return hotkey_; }
void AddChild(MenuItem* child_item);
void AddChild(std::unique_ptr<MenuItem> child_item);
@ -45,7 +46,7 @@ class MenuItem {
protected:
MenuItem(Type type);
MenuItem(Type type, const std::wstring& text);
MenuItem(Type type, const std::wstring& text, const std::wstring& hotkey);
virtual void OnChildAdded(MenuItem* child_item) {}
virtual void OnChildRemoved(MenuItem* child_item) {}
@ -55,7 +56,8 @@ class MenuItem {
Type type_;
MenuItem* parent_item_;
std::vector<MenuItemPtr> children_;
std::wstring text_; // Text associated with this item (typically the title)
std::wstring text_;
std::wstring hotkey_;
};
} // namespace ui

View File

@ -15,8 +15,9 @@ namespace xe {
namespace ui {
namespace win32 {
Win32MenuItem::Win32MenuItem(Type type, int id, const std::wstring& text)
: id_(id), MenuItem(type, text) {
Win32MenuItem::Win32MenuItem(Type type, int id, const std::wstring& text,
const std::wstring& hotkey)
: id_(id), MenuItem(type, text, hotkey) {
switch (type) {
case MenuItem::Type::kNormal:
handle_ = CreateMenu();
@ -29,8 +30,9 @@ Win32MenuItem::Win32MenuItem(Type type, int id, const std::wstring& text)
Win32MenuItem::Win32MenuItem(Type type) : Win32MenuItem(type, 0, L"") {}
Win32MenuItem::Win32MenuItem(Type type, const std::wstring& text)
: Win32MenuItem(type, 0, text) {}
Win32MenuItem::Win32MenuItem(Type type, const std::wstring& text,
const std::wstring& hotkey)
: Win32MenuItem(type, 0, text, hotkey) {}
Win32MenuItem::~Win32MenuItem() {
if (handle_) {
@ -51,8 +53,11 @@ void Win32MenuItem::OnChildAdded(MenuItem* generic_child_item) {
AppendMenuW(handle_, MF_SEPARATOR, child_item->id(), 0);
break;
case MenuItem::Type::kString:
AppendMenuW(handle_, MF_STRING, child_item->id(),
child_item->text().c_str());
auto full_name = child_item->text();
if (!child_item->hotkey().empty()) {
full_name += L"\t" + child_item->hotkey();
}
AppendMenuW(handle_, MF_STRING, child_item->id(), full_name.c_str());
break;
}
}

View File

@ -22,8 +22,10 @@ namespace win32 {
class Win32MenuItem : public MenuItem {
public:
Win32MenuItem(Type type);
Win32MenuItem(Type type, const std::wstring& text);
Win32MenuItem(Type type, int id, const std::wstring& text);
Win32MenuItem(Type type, const std::wstring& text,
const std::wstring& hotkey = L"");
Win32MenuItem(Type type, int id, const std::wstring& text,
const std::wstring& hotkey = L"");
~Win32MenuItem() override;
HMENU handle() { return handle_; }