parent
dd41f01c41
commit
951b2aa5bc
|
@ -18,7 +18,7 @@
|
|||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)build\bin\$(Configuration)\</AdditionalLibraryDirectories>
|
||||
<AdditionalDependencies>ntdll.lib;wsock32.lib;ws2_32.lib;xinput.lib;xaudio2.lib;glu32.lib;opengl32.lib;comctl32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>ntdll.lib;wsock32.lib;ws2_32.lib;xinput.lib;xaudio2.lib;glu32.lib;opengl32.lib;comctl32.lib;shlwapi.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalOptions>/ignore:4006 /ignore:4221 %(AdditionalOptions)</AdditionalOptions>
|
||||
<IgnoreSpecificDefaultLibraries>MSVCRTD</IgnoreSpecificDefaultLibraries>
|
||||
</Link>
|
||||
|
|
|
@ -203,6 +203,7 @@
|
|||
<ClCompile Include="src\xenia\ui\main_window.cc" />
|
||||
<ClCompile Include="src\xenia\ui\menu_item.cc" />
|
||||
<ClCompile Include="src\xenia\ui\win32\win32_control.cc" />
|
||||
<ClCompile Include="src\xenia\ui\win32\win32_file_picker.cc" />
|
||||
<ClCompile Include="src\xenia\ui\win32\win32_loop.cc" />
|
||||
<ClCompile Include="src\xenia\ui\win32\win32_menu_item.cc" />
|
||||
<ClCompile Include="src\xenia\ui\win32\win32_window.cc" />
|
||||
|
@ -459,11 +460,13 @@
|
|||
<ClInclude Include="src\xenia\memory.h" />
|
||||
<ClInclude Include="src\xenia\profiling.h" />
|
||||
<ClInclude Include="src\xenia\ui\control.h" />
|
||||
<ClInclude Include="src\xenia\ui\file_picker.h" />
|
||||
<ClInclude Include="src\xenia\ui\loop.h" />
|
||||
<ClInclude Include="src\xenia\ui\main_window.h" />
|
||||
<ClInclude Include="src\xenia\ui\menu_item.h" />
|
||||
<ClInclude Include="src\xenia\ui\ui_event.h" />
|
||||
<ClInclude Include="src\xenia\ui\win32\win32_control.h" />
|
||||
<ClInclude Include="src\xenia\ui\win32\win32_file_picker.h" />
|
||||
<ClInclude Include="src\xenia\ui\win32\win32_loop.h" />
|
||||
<ClInclude Include="src\xenia\ui\win32\win32_menu_item.h" />
|
||||
<ClInclude Include="src\xenia\ui\win32\win32_window.h" />
|
||||
|
|
|
@ -778,6 +778,9 @@
|
|||
<ClCompile Include="src\xenia\base\platform_win.cc">
|
||||
<Filter>src\xenia\base</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\xenia\ui\win32\win32_file_picker.cc">
|
||||
<Filter>src\xenia\ui\win32</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="src\xenia\emulator.h">
|
||||
|
@ -1506,6 +1509,12 @@
|
|||
<ClInclude Include="src\xenia\apu\xma_context.h">
|
||||
<Filter>src\xenia\apu</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\xenia\ui\file_picker.h">
|
||||
<Filter>src\xenia\ui</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="src\xenia\ui\win32\win32_file_picker.h">
|
||||
<Filter>src\xenia\ui\win32</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="src\xenia\cpu\backend\x64\x64_sequence.inl">
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_UI_FILE_PICKER_H_
|
||||
#define XENIA_UI_FILE_PICKER_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
class FilePicker {
|
||||
public:
|
||||
enum class Mode {
|
||||
kOpen = 0,
|
||||
kSave = 1,
|
||||
};
|
||||
enum class Type {
|
||||
kFile = 0,
|
||||
kDirectory = 1,
|
||||
};
|
||||
|
||||
FilePicker()
|
||||
: mode_(Mode::kOpen),
|
||||
type_(Type::kFile),
|
||||
title_(L"Select Files"),
|
||||
multi_selection_(false) {}
|
||||
virtual ~FilePicker() = default;
|
||||
|
||||
Mode mode() const { return mode_; }
|
||||
void set_mode(Mode mode) { mode_ = mode; }
|
||||
|
||||
Type type() const { return type_; }
|
||||
void set_type(Type type) { type_ = type; }
|
||||
|
||||
std::wstring title() const { return title_; }
|
||||
void set_title(std::wstring title) { title_ = std::move(title); }
|
||||
|
||||
std::vector<std::pair<std::wstring, std::wstring>> extensions() const {
|
||||
return extensions_;
|
||||
}
|
||||
void set_extensions(
|
||||
std::vector<std::pair<std::wstring, std::wstring>> extensions) {
|
||||
extensions_ = std::move(extensions);
|
||||
}
|
||||
|
||||
bool multi_selection() const { return multi_selection_; }
|
||||
void set_multi_selection(bool multi_selection) {
|
||||
multi_selection_ = multi_selection;
|
||||
}
|
||||
|
||||
std::vector<std::wstring> selected_files() const { return selected_files_; }
|
||||
void set_selected_files(std::vector<std::wstring> selected_files) {
|
||||
selected_files_ = std::move(selected_files);
|
||||
}
|
||||
|
||||
virtual bool Show(void* parent_window_handle = nullptr) = 0;
|
||||
|
||||
private:
|
||||
Mode mode_;
|
||||
Type type_;
|
||||
std::wstring title_;
|
||||
std::vector<std::pair<std::wstring, std::wstring>> extensions_;
|
||||
bool multi_selection_;
|
||||
|
||||
std::vector<std::wstring> selected_files_;
|
||||
};
|
||||
|
||||
} // namespace ui
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_UI_FILE_PICKER_H_
|
|
@ -14,6 +14,7 @@
|
|||
#include "xenia/xbox.h"
|
||||
|
||||
// TODO(benvanik): only on windows.
|
||||
#include "xenia/ui/win32/win32_file_picker.h"
|
||||
#include "xenia/ui/win32/win32_loop.h"
|
||||
#include "xenia/ui/win32/win32_menu_item.h"
|
||||
#include "xenia/ui/win32/win32_window.h"
|
||||
|
@ -28,6 +29,7 @@ namespace ui {
|
|||
using PlatformLoop = xe::ui::win32::Win32Loop;
|
||||
using PlatformWindow = xe::ui::win32::Win32Window;
|
||||
using PlatformMenu = xe::ui::win32::Win32MenuItem;
|
||||
using PlatformFilePicker = xe::ui::win32::Win32FilePicker;
|
||||
|
||||
class MainWindow : public PlatformWindow {
|
||||
public:
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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/ui/win32/win32_file_picker.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <windowsx.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <shobjidl.h>
|
||||
|
||||
#include "xenia/base/assert.h"
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
namespace win32 {
|
||||
|
||||
class CDialogEventHandler : public IFileDialogEvents,
|
||||
public IFileDialogControlEvents {
|
||||
public:
|
||||
// IUnknown methods
|
||||
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv) {
|
||||
static const QITAB qit[] = {
|
||||
{&__uuidof(IFileDialogEvents),
|
||||
(int)OFFSETOFCLASS(IFileDialogEvents, CDialogEventHandler)},
|
||||
{&__uuidof(IFileDialogControlEvents),
|
||||
(int)OFFSETOFCLASS(IFileDialogControlEvents, CDialogEventHandler)},
|
||||
{0},
|
||||
};
|
||||
return QISearch(this, qit, riid, ppv);
|
||||
}
|
||||
|
||||
IFACEMETHODIMP_(ULONG) AddRef() { return InterlockedIncrement(&_cRef); }
|
||||
|
||||
IFACEMETHODIMP_(ULONG) Release() {
|
||||
long cRef = InterlockedDecrement(&_cRef);
|
||||
if (!cRef) delete this;
|
||||
return cRef;
|
||||
}
|
||||
|
||||
// IFileDialogEvents methods
|
||||
IFACEMETHODIMP OnFileOk(IFileDialog*) { return S_OK; };
|
||||
IFACEMETHODIMP OnFolderChange(IFileDialog*) { return S_OK; };
|
||||
IFACEMETHODIMP OnFolderChanging(IFileDialog*, IShellItem*) { return S_OK; };
|
||||
IFACEMETHODIMP OnHelp(IFileDialog*) { return S_OK; };
|
||||
IFACEMETHODIMP OnSelectionChange(IFileDialog*) { return S_OK; };
|
||||
IFACEMETHODIMP OnShareViolation(IFileDialog*, IShellItem*,
|
||||
FDE_SHAREVIOLATION_RESPONSE*) {
|
||||
return S_OK;
|
||||
};
|
||||
IFACEMETHODIMP OnTypeChange(IFileDialog* pfd) { return S_OK; };
|
||||
IFACEMETHODIMP OnOverwrite(IFileDialog*, IShellItem*,
|
||||
FDE_OVERWRITE_RESPONSE*) {
|
||||
return S_OK;
|
||||
};
|
||||
|
||||
// IFileDialogControlEvents methods
|
||||
IFACEMETHODIMP OnItemSelected(IFileDialogCustomize* pfdc, DWORD dwIDCtl,
|
||||
DWORD dwIDItem) {
|
||||
return S_OK;
|
||||
};
|
||||
IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize*, DWORD) { return S_OK; };
|
||||
IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize*, DWORD, BOOL) {
|
||||
return S_OK;
|
||||
};
|
||||
IFACEMETHODIMP OnControlActivating(IFileDialogCustomize*, DWORD) {
|
||||
return S_OK;
|
||||
};
|
||||
|
||||
CDialogEventHandler() : _cRef(1){};
|
||||
|
||||
private:
|
||||
~CDialogEventHandler(){};
|
||||
long _cRef;
|
||||
};
|
||||
|
||||
HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void** ppv) {
|
||||
*ppv = NULL;
|
||||
auto dialog_event_handler = new (std::nothrow) CDialogEventHandler();
|
||||
HRESULT hr = dialog_event_handler ? S_OK : E_OUTOFMEMORY;
|
||||
if (SUCCEEDED(hr)) {
|
||||
hr = dialog_event_handler->QueryInterface(riid, ppv);
|
||||
dialog_event_handler->Release();
|
||||
}
|
||||
return hr;
|
||||
}
|
||||
|
||||
Win32FilePicker::Win32FilePicker() = default;
|
||||
|
||||
Win32FilePicker::~Win32FilePicker() = default;
|
||||
|
||||
template <typename T>
|
||||
struct com_ptr {
|
||||
com_ptr() : value(nullptr) {}
|
||||
~com_ptr() { reset(); }
|
||||
void reset() {
|
||||
if (value) {
|
||||
value->Release();
|
||||
value = nullptr;
|
||||
}
|
||||
}
|
||||
operator T*() { return value; }
|
||||
T* operator->() const { return value; }
|
||||
T** addressof() { return &value; }
|
||||
T* value;
|
||||
};
|
||||
|
||||
bool Win32FilePicker::Show(void* parent_window_handle) {
|
||||
// TODO(benvanik): FileSaveDialog.
|
||||
assert_true(mode() == Mode::kOpen);
|
||||
// TODO(benvanik): folder dialogs.
|
||||
assert_true(type() == Type::kFile);
|
||||
|
||||
com_ptr<IFileDialog> file_dialog;
|
||||
HRESULT hr =
|
||||
CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
|
||||
IID_PPV_ARGS(file_dialog.addressof()));
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = file_dialog->SetTitle(title().c_str());
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD flags;
|
||||
hr = file_dialog->GetOptions(&flags);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
// FOS_PICKFOLDERS
|
||||
// FOS_FILEMUSTEXIST
|
||||
// FOS_PATHMUSTEXIST
|
||||
flags |= FOS_FORCEFILESYSTEM;
|
||||
if (multi_selection()) {
|
||||
flags |= FOS_ALLOWMULTISELECT;
|
||||
}
|
||||
hr = file_dialog->SetOptions(flags);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set the file types to display only. Notice that this is a 1-based array.
|
||||
std::vector<COMDLG_FILTERSPEC> save_types;
|
||||
for (auto& extension : extensions()) {
|
||||
save_types.push_back({extension.first.c_str(), extension.second.c_str()});
|
||||
}
|
||||
hr = file_dialog->SetFileTypes(static_cast<UINT>(save_types.size()),
|
||||
save_types.data());
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
hr = file_dialog->SetFileTypeIndex(1);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create an event handling object, and hook it up to the dialog.
|
||||
com_ptr<IFileDialogEvents> file_dialog_events;
|
||||
hr = CDialogEventHandler_CreateInstance(
|
||||
IID_PPV_ARGS(file_dialog_events.addressof()));
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
DWORD cookie;
|
||||
hr = file_dialog->Advise(file_dialog_events, &cookie);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Show the dialog modally.
|
||||
hr = file_dialog->Show(static_cast<HWND>(parent_window_handle));
|
||||
file_dialog->Unadvise(cookie);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Obtain the result once the user clicks the 'Open' button.
|
||||
// The result is an IShellItem object.
|
||||
com_ptr<IShellItem> shell_item;
|
||||
hr = file_dialog->GetResult(shell_item.addressof());
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We are just going to print out the name of the file for sample sake.
|
||||
PWSTR file_path = nullptr;
|
||||
hr = shell_item->GetDisplayName(SIGDN_FILESYSPATH, &file_path);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
return false;
|
||||
}
|
||||
std::vector<std::wstring> selected_files;
|
||||
selected_files.push_back(std::wstring(file_path));
|
||||
set_selected_files(selected_files);
|
||||
CoTaskMemFree(file_path);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace win32
|
||||
} // namespace ui
|
||||
} // namespace xe
|
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* 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. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_UI_WIN32_WIN32_FILE_PICKER_H_
|
||||
#define XENIA_UI_WIN32_WIN32_FILE_PICKER_H_
|
||||
|
||||
#include "xenia/ui/file_picker.h"
|
||||
|
||||
namespace xe {
|
||||
namespace ui {
|
||||
namespace win32 {
|
||||
|
||||
class Win32FilePicker : public FilePicker {
|
||||
public:
|
||||
Win32FilePicker();
|
||||
~Win32FilePicker() override;
|
||||
|
||||
bool Show(void* parent_window_handle) override;
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
} // namespace win32
|
||||
} // namespace ui
|
||||
} // namespace xe
|
||||
|
||||
#endif // XENIA_UI_WIN32_WIN32_FILE_PICKER_H_
|
|
@ -14,6 +14,7 @@
|
|||
#include "xenia/emulator.h"
|
||||
#include "xenia/kernel/kernel.h"
|
||||
#include "xenia/profiling.h"
|
||||
#include "xenia/ui/file_picker.h"
|
||||
#include "xenia/ui/main_window.h"
|
||||
|
||||
DEFINE_string(target, "", "Specifies the target .xex or .iso to execute.");
|
||||
|
@ -33,8 +34,8 @@ int xenia_main(std::vector<std::wstring>& args) {
|
|||
}
|
||||
|
||||
// Grab path from the flag or unnamed argument.
|
||||
std::wstring path;
|
||||
if (!FLAGS_target.empty() || args.size() >= 2) {
|
||||
std::wstring path;
|
||||
if (!FLAGS_target.empty()) {
|
||||
// Passed as a named argument.
|
||||
// TODO(benvanik): find something better than gflags that supports
|
||||
|
@ -44,6 +45,31 @@ int xenia_main(std::vector<std::wstring>& args) {
|
|||
// Passed as an unnamed argument.
|
||||
path = args[1];
|
||||
}
|
||||
}
|
||||
|
||||
// If no path passed, ask the user.
|
||||
if (path.empty()) {
|
||||
ui::PlatformFilePicker file_picker;
|
||||
file_picker.set_mode(ui::FilePicker::Mode::kOpen);
|
||||
file_picker.set_type(ui::FilePicker::Type::kFile);
|
||||
file_picker.set_multi_selection(false);
|
||||
file_picker.set_title(L"Select Content Package");
|
||||
file_picker.set_extensions({
|
||||
{L"Supported Files", L"*.iso;*.xex;*.xcp;*.*"},
|
||||
{L"Disc Image (*.iso)", L"*.iso"},
|
||||
{L"Xbox Executable (*.xex)", L"*.xex"},
|
||||
//{ L"Content Package (*.xcp)", L"*.xcp" },
|
||||
{L"All Files (*.*)", L"*.*"},
|
||||
});
|
||||
if (file_picker.Show(emulator->main_window()->hwnd())) {
|
||||
auto selected_files = file_picker.selected_files();
|
||||
if (!selected_files.empty()) {
|
||||
path = selected_files[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!path.empty()) {
|
||||
// Normalize the path and make absolute.
|
||||
std::wstring abs_path = xe::to_absolute_path(path);
|
||||
|
||||
|
|
Loading…
Reference in New Issue