mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-04-13 09:51:31 +02:00
Merge pull request #4068 from EmptyChaos/wx-hidpi
WX: Comprehensive HiDPI Patch
This commit is contained in:
commit
b8731eb818
3
Externals/wxWidgets3/src/generic/tipwin.cpp
vendored
3
Externals/wxWidgets3/src/generic/tipwin.cpp
vendored
@ -218,6 +218,9 @@ void wxTipWindow::Close()
|
||||
*m_windowPtr = NULL;
|
||||
m_windowPtr = NULL;
|
||||
}
|
||||
// XXX: Dolphin: Prevents an assertion failure due to Close being called multiple times.
|
||||
if (!IsShown())
|
||||
return;
|
||||
|
||||
#if wxUSE_POPUPWIN
|
||||
Show(false);
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cinttypes>
|
||||
#include <climits>
|
||||
#include <memory>
|
||||
|
||||
#include "Common/CDUtils.h"
|
||||
@ -138,8 +139,8 @@ void SConfig::SaveInterfaceSettings(IniFile& ini)
|
||||
interface->Set("OnScreenDisplayMessages", bOnScreenDisplayMessages);
|
||||
interface->Set("HideCursor", bHideCursor);
|
||||
interface->Set("AutoHideCursor", bAutoHideCursor);
|
||||
interface->Set("MainWindowPosX", (iPosX == -32000) ? 0 : iPosX); // TODO - HAX
|
||||
interface->Set("MainWindowPosY", (iPosY == -32000) ? 0 : iPosY); // TODO - HAX
|
||||
interface->Set("MainWindowPosX", iPosX);
|
||||
interface->Set("MainWindowPosY", iPosY);
|
||||
interface->Set("MainWindowWidth", iWidth);
|
||||
interface->Set("MainWindowHeight", iHeight);
|
||||
interface->Set("LanguageCode", m_InterfaceLanguage);
|
||||
@ -402,10 +403,10 @@ void SConfig::LoadInterfaceSettings(IniFile& ini)
|
||||
interface->Get("OnScreenDisplayMessages", &bOnScreenDisplayMessages, true);
|
||||
interface->Get("HideCursor", &bHideCursor, false);
|
||||
interface->Get("AutoHideCursor", &bAutoHideCursor, false);
|
||||
interface->Get("MainWindowPosX", &iPosX, 100);
|
||||
interface->Get("MainWindowPosY", &iPosY, 100);
|
||||
interface->Get("MainWindowWidth", &iWidth, 800);
|
||||
interface->Get("MainWindowHeight", &iHeight, 600);
|
||||
interface->Get("MainWindowPosX", &iPosX, INT_MIN);
|
||||
interface->Get("MainWindowPosY", &iPosY, INT_MIN);
|
||||
interface->Get("MainWindowWidth", &iWidth, -1);
|
||||
interface->Get("MainWindowHeight", &iHeight, -1);
|
||||
interface->Get("LanguageCode", &m_InterfaceLanguage, "");
|
||||
interface->Get("ShowToolbar", &m_InterfaceToolbar, true);
|
||||
interface->Get("ShowStatusbar", &m_InterfaceStatusbar, true);
|
||||
@ -663,10 +664,10 @@ void SConfig::LoadDefaults()
|
||||
bDPL2Decoder = false;
|
||||
iLatency = 14;
|
||||
|
||||
iPosX = 100;
|
||||
iPosY = 100;
|
||||
iWidth = 800;
|
||||
iHeight = 600;
|
||||
iPosX = INT_MIN;
|
||||
iPosY = INT_MIN;
|
||||
iWidth = -1;
|
||||
iHeight = -1;
|
||||
|
||||
m_analytics_id = "";
|
||||
m_analytics_enabled = false;
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
@ -129,8 +130,10 @@ struct SConfig : NonCopyable
|
||||
|
||||
// Display settings
|
||||
std::string strFullscreenResolution;
|
||||
int iRenderWindowXPos = -1, iRenderWindowYPos = -1;
|
||||
int iRenderWindowWidth = 640, iRenderWindowHeight = 480;
|
||||
int iRenderWindowXPos = std::numeric_limits<int>::min();
|
||||
int iRenderWindowYPos = std::numeric_limits<int>::min();
|
||||
int iRenderWindowWidth = -1;
|
||||
int iRenderWindowHeight = -1;
|
||||
bool bRenderWindowAutoSize = false, bKeepWindowOnTop = false;
|
||||
bool bFullscreen = false, bRenderToMain = false;
|
||||
bool bProgressive = false, bPAL60 = false;
|
||||
|
@ -20,8 +20,8 @@ AboutDolphin::AboutDolphin(wxWindow* parent, wxWindowID id, const wxString& titl
|
||||
const wxPoint& position, const wxSize& size, long style)
|
||||
: wxDialog(parent, id, title, position, size, style)
|
||||
{
|
||||
wxGenericStaticBitmap* const sbDolphinLogo =
|
||||
new wxGenericStaticBitmap(this, wxID_ANY, WxUtils::LoadResourceBitmap("dolphin_logo"));
|
||||
wxGenericStaticBitmap* const sbDolphinLogo = new wxGenericStaticBitmap(
|
||||
this, wxID_ANY, WxUtils::LoadScaledResourceBitmap("dolphin_logo", this));
|
||||
|
||||
const wxString DolphinText = _("Dolphin");
|
||||
const wxString RevisionText = scm_desc_str;
|
||||
@ -80,6 +80,12 @@ AboutDolphin::AboutDolphin(wxWindow* parent, wxWindowID id, const wxString& titl
|
||||
|
||||
wxSizerFlags center_flag;
|
||||
center_flag.Center();
|
||||
const int space5 = FromDIP(5);
|
||||
const int space10 = FromDIP(10);
|
||||
const int space15 = FromDIP(15);
|
||||
const int space30 = FromDIP(30);
|
||||
const int space40 = FromDIP(40);
|
||||
const int space75 = FromDIP(75);
|
||||
|
||||
wxBoxSizer* const sCheckUpdates = new wxBoxSizer(wxHORIZONTAL);
|
||||
sCheckUpdates->Add(UpdateText, center_flag);
|
||||
@ -94,30 +100,30 @@ AboutDolphin::AboutDolphin(wxWindow* parent, wxWindowID id, const wxString& titl
|
||||
|
||||
wxBoxSizer* const sInfo = new wxBoxSizer(wxVERTICAL);
|
||||
sInfo->Add(Dolphin);
|
||||
sInfo->AddSpacer(5);
|
||||
sInfo->AddSpacer(space5);
|
||||
sInfo->Add(Revision);
|
||||
sInfo->AddSpacer(10);
|
||||
sInfo->AddSpacer(space10);
|
||||
sInfo->Add(Branch);
|
||||
sInfo->Add(sCheckUpdates);
|
||||
sInfo->Add(Message);
|
||||
sInfo->Add(sLinks);
|
||||
|
||||
wxBoxSizer* const sLogo = new wxBoxSizer(wxVERTICAL);
|
||||
sLogo->AddSpacer(75);
|
||||
sLogo->AddSpacer(space75);
|
||||
sLogo->Add(sbDolphinLogo);
|
||||
sLogo->AddSpacer(40);
|
||||
sLogo->AddSpacer(space40);
|
||||
|
||||
wxBoxSizer* const sMainHor = new wxBoxSizer(wxHORIZONTAL);
|
||||
sMainHor->AddSpacer(30);
|
||||
sMainHor->AddSpacer(space30);
|
||||
sMainHor->Add(sLogo);
|
||||
sMainHor->AddSpacer(30);
|
||||
sMainHor->AddSpacer(space30);
|
||||
sMainHor->Add(sInfo);
|
||||
sMainHor->AddSpacer(30);
|
||||
sMainHor->AddSpacer(space30);
|
||||
|
||||
wxBoxSizer* const sFooter = new wxBoxSizer(wxVERTICAL);
|
||||
sFooter->AddSpacer(15);
|
||||
sFooter->AddSpacer(space15);
|
||||
sFooter->Add(Copyright, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
sFooter->AddSpacer(5);
|
||||
sFooter->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(sMainHor, 1, wxEXPAND);
|
||||
|
@ -40,6 +40,7 @@ set(GUI_SRCS
|
||||
NetPlay/NetPlaySetupFrame.cpp
|
||||
NetPlay/NetWindow.cpp
|
||||
NetPlay/PadMapDialog.cpp
|
||||
DolphinSlider.cpp
|
||||
FifoPlayerDlg.cpp
|
||||
Frame.cpp
|
||||
FrameAui.cpp
|
||||
|
@ -27,10 +27,7 @@
|
||||
#include "DolphinWX/Cheats/CreateCodeDialog.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
const unsigned int MAX_CHEAT_SEARCH_RESULTS_DISPLAY = 1024;
|
||||
}
|
||||
static constexpr unsigned int MAX_CHEAT_SEARCH_RESULTS_DISPLAY = 1024;
|
||||
|
||||
CheatSearchTab::CheatSearchTab(wxWindow* const parent) : wxPanel(parent)
|
||||
{
|
||||
@ -39,13 +36,25 @@ CheatSearchTab::CheatSearchTab(wxWindow* const parent) : wxPanel(parent)
|
||||
|
||||
// first scan button
|
||||
m_btn_init_scan = new wxButton(this, wxID_ANY, _("New Scan"));
|
||||
m_btn_init_scan->SetToolTip(_("Perform a full index of the game's RAM at the current Data Size. "
|
||||
"Required before any Searching can be performed."));
|
||||
m_btn_init_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::OnNewScanClicked, this);
|
||||
m_btn_init_scan->Disable();
|
||||
|
||||
// next scan button
|
||||
m_btn_next_scan = new wxButton(this, wxID_ANY, _("Next Scan"));
|
||||
m_btn_next_scan->SetToolTip(_("Eliminate items from the current scan results that do not match "
|
||||
"the current Search settings."));
|
||||
m_btn_next_scan->Bind(wxEVT_BUTTON, &CheatSearchTab::OnNextScanClicked, this);
|
||||
m_btn_next_scan->Disable();
|
||||
|
||||
m_label_scan_disabled = new wxStaticText(this, wxID_ANY, _("No game is running."));
|
||||
|
||||
// create AR code button
|
||||
m_btn_create_code = new wxButton(this, wxID_ANY, _("Create AR Code"));
|
||||
m_btn_create_code->Bind(wxEVT_BUTTON, &CheatSearchTab::OnCreateARCodeClicked, this);
|
||||
m_btn_create_code->Disable();
|
||||
|
||||
// data sizes radiobox
|
||||
std::array<wxString, 3> data_size_names = {{_("8-bit"), _("16-bit"), _("32-bit")}};
|
||||
m_data_sizes = new wxRadioBox(this, wxID_ANY, _("Data Size"), wxDefaultPosition, wxDefaultSize,
|
||||
@ -54,30 +63,39 @@ CheatSearchTab::CheatSearchTab(wxWindow* const parent) : wxPanel(parent)
|
||||
// ListView for search results
|
||||
m_lview_search_results = new wxListView(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
wxLC_REPORT | wxLC_SINGLE_SEL);
|
||||
ResetListViewColumns();
|
||||
m_lview_search_results->AppendColumn(_("Address"));
|
||||
m_lview_search_results->AppendColumn(_("Value"));
|
||||
m_lview_search_results->AppendColumn(_("Value (float)"));
|
||||
m_lview_search_results->AppendColumn(_("Value (double)"));
|
||||
m_lview_search_results->Bind(wxEVT_LIST_ITEM_ACTIVATED, &CheatSearchTab::OnListViewItemActivated,
|
||||
this);
|
||||
m_lview_search_results->Bind(wxEVT_LIST_ITEM_SELECTED, &CheatSearchTab::OnListViewItemSelected,
|
||||
this);
|
||||
m_lview_search_results->Bind(wxEVT_LIST_ITEM_DESELECTED, &CheatSearchTab::OnListViewItemSelected,
|
||||
this);
|
||||
|
||||
// Result count
|
||||
m_label_results_count = new wxStaticText(this, wxID_ANY, _("Count:"));
|
||||
|
||||
// create AR code button
|
||||
wxButton* const button_cheat_search_copy_address =
|
||||
new wxButton(this, wxID_ANY, _("Create AR Code"));
|
||||
button_cheat_search_copy_address->Bind(wxEVT_BUTTON, &CheatSearchTab::OnCreateARCodeClicked,
|
||||
this);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// results groupbox
|
||||
wxStaticBoxSizer* const sizer_cheat_search_results =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Results"));
|
||||
sizer_cheat_search_results->Add(m_label_results_count, 0, wxALIGN_LEFT | wxALL, 5);
|
||||
sizer_cheat_search_results->Add(m_lview_search_results, 1, wxEXPAND | wxALL, 5);
|
||||
sizer_cheat_search_results->Add(button_cheat_search_copy_address, 0,
|
||||
wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
|
||||
sizer_cheat_search_results->AddSpacer(space5);
|
||||
sizer_cheat_search_results->Add(m_label_results_count, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_cheat_search_results->AddSpacer(space5);
|
||||
sizer_cheat_search_results->Add(m_lview_search_results, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer_cheat_search_results->AddSpacer(space5);
|
||||
sizer_cheat_search_results->Add(m_btn_create_code, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer_cheat_search_results->AddSpacer(space5);
|
||||
|
||||
// search value textbox
|
||||
m_textctrl_value_x = new wxTextCtrl(this, wxID_ANY, "0x0", wxDefaultPosition, wxSize(96, -1));
|
||||
|
||||
wxBoxSizer* const sizer_cheat_filter_text = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_cheat_filter_text->Add(m_textctrl_value_x, 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
m_textctrl_value_x = new wxTextCtrl(this, wxID_ANY, "0x0");
|
||||
m_textctrl_value_x->SetMinSize(WxUtils::GetTextWidgetMinSize(m_textctrl_value_x, "0x00000000 "));
|
||||
m_textctrl_value_x->SetToolTip(
|
||||
_("Value to match against. Can be Hex (\"0x\"), Octal (\"0\") or Decimal. "
|
||||
"Leave blank to filter each result against its own previous value."));
|
||||
|
||||
// Filter types in the compare dropdown
|
||||
// TODO: Implement between search
|
||||
@ -93,33 +111,46 @@ CheatSearchTab::CheatSearchTab(wxWindow* const parent) : wxPanel(parent)
|
||||
|
||||
wxStaticBoxSizer* const sizer_cheat_search_filter =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Search (clear to use previous value)"));
|
||||
sizer_cheat_search_filter->Add(sizer_cheat_filter_text, 0, wxALL | wxEXPAND, 5);
|
||||
sizer_cheat_search_filter->Add(m_search_type, 0, wxALL, 5);
|
||||
|
||||
// left sizer
|
||||
wxBoxSizer* const sizer_left = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_left->Add(sizer_cheat_search_results, 1, wxEXPAND, 5);
|
||||
sizer_cheat_search_filter->AddSpacer(space5);
|
||||
sizer_cheat_search_filter->Add(m_textctrl_value_x, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer_cheat_search_filter->AddSpacer(space5);
|
||||
sizer_cheat_search_filter->Add(m_search_type, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_cheat_search_filter->AddSpacer(space5);
|
||||
|
||||
// button sizer
|
||||
wxBoxSizer* boxButtons = new wxBoxSizer(wxHORIZONTAL);
|
||||
boxButtons->Add(m_btn_init_scan, 1, wxRIGHT, 5);
|
||||
boxButtons->Add(m_btn_next_scan, 1);
|
||||
boxButtons->Add(m_btn_init_scan, 1);
|
||||
boxButtons->Add(m_btn_next_scan, 1, wxLEFT, space5);
|
||||
|
||||
// right sizer
|
||||
wxBoxSizer* const sizer_right = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_right->Add(m_data_sizes, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
sizer_right->Add(sizer_cheat_search_filter, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
sizer_right->Add(m_data_sizes, 0, wxEXPAND);
|
||||
sizer_right->Add(sizer_cheat_search_filter, 0, wxEXPAND | wxTOP, space5);
|
||||
sizer_right->AddStretchSpacer(1);
|
||||
sizer_right->Add(boxButtons, 0, wxTOP | wxEXPAND, 5);
|
||||
sizer_right->Add(m_label_scan_disabled, 0, wxALIGN_CENTER_HORIZONTAL | wxTOP, space5);
|
||||
sizer_right->Add(boxButtons, 0, wxEXPAND | wxTOP, space5);
|
||||
|
||||
// main sizer
|
||||
wxBoxSizer* const sizer_main = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_main->Add(sizer_left, 1, wxEXPAND | wxALL, 5);
|
||||
sizer_main->Add(sizer_right, 0, wxEXPAND | wxALL, 5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(sizer_cheat_search_results, 1, wxEXPAND | wxTOP | wxBOTTOM, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(sizer_right, 0, wxEXPAND | wxTOP | wxBOTTOM, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
|
||||
SetSizerAndFit(sizer_main);
|
||||
}
|
||||
|
||||
void CheatSearchTab::UpdateGUI()
|
||||
{
|
||||
bool core_running = Core::IsRunning();
|
||||
m_btn_init_scan->Enable(core_running);
|
||||
m_btn_next_scan->Enable(core_running && m_scan_is_initialized);
|
||||
m_label_scan_disabled->Show(!core_running);
|
||||
|
||||
Layout(); // Label shown/hidden may require layout adjustment
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnNewScanClicked(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
if (!Core::IsRunningAndStarted())
|
||||
@ -136,6 +167,7 @@ void CheatSearchTab::OnNewScanClicked(wxCommandEvent& WXUNUSED(event))
|
||||
m_search_results.reserve(Memory::RAM_SIZE / m_search_type_size);
|
||||
|
||||
// Enable the "Next Scan" button.
|
||||
m_scan_is_initialized = true;
|
||||
m_btn_next_scan->Enable();
|
||||
|
||||
CheatSearchResult r;
|
||||
@ -183,6 +215,21 @@ void CheatSearchTab::OnCreateARCodeClicked(wxCommandEvent&)
|
||||
arcode_dlg.ShowModal();
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnListViewItemActivated(wxListEvent&)
|
||||
{
|
||||
if (!m_btn_create_code->IsEnabled())
|
||||
return;
|
||||
|
||||
wxCommandEvent fake(wxEVT_BUTTON, m_btn_create_code->GetId());
|
||||
m_btn_create_code->GetEventHandler()->ProcessEvent(fake);
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnListViewItemSelected(wxListEvent&)
|
||||
{
|
||||
// Toggle "Create AR Code" Button
|
||||
m_btn_create_code->Enable(m_lview_search_results->GetSelectedItemCount() > 0);
|
||||
}
|
||||
|
||||
void CheatSearchTab::OnTimerUpdate(wxTimerEvent&)
|
||||
{
|
||||
if (Core::GetState() != Core::CORE_RUN)
|
||||
@ -190,8 +237,8 @@ void CheatSearchTab::OnTimerUpdate(wxTimerEvent&)
|
||||
|
||||
// Only update the currently visible list rows.
|
||||
long first = m_lview_search_results->GetTopItem();
|
||||
long last =
|
||||
std::min(m_lview_search_results->GetItemCount(), m_lview_search_results->GetCountPerPage());
|
||||
long last = std::min<long>(m_lview_search_results->GetItemCount(),
|
||||
first + m_lview_search_results->GetCountPerPage());
|
||||
|
||||
m_lview_search_results->Freeze();
|
||||
|
||||
@ -207,8 +254,8 @@ void CheatSearchTab::OnTimerUpdate(wxTimerEvent&)
|
||||
void CheatSearchTab::UpdateCheatSearchResultsList()
|
||||
{
|
||||
m_update_timer.Stop();
|
||||
m_lview_search_results->ClearAll();
|
||||
ResetListViewColumns();
|
||||
m_lview_search_results->DeleteAllItems();
|
||||
m_btn_create_code->Disable();
|
||||
|
||||
wxString count_label = wxString::Format(_("Count: %lu"), (unsigned long)m_search_results.size());
|
||||
if (m_search_results.size() > MAX_CHEAT_SEARCH_RESULTS_DISPLAY)
|
||||
@ -312,14 +359,6 @@ void CheatSearchTab::FilterCheatSearchResults(u32 value, bool prev)
|
||||
m_search_results.swap(filtered_results);
|
||||
}
|
||||
|
||||
void CheatSearchTab::ResetListViewColumns()
|
||||
{
|
||||
m_lview_search_results->AppendColumn(_("Address"));
|
||||
m_lview_search_results->AppendColumn(_("Value"));
|
||||
m_lview_search_results->AppendColumn(_("Value (float)"));
|
||||
m_lview_search_results->AppendColumn(_("Value (double)"));
|
||||
}
|
||||
|
||||
bool CheatSearchTab::ParseUserEnteredValue(u32* out) const
|
||||
{
|
||||
unsigned long parsed_x_val = 0;
|
||||
|
@ -11,6 +11,7 @@
|
||||
class wxButton;
|
||||
class wxChoice;
|
||||
class wxFocusEvent;
|
||||
class wxListEvent;
|
||||
class wxListView;
|
||||
class wxRadioBox;
|
||||
class wxRadioButton;
|
||||
@ -22,6 +23,8 @@ class CheatSearchTab final : public wxPanel
|
||||
public:
|
||||
CheatSearchTab(wxWindow* const parent);
|
||||
|
||||
void UpdateGUI();
|
||||
|
||||
private:
|
||||
class CheatSearchResult final
|
||||
{
|
||||
@ -34,25 +37,29 @@ private:
|
||||
void UpdateCheatSearchResultsList();
|
||||
void UpdateCheatSearchResultItem(long index);
|
||||
void FilterCheatSearchResults(u32 value, bool prev);
|
||||
void ResetListViewColumns();
|
||||
bool ParseUserEnteredValue(u32* out) const;
|
||||
u32 SwapValue(u32 value) const;
|
||||
|
||||
void OnNewScanClicked(wxCommandEvent&);
|
||||
void OnNextScanClicked(wxCommandEvent&);
|
||||
void OnCreateARCodeClicked(wxCommandEvent&);
|
||||
void OnListViewItemActivated(wxListEvent&);
|
||||
void OnListViewItemSelected(wxListEvent&);
|
||||
void OnTimerUpdate(wxTimerEvent&);
|
||||
|
||||
std::vector<CheatSearchResult> m_search_results;
|
||||
unsigned int m_search_type_size;
|
||||
bool m_scan_is_initialized = false;
|
||||
|
||||
wxChoice* m_search_type;
|
||||
wxListView* m_lview_search_results;
|
||||
wxStaticText* m_label_results_count;
|
||||
wxTextCtrl* m_textctrl_value_x;
|
||||
|
||||
wxButton* m_btn_create_code;
|
||||
wxButton* m_btn_init_scan;
|
||||
wxButton* m_btn_next_scan;
|
||||
wxStaticText* m_label_scan_disabled;
|
||||
|
||||
wxRadioBox* m_data_sizes;
|
||||
|
||||
|
@ -55,13 +55,15 @@ wxCheatsWindow::wxCheatsWindow(wxWindow* const parent)
|
||||
wxDIALOG_NO_PARENT)
|
||||
{
|
||||
// Create the GUI controls
|
||||
Init_ChildControls();
|
||||
CreateGUI();
|
||||
|
||||
// load codes
|
||||
UpdateGUI();
|
||||
wxTheApp->Bind(DOLPHIN_EVT_LOCAL_INI_CHANGED, &wxCheatsWindow::OnLocalGameIniModified, this);
|
||||
|
||||
SetSize(wxSize(-1, 600));
|
||||
SetIcons(WxUtils::GetDolphinIconBundle());
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
Center();
|
||||
Show();
|
||||
}
|
||||
@ -71,8 +73,11 @@ wxCheatsWindow::~wxCheatsWindow()
|
||||
main_frame->g_CheatsWindow = nullptr;
|
||||
}
|
||||
|
||||
void wxCheatsWindow::Init_ChildControls()
|
||||
void wxCheatsWindow::CreateGUI()
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
const int space10 = FromDIP(10);
|
||||
|
||||
// Main Notebook
|
||||
m_notebook_main = new wxNotebook(this, wxID_ANY);
|
||||
|
||||
@ -84,13 +89,15 @@ void wxCheatsWindow::Init_ChildControls()
|
||||
new ActionReplayCodesPanel(tab_cheats, ActionReplayCodesPanel::STYLE_SIDE_PANEL |
|
||||
ActionReplayCodesPanel::STYLE_MODIFY_BUTTONS);
|
||||
|
||||
wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_tab_cheats->Add(m_ar_codes_panel, 1, wxEXPAND | wxALL, 5);
|
||||
wxBoxSizer* sizer_tab_cheats = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_tab_cheats->AddSpacer(space5);
|
||||
sizer_tab_cheats->Add(m_ar_codes_panel, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer_tab_cheats->AddSpacer(space5);
|
||||
|
||||
tab_cheats->SetSizerAndFit(sizer_tab_cheats);
|
||||
|
||||
// Cheat Search Tab
|
||||
wxPanel* const tab_cheat_search = new CheatSearchTab(m_notebook_main);
|
||||
m_tab_cheat_search = new CheatSearchTab(m_notebook_main);
|
||||
|
||||
// Log Tab
|
||||
m_tab_log = new wxPanel(m_notebook_main, wxID_ANY);
|
||||
@ -105,25 +112,30 @@ void wxCheatsWindow::Init_ChildControls()
|
||||
&wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange, this);
|
||||
|
||||
m_checkbox_log_ar->SetValue(ActionReplay::IsSelfLogging());
|
||||
m_textctrl_log = new wxTextCtrl(m_tab_log, wxID_ANY, "", wxDefaultPosition, wxSize(100, -1),
|
||||
wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
|
||||
m_textctrl_log = new wxTextCtrl(m_tab_log, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY | wxTE_DONTWRAP);
|
||||
|
||||
wxBoxSizer* HStrip1 = new wxBoxSizer(wxHORIZONTAL);
|
||||
HStrip1->Add(m_checkbox_log_ar, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
HStrip1->Add(button_updatelog, 0, wxALL, 5);
|
||||
HStrip1->Add(button_clearlog, 0, wxALL, 5);
|
||||
wxBoxSizer* log_control_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
log_control_sizer->Add(m_checkbox_log_ar, 0, wxALIGN_CENTER_VERTICAL);
|
||||
log_control_sizer->Add(button_updatelog, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space10);
|
||||
log_control_sizer->Add(button_clearlog, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space10);
|
||||
|
||||
wxBoxSizer* sTabLog = new wxBoxSizer(wxVERTICAL);
|
||||
sTabLog->Add(HStrip1, 0, wxALL, 5);
|
||||
sTabLog->Add(m_textctrl_log, 1, wxALL | wxEXPAND, 5);
|
||||
sTabLog->AddSpacer(space5);
|
||||
sTabLog->Add(log_control_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space10);
|
||||
sTabLog->AddSpacer(space5);
|
||||
sTabLog->Add(m_textctrl_log, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sTabLog->AddSpacer(space5);
|
||||
|
||||
m_tab_log->SetSizerAndFit(sTabLog);
|
||||
|
||||
// Gecko tab
|
||||
m_geckocode_panel = new Gecko::CodeConfigPanel(m_notebook_main);
|
||||
|
||||
// Add Tabs to Notebook
|
||||
m_notebook_main->AddPage(tab_cheats, _("AR Codes"));
|
||||
m_geckocode_panel = new Gecko::CodeConfigPanel(m_notebook_main);
|
||||
m_notebook_main->AddPage(m_geckocode_panel, _("Gecko Codes"));
|
||||
m_notebook_main->AddPage(tab_cheat_search, _("Cheat Search"));
|
||||
m_notebook_main->AddPage(m_tab_cheat_search, _("Cheat Search"));
|
||||
m_notebook_main->AddPage(m_tab_log, _("Logging"));
|
||||
|
||||
Bind(wxEVT_BUTTON, &wxCheatsWindow::OnEvent_ApplyChanges_Press, this, wxID_APPLY);
|
||||
@ -137,18 +149,23 @@ void wxCheatsWindow::Init_ChildControls()
|
||||
SetAffirmativeId(wxID_CANCEL);
|
||||
|
||||
wxBoxSizer* const sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_notebook_main, 1, wxEXPAND | wxALL, 5);
|
||||
sMain->Add(sButtons, 0, wxRIGHT | wxBOTTOM | wxALIGN_RIGHT, 5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(m_notebook_main, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(sButtons, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->SetMinSize(FromDIP(wxSize(-1, 600)));
|
||||
SetSizerAndFit(sMain);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_ButtonClose_Press(wxCommandEvent& WXUNUSED(event))
|
||||
void wxCheatsWindow::OnEvent_ButtonClose_Press(wxCommandEvent&)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_Close(wxCloseEvent& ev)
|
||||
void wxCheatsWindow::OnEvent_Close(wxCloseEvent&)
|
||||
{
|
||||
// This dialog is created on the heap instead of the stack so we have to destroy ourself.
|
||||
Destroy();
|
||||
}
|
||||
|
||||
@ -164,6 +181,7 @@ void wxCheatsWindow::UpdateGUI()
|
||||
m_gameini_local_path = File::GetUserPath(D_GAMESETTINGS_IDX) + m_game_id + ".ini";
|
||||
Load_ARCodes();
|
||||
Load_GeckoCodes();
|
||||
m_tab_cheat_search->UpdateGUI();
|
||||
|
||||
// enable controls
|
||||
m_button_apply->Enable(Core::IsRunning());
|
||||
@ -194,8 +212,7 @@ void wxCheatsWindow::Load_ARCodes()
|
||||
|
||||
void wxCheatsWindow::Load_GeckoCodes()
|
||||
{
|
||||
m_geckocode_panel->LoadCodes(m_gameini_default, m_gameini_local,
|
||||
SConfig::GetInstance().GetUniqueID(), true);
|
||||
m_geckocode_panel->LoadCodes(m_gameini_default, m_gameini_local, m_game_id, true);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnNewARCodeCreated(wxCommandEvent& ev)
|
||||
@ -243,7 +260,7 @@ void wxCheatsWindow::OnEvent_ApplyChanges_Press(wxCommandEvent& ev)
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent& WXUNUSED(event))
|
||||
void wxCheatsWindow::OnEvent_ButtonUpdateLog_Press(wxCommandEvent&)
|
||||
{
|
||||
wxBeginBusyCursor();
|
||||
m_textctrl_log->Freeze();
|
||||
@ -284,7 +301,7 @@ void wxCheatsWindow::OnClearActionReplayLog(wxCommandEvent& event)
|
||||
OnEvent_ButtonUpdateLog_Press(event);
|
||||
}
|
||||
|
||||
void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent& WXUNUSED(event))
|
||||
void wxCheatsWindow::OnEvent_CheckBoxEnableLogging_StateChange(wxCommandEvent&)
|
||||
{
|
||||
ActionReplay::EnableSelfLogging(m_checkbox_log_ar->IsChecked());
|
||||
}
|
||||
|
@ -7,13 +7,13 @@
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wx/arrstr.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/IniFile.h"
|
||||
|
||||
class CheatSearchTab;
|
||||
class wxButton;
|
||||
class wxCheckBox;
|
||||
class wxNotebook;
|
||||
@ -41,6 +41,7 @@ private:
|
||||
wxButton* m_button_apply;
|
||||
wxNotebook* m_notebook_main;
|
||||
|
||||
CheatSearchTab* m_tab_cheat_search;
|
||||
wxPanel* m_tab_log;
|
||||
|
||||
wxCheckBox* m_checkbox_log_ar;
|
||||
@ -57,7 +58,7 @@ private:
|
||||
|
||||
bool m_ignore_ini_callback = false;
|
||||
|
||||
void Init_ChildControls();
|
||||
void CreateGUI();
|
||||
|
||||
void Load_ARCodes();
|
||||
void Load_GeckoCodes();
|
||||
|
@ -19,8 +19,8 @@ CreateCodeDialog::CreateCodeDialog(wxWindow* const parent, const u32 address)
|
||||
: wxDialog(parent, wxID_ANY, _("Create AR Code")), m_code_address(address)
|
||||
{
|
||||
wxStaticText* const label_name = new wxStaticText(this, wxID_ANY, _("Name: "));
|
||||
m_textctrl_name =
|
||||
new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(256, -1));
|
||||
m_textctrl_name = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(180, -1)));
|
||||
|
||||
wxStaticText* const label_code = new wxStaticText(this, wxID_ANY, _("Code: "));
|
||||
m_textctrl_code = new wxTextCtrl(this, wxID_ANY, wxString::Format("0x%08x", address));
|
||||
@ -33,22 +33,31 @@ CreateCodeDialog::CreateCodeDialog(wxWindow* const parent, const u32 address)
|
||||
m_checkbox_use_hex->SetValue(true);
|
||||
|
||||
wxBoxSizer* const sizer_value_label = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer_value_label->Add(label_value, 0, wxRIGHT, 5);
|
||||
sizer_value_label->Add(m_checkbox_use_hex);
|
||||
const int space5 = FromDIP(5);
|
||||
sizer_value_label->Add(label_value);
|
||||
sizer_value_label->Add(m_checkbox_use_hex, 0, wxLEFT, space5);
|
||||
|
||||
// main sizer
|
||||
wxBoxSizer* const sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_main->Add(label_name, 0, wxALL, 5);
|
||||
sizer_main->Add(m_textctrl_name, 0, wxALL, 5);
|
||||
sizer_main->Add(label_code, 0, wxALL, 5);
|
||||
sizer_main->Add(m_textctrl_code, 0, wxALL, 5);
|
||||
sizer_main->Add(sizer_value_label, 0, wxALL, 5);
|
||||
sizer_main->Add(m_textctrl_value, 0, wxALL, 5);
|
||||
sizer_main->Add(CreateButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT), 0, wxALL, 5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(label_name, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(m_textctrl_name, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(label_code, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(m_textctrl_code, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(sizer_value_label, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(m_textctrl_value, 0, wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(CreateButtonSizer(wxOK | wxCANCEL | wxNO_DEFAULT), 0, wxEXPAND | wxLEFT | wxRIGHT,
|
||||
space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
|
||||
// NOTE: Use default wxCANCEL handling.
|
||||
Bind(wxEVT_BUTTON, &CreateCodeDialog::PressOK, this, wxID_OK);
|
||||
Bind(wxEVT_BUTTON, &CreateCodeDialog::PressCancel, this, wxID_CANCEL);
|
||||
Bind(wxEVT_CLOSE_WINDOW, &CreateCodeDialog::OnEvent_Close, this);
|
||||
|
||||
SetSizerAndFit(sizer_main);
|
||||
SetFocus();
|
||||
@ -82,15 +91,6 @@ void CreateCodeDialog::PressOK(wxCommandEvent& ev)
|
||||
add_event.SetClientData(&new_cheat);
|
||||
GetParent()->GetEventHandler()->ProcessEvent(add_event);
|
||||
|
||||
Close();
|
||||
}
|
||||
|
||||
void CreateCodeDialog::PressCancel(wxCommandEvent& ev)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void CreateCodeDialog::OnEvent_Close(wxCloseEvent& ev)
|
||||
{
|
||||
Destroy();
|
||||
// Allow base class to process. wxDialog will set the return code and hide the window.
|
||||
ev.Skip();
|
||||
}
|
||||
|
@ -26,6 +26,4 @@ private:
|
||||
wxCheckBox* m_checkbox_use_hex;
|
||||
|
||||
void PressOK(wxCommandEvent&);
|
||||
void PressCancel(wxCommandEvent&);
|
||||
void OnEvent_Close(wxCloseEvent& ev);
|
||||
};
|
||||
|
@ -27,8 +27,9 @@ wxDEFINE_EVENT(DOLPHIN_EVT_GECKOCODE_TOGGLED, wxCommandEvent);
|
||||
|
||||
namespace Gecko
|
||||
{
|
||||
static const wxString wxstr_name(wxTRANSLATE("Name: ")), wxstr_notes(wxTRANSLATE("Notes: ")),
|
||||
wxstr_creator(wxTRANSLATE("Creator: "));
|
||||
static const char str_name[] = wxTRANSLATE("Name: ");
|
||||
static const char str_notes[] = wxTRANSLATE("Notes: ");
|
||||
static const char str_creator[] = wxTRANSLATE("Creator: ");
|
||||
|
||||
CodeConfigPanel::CodeConfigPanel(wxWindow* const parent) : wxPanel(parent)
|
||||
{
|
||||
@ -36,40 +37,41 @@ CodeConfigPanel::CodeConfigPanel(wxWindow* const parent) : wxPanel(parent)
|
||||
m_listbox_gcodes->Bind(wxEVT_LISTBOX, &CodeConfigPanel::UpdateInfoBox, this);
|
||||
m_listbox_gcodes->Bind(wxEVT_CHECKLISTBOX, &CodeConfigPanel::ToggleCode, this);
|
||||
|
||||
m_infobox.label_name = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_name));
|
||||
m_infobox.label_creator = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_creator));
|
||||
m_infobox.label_notes = new wxStaticText(this, wxID_ANY, wxGetTranslation(wxstr_notes));
|
||||
m_infobox.label_name = new wxStaticText(this, wxID_ANY, wxGetTranslation(str_name));
|
||||
m_infobox.label_creator = new wxStaticText(this, wxID_ANY, wxGetTranslation(str_creator));
|
||||
m_infobox.label_notes = new wxStaticText(this, wxID_ANY, wxGetTranslation(str_notes));
|
||||
m_infobox.textctrl_notes = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(64, -1), wxTE_MULTILINE | wxTE_READONLY);
|
||||
m_infobox.listbox_codes = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 64));
|
||||
wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
|
||||
m_infobox.listbox_codes =
|
||||
new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDLG_UNIT(this, wxSize(-1, 48)));
|
||||
|
||||
// TODO: buttons to add/edit codes
|
||||
|
||||
// sizers
|
||||
const int space5 = FromDIP(5);
|
||||
wxBoxSizer* const sizer_infobox = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_infobox->Add(m_infobox.label_name, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_creator, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.label_notes, 0, wxBOTTOM, 5);
|
||||
sizer_infobox->Add(m_infobox.textctrl_notes, 0, wxBOTTOM | wxEXPAND, 5);
|
||||
sizer_infobox->Add(m_infobox.listbox_codes, 1, wxEXPAND, 5);
|
||||
sizer_infobox->Add(m_infobox.label_name);
|
||||
sizer_infobox->Add(m_infobox.label_creator, 0, wxTOP, space5);
|
||||
sizer_infobox->Add(m_infobox.label_notes, 0, wxTOP, space5);
|
||||
sizer_infobox->Add(m_infobox.textctrl_notes, 0, wxEXPAND | wxTOP, space5);
|
||||
sizer_infobox->Add(m_infobox.listbox_codes, 1, wxEXPAND | wxTOP, space5);
|
||||
|
||||
// button sizer
|
||||
wxBoxSizer* const sizer_buttons = new wxBoxSizer(wxHORIZONTAL);
|
||||
btn_download = new wxButton(this, wxID_ANY, _("Download Codes (WiiRD Database)"),
|
||||
wxDefaultPosition, wxSize(128, -1));
|
||||
btn_download = new wxButton(this, wxID_ANY, _("Download Codes (WiiRD Database)"));
|
||||
btn_download->Disable();
|
||||
btn_download->Bind(wxEVT_BUTTON, &CodeConfigPanel::DownloadCodes, this);
|
||||
sizer_buttons->AddStretchSpacer(1);
|
||||
sizer_buttons->Add(btn_download, 1, wxEXPAND);
|
||||
|
||||
// horizontal sizer
|
||||
wxBoxSizer* const sizer_vert = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_vert->Add(sizer_infobox, 1, wxEXPAND);
|
||||
sizer_vert->Add(sizer_buttons, 0, wxEXPAND | wxTOP, 5);
|
||||
sizer_buttons->Add(WxUtils::GiveMinSizeDIP(btn_download, wxSize(128, -1)), 1, wxEXPAND);
|
||||
|
||||
wxBoxSizer* const sizer_main = new wxBoxSizer(wxVERTICAL);
|
||||
sizer_main->Add(m_listbox_gcodes, 1, wxALL | wxEXPAND, 5);
|
||||
sizer_main->Add(sizer_vert, 0, wxALL | wxEXPAND, 5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(m_listbox_gcodes, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(sizer_infobox, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
sizer_main->Add(sizer_buttons, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer_main->AddSpacer(space5);
|
||||
|
||||
SetSizerAndFit(sizer_main);
|
||||
}
|
||||
@ -83,7 +85,7 @@ void CodeConfigPanel::UpdateCodeList(bool checkRunning)
|
||||
// add the codes to the listbox
|
||||
for (const GeckoCode& code : m_gcodes)
|
||||
{
|
||||
m_listbox_gcodes->Append(StrToWxStr(code.name));
|
||||
m_listbox_gcodes->Append(m_listbox_gcodes->EscapeMnemonics(StrToWxStr(code.name)));
|
||||
if (code.enabled)
|
||||
{
|
||||
m_listbox_gcodes->Check(m_listbox_gcodes->GetCount() - 1, true);
|
||||
@ -126,7 +128,7 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
|
||||
|
||||
if (sel > -1)
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name) + StrToWxStr(m_gcodes[sel].name));
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(str_name) + StrToWxStr(m_gcodes[sel].name));
|
||||
|
||||
// notes textctrl
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
@ -136,7 +138,7 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
|
||||
}
|
||||
m_infobox.textctrl_notes->ScrollLines(-99); // silly
|
||||
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator) +
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(str_creator) +
|
||||
StrToWxStr(m_gcodes[sel].creator));
|
||||
|
||||
// add codes to info listbox
|
||||
@ -147,9 +149,9 @@ void CodeConfigPanel::UpdateInfoBox(wxCommandEvent&)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(wxstr_name));
|
||||
m_infobox.label_name->SetLabel(wxGetTranslation(str_name));
|
||||
m_infobox.textctrl_notes->Clear();
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(wxstr_creator));
|
||||
m_infobox.label_creator->SetLabel(wxGetTranslation(str_creator));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,9 +7,7 @@
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/datectrl.h>
|
||||
#include <wx/dateevt.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/time.h>
|
||||
#include <wx/timectrl.h>
|
||||
@ -17,6 +15,7 @@
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "DolphinWX/Config/AdvancedConfigPane.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
|
||||
AdvancedConfigPane::AdvancedConfigPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id)
|
||||
{
|
||||
@ -29,7 +28,7 @@ void AdvancedConfigPane::InitializeGUI()
|
||||
{
|
||||
m_clock_override_checkbox = new wxCheckBox(this, wxID_ANY, _("Enable CPU Clock Override"));
|
||||
m_clock_override_slider =
|
||||
new wxSlider(this, wxID_ANY, 100, 0, 150, wxDefaultPosition, wxSize(200, -1));
|
||||
new DolphinSlider(this, wxID_ANY, 100, 0, 150, wxDefaultPosition, FromDIP(wxSize(200, -1)));
|
||||
m_clock_override_text = new wxStaticText(this, wxID_ANY, "");
|
||||
|
||||
m_clock_override_checkbox->Bind(wxEVT_CHECKBOX,
|
||||
@ -67,47 +66,47 @@ void AdvancedConfigPane::InitializeGUI()
|
||||
clock_override_description->Wrap(550);
|
||||
custom_rtc_description->Wrap(550);
|
||||
#else
|
||||
clock_override_description->Wrap(400);
|
||||
custom_rtc_description->Wrap(400);
|
||||
clock_override_description->Wrap(FromDIP(400));
|
||||
custom_rtc_description->Wrap(FromDIP(400));
|
||||
#endif
|
||||
|
||||
wxBoxSizer* const clock_override_checkbox_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
clock_override_checkbox_sizer->Add(m_clock_override_checkbox, 1, wxALL, 5);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const clock_override_slider_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
clock_override_slider_sizer->Add(m_clock_override_slider, 1, wxALL, 5);
|
||||
clock_override_slider_sizer->Add(m_clock_override_text, 1, wxALL, 5);
|
||||
|
||||
wxBoxSizer* const clock_override_description_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
clock_override_description_sizer->Add(clock_override_description, 1, wxALL, 5);
|
||||
clock_override_slider_sizer->Add(m_clock_override_slider, 1);
|
||||
clock_override_slider_sizer->Add(m_clock_override_text, 1, wxLEFT, space5);
|
||||
|
||||
wxStaticBoxSizer* const cpu_options_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("CPU Options"));
|
||||
cpu_options_sizer->Add(clock_override_checkbox_sizer);
|
||||
cpu_options_sizer->Add(clock_override_slider_sizer);
|
||||
cpu_options_sizer->Add(clock_override_description_sizer);
|
||||
cpu_options_sizer->AddSpacer(space5);
|
||||
cpu_options_sizer->Add(m_clock_override_checkbox, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
cpu_options_sizer->AddSpacer(space5);
|
||||
cpu_options_sizer->Add(clock_override_slider_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
cpu_options_sizer->AddSpacer(space5);
|
||||
cpu_options_sizer->Add(clock_override_description, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
cpu_options_sizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const custom_rtc_checkbox_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
custom_rtc_checkbox_sizer->Add(m_custom_rtc_checkbox, 1, wxALL, 5);
|
||||
|
||||
wxGridBagSizer* const custom_rtc_date_time_sizer = new wxGridBagSizer();
|
||||
custom_rtc_date_time_sizer->Add(m_custom_rtc_date_picker, wxGBPosition(0, 0), wxDefaultSpan,
|
||||
wxEXPAND | wxALL, 5);
|
||||
custom_rtc_date_time_sizer->Add(m_custom_rtc_time_picker, wxGBPosition(0, 1), wxDefaultSpan,
|
||||
wxEXPAND | wxALL, 5);
|
||||
|
||||
wxBoxSizer* const custom_rtc_description_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
custom_rtc_description_sizer->Add(custom_rtc_description, 1, wxALL, 5);
|
||||
wxFlexGridSizer* const custom_rtc_date_time_sizer =
|
||||
new wxFlexGridSizer(2, wxSize(space5, space5));
|
||||
custom_rtc_date_time_sizer->Add(m_custom_rtc_date_picker, 0, wxEXPAND);
|
||||
custom_rtc_date_time_sizer->Add(m_custom_rtc_time_picker, 0, wxEXPAND);
|
||||
|
||||
wxStaticBoxSizer* const custom_rtc_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Custom RTC Options"));
|
||||
custom_rtc_sizer->Add(custom_rtc_checkbox_sizer);
|
||||
custom_rtc_sizer->Add(custom_rtc_date_time_sizer);
|
||||
custom_rtc_sizer->Add(custom_rtc_description_sizer);
|
||||
custom_rtc_sizer->AddSpacer(space5);
|
||||
custom_rtc_sizer->Add(m_custom_rtc_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
custom_rtc_sizer->AddSpacer(space5);
|
||||
custom_rtc_sizer->Add(custom_rtc_date_time_sizer, 0, wxLEFT | wxRIGHT, space5);
|
||||
custom_rtc_sizer->AddSpacer(space5);
|
||||
custom_rtc_sizer->Add(custom_rtc_description, 0, wxLEFT | wxRIGHT, space5);
|
||||
custom_rtc_sizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(cpu_options_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(custom_rtc_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(cpu_options_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(custom_rtc_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
}
|
||||
|
@ -6,9 +6,9 @@
|
||||
|
||||
#include <wx/panel.h>
|
||||
|
||||
class DolphinSlider;
|
||||
class wxCheckBox;
|
||||
class wxDatePickerCtrl;
|
||||
class wxSlider;
|
||||
class wxStaticText;
|
||||
class wxTimePickerCtrl;
|
||||
|
||||
@ -37,7 +37,7 @@ private:
|
||||
u32 m_temp_time;
|
||||
|
||||
wxCheckBox* m_clock_override_checkbox;
|
||||
wxSlider* m_clock_override_slider;
|
||||
DolphinSlider* m_clock_override_slider;
|
||||
wxStaticText* m_clock_override_text;
|
||||
wxCheckBox* m_custom_rtc_checkbox;
|
||||
wxDatePickerCtrl* m_custom_rtc_date_picker;
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/radiobox.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
@ -18,6 +17,7 @@
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "DolphinWX/Config/AudioConfigPane.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
AudioConfigPane::AudioConfigPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id)
|
||||
@ -37,8 +37,8 @@ void AudioConfigPane::InitializeGUI()
|
||||
new wxRadioBox(this, wxID_ANY, _("DSP Emulator Engine"), wxDefaultPosition, wxDefaultSize,
|
||||
m_dsp_engine_strings, 0, wxRA_SPECIFY_ROWS);
|
||||
m_dpl2_decoder_checkbox = new wxCheckBox(this, wxID_ANY, _("Dolby Pro Logic II decoder"));
|
||||
m_volume_slider = new wxSlider(this, wxID_ANY, 0, 0, 100, wxDefaultPosition, wxDefaultSize,
|
||||
wxSL_VERTICAL | wxSL_INVERSE);
|
||||
m_volume_slider = new DolphinSlider(this, wxID_ANY, 0, 0, 100, wxDefaultPosition, wxDefaultSize,
|
||||
wxSL_VERTICAL | wxSL_INVERSE);
|
||||
m_volume_text = new wxStaticText(this, wxID_ANY, "");
|
||||
m_audio_backend_choice =
|
||||
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_audio_backend_strings);
|
||||
@ -64,34 +64,51 @@ void AudioConfigPane::InitializeGUI()
|
||||
_("Enables Dolby Pro Logic II emulation using 5.1 surround. OpenAL or Pulse backends only."));
|
||||
#endif
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxStaticBoxSizer* const dsp_engine_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Sound Settings"));
|
||||
dsp_engine_sizer->Add(m_dsp_engine_radiobox, 0, wxALL | wxEXPAND, 5);
|
||||
dsp_engine_sizer->Add(m_dpl2_decoder_checkbox, 0, wxALL, 5);
|
||||
dsp_engine_sizer->Add(m_dsp_engine_radiobox, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
dsp_engine_sizer->AddSpacer(space5);
|
||||
dsp_engine_sizer->AddStretchSpacer();
|
||||
dsp_engine_sizer->Add(m_dpl2_decoder_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
dsp_engine_sizer->AddStretchSpacer();
|
||||
dsp_engine_sizer->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const volume_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("Volume"));
|
||||
volume_sizer->Add(m_volume_slider, 1, wxLEFT | wxRIGHT, 13);
|
||||
volume_sizer->Add(m_volume_text, 0, wxALIGN_CENTER | wxALL, 5);
|
||||
volume_sizer->Add(m_volume_slider, 1, wxALIGN_CENTER_HORIZONTAL);
|
||||
volume_sizer->Add(m_volume_text, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, space5);
|
||||
volume_sizer->AddSpacer(space5);
|
||||
|
||||
wxGridBagSizer* const backend_grid_sizer = new wxGridBagSizer();
|
||||
wxGridBagSizer* const backend_grid_sizer = new wxGridBagSizer(space5, space5);
|
||||
backend_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Audio Backend:")), wxGBPosition(0, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
backend_grid_sizer->Add(m_audio_backend_choice, wxGBPosition(0, 1), wxDefaultSpan, wxALL, 5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
backend_grid_sizer->Add(m_audio_backend_choice, wxGBPosition(0, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
backend_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Latency:")), wxGBPosition(1, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
backend_grid_sizer->Add(m_audio_latency_spinctrl, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
backend_grid_sizer->Add(m_audio_latency_spinctrl, wxGBPosition(1, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxStaticBoxSizer* const backend_static_box_sizer =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, this, _("Backend Settings"));
|
||||
backend_static_box_sizer->Add(backend_grid_sizer, 0, wxEXPAND);
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Backend Settings"));
|
||||
backend_static_box_sizer->AddSpacer(space5);
|
||||
backend_static_box_sizer->Add(backend_grid_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
backend_static_box_sizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const dsp_audio_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
dsp_audio_sizer->Add(dsp_engine_sizer, 1, wxEXPAND | wxALL, 5);
|
||||
dsp_audio_sizer->Add(volume_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
dsp_audio_sizer->AddSpacer(space5);
|
||||
dsp_audio_sizer->Add(dsp_engine_sizer, 1, wxEXPAND | wxTOP | wxBOTTOM, space5);
|
||||
dsp_audio_sizer->AddSpacer(space5);
|
||||
dsp_audio_sizer->Add(volume_sizer, 0, wxEXPAND | wxTOP | wxBOTTOM, space5);
|
||||
dsp_audio_sizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(dsp_audio_sizer, 0, wxALL | wxEXPAND);
|
||||
main_sizer->Add(backend_static_box_sizer, 0, wxALL | wxEXPAND, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(dsp_audio_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(backend_static_box_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
SetSizerAndFit(main_sizer);
|
||||
}
|
||||
@ -180,10 +197,10 @@ void AudioConfigPane::PopulateBackendChoiceBox()
|
||||
for (const std::string& backend : AudioCommon::GetSoundBackends())
|
||||
{
|
||||
m_audio_backend_choice->Append(wxGetTranslation(StrToWxStr(backend)));
|
||||
|
||||
int num = m_audio_backend_choice->FindString(StrToWxStr(SConfig::GetInstance().sBackend));
|
||||
m_audio_backend_choice->SetSelection(num);
|
||||
}
|
||||
|
||||
int num = m_audio_backend_choice->FindString(StrToWxStr(SConfig::GetInstance().sBackend));
|
||||
m_audio_backend_choice->SetSelection(num);
|
||||
}
|
||||
|
||||
bool AudioConfigPane::SupportsVolumeChanges(const std::string& backend)
|
||||
|
@ -8,10 +8,10 @@
|
||||
#include <wx/arrstr.h>
|
||||
#include <wx/panel.h>
|
||||
|
||||
class DolphinSlider;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
class wxRadioBox;
|
||||
class wxSlider;
|
||||
class wxSpinCtrl;
|
||||
class wxStaticText;
|
||||
|
||||
@ -39,7 +39,7 @@ private:
|
||||
|
||||
wxRadioBox* m_dsp_engine_radiobox;
|
||||
wxCheckBox* m_dpl2_decoder_checkbox;
|
||||
wxSlider* m_volume_slider;
|
||||
DolphinSlider* m_volume_slider;
|
||||
wxStaticText* m_volume_text;
|
||||
wxChoice* m_audio_backend_choice;
|
||||
wxSpinCtrl* m_audio_latency_spinctrl;
|
||||
|
@ -76,16 +76,23 @@ void CConfigMain::CreateGUIControls()
|
||||
Notebook->AddPage(path_pane, _("Paths"));
|
||||
Notebook->AddPage(advanced_pane, _("Advanced"));
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(Notebook, 1, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(CreateButtonSizer(wxCLOSE), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(Notebook, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(CreateButtonSizer(wxCLOSE), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
#ifdef __APPLE__
|
||||
main_sizer->SetMinSize(550, 0);
|
||||
#else
|
||||
main_sizer->SetMinSize(400, 0);
|
||||
main_sizer->SetMinSize(FromDIP(400), 0);
|
||||
#endif
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(main_sizer);
|
||||
Center();
|
||||
SetFocus();
|
||||
|
@ -15,10 +15,8 @@ wxDEFINE_EVENT(wxEVT_ADAPTER_UPDATE, wxCommandEvent);
|
||||
|
||||
GCAdapterConfigDiag::GCAdapterConfigDiag(wxWindow* const parent, const wxString& name,
|
||||
const int tab_num)
|
||||
: wxDialog(parent, wxID_ANY, name, wxPoint(128, -1)), m_pad_id(tab_num)
|
||||
: wxDialog(parent, wxID_ANY, name), m_pad_id(tab_num)
|
||||
{
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxCheckBox* const gamecube_rumble = new wxCheckBox(this, wxID_ANY, _("Rumble"));
|
||||
gamecube_rumble->SetValue(SConfig::GetInstance().m_AdapterRumble[m_pad_id]);
|
||||
gamecube_rumble->Bind(wxEVT_CHECKBOX, &GCAdapterConfigDiag::OnAdapterRumble, this);
|
||||
@ -43,12 +41,16 @@ GCAdapterConfigDiag::GCAdapterConfigDiag(wxWindow* const parent, const wxString&
|
||||
}
|
||||
GCAdapter::SetAdapterCallback(std::bind(&GCAdapterConfigDiag::ScheduleAdapterUpdate, this));
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxVERTICAL);
|
||||
szr->Add(m_adapter_status, 0, wxEXPAND);
|
||||
szr->Add(gamecube_rumble, 0, wxEXPAND);
|
||||
szr->Add(gamecube_konga, 0, wxEXPAND);
|
||||
szr->Add(CreateButtonSizer(wxCLOSE), 0, wxEXPAND | wxALL, 5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(CreateButtonSizer(wxCLOSE | wxNO_DEFAULT), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr->AddSpacer(space5);
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetSizerAndFit(szr);
|
||||
Center();
|
||||
|
||||
|
@ -100,42 +100,51 @@ void GameCubeConfigPane::InitializeGUI()
|
||||
new wxButton(this, wxID_ANY, "...", wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
m_memcard_path[1]->Bind(wxEVT_BUTTON, &GameCubeConfigPane::OnSlotBButtonClick, this);
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
const int space10 = FromDIP(10);
|
||||
|
||||
// Populate the GameCube page
|
||||
wxGridBagSizer* const sGamecubeIPLSettings = new wxGridBagSizer();
|
||||
sGamecubeIPLSettings->Add(m_skip_bios_checkbox, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL, 5);
|
||||
wxGridBagSizer* const sGamecubeIPLSettings = new wxGridBagSizer(space5, space5);
|
||||
sGamecubeIPLSettings->Add(m_skip_bios_checkbox, wxGBPosition(0, 0), wxGBSpan(1, 2));
|
||||
sGamecubeIPLSettings->Add(new wxStaticText(this, wxID_ANY, _("System Language:")),
|
||||
wxGBPosition(1, 0), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
sGamecubeIPLSettings->Add(m_system_lang_choice, wxGBPosition(1, 1), wxDefaultSpan,
|
||||
wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
sGamecubeIPLSettings->Add(m_override_lang_checkbox, wxGBPosition(2, 0), wxGBSpan(1, 2), wxALL, 5);
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
sGamecubeIPLSettings->Add(m_override_lang_checkbox, wxGBPosition(2, 0), wxGBSpan(1, 2));
|
||||
|
||||
wxStaticBoxSizer* const sbGamecubeIPLSettings =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("IPL Settings"));
|
||||
sbGamecubeIPLSettings->Add(sGamecubeIPLSettings);
|
||||
sbGamecubeIPLSettings->AddSpacer(space5);
|
||||
sbGamecubeIPLSettings->Add(sGamecubeIPLSettings, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbGamecubeIPLSettings->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const sbGamecubeDeviceSettings =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Device Settings"));
|
||||
wxGridBagSizer* const sbGamecubeEXIDevSettings = new wxGridBagSizer(10, 10);
|
||||
|
||||
wxGridBagSizer* const gamecube_EXIDev_sizer = new wxGridBagSizer(space10, space10);
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
sbGamecubeEXIDevSettings->Add(GCEXIDeviceText[i], wxGBPosition(i, 0), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
sbGamecubeEXIDevSettings->Add(m_exi_devices[i], wxGBPosition(i, 1),
|
||||
wxGBSpan(1, (i < 2) ? 1 : 2), wxALIGN_CENTER_VERTICAL);
|
||||
gamecube_EXIDev_sizer->Add(GCEXIDeviceText[i], wxGBPosition(i, 0), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
gamecube_EXIDev_sizer->Add(m_exi_devices[i], wxGBPosition(i, 1), wxGBSpan(1, (i < 2) ? 1 : 2),
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
if (i < 2)
|
||||
sbGamecubeEXIDevSettings->Add(m_memcard_path[i], wxGBPosition(i, 2), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
gamecube_EXIDev_sizer->Add(m_memcard_path[i], wxGBPosition(i, 2), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
if (NetPlay::IsNetPlayRunning())
|
||||
m_exi_devices[i]->Disable();
|
||||
}
|
||||
sbGamecubeDeviceSettings->Add(sbGamecubeEXIDevSettings, 0, wxALL, 5);
|
||||
sbGamecubeDeviceSettings->AddSpacer(space5);
|
||||
sbGamecubeDeviceSettings->Add(gamecube_EXIDev_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbGamecubeDeviceSettings->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(sbGamecubeIPLSettings, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(sbGamecubeDeviceSettings, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(sbGamecubeIPLSettings, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(sbGamecubeDeviceSettings, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
}
|
||||
|
@ -101,32 +101,51 @@ void GeneralConfigPane::InitializeGUI()
|
||||
m_throttler_choice->Bind(wxEVT_CHOICE, &GeneralConfigPane::OnThrottlerChoiceChanged, this);
|
||||
m_cpu_engine_radiobox->Bind(wxEVT_RADIOBOX, &GeneralConfigPane::OnCPUEngineRadioBoxChanged, this);
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const throttler_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
throttler_sizer->AddSpacer(space5);
|
||||
throttler_sizer->Add(new wxStaticText(this, wxID_ANY, _("Speed Limit:")), 0,
|
||||
wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
throttler_sizer->Add(m_throttler_choice, 0, wxLEFT | wxRIGHT | wxBOTTOM | wxEXPAND, 5);
|
||||
wxALIGN_CENTER_VERTICAL | wxBOTTOM, space5);
|
||||
throttler_sizer->AddSpacer(space5);
|
||||
throttler_sizer->Add(m_throttler_choice, 0, wxALIGN_CENTER_VERTICAL | wxBOTTOM, space5);
|
||||
throttler_sizer->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const basic_settings_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Basic Settings"));
|
||||
basic_settings_sizer->Add(m_dual_core_checkbox, 0, wxALL, 5);
|
||||
basic_settings_sizer->Add(m_idle_skip_checkbox, 0, wxALL, 5);
|
||||
basic_settings_sizer->Add(m_cheats_checkbox, 0, wxALL, 5);
|
||||
basic_settings_sizer->AddSpacer(space5);
|
||||
basic_settings_sizer->Add(m_dual_core_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
basic_settings_sizer->AddSpacer(space5);
|
||||
basic_settings_sizer->Add(m_idle_skip_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
basic_settings_sizer->AddSpacer(space5);
|
||||
basic_settings_sizer->Add(m_cheats_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
basic_settings_sizer->AddSpacer(space5);
|
||||
basic_settings_sizer->Add(throttler_sizer);
|
||||
|
||||
wxStaticBoxSizer* const analytics_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Usage Statistics Reporting Settings"));
|
||||
analytics_sizer->Add(m_analytics_checkbox, 0, wxALL, 5);
|
||||
analytics_sizer->Add(m_analytics_new_id, 0, wxALL, 5);
|
||||
analytics_sizer->AddSpacer(space5);
|
||||
analytics_sizer->Add(m_analytics_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
analytics_sizer->AddSpacer(space5);
|
||||
analytics_sizer->Add(m_analytics_new_id, 0, wxLEFT | wxRIGHT, space5);
|
||||
analytics_sizer->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const advanced_settings_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Advanced Settings"));
|
||||
advanced_settings_sizer->Add(m_cpu_engine_radiobox, 0, wxALL, 5);
|
||||
advanced_settings_sizer->Add(m_force_ntscj_checkbox, 0, wxALL, 5);
|
||||
advanced_settings_sizer->AddSpacer(space5);
|
||||
advanced_settings_sizer->Add(m_cpu_engine_radiobox, 0, wxLEFT | wxRIGHT, space5);
|
||||
advanced_settings_sizer->AddSpacer(space5);
|
||||
advanced_settings_sizer->Add(m_force_ntscj_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
advanced_settings_sizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(basic_settings_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(analytics_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(advanced_settings_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(basic_settings_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(analytics_sizer, 0, wxEXPAND | wxLEFT | wxLEFT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(advanced_settings_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <wx/choice.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/language.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
@ -30,7 +31,7 @@
|
||||
#include "DolphinWX/X11Utils.h"
|
||||
#endif
|
||||
|
||||
static const std::array<std::string, 29> language_ids = {{
|
||||
static const std::array<std::string, 29> language_ids{{
|
||||
"",
|
||||
|
||||
"ms", "ca", "cs", "da", "de", "en", "es", "fr", "hr", "it", "hu", "nl",
|
||||
@ -115,27 +116,36 @@ void InterfaceConfigPane::InitializeGUI()
|
||||
m_interface_lang_choice->SetToolTip(
|
||||
_("Change the language of the user interface.\nRequires restart."));
|
||||
|
||||
wxGridBagSizer* const language_and_theme_grid_sizer = new wxGridBagSizer();
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxGridBagSizer* const language_and_theme_grid_sizer = new wxGridBagSizer(space5, space5);
|
||||
language_and_theme_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Language:")),
|
||||
wxGBPosition(0, 0), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
language_and_theme_grid_sizer->Add(m_interface_lang_choice, wxGBPosition(0, 1), wxDefaultSpan,
|
||||
wxALL, 5);
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
language_and_theme_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Theme:")),
|
||||
wxGBPosition(1, 0), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
language_and_theme_grid_sizer->Add(m_theme_choice, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5);
|
||||
wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
language_and_theme_grid_sizer->Add(m_theme_choice, wxGBPosition(1, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxStaticBoxSizer* const main_static_box_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Interface Settings"));
|
||||
main_static_box_sizer->Add(m_confirm_stop_checkbox, 0, wxALL, 5);
|
||||
main_static_box_sizer->Add(m_panic_handlers_checkbox, 0, wxALL, 5);
|
||||
main_static_box_sizer->Add(m_osd_messages_checkbox, 0, wxALL, 5);
|
||||
main_static_box_sizer->Add(m_pause_focus_lost_checkbox, 0, wxALL, 5);
|
||||
main_static_box_sizer->Add(language_and_theme_grid_sizer, 0, wxEXPAND | wxALL, 0);
|
||||
main_static_box_sizer->AddSpacer(space5);
|
||||
main_static_box_sizer->Add(m_confirm_stop_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_static_box_sizer->AddSpacer(space5);
|
||||
main_static_box_sizer->Add(m_panic_handlers_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_static_box_sizer->AddSpacer(space5);
|
||||
main_static_box_sizer->Add(m_osd_messages_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_static_box_sizer->AddSpacer(space5);
|
||||
main_static_box_sizer->Add(m_pause_focus_lost_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_static_box_sizer->AddSpacer(space5);
|
||||
main_static_box_sizer->Add(language_and_theme_grid_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_static_box_sizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const main_box_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_box_sizer->Add(main_static_box_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_box_sizer->AddSpacer(space5);
|
||||
main_box_sizer->Add(main_static_box_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_box_sizer->AddSpacer(space5);
|
||||
|
||||
SetSizer(main_box_sizer);
|
||||
}
|
||||
@ -212,7 +222,10 @@ void InterfaceConfigPane::OnInterfaceLanguageChoiceChanged(wxCommandEvent& event
|
||||
{
|
||||
if (SConfig::GetInstance().m_InterfaceLanguage !=
|
||||
language_ids[m_interface_lang_choice->GetSelection()])
|
||||
SuccessAlertT("You must restart Dolphin in order for the change to take effect.");
|
||||
{
|
||||
wxMessageBox(_("You must restart Dolphin in order for the change to take effect."),
|
||||
_("Restart Required"), wxOK | wxICON_INFORMATION, this);
|
||||
}
|
||||
|
||||
SConfig::GetInstance().m_InterfaceLanguage =
|
||||
language_ids[m_interface_lang_choice->GetSelection()];
|
||||
|
@ -77,45 +77,49 @@ void PathConfigPane::InitializeGUI()
|
||||
m_wii_sdcard_filepicker->Bind(wxEVT_FILEPICKER_CHANGED, &PathConfigPane::OnSdCardPathChanged,
|
||||
this);
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const iso_button_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
iso_button_sizer->Add(m_recursive_iso_paths_checkbox, 0, wxALL | wxALIGN_CENTER);
|
||||
iso_button_sizer->Add(m_recursive_iso_paths_checkbox, 0, wxALIGN_CENTER_VERTICAL);
|
||||
iso_button_sizer->AddStretchSpacer();
|
||||
iso_button_sizer->Add(m_add_iso_path_button, 0, wxALL);
|
||||
iso_button_sizer->Add(m_remove_iso_path_button, 0, wxALL);
|
||||
iso_button_sizer->Add(m_add_iso_path_button, 0, wxALIGN_CENTER_VERTICAL);
|
||||
iso_button_sizer->Add(m_remove_iso_path_button, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxStaticBoxSizer* const iso_listbox_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("ISO Directories"));
|
||||
iso_listbox_sizer->Add(m_iso_paths_listbox, 1, wxEXPAND | wxALL, 0);
|
||||
iso_listbox_sizer->Add(iso_button_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
iso_listbox_sizer->Add(m_iso_paths_listbox, 1, wxEXPAND);
|
||||
iso_listbox_sizer->AddSpacer(space5);
|
||||
iso_listbox_sizer->Add(iso_button_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
iso_listbox_sizer->AddSpacer(space5);
|
||||
|
||||
wxGridBagSizer* const picker_sizer = new wxGridBagSizer();
|
||||
wxGridBagSizer* const picker_sizer = new wxGridBagSizer(space5, space5);
|
||||
picker_sizer->Add(new wxStaticText(this, wxID_ANY, _("Default ISO:")), wxGBPosition(0, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
picker_sizer->Add(m_default_iso_filepicker, wxGBPosition(0, 1), wxDefaultSpan, wxEXPAND | wxALL,
|
||||
5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
picker_sizer->Add(m_default_iso_filepicker, wxGBPosition(0, 1), wxDefaultSpan, wxEXPAND);
|
||||
picker_sizer->Add(new wxStaticText(this, wxID_ANY, _("DVD Root:")), wxGBPosition(1, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
picker_sizer->Add(m_dvd_root_dirpicker, wxGBPosition(1, 1), wxDefaultSpan, wxEXPAND | wxALL, 5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
picker_sizer->Add(m_dvd_root_dirpicker, wxGBPosition(1, 1), wxDefaultSpan, wxEXPAND);
|
||||
picker_sizer->Add(new wxStaticText(this, wxID_ANY, _("Apploader:")), wxGBPosition(2, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
picker_sizer->Add(m_apploader_path_filepicker, wxGBPosition(2, 1), wxDefaultSpan,
|
||||
wxEXPAND | wxALL, 5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
picker_sizer->Add(m_apploader_path_filepicker, wxGBPosition(2, 1), wxDefaultSpan, wxEXPAND);
|
||||
picker_sizer->Add(new wxStaticText(this, wxID_ANY, _("Wii NAND Root:")), wxGBPosition(3, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
picker_sizer->Add(m_nand_root_dirpicker, wxGBPosition(3, 1), wxDefaultSpan, wxEXPAND | wxALL, 5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
picker_sizer->Add(m_nand_root_dirpicker, wxGBPosition(3, 1), wxDefaultSpan, wxEXPAND);
|
||||
picker_sizer->Add(new wxStaticText(this, wxID_ANY, _("Dump Path:")), wxGBPosition(4, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
picker_sizer->Add(m_dump_path_dirpicker, wxGBPosition(4, 1), wxDefaultSpan, wxEXPAND | wxALL, 5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
picker_sizer->Add(m_dump_path_dirpicker, wxGBPosition(4, 1), wxDefaultSpan, wxEXPAND);
|
||||
picker_sizer->Add(new wxStaticText(this, wxID_ANY, _("SD Card Path:")), wxGBPosition(5, 0),
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
picker_sizer->Add(m_wii_sdcard_filepicker, wxGBPosition(5, 1), wxDefaultSpan, wxEXPAND | wxALL,
|
||||
5);
|
||||
wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
picker_sizer->Add(m_wii_sdcard_filepicker, wxGBPosition(5, 1), wxDefaultSpan, wxEXPAND);
|
||||
picker_sizer->AddGrowableCol(1);
|
||||
|
||||
// Populate the Paths page
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(iso_listbox_sizer, 1, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(picker_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(iso_listbox_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(picker_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
}
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
#include "DolphinWX/Config/WiiConfigPane.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
WiiConfigPane::WiiConfigPane(wxWindow* parent, wxWindowID id) : wxPanel(parent, id)
|
||||
@ -52,14 +53,10 @@ void WiiConfigPane::InitializeGUI()
|
||||
m_connect_keyboard_checkbox = new wxCheckBox(this, wxID_ANY, _("Connect USB Keyboard"));
|
||||
m_bt_sensor_bar_pos =
|
||||
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, m_bt_sensor_bar_pos_strings);
|
||||
m_bt_sensor_bar_sens = new wxSlider(this, wxID_ANY, 0, 0, 4);
|
||||
m_bt_speaker_volume = new wxSlider(this, wxID_ANY, 0, 0, 127);
|
||||
m_bt_sensor_bar_sens = new DolphinSlider(this, wxID_ANY, 0, 0, 4);
|
||||
m_bt_speaker_volume = new DolphinSlider(this, wxID_ANY, 0, 0, 127);
|
||||
m_bt_wiimote_motor = new wxCheckBox(this, wxID_ANY, _("Wiimote Motor"));
|
||||
|
||||
// With some GTK themes, no minimum size will be applied - so do this manually here
|
||||
m_bt_sensor_bar_sens->SetMinSize(wxSize(100, -1));
|
||||
m_bt_speaker_volume->SetMinSize(wxSize(100, -1));
|
||||
|
||||
m_screensaver_checkbox->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnScreenSaverCheckBoxChanged, this);
|
||||
m_pal60_mode_checkbox->Bind(wxEVT_CHECKBOX, &WiiConfigPane::OnPAL60CheckBoxChanged, this);
|
||||
m_aspect_ratio_choice->Bind(wxEVT_CHOICE, &WiiConfigPane::OnAspectRatioChoiceChanged, this);
|
||||
@ -79,67 +76,78 @@ void WiiConfigPane::InitializeGUI()
|
||||
m_sd_card_checkbox->SetToolTip(_("Saved to /Wii/sd.raw (default size is 128mb)"));
|
||||
m_connect_keyboard_checkbox->SetToolTip(_("May cause slow down in Wii Menu and some games."));
|
||||
|
||||
wxGridBagSizer* const misc_settings_grid_sizer = new wxGridBagSizer();
|
||||
misc_settings_grid_sizer->Add(m_screensaver_checkbox, wxGBPosition(0, 0), wxGBSpan(1, 2), wxALL,
|
||||
5);
|
||||
misc_settings_grid_sizer->Add(m_pal60_mode_checkbox, wxGBPosition(1, 0), wxGBSpan(1, 2), wxALL,
|
||||
5);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxGridBagSizer* const misc_settings_grid_sizer = new wxGridBagSizer(space5, space5);
|
||||
misc_settings_grid_sizer->Add(m_screensaver_checkbox, wxGBPosition(0, 0), wxGBSpan(1, 2));
|
||||
misc_settings_grid_sizer->Add(m_pal60_mode_checkbox, wxGBPosition(1, 0), wxGBSpan(1, 2));
|
||||
misc_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Aspect Ratio:")),
|
||||
wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5);
|
||||
misc_settings_grid_sizer->Add(m_aspect_ratio_choice, wxGBPosition(2, 1), wxDefaultSpan, wxALL, 5);
|
||||
wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
misc_settings_grid_sizer->Add(m_aspect_ratio_choice, wxGBPosition(2, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
misc_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("System Language:")),
|
||||
wxGBPosition(3, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5);
|
||||
misc_settings_grid_sizer->Add(m_system_language_choice, wxGBPosition(3, 1), wxDefaultSpan, wxALL,
|
||||
5);
|
||||
wxGBPosition(3, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
misc_settings_grid_sizer->Add(m_system_language_choice, wxGBPosition(3, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
auto* const bt_sensor_bar_pos_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
bt_sensor_bar_pos_sizer->Add(new wxStaticText(this, wxID_ANY, _("Min")), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
bt_sensor_bar_pos_sizer->Add(m_bt_sensor_bar_sens);
|
||||
bt_sensor_bar_pos_sizer->Add(m_bt_sensor_bar_sens, 0, wxALIGN_CENTER_VERTICAL);
|
||||
bt_sensor_bar_pos_sizer->Add(new wxStaticText(this, wxID_ANY, _("Max")), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
auto* const bt_speaker_volume_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
bt_speaker_volume_sizer->Add(new wxStaticText(this, wxID_ANY, _("Min")), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
bt_speaker_volume_sizer->Add(m_bt_speaker_volume);
|
||||
bt_speaker_volume_sizer->Add(m_bt_speaker_volume, 0, wxALIGN_CENTER_VERTICAL);
|
||||
bt_speaker_volume_sizer->Add(new wxStaticText(this, wxID_ANY, _("Max")), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxGridBagSizer* const bt_settings_grid_sizer = new wxGridBagSizer();
|
||||
wxGridBagSizer* const bt_settings_grid_sizer = new wxGridBagSizer(space5, space5);
|
||||
bt_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Sensor Bar Position:")),
|
||||
wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5);
|
||||
bt_settings_grid_sizer->Add(m_bt_sensor_bar_pos, wxGBPosition(0, 1), wxDefaultSpan, wxALL, 5);
|
||||
wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
bt_settings_grid_sizer->Add(m_bt_sensor_bar_pos, wxGBPosition(0, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
bt_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("IR Sensitivity:")),
|
||||
wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5);
|
||||
bt_settings_grid_sizer->Add(bt_sensor_bar_pos_sizer, wxGBPosition(1, 1), wxDefaultSpan, wxALL, 5);
|
||||
wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
bt_settings_grid_sizer->Add(bt_sensor_bar_pos_sizer, wxGBPosition(1, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
bt_settings_grid_sizer->Add(new wxStaticText(this, wxID_ANY, _("Speaker Volume:")),
|
||||
wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5);
|
||||
bt_settings_grid_sizer->Add(bt_speaker_volume_sizer, wxGBPosition(2, 1), wxDefaultSpan, wxALL, 5);
|
||||
bt_settings_grid_sizer->Add(m_bt_wiimote_motor, wxGBPosition(3, 0), wxGBSpan(1, 2), wxALL, 5);
|
||||
wxGBPosition(2, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
bt_settings_grid_sizer->Add(bt_speaker_volume_sizer, wxGBPosition(2, 1), wxDefaultSpan,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
bt_settings_grid_sizer->Add(m_bt_wiimote_motor, wxGBPosition(3, 0), wxGBSpan(1, 2),
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxStaticBoxSizer* const misc_settings_static_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Misc Settings"));
|
||||
misc_settings_static_sizer->Add(misc_settings_grid_sizer);
|
||||
misc_settings_static_sizer->AddSpacer(space5);
|
||||
misc_settings_static_sizer->Add(misc_settings_grid_sizer, 0, wxLEFT | wxRIGHT, space5);
|
||||
misc_settings_static_sizer->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const device_settings_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Device Settings"));
|
||||
device_settings_sizer->Add(m_sd_card_checkbox, 0, wxALL, 5);
|
||||
device_settings_sizer->Add(m_connect_keyboard_checkbox, 0, wxALL, 5);
|
||||
device_settings_sizer->AddSpacer(space5);
|
||||
device_settings_sizer->Add(m_sd_card_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
device_settings_sizer->AddSpacer(space5);
|
||||
device_settings_sizer->Add(m_connect_keyboard_checkbox, 0, wxLEFT | wxRIGHT, space5);
|
||||
device_settings_sizer->AddSpacer(space5);
|
||||
|
||||
auto* const bt_settings_static_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("Wii Remote Settings"));
|
||||
bt_settings_static_sizer->Add(bt_settings_grid_sizer);
|
||||
bt_settings_static_sizer->AddSpacer(space5);
|
||||
bt_settings_static_sizer->Add(bt_settings_grid_sizer, 0, wxLEFT | wxRIGHT, space5);
|
||||
bt_settings_static_sizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->Add(misc_settings_static_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(device_settings_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->Add(bt_settings_static_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(misc_settings_static_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(device_settings_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(bt_settings_static_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
SetSizer(main_sizer);
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ namespace DiscIO
|
||||
enum class Language;
|
||||
}
|
||||
|
||||
class DolphinSlider;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
class wxSlider;
|
||||
@ -53,7 +54,7 @@ private:
|
||||
wxChoice* m_aspect_ratio_choice;
|
||||
|
||||
wxChoice* m_bt_sensor_bar_pos;
|
||||
wxSlider* m_bt_sensor_bar_sens;
|
||||
wxSlider* m_bt_speaker_volume;
|
||||
DolphinSlider* m_bt_sensor_bar_sens;
|
||||
DolphinSlider* m_bt_speaker_volume;
|
||||
wxCheckBox* m_bt_wiimote_motor;
|
||||
};
|
||||
|
@ -13,7 +13,7 @@
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
@ -29,11 +29,12 @@
|
||||
#include "Core/HotkeyManager.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_usb_bt_real.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/NetPlayProto.h"
|
||||
#include "DolphinWX/Config/GCAdapterConfigDiag.h"
|
||||
#include "DolphinWX/ControllerConfigDiag.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "DolphinWX/InputConfigDiag.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
@ -47,15 +48,18 @@ ControllerConfigDiag::ControllerConfigDiag(wxWindow* const parent)
|
||||
_("Steering Wheel"), _("Dance Mat"), _("DK Bongos"), _("GBA"),
|
||||
_("Keyboard")}};
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// Combine all UI controls into their own encompassing sizer.
|
||||
wxBoxSizer* control_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
control_sizer->Add(CreateGamecubeSizer(), 0, wxEXPAND | wxALL, 5);
|
||||
control_sizer->Add(CreateWiimoteConfigSizer(), 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
main_sizer->Add(control_sizer, 0, wxEXPAND);
|
||||
main_sizer->Add(CreateButtonSizer(wxCLOSE), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(CreateGamecubeSizer(), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(CreateWiimoteConfigSizer(), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(CreateButtonSizer(wxCLOSE | wxNO_DEFAULT), 0, wxEXPAND | wxLEFT | wxRIGHT,
|
||||
space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, &ControllerConfigDiag::OnClose, this);
|
||||
Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnCloseButton, this, wxID_CLOSE);
|
||||
@ -131,25 +135,31 @@ void ControllerConfigDiag::UpdateUI()
|
||||
}
|
||||
}
|
||||
|
||||
wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
|
||||
wxSizer* ControllerConfigDiag::CreateGamecubeSizer()
|
||||
{
|
||||
wxStaticBoxSizer* const gamecube_static_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, _("GameCube Controllers"));
|
||||
wxFlexGridSizer* const gamecube_flex_sizer = new wxFlexGridSizer(3, 5, 5);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
auto* gamecube_static_sizer = new wxStaticBoxSizer(wxVERTICAL, this, _("GameCube Controllers"));
|
||||
auto* gamecube_flex_sizer = new wxFlexGridSizer(3, space5, space5);
|
||||
gamecube_flex_sizer->AddGrowableCol(1);
|
||||
gamecube_static_sizer->AddSpacer(space5);
|
||||
gamecube_static_sizer->Add(gamecube_flex_sizer, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
gamecube_static_sizer->AddSpacer(space5);
|
||||
|
||||
wxStaticText* pad_labels[4];
|
||||
wxChoice* pad_type_choices[4];
|
||||
|
||||
for (int i = 0; i < 4; i++)
|
||||
{
|
||||
pad_labels[i] = new wxStaticText(this, wxID_ANY, wxString::Format(_("Port %i"), i + 1));
|
||||
pad_labels[i] = new wxStaticText(gamecube_static_sizer->GetStaticBox(), wxID_ANY,
|
||||
wxString::Format(_("Port %i"), i + 1));
|
||||
|
||||
// Create an ID for the config button.
|
||||
const wxWindowID button_id = wxWindow::NewControlId();
|
||||
m_gc_port_from_config_id.emplace(button_id, i);
|
||||
m_gc_port_configure_button[i] =
|
||||
new wxButton(this, button_id, _("Configure"), wxDefaultPosition, wxSize(100, -1));
|
||||
new wxButton(gamecube_static_sizer->GetStaticBox(), button_id, _("Configure"),
|
||||
wxDefaultPosition, wxDLG_UNIT(this, wxSize(60, -1)));
|
||||
m_gc_port_configure_button[i]->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnGameCubeConfigButton,
|
||||
this);
|
||||
|
||||
@ -157,8 +167,9 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
|
||||
const wxWindowID choice_id = wxWindow::NewControlId();
|
||||
m_gc_port_from_choice_id.emplace(choice_id, i);
|
||||
|
||||
pad_type_choices[i] = new wxChoice(this, choice_id, wxDefaultPosition, wxDefaultSize,
|
||||
m_gc_pad_type_strs.size(), m_gc_pad_type_strs.data());
|
||||
pad_type_choices[i] =
|
||||
new wxChoice(gamecube_static_sizer->GetStaticBox(), choice_id, wxDefaultPosition,
|
||||
wxDefaultSize, m_gc_pad_type_strs.size(), m_gc_pad_type_strs.data());
|
||||
|
||||
pad_type_choices[i]->Bind(wxEVT_CHOICE, &ControllerConfigDiag::OnGameCubePortChanged, this);
|
||||
|
||||
@ -199,35 +210,38 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateGamecubeSizer()
|
||||
|
||||
// Add to the sizer
|
||||
gamecube_flex_sizer->Add(pad_labels[i], 0, wxALIGN_CENTER_VERTICAL);
|
||||
gamecube_flex_sizer->Add(pad_type_choices[i], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND);
|
||||
gamecube_flex_sizer->Add(m_gc_port_configure_button[i], 1, wxEXPAND);
|
||||
gamecube_flex_sizer->Add(WxUtils::GiveMinSize(pad_type_choices[i], wxDefaultSize), 0, wxEXPAND);
|
||||
gamecube_flex_sizer->Add(m_gc_port_configure_button[i], 0, wxEXPAND);
|
||||
}
|
||||
|
||||
gamecube_static_sizer->Add(gamecube_flex_sizer, 0, wxEXPAND | wxALL, 5);
|
||||
gamecube_static_sizer->AddSpacer(5);
|
||||
|
||||
return gamecube_static_sizer;
|
||||
}
|
||||
|
||||
wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer()
|
||||
wxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer()
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
const int space20 = FromDIP(20);
|
||||
|
||||
auto* const box = new wxStaticBoxSizer(wxVERTICAL, this, _("Wiimotes"));
|
||||
|
||||
m_passthrough_bt_radio = new wxRadioButton(this, wxID_ANY, _("Passthrough a Bluetooth adapter"),
|
||||
wxDefaultPosition, wxDefaultSize, wxRB_GROUP);
|
||||
m_passthrough_bt_radio->Bind(wxEVT_RADIOBUTTON, &ControllerConfigDiag::OnBluetoothModeChanged,
|
||||
this);
|
||||
box->Add(m_passthrough_bt_radio, 0, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 5);
|
||||
box->Add(CreatePassthroughBTConfigSizer(), 0, wxALL | wxEXPAND, 5);
|
||||
box->AddSpacer(space5);
|
||||
box->Add(m_passthrough_bt_radio, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
box->AddSpacer(space5);
|
||||
box->Add(CreatePassthroughBTConfigSizer(), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
|
||||
box->AddSpacer(10);
|
||||
box->AddSpacer(space20);
|
||||
|
||||
m_emulated_bt_radio = new wxRadioButton(this, wxID_ANY, _("Emulate the Wii's Bluetooth adapter"));
|
||||
m_emulated_bt_radio->Bind(wxEVT_RADIOBUTTON, &ControllerConfigDiag::OnBluetoothModeChanged, this);
|
||||
|
||||
box->Add(m_emulated_bt_radio, 0, wxALL | wxEXPAND, 5);
|
||||
box->Add(CreateEmulatedBTConfigSizer(), 0, wxALL | wxEXPAND, 5);
|
||||
box->AddSpacer(5);
|
||||
box->Add(m_emulated_bt_radio, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
box->AddSpacer(space5);
|
||||
box->Add(CreateEmulatedBTConfigSizer(), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
box->AddSpacer(space5);
|
||||
|
||||
if (SConfig::GetInstance().m_bt_passthrough_enabled)
|
||||
m_passthrough_bt_radio->SetValue(true);
|
||||
@ -237,46 +251,45 @@ wxStaticBoxSizer* ControllerConfigDiag::CreateWiimoteConfigSizer()
|
||||
return box;
|
||||
}
|
||||
|
||||
wxBoxSizer* ControllerConfigDiag::CreatePassthroughBTConfigSizer()
|
||||
wxSizer* ControllerConfigDiag::CreatePassthroughBTConfigSizer()
|
||||
{
|
||||
auto* const sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
m_passthrough_sync_text = new wxStaticText(this, wxID_ANY, _("Sync real Wiimotes and pair them"));
|
||||
m_passthrough_sync_btn =
|
||||
new wxButton(this, wxID_ANY, _("Sync"), wxDefaultPosition, wxSize(100, -1));
|
||||
new wxButton(this, wxID_ANY, _("Sync"), wxDefaultPosition, wxDLG_UNIT(this, wxSize(60, -1)));
|
||||
m_passthrough_sync_btn->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnPassthroughScanButton, this);
|
||||
|
||||
m_passthrough_reset_text =
|
||||
new wxStaticText(this, wxID_ANY, _("Reset all saved Wiimote pairings"));
|
||||
m_passthrough_reset_btn =
|
||||
new wxButton(this, wxID_ANY, _("Reset"), wxDefaultPosition, wxSize(100, -1));
|
||||
new wxButton(this, wxID_ANY, _("Reset"), wxDefaultPosition, wxDLG_UNIT(this, wxSize(60, -1)));
|
||||
m_passthrough_reset_btn->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnPassthroughResetButton,
|
||||
this);
|
||||
|
||||
auto* const sync_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sync_sizer->Add(m_passthrough_sync_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
sync_sizer->AddStretchSpacer();
|
||||
sync_sizer->Add(m_passthrough_sync_btn, 0, wxEXPAND);
|
||||
auto* const reset_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
reset_sizer->Add(m_passthrough_reset_text, 0, wxALL | wxALIGN_CENTER_VERTICAL, 5);
|
||||
reset_sizer->AddStretchSpacer();
|
||||
reset_sizer->Add(m_passthrough_reset_btn, 0, wxEXPAND);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
sizer->Add(sync_sizer, 0, wxEXPAND);
|
||||
sizer->AddSpacer(5);
|
||||
sizer->Add(reset_sizer, 0, wxEXPAND);
|
||||
return sizer;
|
||||
auto* grid = new wxFlexGridSizer(3, space5, space5);
|
||||
grid->AddGrowableCol(1);
|
||||
|
||||
grid->Add(m_passthrough_sync_text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid->AddSpacer(1);
|
||||
grid->Add(m_passthrough_sync_btn, 0, wxEXPAND);
|
||||
|
||||
grid->Add(m_passthrough_reset_text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid->AddSpacer(1);
|
||||
grid->Add(m_passthrough_reset_btn, 0, wxEXPAND);
|
||||
|
||||
return grid;
|
||||
}
|
||||
|
||||
wxBoxSizer* ControllerConfigDiag::CreateEmulatedBTConfigSizer()
|
||||
wxSizer* ControllerConfigDiag::CreateEmulatedBTConfigSizer()
|
||||
{
|
||||
static const std::array<wxString, 4> src_choices = {
|
||||
const std::array<wxString, 4> src_choices{
|
||||
{_("None"), _("Emulated Wiimote"), _("Real Wiimote"), _("Hybrid Wiimote")}};
|
||||
|
||||
auto* const sizer = new wxBoxSizer(wxVERTICAL);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// Source selector grid
|
||||
auto* const grid = new wxFlexGridSizer(3, 5, 5);
|
||||
auto* const grid = new wxFlexGridSizer(3, space5, space5);
|
||||
grid->AddGrowableCol(1);
|
||||
|
||||
for (unsigned int i = 0; i < MAX_WIIMOTES; ++i)
|
||||
@ -296,53 +309,58 @@ wxBoxSizer* ControllerConfigDiag::CreateEmulatedBTConfigSizer()
|
||||
src_choices.size(), src_choices.data());
|
||||
m_wiimote_sources[i]->Bind(wxEVT_CHOICE, &ControllerConfigDiag::OnWiimoteSourceChanged, this);
|
||||
|
||||
m_wiimote_configure_button[i] =
|
||||
new wxButton(this, config_bt_id, _("Configure"), wxDefaultPosition, wxSize(100, -1));
|
||||
m_wiimote_configure_button[i] = new wxButton(
|
||||
this, config_bt_id, _("Configure"), wxDefaultPosition, wxDLG_UNIT(this, wxSize(60, -1)));
|
||||
m_wiimote_configure_button[i]->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnWiimoteConfigButton,
|
||||
this);
|
||||
|
||||
grid->Add(m_wiimote_labels[i], 0, wxALIGN_CENTER_VERTICAL);
|
||||
grid->Add(m_wiimote_sources[i], 0, wxALIGN_CENTER_VERTICAL | wxEXPAND);
|
||||
grid->Add(m_wiimote_configure_button[i], 1, wxEXPAND);
|
||||
grid->Add(WxUtils::GiveMinSize(m_wiimote_sources[i], wxDefaultSize), 0, wxEXPAND);
|
||||
grid->Add(m_wiimote_configure_button[i], 0, wxEXPAND);
|
||||
}
|
||||
|
||||
sizer->Add(grid, 0, wxEXPAND);
|
||||
sizer->AddSpacer(5);
|
||||
|
||||
// Scanning controls
|
||||
m_enable_continuous_scanning = new wxCheckBox(this, wxID_ANY, _("Continuous Scanning"));
|
||||
m_enable_continuous_scanning->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnContinuousScanning,
|
||||
this);
|
||||
m_enable_continuous_scanning->SetValue(SConfig::GetInstance().m_WiimoteContinuousScanning);
|
||||
m_refresh_wm_button =
|
||||
new wxButton(this, wxID_ANY, _("Refresh"), wxDefaultPosition, wxSize(100, -1));
|
||||
m_refresh_wm_button = new wxButton(this, wxID_ANY, _("Refresh"), wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(60, -1)));
|
||||
m_refresh_wm_button->Bind(wxEVT_BUTTON, &ControllerConfigDiag::OnWiimoteRefreshButton, this);
|
||||
|
||||
m_unsupported_bt_text =
|
||||
new wxStaticText(this, wxID_ANY, _("A supported Bluetooth device could not be found,\n"
|
||||
"so you must connect Wiimotes manually."));
|
||||
m_unsupported_bt_text->Show(!WiimoteReal::g_wiimote_scanner.IsReady());
|
||||
sizer->Add(m_unsupported_bt_text, 0, wxALIGN_CENTER | wxALL, 5);
|
||||
|
||||
auto* const scanning_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
scanning_sizer->Add(m_enable_continuous_scanning, 0, wxALIGN_CENTER_VERTICAL);
|
||||
scanning_sizer->AddStretchSpacer();
|
||||
scanning_sizer->Add(m_refresh_wm_button, 0, wxALL | wxEXPAND);
|
||||
sizer->Add(scanning_sizer, 0, wxEXPAND);
|
||||
|
||||
// Balance Board
|
||||
m_balance_board_checkbox = new wxCheckBox(this, wxID_ANY, _("Real Balance Board"));
|
||||
m_balance_board_checkbox->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnBalanceBoardChanged,
|
||||
this);
|
||||
m_balance_board_checkbox->SetValue(g_wiimote_sources[WIIMOTE_BALANCE_BOARD] == WIIMOTE_SRC_REAL);
|
||||
sizer->Add(m_balance_board_checkbox);
|
||||
sizer->AddSpacer(5);
|
||||
|
||||
// Speaker data
|
||||
m_enable_speaker_data = new wxCheckBox(this, wxID_ANY, _("Enable Speaker Data"));
|
||||
m_enable_speaker_data->Bind(wxEVT_CHECKBOX, &ControllerConfigDiag::OnEnableSpeaker, this);
|
||||
m_enable_speaker_data->SetValue(SConfig::GetInstance().m_WiimoteEnableSpeaker);
|
||||
sizer->Add(m_enable_speaker_data);
|
||||
|
||||
auto* const checkbox_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
checkbox_sizer->Add(m_enable_continuous_scanning);
|
||||
checkbox_sizer->AddSpacer(space5);
|
||||
checkbox_sizer->Add(m_balance_board_checkbox);
|
||||
checkbox_sizer->AddSpacer(space5);
|
||||
checkbox_sizer->Add(m_enable_speaker_data);
|
||||
|
||||
auto* const scanning_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
scanning_sizer->Add(checkbox_sizer, 1, wxEXPAND);
|
||||
scanning_sizer->Add(m_refresh_wm_button, 0, wxALIGN_TOP);
|
||||
|
||||
auto* const sizer = new wxBoxSizer(wxVERTICAL);
|
||||
sizer->Add(grid, 0, wxEXPAND);
|
||||
sizer->AddSpacer(space5);
|
||||
sizer->Add(m_unsupported_bt_text, 0, wxALIGN_CENTER | wxLEFT | wxRIGHT, space5);
|
||||
sizer->AddSpacer(space5);
|
||||
sizer->Add(scanning_sizer, 0, wxEXPAND);
|
||||
|
||||
return sizer;
|
||||
}
|
||||
@ -428,21 +446,21 @@ void ControllerConfigDiag::OnGameCubeConfigButton(wxCommandEvent& event)
|
||||
|
||||
if (SConfig::GetInstance().m_SIDevice[port_num] == SIDEVICE_GC_KEYBOARD)
|
||||
{
|
||||
InputConfigDialog m_ConfigFrame(this, *key_plugin, _("GameCube Controller Configuration"),
|
||||
port_num);
|
||||
m_ConfigFrame.ShowModal();
|
||||
InputConfigDialog config_diag(this, *key_plugin, _("GameCube Keyboard Configuration"),
|
||||
port_num);
|
||||
config_diag.ShowModal();
|
||||
}
|
||||
else if (SConfig::GetInstance().m_SIDevice[port_num] == SIDEVICE_WIIU_ADAPTER)
|
||||
{
|
||||
GCAdapterConfigDiag m_ConfigFramg(this, _("Wii U Gamecube Controller Adapter Configuration"),
|
||||
port_num);
|
||||
m_ConfigFramg.ShowModal();
|
||||
GCAdapterConfigDiag config_diag(this, _("Wii U Gamecube Controller Adapter Configuration"),
|
||||
port_num);
|
||||
config_diag.ShowModal();
|
||||
}
|
||||
else
|
||||
{
|
||||
InputConfigDialog m_ConfigFrame(this, *pad_plugin, _("GameCube Controller Configuration"),
|
||||
port_num);
|
||||
m_ConfigFrame.ShowModal();
|
||||
InputConfigDialog config_diag(this, *pad_plugin, _("GameCube Controller Configuration"),
|
||||
port_num);
|
||||
config_diag.ShowModal();
|
||||
}
|
||||
|
||||
HotkeyManagerEmu::Enable(true);
|
||||
|
@ -17,7 +17,6 @@ class InputConfig;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
class wxRadioButton;
|
||||
class wxStaticBoxSizer;
|
||||
class wxStaticText;
|
||||
|
||||
class ControllerConfigDiag final : public wxDialog
|
||||
@ -28,10 +27,10 @@ public:
|
||||
private:
|
||||
void UpdateUI();
|
||||
|
||||
wxStaticBoxSizer* CreateGamecubeSizer();
|
||||
wxStaticBoxSizer* CreateWiimoteConfigSizer();
|
||||
wxBoxSizer* CreatePassthroughBTConfigSizer();
|
||||
wxBoxSizer* CreateEmulatedBTConfigSizer();
|
||||
wxSizer* CreateGamecubeSizer();
|
||||
wxSizer* CreateWiimoteConfigSizer();
|
||||
wxSizer* CreatePassthroughBTConfigSizer();
|
||||
wxSizer* CreateEmulatedBTConfigSizer();
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnCloseButton(wxCommandEvent& event);
|
||||
|
@ -23,11 +23,15 @@ BreakPointDlg::BreakPointDlg(CBreakPointWindow* _Parent)
|
||||
|
||||
m_pEditAddress = new wxTextCtrl(this, wxID_ANY, "80000000");
|
||||
|
||||
wxBoxSizer* sMainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
sMainSizer->Add(m_pEditAddress, 0, wxEXPAND | wxALL, 5);
|
||||
sMainSizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxALL, 5);
|
||||
const int space5 = FromDIP(5);
|
||||
wxBoxSizer* main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(m_pEditAddress, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
|
||||
SetSizerAndFit(sMainSizer);
|
||||
SetSizerAndFit(main_szr);
|
||||
SetFocus();
|
||||
}
|
||||
|
||||
|
@ -25,7 +25,7 @@ CBreakPointView::CBreakPointView(wxWindow* parent, const wxWindowID id)
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void CBreakPointView::Update()
|
||||
void CBreakPointView::Repopulate()
|
||||
{
|
||||
ClearAll();
|
||||
|
||||
@ -98,6 +98,6 @@ void CBreakPointView::DeleteCurrentSelection()
|
||||
u32 Address = (u32)GetItemData(item);
|
||||
PowerPC::breakpoints.Remove(Address);
|
||||
PowerPC::memchecks.Remove(Address);
|
||||
Update();
|
||||
Repopulate();
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,6 @@ class CBreakPointView : public wxListCtrl
|
||||
public:
|
||||
CBreakPointView(wxWindow* parent, const wxWindowID id);
|
||||
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
void DeleteCurrentSelection();
|
||||
};
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
|
||||
// clang-format off
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/aui/framemanager.h>
|
||||
@ -32,11 +34,15 @@ public:
|
||||
: DolphinAuiToolBar(parent, id, wxDefaultPosition, wxDefaultSize,
|
||||
wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_TEXT)
|
||||
{
|
||||
SetToolBitmapSize(wxSize(24, 24));
|
||||
wxSize bitmap_size = FromDIP(wxSize(24, 24));
|
||||
SetToolBitmapSize(bitmap_size);
|
||||
|
||||
m_Bitmaps[Toolbar_Delete] = WxUtils::LoadResourceBitmap("toolbar_debugger_delete");
|
||||
m_Bitmaps[Toolbar_Add_BP] = WxUtils::LoadResourceBitmap("toolbar_add_breakpoint");
|
||||
m_Bitmaps[Toolbar_Add_MC] = WxUtils::LoadResourceBitmap("toolbar_add_memorycheck");
|
||||
static const std::array<const char* const, Num_Bitmaps> image_names{
|
||||
{"toolbar_debugger_delete", "toolbar_add_breakpoint", "toolbar_add_memorycheck"}};
|
||||
for (std::size_t i = 0; i < image_names.size(); ++i)
|
||||
m_Bitmaps[i] =
|
||||
WxUtils::LoadScaledResourceBitmap(image_names[i], this, bitmap_size, wxDefaultSize,
|
||||
WxUtils::LSI_SCALE_DOWN | WxUtils::LSI_ALIGN_CENTER);
|
||||
|
||||
AddTool(ID_DELETE, _("Delete"), m_Bitmaps[Toolbar_Delete]);
|
||||
Bind(wxEVT_TOOL, &CBreakPointWindow::OnDelete, parent, ID_DELETE);
|
||||
@ -84,8 +90,6 @@ CBreakPointWindow::CBreakPointWindow(CCodeWindow* _pCodeWindow, wxWindow* parent
|
||||
const wxSize& size, long style)
|
||||
: wxPanel(parent, id, position, size, style, title), m_pCodeWindow(_pCodeWindow)
|
||||
{
|
||||
Bind(wxEVT_CLOSE_WINDOW, &CBreakPointWindow::OnClose, this);
|
||||
|
||||
m_mgr.SetManagedWindow(this);
|
||||
m_mgr.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE);
|
||||
|
||||
@ -108,15 +112,9 @@ CBreakPointWindow::~CBreakPointWindow()
|
||||
m_mgr.UnInit();
|
||||
}
|
||||
|
||||
void CBreakPointWindow::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
SaveAll();
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void CBreakPointWindow::NotifyUpdate()
|
||||
{
|
||||
m_BreakPointListView->Update();
|
||||
m_BreakPointListView->Repopulate();
|
||||
}
|
||||
|
||||
void CBreakPointWindow::OnDelete(wxCommandEvent& WXUNUSED(event))
|
||||
|
@ -21,21 +21,21 @@ public:
|
||||
~CBreakPointWindow();
|
||||
|
||||
void NotifyUpdate();
|
||||
void SaveAll();
|
||||
void LoadAll();
|
||||
|
||||
private:
|
||||
friend class CBreakPointBar;
|
||||
|
||||
void OnDelete(wxCommandEvent& WXUNUSED(event));
|
||||
void OnClear(wxCommandEvent& WXUNUSED(event));
|
||||
void OnAddBreakPoint(wxCommandEvent& WXUNUSED(event));
|
||||
void OnAddMemoryCheck(wxCommandEvent& WXUNUSED(event));
|
||||
void Event_SaveAll(wxCommandEvent& WXUNUSED(event));
|
||||
void SaveAll();
|
||||
void Event_LoadAll(wxCommandEvent& WXUNUSED(event));
|
||||
void LoadAll();
|
||||
void OnSelectBP(wxListEvent& event);
|
||||
|
||||
private:
|
||||
wxAuiManager m_mgr;
|
||||
CBreakPointView* m_BreakPointListView;
|
||||
CCodeWindow* m_pCodeWindow;
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnSelectBP(wxListEvent& event);
|
||||
};
|
||||
|
@ -53,9 +53,9 @@ CCodeView::CCodeView(DebugInterface* debuginterface, SymbolDB* symboldb, wxWindo
|
||||
wxWindowID Id)
|
||||
: wxControl(parent, Id), m_debugger(debuginterface), m_symbol_db(symboldb), m_plain(false),
|
||||
m_curAddress(debuginterface->GetPC()), m_align(debuginterface->GetInstructionSize(0)),
|
||||
m_rowHeight(13), m_selection(0), m_oldSelection(0), m_selecting(false), m_lx(-1), m_ly(-1)
|
||||
m_rowHeight(FromDIP(13)), m_left_col_width(FromDIP(LEFT_COL_WIDTH)), m_selection(0),
|
||||
m_oldSelection(0), m_selecting(false)
|
||||
{
|
||||
Bind(wxEVT_ERASE_BACKGROUND, &CCodeView::OnErase, this);
|
||||
Bind(wxEVT_PAINT, &CCodeView::OnPaint, this);
|
||||
Bind(wxEVT_MOUSEWHEEL, &CCodeView::OnScrollWheel, this);
|
||||
Bind(wxEVT_LEFT_DOWN, &CCodeView::OnMouseDown, this);
|
||||
@ -65,6 +65,13 @@ CCodeView::CCodeView(DebugInterface* debuginterface, SymbolDB* symboldb, wxWindo
|
||||
Bind(wxEVT_RIGHT_UP, &CCodeView::OnMouseUpR, this);
|
||||
Bind(wxEVT_MENU, &CCodeView::OnPopupMenu, this);
|
||||
Bind(wxEVT_SIZE, &CCodeView::OnResize, this);
|
||||
|
||||
// Disable the erase event, the entire window is being painted so the erase
|
||||
// event will just cause unnecessary flicker.
|
||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
#if defined(__WXMSW__) || defined(__WXGTK__)
|
||||
SetDoubleBuffered(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
int CCodeView::YToAddress(int y)
|
||||
@ -80,7 +87,7 @@ void CCodeView::OnMouseDown(wxMouseEvent& event)
|
||||
int x = event.m_x;
|
||||
int y = event.m_y;
|
||||
|
||||
if (x > 16)
|
||||
if (x > m_left_col_width)
|
||||
{
|
||||
m_oldSelection = m_selection;
|
||||
m_selection = YToAddress(y);
|
||||
@ -131,7 +138,7 @@ void CCodeView::OnMouseMove(wxMouseEvent& event)
|
||||
{
|
||||
wxRect rc = GetClientRect();
|
||||
|
||||
if (event.m_leftDown && event.m_x > 16)
|
||||
if (event.m_leftDown && event.m_x > m_left_col_width)
|
||||
{
|
||||
if (event.m_y < 0)
|
||||
{
|
||||
@ -162,7 +169,7 @@ void CCodeView::RaiseEvent()
|
||||
|
||||
void CCodeView::OnMouseUpL(wxMouseEvent& event)
|
||||
{
|
||||
if (event.m_x > 16)
|
||||
if (event.m_x > m_left_col_width)
|
||||
{
|
||||
m_curAddress = YToAddress(event.m_y);
|
||||
m_selecting = false;
|
||||
@ -222,10 +229,6 @@ void CCodeView::InsertBlrNop(int Blr)
|
||||
|
||||
void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
||||
{
|
||||
#if wxUSE_CLIPBOARD
|
||||
wxTheClipboard->Open();
|
||||
#endif
|
||||
|
||||
switch (event.GetId())
|
||||
{
|
||||
case IDM_GOTOINMEMVIEW:
|
||||
@ -234,11 +237,15 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
case IDM_COPYADDRESS:
|
||||
{
|
||||
wxClipboardLocker locker;
|
||||
wxTheClipboard->SetData(new wxTextDataObject(wxString::Format("%08x", m_selection)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_COPYCODE:
|
||||
{
|
||||
wxClipboardLocker locker;
|
||||
std::string disasm = m_debugger->Disassemble(m_selection);
|
||||
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm)));
|
||||
}
|
||||
@ -246,8 +253,9 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
||||
|
||||
case IDM_COPYHEX:
|
||||
{
|
||||
std::string temp = StringFromFormat("%08x", m_debugger->ReadInstruction(m_selection));
|
||||
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
|
||||
wxClipboardLocker locker;
|
||||
wxTheClipboard->SetData(
|
||||
new wxTextDataObject(wxString::Format("%08x", m_debugger->ReadInstruction(m_selection))));
|
||||
}
|
||||
break;
|
||||
|
||||
@ -266,6 +274,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
||||
std::string disasm = m_debugger->Disassemble(addr);
|
||||
text += StringFromFormat("%08x: ", addr) + disasm + "\r\n";
|
||||
}
|
||||
wxClipboardLocker locker;
|
||||
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text)));
|
||||
}
|
||||
}
|
||||
@ -283,6 +292,7 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
||||
InsertBlrNop(0);
|
||||
Refresh();
|
||||
break;
|
||||
|
||||
case IDM_INSERTNOP:
|
||||
InsertBlrNop(1);
|
||||
Refresh();
|
||||
@ -332,12 +342,11 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
|
||||
|
||||
case IDM_PATCHALERT:
|
||||
break;
|
||||
}
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
wxTheClipboard->Close();
|
||||
#endif
|
||||
event.Skip();
|
||||
default:
|
||||
event.Skip();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeView::OnMouseUpR(wxMouseEvent& event)
|
||||
@ -363,104 +372,112 @@ void CCodeView::OnMouseUpR(wxMouseEvent& event)
|
||||
menu.Append(IDM_JITRESULTS, _("PPC vs X86"))->Enable(Core::IsRunning());
|
||||
menu.Append(IDM_INSERTBLR, _("Insert &blr"))->Enable(Core::IsRunning());
|
||||
menu.Append(IDM_INSERTNOP, _("Insert &nop"))->Enable(Core::IsRunning());
|
||||
menu.Append(IDM_PATCHALERT, _("Patch alert"))->Enable(Core::IsRunning());
|
||||
// menu.Append(IDM_PATCHALERT, _("Patch alert"))->Enable(Core::IsRunning());
|
||||
PopupMenu(&menu);
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void CCodeView::OnErase(wxEraseEvent& event)
|
||||
{
|
||||
}
|
||||
|
||||
void CCodeView::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
// -------------------------
|
||||
// General settings
|
||||
// -------------------------
|
||||
std::unique_ptr<wxGraphicsContext> ctx(wxGraphicsContext::Create(wxPaintDC(this)));
|
||||
wxPaintDC paint_dc(this);
|
||||
wxRect rc = GetClientRect();
|
||||
int char_width;
|
||||
|
||||
paint_dc.SetFont(DebuggerFont);
|
||||
{
|
||||
wxFontMetrics metrics = paint_dc.GetFontMetrics();
|
||||
char_width = metrics.averageWidth;
|
||||
if (metrics.height > m_rowHeight)
|
||||
m_rowHeight = metrics.height;
|
||||
}
|
||||
|
||||
std::unique_ptr<wxGraphicsContext> ctx(wxGraphicsContext::Create(paint_dc));
|
||||
ctx->DisableOffset(); // Incompatible with matrix transforms
|
||||
ctx->SetFont(DebuggerFont, *wxBLACK);
|
||||
|
||||
wxDouble w, h;
|
||||
ctx->GetTextExtent("0WJyq", &w, &h);
|
||||
|
||||
if (h > m_rowHeight)
|
||||
m_rowHeight = h;
|
||||
|
||||
ctx->GetTextExtent("W", &w, &h);
|
||||
int charWidth = w;
|
||||
|
||||
struct branch
|
||||
struct Branch
|
||||
{
|
||||
int src, dst, srcAddr;
|
||||
};
|
||||
|
||||
branch branches[256];
|
||||
int numBranches = 0;
|
||||
// TODO: Add any drawing code here...
|
||||
int width = rc.width;
|
||||
int numRows = ((rc.height / m_rowHeight) / 2) + 2;
|
||||
Branch branches[256];
|
||||
int num_branches = 0;
|
||||
const int num_rows = ((rc.height / m_rowHeight) / 2) + 2;
|
||||
|
||||
const double scale = FromDIP(1024) / 1024.0;
|
||||
const int pen_width = static_cast<int>(std::ceil(scale));
|
||||
const int col_width = rc.width - m_left_col_width;
|
||||
const int text_col = m_left_col_width + pen_width / 2 + 1; // 1 unscaled pixel
|
||||
const int bp_offset_x = FromDIP(LEFT_COL_WIDTH / 8);
|
||||
const wxSize bp_size = FromDIP(wxSize(LEFT_COL_WIDTH * 3 / 4, LEFT_COL_WIDTH * 3 / 4));
|
||||
const int bp_offset_y = (m_rowHeight - bp_size.GetHeight()) / 2;
|
||||
// ------------
|
||||
|
||||
// -------------------------
|
||||
// Colors and brushes
|
||||
// -------------------------
|
||||
|
||||
const wxColour bgColor = *wxWHITE;
|
||||
wxPen nullPen(bgColor);
|
||||
wxPen currentPen(*wxBLACK_PEN);
|
||||
wxPen selPen(*wxGREY_PEN);
|
||||
nullPen.SetStyle(wxPENSTYLE_TRANSPARENT);
|
||||
currentPen.SetStyle(wxPENSTYLE_SOLID);
|
||||
wxBrush currentBrush(*wxLIGHT_GREY_BRUSH);
|
||||
wxBrush pcBrush(*wxGREEN_BRUSH);
|
||||
wxBrush bpBrush(*wxRED_BRUSH);
|
||||
wxColour branch_color = wxTheColourDatabase->Find("PURPLE");
|
||||
wxColour blr_color = wxTheColourDatabase->Find("DARK GREEN");
|
||||
wxColour instr_color = wxTheColourDatabase->Find("VIOLET");
|
||||
wxGraphicsPen null_pen = ctx->CreatePen(*wxTRANSPARENT_PEN);
|
||||
wxGraphicsPen focus_pen = ctx->CreatePen(wxPen(*wxBLACK, pen_width));
|
||||
wxGraphicsPen selection_pen = ctx->CreatePen(wxPen("GREY", pen_width));
|
||||
wxGraphicsBrush pc_brush = ctx->CreateBrush(*wxGREEN_BRUSH);
|
||||
wxGraphicsBrush bp_brush = ctx->CreateBrush(*wxRED_BRUSH);
|
||||
wxGraphicsBrush back_brush = ctx->CreateBrush(*wxWHITE_BRUSH);
|
||||
wxGraphicsBrush null_brush = ctx->CreateBrush(*wxTRANSPARENT_BRUSH);
|
||||
|
||||
wxBrush bgBrush(bgColor);
|
||||
wxBrush nullBrush(bgColor);
|
||||
nullBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);
|
||||
|
||||
ctx->SetPen(nullPen);
|
||||
ctx->SetBrush(bgBrush);
|
||||
ctx->DrawRectangle(0, 0, 16, rc.height);
|
||||
ctx->DrawRectangle(0, 0, rc.width, 5);
|
||||
// ------------
|
||||
|
||||
// -----------------------------
|
||||
// Walk through all visible rows
|
||||
// -----------------------------
|
||||
for (int i = -numRows; i <= numRows; i++)
|
||||
for (int i = -num_rows; i <= num_rows; i++)
|
||||
{
|
||||
unsigned int address = m_curAddress + (i * m_align);
|
||||
|
||||
int rowY1 = (rc.height / 2) + (m_rowHeight * i) - (m_rowHeight / 2);
|
||||
int rowY2 = (rc.height / 2) + (m_rowHeight * i) + (m_rowHeight / 2);
|
||||
int row_y = (rc.height / 2) + (m_rowHeight * i) - (m_rowHeight / 2);
|
||||
|
||||
wxString temp = wxString::Format("%08x", address);
|
||||
u32 color = m_debugger->GetColor(address);
|
||||
wxBrush rowBrush(wxColour(color >> 16, color >> 8, color));
|
||||
ctx->SetBrush(nullBrush);
|
||||
ctx->SetPen(nullPen);
|
||||
ctx->DrawRectangle(0, rowY1, 16, rowY2 - rowY1 + 2);
|
||||
|
||||
if (m_selecting && (address == m_selection))
|
||||
ctx->SetPen(selPen);
|
||||
else
|
||||
ctx->SetPen(i == 0 ? currentPen : nullPen);
|
||||
wxBrush row_brush(wxColour(color >> 16, color >> 8, color));
|
||||
ctx->SetBrush(back_brush);
|
||||
ctx->SetPen(null_pen);
|
||||
ctx->DrawRectangle(0, row_y, m_left_col_width, m_rowHeight);
|
||||
|
||||
if (address == m_debugger->GetPC())
|
||||
ctx->SetBrush(pcBrush);
|
||||
ctx->SetBrush(pc_brush);
|
||||
else
|
||||
ctx->SetBrush(rowBrush);
|
||||
ctx->SetBrush(row_brush);
|
||||
|
||||
ctx->SetPen(null_pen);
|
||||
ctx->DrawRectangle(m_left_col_width, row_y, col_width, m_rowHeight);
|
||||
if (i == 0 || (m_selecting && address == m_selection))
|
||||
{
|
||||
if (m_selecting && address == m_selection)
|
||||
ctx->SetPen(selection_pen);
|
||||
else
|
||||
ctx->SetPen(focus_pen);
|
||||
ctx->SetBrush(null_brush);
|
||||
// In a graphics context, the border of a rectangle is drawn along the edge,
|
||||
// it does not count towards the width of the rectangle (i.e. drawn right on
|
||||
// the pixel boundary of the fill area, half inside, half outside. For example
|
||||
// a rect with a 1px pen at (5,5)->(10,10) will have an actual screen size of
|
||||
// (4.5,4.5)->(10.5,10.5) with the line being aliased on the half-pixels)
|
||||
double offset = pen_width / 2.0;
|
||||
ctx->DrawRectangle(m_left_col_width + offset, row_y + offset, col_width - pen_width,
|
||||
m_rowHeight - pen_width);
|
||||
}
|
||||
|
||||
ctx->DrawRectangle(16, rowY1, width, rowY2 - rowY1 + 1);
|
||||
ctx->SetBrush(currentBrush);
|
||||
if (!m_plain)
|
||||
{
|
||||
// the address text is dark red
|
||||
ctx->SetFont(DebuggerFont, wxColour("#600000"));
|
||||
ctx->DrawText(temp, 17, rowY1);
|
||||
ctx->SetFont(DebuggerFont, wxColour(0x60, 0x00, 0x00));
|
||||
ctx->DrawText(temp, text_col, row_y);
|
||||
ctx->SetFont(DebuggerFont, *wxBLACK);
|
||||
}
|
||||
|
||||
@ -488,31 +505,32 @@ void CCodeView::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
u32 offs = std::stoul(hex_str, nullptr, 16);
|
||||
|
||||
branches[numBranches].src = rowY1 + (m_rowHeight / 2);
|
||||
branches[numBranches].srcAddr = (address / m_align);
|
||||
branches[numBranches++].dst =
|
||||
(int)(rowY1 + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align +
|
||||
branches[num_branches].src = row_y + (m_rowHeight / 2);
|
||||
branches[num_branches].srcAddr = (address / m_align);
|
||||
branches[num_branches++].dst =
|
||||
(int)(row_y + ((s64)(u32)offs - (s64)(u32)address) * m_rowHeight / m_align +
|
||||
m_rowHeight / 2);
|
||||
desc = StringFromFormat("-->%s", m_debugger->GetDescription(offs).c_str());
|
||||
|
||||
// the -> arrow illustrations are purple
|
||||
ctx->SetFont(DebuggerFont, wxTheColourDatabase->Find("PURPLE"));
|
||||
ctx->SetFont(DebuggerFont, branch_color);
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx->SetFont(DebuggerFont, *wxBLACK);
|
||||
}
|
||||
|
||||
ctx->DrawText(StrToWxStr(operands), 17 + 17 * charWidth, rowY1);
|
||||
ctx->DrawText(StrToWxStr(operands), text_col + 17 * char_width, row_y);
|
||||
// ------------
|
||||
|
||||
// Show blr as its' own color
|
||||
if (opcode == "blr")
|
||||
ctx->SetFont(DebuggerFont, wxTheColourDatabase->Find("DARK GREEN"));
|
||||
ctx->SetFont(DebuggerFont, blr_color);
|
||||
else
|
||||
ctx->SetFont(DebuggerFont, wxTheColourDatabase->Find("VIOLET"));
|
||||
ctx->SetFont(DebuggerFont, instr_color);
|
||||
|
||||
ctx->DrawText(StrToWxStr(opcode), 17 + (m_plain ? 1 * charWidth : 9 * charWidth), rowY1);
|
||||
ctx->DrawText(StrToWxStr(opcode), text_col + (m_plain ? 1 * char_width : 9 * char_width),
|
||||
row_y);
|
||||
|
||||
if (desc.empty())
|
||||
{
|
||||
@ -527,15 +545,16 @@ void CCodeView::OnPaint(wxPaintEvent& event)
|
||||
// UnDecorateSymbolName(desc,temp,255,UNDNAME_COMPLETE);
|
||||
if (!desc.empty())
|
||||
{
|
||||
ctx->DrawText(StrToWxStr(desc), 17 + 35 * charWidth, rowY1);
|
||||
ctx->DrawText(StrToWxStr(desc), text_col + 45 * char_width, row_y);
|
||||
}
|
||||
}
|
||||
|
||||
// Show red breakpoint dot
|
||||
if (m_debugger->IsBreakpoint(address))
|
||||
{
|
||||
ctx->SetBrush(bpBrush);
|
||||
ctx->DrawRectangle(2, rowY1 + 1, 11, 11);
|
||||
ctx->SetPen(null_pen);
|
||||
ctx->SetBrush(bp_brush);
|
||||
ctx->DrawEllipse(bp_offset_x, row_y + bp_offset_y, bp_size.GetWidth(), bp_size.GetHeight());
|
||||
}
|
||||
}
|
||||
} // end of for
|
||||
@ -544,22 +563,24 @@ void CCodeView::OnPaint(wxPaintEvent& event)
|
||||
// -------------------------
|
||||
// Colors and brushes
|
||||
// -------------------------
|
||||
ctx->SetPen(currentPen);
|
||||
ctx->SetPen(focus_pen);
|
||||
|
||||
for (int i = 0; i < numBranches; i++)
|
||||
wxGraphicsPath branch_path = ctx->CreatePath();
|
||||
|
||||
for (int i = 0; i < num_branches; ++i)
|
||||
{
|
||||
int x = 17 + 49 * charWidth + (branches[i].srcAddr % 9) * 8;
|
||||
MoveTo(x - 2, branches[i].src);
|
||||
int x = text_col + 52 * char_width + (branches[i].srcAddr % 9) * 8;
|
||||
branch_path.MoveToPoint(x - 2 * scale, branches[i].src);
|
||||
|
||||
if (branches[i].dst < rc.height + 400 && branches[i].dst > -400)
|
||||
{
|
||||
LineTo(ctx, x + 2, branches[i].src);
|
||||
LineTo(ctx, x + 2, branches[i].dst);
|
||||
LineTo(ctx, x - 4, branches[i].dst);
|
||||
branch_path.AddLineToPoint(x + 2 * scale, branches[i].src);
|
||||
branch_path.AddLineToPoint(x + 2 * scale, branches[i].dst);
|
||||
branch_path.AddLineToPoint(x - 4 * scale, branches[i].dst);
|
||||
|
||||
MoveTo(x, branches[i].dst - 4);
|
||||
LineTo(ctx, x - 4, branches[i].dst);
|
||||
LineTo(ctx, x + 1, branches[i].dst + 5);
|
||||
branch_path.MoveToPoint(x, branches[i].dst - 4 * scale);
|
||||
branch_path.AddLineToPoint(x - 4 * scale, branches[i].dst);
|
||||
branch_path.AddLineToPoint(x + 1 * scale, branches[i].dst + 5 * scale);
|
||||
}
|
||||
// else
|
||||
//{
|
||||
@ -575,18 +596,19 @@ void CCodeView::OnPaint(wxPaintEvent& event)
|
||||
// LineTo(ctx, x, branches[i].dst+4);
|
||||
// LineTo(ctx, x-2, branches[i].dst);
|
||||
}
|
||||
|
||||
// If the pen width is odd then we need to offset the path so that lines are drawn in
|
||||
// the middle of pixels instead of the edge so we don't get aliasing.
|
||||
if (pen_width & 1)
|
||||
{
|
||||
wxGraphicsMatrix matrix = ctx->CreateMatrix();
|
||||
matrix.Translate(0.5, 0.5);
|
||||
branch_path.Transform(matrix);
|
||||
}
|
||||
ctx->StrokePath(branch_path);
|
||||
// ------------
|
||||
}
|
||||
|
||||
void CCodeView::LineTo(std::unique_ptr<wxGraphicsContext>& ctx, int x, int y)
|
||||
{
|
||||
std::vector<wxPoint2DDouble> points{wxPoint2DDouble(m_lx, m_ly), wxPoint2DDouble(x, y)};
|
||||
|
||||
ctx->DrawLines(points.size(), points.data());
|
||||
m_lx = x;
|
||||
m_ly = y;
|
||||
}
|
||||
|
||||
void CCodeView::OnResize(wxSizeEvent& event)
|
||||
{
|
||||
Refresh();
|
||||
|
@ -40,7 +40,6 @@ public:
|
||||
void SetPlain() { m_plain = true; }
|
||||
private:
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnErase(wxEraseEvent& event);
|
||||
void OnScrollWheel(wxMouseEvent& event);
|
||||
void OnMouseDown(wxMouseEvent& event);
|
||||
void OnMouseMove(wxMouseEvent& event);
|
||||
@ -55,14 +54,6 @@ private:
|
||||
u32 AddrToBranch(u32 addr);
|
||||
void OnResize(wxSizeEvent& event);
|
||||
|
||||
void MoveTo(int x, int y)
|
||||
{
|
||||
m_lx = x;
|
||||
m_ly = y;
|
||||
}
|
||||
|
||||
void LineTo(std::unique_ptr<wxGraphicsContext>& dc, int x, int y);
|
||||
|
||||
struct BlrStruct // for IDM_INSERTBLR
|
||||
{
|
||||
u32 address;
|
||||
@ -70,6 +61,8 @@ private:
|
||||
};
|
||||
std::vector<BlrStruct> m_blrList;
|
||||
|
||||
static constexpr int LEFT_COL_WIDTH = 16;
|
||||
|
||||
DebugInterface* m_debugger;
|
||||
SymbolDB* m_symbol_db;
|
||||
|
||||
@ -78,10 +71,9 @@ private:
|
||||
int m_curAddress;
|
||||
int m_align;
|
||||
int m_rowHeight;
|
||||
int m_left_col_width;
|
||||
|
||||
u32 m_selection;
|
||||
u32 m_oldSelection;
|
||||
bool m_selecting;
|
||||
|
||||
int m_lx, m_ly;
|
||||
};
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -43,6 +44,7 @@
|
||||
#include "DolphinWX/Debugger/CodeWindow.h"
|
||||
#include "DolphinWX/Debugger/DebuggerUIUtil.h"
|
||||
#include "DolphinWX/Debugger/JitWindow.h"
|
||||
#include "DolphinWX/Debugger/MemoryWindow.h"
|
||||
#include "DolphinWX/Debugger/RegisterWindow.h"
|
||||
#include "DolphinWX/Debugger/WatchWindow.h"
|
||||
#include "DolphinWX/AuiToolBar.h"
|
||||
@ -53,9 +55,8 @@
|
||||
CCodeWindow::CCodeWindow(const SConfig& _LocalCoreStartupParameter, CFrame* parent, wxWindowID id,
|
||||
const wxPoint& position, const wxSize& size, long style,
|
||||
const wxString& name)
|
||||
: wxPanel(parent, id, position, size, style, name), Parent(parent), m_RegisterWindow(nullptr),
|
||||
m_WatchWindow(nullptr), m_BreakpointWindow(nullptr), m_MemoryWindow(nullptr),
|
||||
m_JitWindow(nullptr), m_SoundWindow(nullptr), m_VideoWindow(nullptr), codeview(nullptr)
|
||||
: wxPanel(parent, id, position, size, style, name), m_sibling_panels(), Parent(parent),
|
||||
codeview(nullptr)
|
||||
{
|
||||
InitBitmaps();
|
||||
|
||||
@ -87,21 +88,31 @@ CCodeWindow::CCodeWindow(const SConfig& _LocalCoreStartupParameter, CFrame* pare
|
||||
|
||||
m_aui_manager.SetManagedWindow(this);
|
||||
m_aui_manager.SetFlags(wxAUI_MGR_DEFAULT | wxAUI_MGR_LIVE_RESIZE);
|
||||
m_aui_manager.AddPane(m_aui_toolbar,
|
||||
wxAuiPaneInfo().MinSize(150, -1).ToolbarPane().Top().Floatable(false));
|
||||
m_aui_manager.AddPane(
|
||||
callstack,
|
||||
wxAuiPaneInfo().MinSize(150, 100).Left().CloseButton(false).Floatable(false).Caption(
|
||||
_("Callstack")));
|
||||
m_aui_manager.AddPane(
|
||||
symbols, wxAuiPaneInfo().MinSize(150, 100).Left().CloseButton(false).Floatable(false).Caption(
|
||||
_("Symbols")));
|
||||
m_aui_manager.AddPane(
|
||||
calls, wxAuiPaneInfo().MinSize(150, 100).Left().CloseButton(false).Floatable(false).Caption(
|
||||
_("Function calls")));
|
||||
m_aui_manager.AddPane(
|
||||
callers, wxAuiPaneInfo().MinSize(150, 100).Left().CloseButton(false).Floatable(false).Caption(
|
||||
_("Function callers")));
|
||||
m_aui_manager.AddPane(m_aui_toolbar, wxAuiPaneInfo().ToolbarPane().Top().Floatable(false));
|
||||
m_aui_manager.AddPane(callstack, wxAuiPaneInfo()
|
||||
.MinSize(FromDIP(wxSize(150, 100)))
|
||||
.Left()
|
||||
.CloseButton(false)
|
||||
.Floatable(false)
|
||||
.Caption(_("Callstack")));
|
||||
m_aui_manager.AddPane(symbols, wxAuiPaneInfo()
|
||||
.MinSize(FromDIP(wxSize(150, 100)))
|
||||
.Left()
|
||||
.CloseButton(false)
|
||||
.Floatable(false)
|
||||
.Caption(_("Symbols")));
|
||||
m_aui_manager.AddPane(calls, wxAuiPaneInfo()
|
||||
.MinSize(FromDIP(wxSize(150, 100)))
|
||||
.Left()
|
||||
.CloseButton(false)
|
||||
.Floatable(false)
|
||||
.Caption(_("Function calls")));
|
||||
m_aui_manager.AddPane(callers, wxAuiPaneInfo()
|
||||
.MinSize(FromDIP(wxSize(150, 100)))
|
||||
.Left()
|
||||
.CloseButton(false)
|
||||
.Floatable(false)
|
||||
.Caption(_("Function callers")));
|
||||
m_aui_manager.AddPane(codeview, wxAuiPaneInfo().CenterPane().CloseButton(false).Floatable(false));
|
||||
m_aui_manager.Update();
|
||||
|
||||
@ -143,30 +154,30 @@ void CCodeWindow::OnHostMessage(wxCommandEvent& event)
|
||||
{
|
||||
case IDM_NOTIFY_MAP_LOADED:
|
||||
NotifyMapLoaded();
|
||||
if (m_BreakpointWindow)
|
||||
m_BreakpointWindow->NotifyUpdate();
|
||||
if (HasPanel<CBreakPointWindow>())
|
||||
GetPanel<CBreakPointWindow>()->NotifyUpdate();
|
||||
break;
|
||||
|
||||
case IDM_UPDATE_DISASM_DIALOG:
|
||||
Update();
|
||||
if (CPU::IsStepping())
|
||||
Parent->UpdateGUI();
|
||||
if (m_RegisterWindow)
|
||||
m_RegisterWindow->NotifyUpdate();
|
||||
if (m_WatchWindow)
|
||||
m_WatchWindow->NotifyUpdate();
|
||||
Repopulate();
|
||||
if (HasPanel<CRegisterWindow>())
|
||||
GetPanel<CRegisterWindow>()->NotifyUpdate();
|
||||
if (HasPanel<CWatchWindow>())
|
||||
GetPanel<CWatchWindow>()->NotifyUpdate();
|
||||
if (HasPanel<CMemoryWindow>())
|
||||
GetPanel<CMemoryWindow>()->Refresh();
|
||||
break;
|
||||
|
||||
case IDM_UPDATE_BREAKPOINTS:
|
||||
if (m_BreakpointWindow)
|
||||
m_BreakpointWindow->NotifyUpdate();
|
||||
Repopulate();
|
||||
if (HasPanel<CBreakPointWindow>())
|
||||
GetPanel<CBreakPointWindow>()->NotifyUpdate();
|
||||
if (HasPanel<CMemoryWindow>())
|
||||
GetPanel<CMemoryWindow>()->Refresh();
|
||||
break;
|
||||
|
||||
case IDM_UPDATE_JIT_PANE:
|
||||
// Check if the JIT pane is in the AUI notebook. If not, add it and switch to it.
|
||||
if (!m_JitWindow)
|
||||
ToggleJitWindow(true);
|
||||
m_JitWindow->ViewAddr(codeview->GetSelection());
|
||||
RequirePanel<CJitWindow>()->ViewAddr(codeview->GetSelection());
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -194,12 +205,12 @@ void CCodeWindow::OnCodeStep(wxCommandEvent& event)
|
||||
|
||||
case IDM_SKIP:
|
||||
PC += 4;
|
||||
Update();
|
||||
Repopulate();
|
||||
break;
|
||||
|
||||
case IDM_SETPC:
|
||||
PC = codeview->GetSelection();
|
||||
Update();
|
||||
Repopulate();
|
||||
break;
|
||||
|
||||
case IDM_GOTOPC:
|
||||
@ -372,8 +383,12 @@ void CCodeWindow::StepOut()
|
||||
PowerPC::SetMode(old_mode);
|
||||
CPU::PauseAndLock(false, false);
|
||||
|
||||
Host_UpdateDisasmDialog();
|
||||
UpdateButtonStates();
|
||||
JumpToAddress(PC);
|
||||
{
|
||||
wxCommandEvent ev(wxEVT_HOST_COMMAND, IDM_UPDATE_DISASM_DIALOG);
|
||||
GetEventHandler()->ProcessEvent(ev);
|
||||
}
|
||||
|
||||
// Update all toolbars in the aui manager
|
||||
Parent->UpdateGUI();
|
||||
}
|
||||
@ -385,7 +400,7 @@ void CCodeWindow::ToggleBreakpoint()
|
||||
{
|
||||
if (codeview)
|
||||
codeview->ToggleBreakpoint(codeview->GetSelection());
|
||||
Update();
|
||||
Repopulate();
|
||||
}
|
||||
}
|
||||
|
||||
@ -666,19 +681,18 @@ bool CCodeWindow::JITNoBlockLinking()
|
||||
// Toolbar
|
||||
void CCodeWindow::InitBitmaps()
|
||||
{
|
||||
m_Bitmaps[Toolbar_Step] = WxUtils::LoadResourceBitmap("toolbar_debugger_step");
|
||||
m_Bitmaps[Toolbar_StepOver] = WxUtils::LoadResourceBitmap("toolbar_debugger_step_over");
|
||||
m_Bitmaps[Toolbar_StepOut] = WxUtils::LoadResourceBitmap("toolbar_debugger_step_out");
|
||||
m_Bitmaps[Toolbar_Skip] = WxUtils::LoadResourceBitmap("toolbar_debugger_skip");
|
||||
m_Bitmaps[Toolbar_GotoPC] = WxUtils::LoadResourceBitmap("toolbar_debugger_goto_pc");
|
||||
m_Bitmaps[Toolbar_SetPC] = WxUtils::LoadResourceBitmap("toolbar_debugger_set_pc");
|
||||
static constexpr std::array<const char* const, Toolbar_Debug_Bitmap_Max> s_image_names{
|
||||
{"toolbar_debugger_step", "toolbar_debugger_step_over", "toolbar_debugger_step_out",
|
||||
"toolbar_debugger_skip", "toolbar_debugger_goto_pc", "toolbar_debugger_set_pc"}};
|
||||
const wxSize tool_size = Parent->GetToolbarBitmapSize();
|
||||
for (std::size_t i = 0; i < s_image_names.size(); ++i)
|
||||
m_Bitmaps[i] =
|
||||
WxUtils::LoadScaledResourceBitmap(s_image_names[i], Parent, tool_size, wxDefaultSize,
|
||||
WxUtils::LSI_SCALE_DOWN | WxUtils::LSI_ALIGN_CENTER);
|
||||
}
|
||||
|
||||
void CCodeWindow::PopulateToolbar(wxToolBar* toolBar)
|
||||
{
|
||||
int w = m_Bitmaps[0].GetWidth(), h = m_Bitmaps[0].GetHeight();
|
||||
|
||||
toolBar->SetToolBitmapSize(wxSize(w, h));
|
||||
WxUtils::AddToolbarButton(toolBar, IDM_STEP, _("Step"), m_Bitmaps[Toolbar_Step],
|
||||
_("Step into the next instruction"));
|
||||
WxUtils::AddToolbarButton(toolBar, IDM_STEPOVER, _("Step Over"), m_Bitmaps[Toolbar_StepOver],
|
||||
@ -695,7 +709,7 @@ void CCodeWindow::PopulateToolbar(wxToolBar* toolBar)
|
||||
}
|
||||
|
||||
// Update GUI
|
||||
void CCodeWindow::Update()
|
||||
void CCodeWindow::Repopulate()
|
||||
{
|
||||
if (!codeview)
|
||||
return;
|
||||
@ -714,41 +728,28 @@ void CCodeWindow::UpdateButtonStates()
|
||||
bool Initialized = (Core::GetState() != Core::CORE_UNINITIALIZED);
|
||||
bool Pause = (Core::GetState() == Core::CORE_PAUSE);
|
||||
bool Stepping = CPU::IsStepping();
|
||||
bool can_step = Initialized && Stepping;
|
||||
wxToolBar* ToolBar = GetToolBar();
|
||||
|
||||
// Toolbar
|
||||
if (!ToolBar)
|
||||
return;
|
||||
|
||||
if (!Initialized)
|
||||
{
|
||||
ToolBar->EnableTool(IDM_STEPOVER, false);
|
||||
ToolBar->EnableTool(IDM_STEPOUT, false);
|
||||
ToolBar->EnableTool(IDM_SKIP, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Stepping)
|
||||
{
|
||||
ToolBar->EnableTool(IDM_STEPOVER, false);
|
||||
ToolBar->EnableTool(IDM_STEPOUT, false);
|
||||
ToolBar->EnableTool(IDM_SKIP, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
ToolBar->EnableTool(IDM_STEPOVER, true);
|
||||
ToolBar->EnableTool(IDM_STEPOUT, true);
|
||||
ToolBar->EnableTool(IDM_SKIP, true);
|
||||
}
|
||||
}
|
||||
|
||||
ToolBar->EnableTool(IDM_STEP, Initialized && Stepping);
|
||||
ToolBar->EnableTool(IDM_STEP, can_step);
|
||||
ToolBar->EnableTool(IDM_STEPOVER, can_step);
|
||||
ToolBar->EnableTool(IDM_STEPOUT, can_step);
|
||||
ToolBar->EnableTool(IDM_SKIP, can_step);
|
||||
ToolBar->EnableTool(IDM_SETPC, Pause);
|
||||
ToolBar->Realize();
|
||||
|
||||
// Menu bar
|
||||
// ------------------
|
||||
GetMenuBar()->Enable(IDM_INTERPRETER, Pause); // CPU Mode
|
||||
|
||||
GetMenuBar()->Enable(IDM_STEP, can_step);
|
||||
GetMenuBar()->Enable(IDM_STEPOVER, can_step);
|
||||
GetMenuBar()->Enable(IDM_STEPOUT, can_step);
|
||||
|
||||
GetMenuBar()->Enable(IDM_JIT_NO_BLOCK_CACHE, !Initialized);
|
||||
|
||||
GetMenuBar()->Enable(IDM_JIT_OFF, Pause);
|
||||
|
@ -4,6 +4,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <wx/aui/framemanager.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/panel.h>
|
||||
@ -12,16 +14,16 @@
|
||||
#include "Common/Event.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
|
||||
class CCodeView;
|
||||
class CFrame;
|
||||
struct SConfig;
|
||||
class CBreakPointWindow;
|
||||
class CRegisterWindow;
|
||||
class CWatchWindow;
|
||||
class CBreakPointWindow;
|
||||
class CMemoryWindow;
|
||||
class CJitWindow;
|
||||
class CCodeView;
|
||||
class DSPDebuggerLLE;
|
||||
class GFXDebuggerPanel;
|
||||
struct SConfig;
|
||||
|
||||
class DolphinAuiToolBar;
|
||||
class wxListBox;
|
||||
@ -29,6 +31,48 @@ class wxMenu;
|
||||
class wxMenuBar;
|
||||
class wxToolBar;
|
||||
|
||||
namespace Details
|
||||
{
|
||||
template <class T>
|
||||
struct DebugPanelToID;
|
||||
|
||||
template <>
|
||||
struct DebugPanelToID<CBreakPointWindow>
|
||||
{
|
||||
static constexpr int ID = IDM_BREAKPOINT_WINDOW;
|
||||
};
|
||||
template <>
|
||||
struct DebugPanelToID<CRegisterWindow>
|
||||
{
|
||||
static constexpr int ID = IDM_REGISTER_WINDOW;
|
||||
};
|
||||
template <>
|
||||
struct DebugPanelToID<CWatchWindow>
|
||||
{
|
||||
static constexpr int ID = IDM_WATCH_WINDOW;
|
||||
};
|
||||
template <>
|
||||
struct DebugPanelToID<CMemoryWindow>
|
||||
{
|
||||
static constexpr int ID = IDM_MEMORY_WINDOW;
|
||||
};
|
||||
template <>
|
||||
struct DebugPanelToID<CJitWindow>
|
||||
{
|
||||
static constexpr int ID = IDM_JIT_WINDOW;
|
||||
};
|
||||
template <>
|
||||
struct DebugPanelToID<DSPDebuggerLLE>
|
||||
{
|
||||
static constexpr int ID = IDM_SOUND_WINDOW;
|
||||
};
|
||||
template <>
|
||||
struct DebugPanelToID<GFXDebuggerPanel>
|
||||
{
|
||||
static constexpr int ID = IDM_VIDEO_WINDOW;
|
||||
};
|
||||
}
|
||||
|
||||
class CCodeWindow : public wxPanel
|
||||
{
|
||||
public:
|
||||
@ -41,10 +85,8 @@ public:
|
||||
void Save();
|
||||
|
||||
// Parent interaction
|
||||
CFrame* Parent;
|
||||
wxMenuBar* GetMenuBar();
|
||||
wxToolBar* GetToolBar();
|
||||
wxBitmap m_Bitmaps[Toolbar_Debug_Bitmap_Max];
|
||||
|
||||
bool UseInterpreter();
|
||||
bool BootToPause();
|
||||
@ -53,7 +95,7 @@ public:
|
||||
bool JITNoBlockLinking();
|
||||
bool JumpToAddress(u32 address);
|
||||
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
void NotifyMapLoaded();
|
||||
void CreateMenu(const SConfig& _LocalCoreStartupParameter, wxMenuBar* pMenuBar);
|
||||
void CreateMenuOptions(wxMenu* pMenu);
|
||||
@ -63,29 +105,35 @@ public:
|
||||
void OpenPages();
|
||||
|
||||
// Menu bar
|
||||
void ToggleCodeWindow(bool bShow);
|
||||
void ToggleRegisterWindow(bool bShow);
|
||||
void ToggleWatchWindow(bool bShow);
|
||||
void ToggleBreakPointWindow(bool bShow);
|
||||
void ToggleMemoryWindow(bool bShow);
|
||||
void ToggleJitWindow(bool bShow);
|
||||
void ToggleSoundWindow(bool bShow);
|
||||
void ToggleVideoWindow(bool bShow);
|
||||
// FIXME: This belongs in a separate class.
|
||||
void TogglePanel(int id, bool show);
|
||||
wxPanel* GetUntypedPanel(int id) const;
|
||||
bool HasUntypedPanel(int id) const { return GetUntypedPanel(id) != nullptr; }
|
||||
template <class T>
|
||||
T* GetPanel() const
|
||||
{
|
||||
return static_cast<T*>(GetUntypedPanel(Details::DebugPanelToID<T>::ID));
|
||||
}
|
||||
template <class T>
|
||||
bool HasPanel() const
|
||||
{
|
||||
return HasUntypedPanel(Details::DebugPanelToID<T>::ID);
|
||||
}
|
||||
template <class T>
|
||||
T* RequirePanel()
|
||||
{
|
||||
if (T* p = GetPanel<T>())
|
||||
return p;
|
||||
|
||||
// Sub dialogs
|
||||
CRegisterWindow* m_RegisterWindow;
|
||||
CWatchWindow* m_WatchWindow;
|
||||
CBreakPointWindow* m_BreakpointWindow;
|
||||
CMemoryWindow* m_MemoryWindow;
|
||||
CJitWindow* m_JitWindow;
|
||||
DSPDebuggerLLE* m_SoundWindow;
|
||||
GFXDebuggerPanel* m_VideoWindow;
|
||||
TogglePanel(Details::DebugPanelToID<T>::ID, true);
|
||||
return GetPanel<T>();
|
||||
}
|
||||
|
||||
// Settings
|
||||
bool bAutomaticStart;
|
||||
bool bBootToPause;
|
||||
bool bShowOnStart[IDM_VIDEO_WINDOW - IDM_LOG_WINDOW + 1];
|
||||
int iNbAffiliation[IDM_CODE_WINDOW - IDM_LOG_WINDOW + 1];
|
||||
bool bShowOnStart[IDM_DEBUG_WINDOW_LIST_END - IDM_DEBUG_WINDOW_LIST_START];
|
||||
int iNbAffiliation[IDM_DEBUG_WINDOW_LIST_END - IDM_DEBUG_WINDOW_LIST_START];
|
||||
|
||||
private:
|
||||
void OnCPUMode(wxCommandEvent& event);
|
||||
@ -99,7 +147,6 @@ private:
|
||||
void OnProfilerMenu(wxCommandEvent& event);
|
||||
|
||||
void OnSymbolListChange(wxCommandEvent& event);
|
||||
void OnSymbolListContextMenu(wxContextMenuEvent& event);
|
||||
void OnCallstackListChange(wxCommandEvent& event);
|
||||
void OnCallersListChange(wxCommandEvent& event);
|
||||
void OnCallsListChange(wxCommandEvent& event);
|
||||
@ -116,7 +163,15 @@ private:
|
||||
void UpdateCallstack();
|
||||
|
||||
void InitBitmaps();
|
||||
wxPanel* CreateSiblingPanel(int id);
|
||||
|
||||
wxBitmap m_Bitmaps[Toolbar_Debug_Bitmap_Max];
|
||||
|
||||
// Sibling debugger panels
|
||||
// FIXME: This obviously belongs in some manager class above this one.
|
||||
std::array<wxPanel*, IDM_DEBUG_WINDOW_LIST_END - IDM_DEBUG_WINDOW_LIST_START> m_sibling_panels;
|
||||
|
||||
CFrame* Parent;
|
||||
CCodeView* codeview;
|
||||
wxListBox* callstack;
|
||||
wxListBox* symbols;
|
||||
|
@ -453,7 +453,7 @@ void CCodeWindow::OnSymbolsMenu(wxCommandEvent& event)
|
||||
break;
|
||||
case IDM_PATCH_HLE_FUNCTIONS:
|
||||
HLE::PatchFunctions();
|
||||
Update();
|
||||
Repopulate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -464,7 +464,6 @@ void CCodeWindow::NotifyMapLoaded()
|
||||
return;
|
||||
|
||||
g_symbolDB.FillInCallers();
|
||||
// symbols->Show(false); // hide it for faster filling
|
||||
symbols->Freeze(); // HyperIris: wx style fast filling
|
||||
symbols->Clear();
|
||||
for (const auto& symbol : g_symbolDB.Symbols())
|
||||
@ -473,8 +472,7 @@ void CCodeWindow::NotifyMapLoaded()
|
||||
symbols->SetClientData(idx, (void*)&symbol.second);
|
||||
}
|
||||
symbols->Thaw();
|
||||
// symbols->Show(true);
|
||||
Update();
|
||||
Repopulate();
|
||||
}
|
||||
|
||||
void CCodeWindow::OnSymbolListChange(wxCommandEvent& event)
|
||||
@ -487,8 +485,9 @@ void CCodeWindow::OnSymbolListChange(wxCommandEvent& event)
|
||||
{
|
||||
if (pSymbol->type == Symbol::Type::Data)
|
||||
{
|
||||
if (m_MemoryWindow) // && m_MemoryWindow->IsVisible())
|
||||
m_MemoryWindow->JumpToAddress(pSymbol->address);
|
||||
CMemoryWindow* memory = GetPanel<CMemoryWindow>();
|
||||
if (memory)
|
||||
memory->JumpToAddress(pSymbol->address);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -498,10 +497,6 @@ void CCodeWindow::OnSymbolListChange(wxCommandEvent& event)
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::OnSymbolListContextMenu(wxContextMenuEvent& event)
|
||||
{
|
||||
}
|
||||
|
||||
// Change the global DebuggerFont
|
||||
void CCodeWindow::OnChangeFont(wxCommandEvent& event)
|
||||
{
|
||||
@ -511,157 +506,104 @@ void CCodeWindow::OnChangeFont(wxCommandEvent& event)
|
||||
wxFontDialog dialog(this, data);
|
||||
if (dialog.ShowModal() == wxID_OK)
|
||||
DebuggerFont = dialog.GetFontData().GetChosenFont();
|
||||
|
||||
// TODO: Send event to all panels that tells them to reload the font when it changes.
|
||||
}
|
||||
|
||||
// Toggle windows
|
||||
|
||||
wxPanel* CCodeWindow::GetUntypedPanel(int id) const
|
||||
{
|
||||
wxASSERT_MSG(id >= IDM_DEBUG_WINDOW_LIST_START && id < IDM_DEBUG_WINDOW_LIST_END,
|
||||
"ID out of range");
|
||||
wxASSERT_MSG(id != IDM_LOG_WINDOW && id != IDM_LOG_CONFIG_WINDOW,
|
||||
"Log windows are managed separately");
|
||||
return m_sibling_panels.at(id - IDM_DEBUG_WINDOW_LIST_START);
|
||||
}
|
||||
|
||||
void CCodeWindow::TogglePanel(int id, bool show)
|
||||
{
|
||||
wxPanel* panel = GetUntypedPanel(id);
|
||||
|
||||
// Not all the panels (i.e. CodeWindow) have corresponding menu options.
|
||||
wxMenuItem* item = GetMenuBar()->FindItem(id);
|
||||
if (item)
|
||||
item->Check(show);
|
||||
|
||||
if (show)
|
||||
{
|
||||
if (!panel)
|
||||
{
|
||||
panel = CreateSiblingPanel(id);
|
||||
}
|
||||
Parent->DoAddPage(panel, iNbAffiliation[id - IDM_DEBUG_WINDOW_LIST_START],
|
||||
Parent->bFloatWindow[id - IDM_DEBUG_WINDOW_LIST_START]);
|
||||
}
|
||||
else if (panel) // Close
|
||||
{
|
||||
Parent->DoRemovePage(panel, panel == this);
|
||||
m_sibling_panels[id - IDM_DEBUG_WINDOW_LIST_START] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
wxPanel* CCodeWindow::CreateSiblingPanel(int id)
|
||||
{
|
||||
// Includes range check inside the get call
|
||||
wxASSERT_MSG(!GetUntypedPanel(id), "Panel must not already exist");
|
||||
|
||||
wxPanel* panel = nullptr;
|
||||
switch (id)
|
||||
{
|
||||
// case IDM_LOG_WINDOW: // These exist separately in CFrame.
|
||||
// case IDM_LOG_CONFIG_WINDOW:
|
||||
case IDM_REGISTER_WINDOW:
|
||||
panel = new CRegisterWindow(Parent, IDM_REGISTER_WINDOW);
|
||||
break;
|
||||
case IDM_WATCH_WINDOW:
|
||||
panel = new CWatchWindow(Parent, IDM_WATCH_WINDOW);
|
||||
break;
|
||||
case IDM_BREAKPOINT_WINDOW:
|
||||
panel = new CBreakPointWindow(this, Parent, IDM_BREAKPOINT_WINDOW);
|
||||
break;
|
||||
case IDM_MEMORY_WINDOW:
|
||||
panel = new CMemoryWindow(Parent, IDM_MEMORY_WINDOW);
|
||||
break;
|
||||
case IDM_JIT_WINDOW:
|
||||
panel = new CJitWindow(Parent, IDM_JIT_WINDOW);
|
||||
break;
|
||||
case IDM_SOUND_WINDOW:
|
||||
panel = new DSPDebuggerLLE(Parent, IDM_SOUND_WINDOW);
|
||||
break;
|
||||
case IDM_VIDEO_WINDOW:
|
||||
panel = new GFXDebuggerPanel(Parent, IDM_VIDEO_WINDOW);
|
||||
break;
|
||||
case IDM_CODE_WINDOW:
|
||||
panel = this;
|
||||
break;
|
||||
default:
|
||||
wxTrap();
|
||||
break;
|
||||
}
|
||||
|
||||
m_sibling_panels[id - IDM_DEBUG_WINDOW_LIST_START] = panel;
|
||||
return panel;
|
||||
}
|
||||
|
||||
void CCodeWindow::OpenPages()
|
||||
{
|
||||
ToggleCodeWindow(true);
|
||||
if (bShowOnStart[0])
|
||||
// This is forced, and should always be placed as the first tab in the notebook.
|
||||
TogglePanel(IDM_CODE_WINDOW, true);
|
||||
|
||||
// These panels are managed separately by CFrame
|
||||
if (bShowOnStart[IDM_LOG_WINDOW - IDM_DEBUG_WINDOW_LIST_START])
|
||||
Parent->ToggleLogWindow(true);
|
||||
if (bShowOnStart[IDM_LOG_CONFIG_WINDOW - IDM_LOG_WINDOW])
|
||||
if (bShowOnStart[IDM_LOG_CONFIG_WINDOW - IDM_DEBUG_WINDOW_LIST_START])
|
||||
Parent->ToggleLogConfigWindow(true);
|
||||
if (bShowOnStart[IDM_REGISTER_WINDOW - IDM_LOG_WINDOW])
|
||||
ToggleRegisterWindow(true);
|
||||
if (bShowOnStart[IDM_WATCH_WINDOW - IDM_LOG_WINDOW])
|
||||
ToggleWatchWindow(true);
|
||||
if (bShowOnStart[IDM_BREAKPOINT_WINDOW - IDM_LOG_WINDOW])
|
||||
ToggleBreakPointWindow(true);
|
||||
if (bShowOnStart[IDM_MEMORY_WINDOW - IDM_LOG_WINDOW])
|
||||
ToggleMemoryWindow(true);
|
||||
if (bShowOnStart[IDM_JIT_WINDOW - IDM_LOG_WINDOW])
|
||||
ToggleJitWindow(true);
|
||||
if (bShowOnStart[IDM_SOUND_WINDOW - IDM_LOG_WINDOW])
|
||||
ToggleSoundWindow(true);
|
||||
if (bShowOnStart[IDM_VIDEO_WINDOW - IDM_LOG_WINDOW])
|
||||
ToggleVideoWindow(true);
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleCodeWindow(bool bShow)
|
||||
{
|
||||
if (bShow)
|
||||
Parent->DoAddPage(this, iNbAffiliation[IDM_CODE_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_CODE_WINDOW - IDM_LOG_WINDOW]);
|
||||
else // Hide
|
||||
Parent->DoRemovePage(this);
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleRegisterWindow(bool bShow)
|
||||
{
|
||||
GetMenuBar()->FindItem(IDM_REGISTER_WINDOW)->Check(bShow);
|
||||
if (bShow)
|
||||
// Iterate normal panels that don't have weird rules.
|
||||
for (int i = IDM_REGISTER_WINDOW; i < IDM_CODE_WINDOW; ++i)
|
||||
{
|
||||
if (!m_RegisterWindow)
|
||||
m_RegisterWindow = new CRegisterWindow(Parent, IDM_REGISTER_WINDOW);
|
||||
Parent->DoAddPage(m_RegisterWindow, iNbAffiliation[IDM_REGISTER_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_REGISTER_WINDOW - IDM_LOG_WINDOW]);
|
||||
}
|
||||
else // Close
|
||||
{
|
||||
Parent->DoRemovePage(m_RegisterWindow, false);
|
||||
m_RegisterWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleWatchWindow(bool bShow)
|
||||
{
|
||||
GetMenuBar()->FindItem(IDM_WATCH_WINDOW)->Check(bShow);
|
||||
if (bShow)
|
||||
{
|
||||
if (!m_WatchWindow)
|
||||
m_WatchWindow = new CWatchWindow(Parent, IDM_WATCH_WINDOW);
|
||||
Parent->DoAddPage(m_WatchWindow, iNbAffiliation[IDM_WATCH_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_WATCH_WINDOW - IDM_LOG_WINDOW]);
|
||||
}
|
||||
else // Close
|
||||
{
|
||||
Parent->DoRemovePage(m_WatchWindow, false);
|
||||
m_WatchWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleBreakPointWindow(bool bShow)
|
||||
{
|
||||
GetMenuBar()->FindItem(IDM_BREAKPOINT_WINDOW)->Check(bShow);
|
||||
if (bShow)
|
||||
{
|
||||
if (!m_BreakpointWindow)
|
||||
m_BreakpointWindow = new CBreakPointWindow(this, Parent, IDM_BREAKPOINT_WINDOW);
|
||||
Parent->DoAddPage(m_BreakpointWindow, iNbAffiliation[IDM_BREAKPOINT_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_BREAKPOINT_WINDOW - IDM_LOG_WINDOW]);
|
||||
}
|
||||
else // Close
|
||||
{
|
||||
Parent->DoRemovePage(m_BreakpointWindow, false);
|
||||
m_BreakpointWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleMemoryWindow(bool bShow)
|
||||
{
|
||||
GetMenuBar()->FindItem(IDM_MEMORY_WINDOW)->Check(bShow);
|
||||
if (bShow)
|
||||
{
|
||||
if (!m_MemoryWindow)
|
||||
m_MemoryWindow = new CMemoryWindow(this, Parent, IDM_MEMORY_WINDOW);
|
||||
Parent->DoAddPage(m_MemoryWindow, iNbAffiliation[IDM_MEMORY_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_MEMORY_WINDOW - IDM_LOG_WINDOW]);
|
||||
}
|
||||
else // Close
|
||||
{
|
||||
Parent->DoRemovePage(m_MemoryWindow, false);
|
||||
m_MemoryWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleJitWindow(bool bShow)
|
||||
{
|
||||
GetMenuBar()->FindItem(IDM_JIT_WINDOW)->Check(bShow);
|
||||
if (bShow)
|
||||
{
|
||||
if (!m_JitWindow)
|
||||
m_JitWindow = new CJitWindow(Parent, IDM_JIT_WINDOW);
|
||||
Parent->DoAddPage(m_JitWindow, iNbAffiliation[IDM_JIT_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_JIT_WINDOW - IDM_LOG_WINDOW]);
|
||||
}
|
||||
else // Close
|
||||
{
|
||||
Parent->DoRemovePage(m_JitWindow, false);
|
||||
m_JitWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleSoundWindow(bool bShow)
|
||||
{
|
||||
GetMenuBar()->FindItem(IDM_SOUND_WINDOW)->Check(bShow);
|
||||
if (bShow)
|
||||
{
|
||||
if (!m_SoundWindow)
|
||||
m_SoundWindow = new DSPDebuggerLLE(Parent, IDM_SOUND_WINDOW);
|
||||
Parent->DoAddPage(m_SoundWindow, iNbAffiliation[IDM_SOUND_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_SOUND_WINDOW - IDM_LOG_WINDOW]);
|
||||
}
|
||||
else // Close
|
||||
{
|
||||
Parent->DoRemovePage(m_SoundWindow, false);
|
||||
m_SoundWindow = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CCodeWindow::ToggleVideoWindow(bool bShow)
|
||||
{
|
||||
GetMenuBar()->FindItem(IDM_VIDEO_WINDOW)->Check(bShow);
|
||||
if (bShow)
|
||||
{
|
||||
if (!m_VideoWindow)
|
||||
m_VideoWindow = new GFXDebuggerPanel(Parent, IDM_VIDEO_WINDOW);
|
||||
Parent->DoAddPage(m_VideoWindow, iNbAffiliation[IDM_VIDEO_WINDOW - IDM_LOG_WINDOW],
|
||||
Parent->bFloatWindow[IDM_VIDEO_WINDOW - IDM_LOG_WINDOW]);
|
||||
}
|
||||
else // Close
|
||||
{
|
||||
Parent->DoRemovePage(m_VideoWindow, false);
|
||||
m_VideoWindow = nullptr;
|
||||
if (bShowOnStart[i - IDM_DEBUG_WINDOW_LIST_START])
|
||||
TogglePanel(i, true);
|
||||
}
|
||||
}
|
||||
|
@ -32,9 +32,8 @@ static DSPDebuggerLLE* m_DebuggerFrame = nullptr;
|
||||
|
||||
DSPDebuggerLLE::DSPDebuggerLLE(wxWindow* parent, wxWindowID id)
|
||||
: wxPanel(parent, id, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("DSP LLE Debugger")),
|
||||
m_CachedStepCounter(-1)
|
||||
m_CachedStepCounter(-1), m_toolbar_item_size(FromDIP(wxSize(16, 16)))
|
||||
{
|
||||
Bind(wxEVT_CLOSE_WINDOW, &DSPDebuggerLLE::OnClose, this);
|
||||
Bind(wxEVT_MENU, &DSPDebuggerLLE::OnChangeState, this, ID_RUNTOOL, ID_SHOWPCTOOL);
|
||||
|
||||
m_DebuggerFrame = this;
|
||||
@ -46,11 +45,12 @@ DSPDebuggerLLE::DSPDebuggerLLE(wxWindow* parent, wxWindowID id)
|
||||
m_Toolbar =
|
||||
new DolphinAuiToolBar(this, ID_TOOLBAR, wxDefaultPosition, wxDefaultSize, wxAUI_TB_HORZ_TEXT);
|
||||
m_Toolbar->AddTool(ID_RUNTOOL, _("Pause"),
|
||||
wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, wxSize(10, 10)));
|
||||
wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, m_toolbar_item_size));
|
||||
m_Toolbar->AddTool(ID_STEPTOOL, _("Step"),
|
||||
wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_OTHER, wxSize(10, 10)));
|
||||
m_Toolbar->AddTool(ID_SHOWPCTOOL, _("Show PC"),
|
||||
wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_OTHER, wxSize(10, 10)));
|
||||
wxArtProvider::GetBitmap(wxART_GO_DOWN, wxART_OTHER, m_toolbar_item_size));
|
||||
m_Toolbar->AddTool(
|
||||
ID_SHOWPCTOOL, _("Show PC"),
|
||||
wxArtProvider::GetBitmap(wxART_GO_TO_PARENT, wxART_OTHER, m_toolbar_item_size));
|
||||
m_Toolbar->AddSeparator();
|
||||
|
||||
m_addr_txtctrl = new wxTextCtrl(m_Toolbar, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
@ -60,8 +60,8 @@ DSPDebuggerLLE::DSPDebuggerLLE(wxWindow* parent, wxWindowID id)
|
||||
m_Toolbar->AddControl(m_addr_txtctrl);
|
||||
m_Toolbar->Realize();
|
||||
|
||||
m_SymbolList =
|
||||
new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(140, 100), 0, nullptr, wxLB_SORT);
|
||||
m_SymbolList = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDLG_UNIT(this, wxSize(100, 80)),
|
||||
0, nullptr, wxLB_SORT);
|
||||
m_SymbolList->Bind(wxEVT_LISTBOX, &DSPDebuggerLLE::OnSymbolListChange, this);
|
||||
|
||||
m_MainNotebook = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize,
|
||||
@ -71,15 +71,14 @@ DSPDebuggerLLE::DSPDebuggerLLE(wxWindow* parent, wxWindowID id)
|
||||
wxBoxSizer* code_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
m_CodeView = new CCodeView(&debug_interface, &DSPSymbols::g_dsp_symbol_db, code_panel);
|
||||
m_CodeView->SetPlain();
|
||||
code_sizer->Add(m_CodeView, 1, wxALL | wxEXPAND);
|
||||
code_sizer->Add(m_CodeView, 1, wxEXPAND);
|
||||
code_panel->SetSizer(code_sizer);
|
||||
m_MainNotebook->AddPage(code_panel, _("Disassembly"), true);
|
||||
|
||||
wxPanel* mem_panel = new wxPanel(m_MainNotebook, wxID_ANY);
|
||||
wxBoxSizer* mem_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
// TODO insert memViewer class
|
||||
m_MemView = new CMemoryView(&debug_interface, mem_panel);
|
||||
mem_sizer->Add(m_MemView, 1, wxALL | wxEXPAND);
|
||||
mem_sizer->Add(m_MemView, 1, wxEXPAND);
|
||||
mem_panel->SetSizer(mem_sizer);
|
||||
m_MainNotebook->AddPage(mem_panel, _("Memory"));
|
||||
|
||||
@ -111,11 +110,6 @@ DSPDebuggerLLE::~DSPDebuggerLLE()
|
||||
m_DebuggerFrame = nullptr;
|
||||
}
|
||||
|
||||
void DSPDebuggerLLE::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
|
||||
{
|
||||
if (DSPCore_GetState() == DSPCORE_STOP)
|
||||
@ -134,7 +128,7 @@ void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
|
||||
if (DSPCore_GetState() == DSPCORE_STEPPING)
|
||||
{
|
||||
DSPCore_Step();
|
||||
Update();
|
||||
Repopulate();
|
||||
}
|
||||
break;
|
||||
|
||||
@ -149,24 +143,24 @@ void DSPDebuggerLLE::OnChangeState(wxCommandEvent& event)
|
||||
|
||||
void Host_RefreshDSPDebuggerWindow()
|
||||
{
|
||||
// FIXME: This should use QueueEvent to post the update request to the UI thread.
|
||||
// Need to check if this can safely be performed asynchronously or if it races.
|
||||
// FIXME: This probably belongs in Main.cpp with the other host functions.
|
||||
// NOTE: The DSP never tells us when it shuts down. It probably should.
|
||||
if (m_DebuggerFrame)
|
||||
m_DebuggerFrame->Update();
|
||||
m_DebuggerFrame->Repopulate();
|
||||
}
|
||||
|
||||
void DSPDebuggerLLE::Update()
|
||||
void DSPDebuggerLLE::Repopulate()
|
||||
{
|
||||
#if defined __WXGTK__
|
||||
if (!wxIsMainThread())
|
||||
wxMutexGuiEnter();
|
||||
#endif
|
||||
UpdateSymbolMap();
|
||||
UpdateDisAsmListView();
|
||||
UpdateRegisterFlags();
|
||||
UpdateState();
|
||||
#if defined __WXGTK__
|
||||
if (!wxIsMainThread())
|
||||
wxMutexGuiLeave();
|
||||
#endif
|
||||
}
|
||||
|
||||
void DSPDebuggerLLE::FocusOnPC()
|
||||
@ -180,14 +174,14 @@ void DSPDebuggerLLE::UpdateState()
|
||||
{
|
||||
m_Toolbar->SetToolLabel(ID_RUNTOOL, _("Pause"));
|
||||
m_Toolbar->SetToolBitmap(
|
||||
ID_RUNTOOL, wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, wxSize(10, 10)));
|
||||
ID_RUNTOOL, wxArtProvider::GetBitmap(wxART_TICK_MARK, wxART_OTHER, m_toolbar_item_size));
|
||||
m_Toolbar->EnableTool(ID_STEPTOOL, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Toolbar->SetToolLabel(ID_RUNTOOL, _("Run"));
|
||||
m_Toolbar->SetToolBitmap(
|
||||
ID_RUNTOOL, wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_OTHER, wxSize(10, 10)));
|
||||
ID_RUNTOOL, wxArtProvider::GetBitmap(wxART_GO_FORWARD, wxART_OTHER, m_toolbar_item_size));
|
||||
m_Toolbar->EnableTool(ID_STEPTOOL, true);
|
||||
}
|
||||
m_Toolbar->Realize();
|
||||
@ -201,7 +195,7 @@ void DSPDebuggerLLE::UpdateDisAsmListView()
|
||||
// show PC
|
||||
FocusOnPC();
|
||||
m_CachedStepCounter = g_dsp.step_counter;
|
||||
m_Regs->Update();
|
||||
m_Regs->Repopulate();
|
||||
}
|
||||
|
||||
void DSPDebuggerLLE::UpdateSymbolMap()
|
||||
|
@ -23,7 +23,7 @@ public:
|
||||
DSPDebuggerLLE(wxWindow* parent, wxWindowID id = wxID_ANY);
|
||||
virtual ~DSPDebuggerLLE();
|
||||
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
|
||||
private:
|
||||
enum
|
||||
@ -52,8 +52,8 @@ private:
|
||||
wxListBox* m_SymbolList;
|
||||
wxTextCtrl* m_addr_txtctrl;
|
||||
wxAuiNotebook* m_MainNotebook;
|
||||
wxSize m_toolbar_item_size;
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnChangeState(wxCommandEvent& event);
|
||||
// void OnRightClick(wxListEvent& event);
|
||||
// void OnDoubleClick(wxListEvent& event);
|
||||
|
@ -71,7 +71,7 @@ wxGridCellAttr* CDSPRegTable::GetAttr(int row, int col, wxGridCellAttr::wxAttrKi
|
||||
}
|
||||
|
||||
DSPRegisterView::DSPRegisterView(wxWindow* parent, wxWindowID id)
|
||||
: wxGrid(parent, id, wxDefaultPosition, wxSize(130, 120))
|
||||
: wxGrid(parent, id, wxDefaultPosition, wxDLG_UNIT(parent, wxSize(100, 80)))
|
||||
{
|
||||
m_register_table = new CDSPRegTable();
|
||||
|
||||
@ -83,7 +83,7 @@ DSPRegisterView::DSPRegisterView(wxWindow* parent, wxWindowID id)
|
||||
AutoSizeColumns();
|
||||
}
|
||||
|
||||
void DSPRegisterView::Update()
|
||||
void DSPRegisterView::Repopulate()
|
||||
{
|
||||
m_register_table->UpdateCachedRegs();
|
||||
ForceRefresh();
|
||||
|
@ -38,7 +38,7 @@ class DSPRegisterView : public wxGrid
|
||||
{
|
||||
public:
|
||||
DSPRegisterView(wxWindow* parent, wxWindowID id = wxID_ANY);
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
|
||||
private:
|
||||
// Owned by wx. Deleted implicitly upon destruction.
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/IniFile.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
@ -26,10 +27,6 @@ GFXDebuggerPanel::GFXDebuggerPanel(wxWindow* parent, wxWindowID id, const wxPoin
|
||||
g_pdebugger = this;
|
||||
|
||||
CreateGUIControls();
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, &GFXDebuggerPanel::OnClose, this);
|
||||
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
GFXDebuggerPanel::~GFXDebuggerPanel()
|
||||
@ -38,55 +35,6 @@ GFXDebuggerPanel::~GFXDebuggerPanel()
|
||||
GFXDebuggerPauseFlag = false;
|
||||
}
|
||||
|
||||
void GFXDebuggerPanel::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
// save the window position when we hide the window
|
||||
SaveSettings();
|
||||
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void GFXDebuggerPanel::SaveSettings() const
|
||||
{
|
||||
IniFile file;
|
||||
file.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
|
||||
|
||||
// TODO: make this work when we close the entire program too, currently on total close we get
|
||||
// weird values, perhaps because of some conflict with the rendering window
|
||||
|
||||
// TODO: get the screen resolution and make limits from that
|
||||
if (GetPosition().x < 1000 && GetPosition().y < 1000 && GetSize().GetWidth() < 1000 &&
|
||||
GetSize().GetHeight() < 1000)
|
||||
{
|
||||
IniFile::Section* video_window = file.GetOrCreateSection("VideoWindow");
|
||||
video_window->Set("x", GetPosition().x);
|
||||
video_window->Set("y", GetPosition().y);
|
||||
video_window->Set("w", GetSize().GetWidth());
|
||||
video_window->Set("h", GetSize().GetHeight());
|
||||
}
|
||||
|
||||
file.Save(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
|
||||
}
|
||||
|
||||
void GFXDebuggerPanel::LoadSettings()
|
||||
{
|
||||
IniFile file;
|
||||
file.Load(File::GetUserPath(F_DEBUGGERCONFIG_IDX));
|
||||
|
||||
int x = 100;
|
||||
int y = 100;
|
||||
int w = 100;
|
||||
int h = 100;
|
||||
|
||||
IniFile::Section* video_window = file.GetOrCreateSection("VideoWindow");
|
||||
video_window->Get("x", &x, GetPosition().x);
|
||||
video_window->Get("y", &y, GetPosition().y);
|
||||
video_window->Get("w", &w, GetSize().GetWidth());
|
||||
video_window->Get("h", &h, GetSize().GetHeight());
|
||||
|
||||
SetSize(x, y, w, h);
|
||||
}
|
||||
|
||||
struct PauseEventMap
|
||||
{
|
||||
PauseEvent event;
|
||||
@ -118,10 +66,9 @@ void GFXDebuggerPanel::CreateGUIControls()
|
||||
|
||||
{NEXT_ERROR, _("Error")}};
|
||||
pauseEventMap = map;
|
||||
const int numPauseEventMap = sizeof(map) / sizeof(PauseEventMap);
|
||||
static constexpr int numPauseEventMap = ArraySize(map);
|
||||
|
||||
// Basic settings
|
||||
CenterOnParent();
|
||||
const int space3 = FromDIP(3);
|
||||
|
||||
m_pButtonPause = new wxButton(this, wxID_ANY, _("Pause"), wxDefaultPosition, wxDefaultSize, 0,
|
||||
wxDefaultValidator, _("Pause"));
|
||||
@ -139,10 +86,11 @@ void GFXDebuggerPanel::CreateGUIControls()
|
||||
wxDefaultValidator, _("Continue"));
|
||||
m_pButtonCont->Bind(wxEVT_BUTTON, &GFXDebuggerPanel::OnContButton, this);
|
||||
|
||||
m_pCount = new wxTextCtrl(this, wxID_ANY, "1", wxDefaultPosition, wxSize(50, 25), wxTE_RIGHT,
|
||||
m_pCount = new wxTextCtrl(this, wxID_ANY, "1", wxDefaultPosition, wxDefaultSize, wxTE_RIGHT,
|
||||
wxDefaultValidator, _("Count"));
|
||||
m_pCount->SetMinSize(WxUtils::GetTextWidgetMinSize(m_pCount, 10000));
|
||||
|
||||
m_pPauseAtList = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxSize(100, 25), 0, nullptr, 0,
|
||||
m_pPauseAtList = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, 0,
|
||||
wxDefaultValidator, _("PauseAtList"));
|
||||
for (int i = 0; i < numPauseEventMap; i++)
|
||||
{
|
||||
@ -180,7 +128,7 @@ void GFXDebuggerPanel::CreateGUIControls()
|
||||
m_pButtonClearPixelShaderCache->Bind(wxEVT_BUTTON,
|
||||
&GFXDebuggerPanel::OnClearPixelShaderCacheButton, this);
|
||||
|
||||
m_pDumpList = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxSize(120, 25), 0, nullptr, 0,
|
||||
m_pDumpList = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, 0,
|
||||
wxDefaultValidator, _("DumpList"));
|
||||
m_pDumpList->Insert(_("Pixel Shader"), 0);
|
||||
m_pDumpList->Append(_("Vertex Shader"));
|
||||
@ -196,31 +144,40 @@ void GFXDebuggerPanel::CreateGUIControls()
|
||||
|
||||
wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticBoxSizer* const pFlowCtrlBox = new wxStaticBoxSizer(wxVERTICAL, this, _("Flow Control"));
|
||||
wxBoxSizer* const pPauseAtNextSzr = new wxBoxSizer(wxHORIZONTAL);
|
||||
pFlowCtrlBox->Add(m_pButtonPause);
|
||||
pPauseAtNextSzr->Add(m_pButtonPauseAtNext);
|
||||
pPauseAtNextSzr->Add(m_pCount);
|
||||
pPauseAtNextSzr->Add(m_pPauseAtList);
|
||||
pFlowCtrlBox->Add(pPauseAtNextSzr);
|
||||
pFlowCtrlBox->Add(m_pButtonPauseAtNextFrame);
|
||||
pFlowCtrlBox->Add(m_pButtonCont);
|
||||
pPauseAtNextSzr->Add(m_pCount, 0, wxALIGN_CENTER_VERTICAL);
|
||||
pPauseAtNextSzr->Add(m_pPauseAtList, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space3);
|
||||
|
||||
wxFlexGridSizer* const flow_szr = new wxFlexGridSizer(2, space3, space3);
|
||||
flow_szr->Add(m_pButtonPause, 0, wxEXPAND);
|
||||
flow_szr->AddSpacer(1);
|
||||
flow_szr->Add(m_pButtonPauseAtNext, 0, wxEXPAND);
|
||||
flow_szr->Add(pPauseAtNextSzr, 0, wxEXPAND);
|
||||
flow_szr->Add(m_pButtonPauseAtNextFrame, 0, wxEXPAND);
|
||||
flow_szr->AddSpacer(1);
|
||||
flow_szr->Add(m_pButtonCont, 0, wxEXPAND);
|
||||
flow_szr->AddSpacer(1);
|
||||
|
||||
wxStaticBoxSizer* const pFlowCtrlBox = new wxStaticBoxSizer(wxVERTICAL, this, _("Flow Control"));
|
||||
pFlowCtrlBox->Add(flow_szr, 1, wxEXPAND);
|
||||
|
||||
wxBoxSizer* const pDumpSzr = new wxBoxSizer(wxHORIZONTAL);
|
||||
pDumpSzr->Add(m_pButtonDump, 0, wxALIGN_CENTER_VERTICAL);
|
||||
pDumpSzr->Add(m_pDumpList, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space3);
|
||||
|
||||
wxGridSizer* const pDbgGrid = new wxGridSizer(2, space3, space3);
|
||||
pDbgGrid->Add(m_pButtonUpdateScreen, 0, wxEXPAND);
|
||||
pDbgGrid->Add(m_pButtonClearScreen, 0, wxEXPAND);
|
||||
pDbgGrid->Add(m_pButtonClearTextureCache, 0, wxEXPAND);
|
||||
pDbgGrid->Add(m_pButtonClearVertexShaderCache, 0, wxEXPAND);
|
||||
pDbgGrid->Add(m_pButtonClearPixelShaderCache, 0, wxEXPAND);
|
||||
|
||||
wxStaticBoxSizer* const pDebugBox = new wxStaticBoxSizer(wxVERTICAL, this, _("Debugging"));
|
||||
wxBoxSizer* const pDumpSzr = new wxBoxSizer(wxHORIZONTAL);
|
||||
pDumpSzr->Add(m_pButtonDump);
|
||||
pDumpSzr->Add(m_pDumpList);
|
||||
pDebugBox->Add(pDumpSzr);
|
||||
wxGridSizer* const pDbgGrid = new wxGridSizer(2, 5, 5);
|
||||
pDbgGrid->Add(m_pButtonUpdateScreen);
|
||||
pDbgGrid->Add(m_pButtonClearScreen);
|
||||
pDbgGrid->Add(m_pButtonClearTextureCache);
|
||||
pDbgGrid->Add(m_pButtonClearVertexShaderCache);
|
||||
pDbgGrid->Add(m_pButtonClearPixelShaderCache);
|
||||
pDebugBox->Add(pDbgGrid);
|
||||
pDebugBox->Add(pDumpSzr, 0, wxEXPAND);
|
||||
pDebugBox->Add(pDbgGrid, 1, wxTOP, space3);
|
||||
|
||||
sMain->Add(pFlowCtrlBox, 0, 0, 5);
|
||||
sMain->Add(pDebugBox, 0, 0, 5);
|
||||
sMain->Add(pFlowCtrlBox);
|
||||
sMain->Add(pDebugBox);
|
||||
SetSizerAndFit(sMain);
|
||||
|
||||
OnContinue();
|
||||
@ -248,12 +205,6 @@ void GFXDebuggerPanel::OnContinue()
|
||||
m_pButtonClearPixelShaderCache->Disable();
|
||||
}
|
||||
|
||||
// General settings
|
||||
void GFXDebuggerPanel::GeneralSettings(wxCommandEvent& event)
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
void GFXDebuggerPanel::OnPauseButton(wxCommandEvent& event)
|
||||
{
|
||||
GFXDebuggerPauseFlag = true;
|
||||
|
@ -20,9 +20,6 @@ public:
|
||||
|
||||
virtual ~GFXDebuggerPanel();
|
||||
|
||||
void SaveSettings() const;
|
||||
void LoadSettings();
|
||||
|
||||
bool bInfoLog;
|
||||
bool bPrimLog;
|
||||
bool bSaveTextures;
|
||||
@ -49,11 +46,8 @@ private:
|
||||
wxButton* m_pButtonClearPixelShaderCache;
|
||||
wxTextCtrl* m_pCount;
|
||||
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void CreateGUIControls();
|
||||
|
||||
void GeneralSettings(wxCommandEvent& event);
|
||||
|
||||
// These set GFXDebuggerPauseFlag to true (either immediately or once the specified event has
|
||||
// occurred)
|
||||
void OnPauseButton(wxCommandEvent& event);
|
||||
|
@ -34,7 +34,8 @@ CJitWindow::CJitWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos, cons
|
||||
sizerSplit->Add(x86_box = new wxTextCtrl(this, wxID_ANY, "(x86)", wxDefaultPosition,
|
||||
wxDefaultSize, wxTE_MULTILINE),
|
||||
1, wxEXPAND);
|
||||
sizerBig->Add(block_list = new JitBlockList(this, wxID_ANY, wxDefaultPosition, wxSize(100, 140),
|
||||
sizerBig->Add(block_list = new JitBlockList(this, wxID_ANY, wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(80, 96)),
|
||||
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT |
|
||||
wxLC_SINGLE_SEL | wxLC_SORT_ASCENDING),
|
||||
0, wxEXPAND);
|
||||
@ -43,10 +44,7 @@ CJitWindow::CJitWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos, cons
|
||||
sizerBig->Add(button_refresh = new wxButton(this, wxID_ANY, _("&Refresh")));
|
||||
button_refresh->Bind(wxEVT_BUTTON, &CJitWindow::OnRefresh, this);
|
||||
|
||||
SetSizer(sizerBig);
|
||||
|
||||
sizerSplit->Fit(this);
|
||||
sizerBig->Fit(this);
|
||||
SetSizerAndFit(sizerBig);
|
||||
|
||||
#if defined(_M_X86)
|
||||
m_disassembler.reset(GetNewDisassembler("x86"));
|
||||
@ -59,7 +57,7 @@ CJitWindow::CJitWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos, cons
|
||||
|
||||
void CJitWindow::OnRefresh(wxCommandEvent& /*event*/)
|
||||
{
|
||||
block_list->Update();
|
||||
block_list->Repopulate();
|
||||
}
|
||||
|
||||
void CJitWindow::ViewAddr(u32 em_address)
|
||||
@ -135,7 +133,7 @@ void CJitWindow::Compare(u32 em_address)
|
||||
}
|
||||
}
|
||||
|
||||
void CJitWindow::Update()
|
||||
void CJitWindow::Repopulate()
|
||||
{
|
||||
}
|
||||
|
||||
@ -181,6 +179,6 @@ void JitBlockList::Init()
|
||||
InsertColumn(COLUMN_COST, _("Cost"));
|
||||
}
|
||||
|
||||
void JitBlockList::Update()
|
||||
void JitBlockList::Repopulate()
|
||||
{
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ public:
|
||||
JitBlockList(wxWindow* parent, const wxWindowID id, const wxPoint& pos, const wxSize& size,
|
||||
long style);
|
||||
void Init();
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
};
|
||||
|
||||
class CJitWindow : public wxPanel
|
||||
@ -33,7 +33,7 @@ public:
|
||||
const wxString& name = _("JIT Block Viewer"));
|
||||
|
||||
void ViewAddr(u32 em_address);
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
|
||||
private:
|
||||
void OnRefresh(wxCommandEvent& /*event*/);
|
||||
|
@ -22,6 +22,8 @@ MemoryCheckDlg::MemoryCheckDlg(CBreakPointWindow* parent)
|
||||
Bind(wxEVT_BUTTON, &MemoryCheckDlg::OnOK, this, wxID_OK);
|
||||
Bind(wxEVT_RADIOBUTTON, &MemoryCheckDlg::OnRadioButtonClick, this);
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
m_textAddress = new wxStaticText(this, wxID_ANY, _("Address"));
|
||||
m_textStartAddress = new wxStaticText(this, wxID_ANY, _("Start"));
|
||||
m_textStartAddress->Disable();
|
||||
@ -46,14 +48,22 @@ MemoryCheckDlg::MemoryCheckDlg(CBreakPointWindow* parent)
|
||||
m_radioBreakLog->SetValue(true);
|
||||
|
||||
auto* sAddressBox = new wxBoxSizer(wxHORIZONTAL);
|
||||
sAddressBox->Add(m_textAddress, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sAddressBox->Add(m_pEditAddress, 1, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, 10);
|
||||
sAddressBox->AddSpacer(space5);
|
||||
sAddressBox->Add(m_textAddress, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sAddressBox->AddSpacer(space5);
|
||||
sAddressBox->Add(m_pEditAddress, 1, wxALIGN_CENTER_VERTICAL);
|
||||
sAddressBox->AddSpacer(space5);
|
||||
|
||||
auto* sAddressRangeBox = new wxBoxSizer(wxHORIZONTAL);
|
||||
sAddressRangeBox->Add(m_textStartAddress, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sAddressRangeBox->Add(m_pEditStartAddress, 1, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, 10);
|
||||
sAddressRangeBox->Add(m_textEndAddress, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sAddressRangeBox->Add(m_pEditEndAddress, 1, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, 5);
|
||||
sAddressRangeBox->AddSpacer(space5);
|
||||
sAddressRangeBox->Add(m_textStartAddress, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sAddressRangeBox->AddSpacer(space5);
|
||||
sAddressRangeBox->Add(m_pEditStartAddress, 1, wxALIGN_CENTER_VERTICAL);
|
||||
sAddressRangeBox->AddSpacer(space5);
|
||||
sAddressRangeBox->Add(m_textEndAddress, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sAddressRangeBox->AddSpacer(space5);
|
||||
sAddressRangeBox->Add(m_pEditEndAddress, 1, wxALIGN_CENTER_VERTICAL);
|
||||
sAddressRangeBox->AddSpacer(space5);
|
||||
|
||||
auto* sActions = new wxStaticBoxSizer(wxVERTICAL, this, _("Action"));
|
||||
sActions->Add(m_radioRead, 0, wxEXPAND);
|
||||
@ -67,19 +77,26 @@ MemoryCheckDlg::MemoryCheckDlg(CBreakPointWindow* parent)
|
||||
sFlags->Add(m_radioBreakLog);
|
||||
|
||||
auto* sOptionsBox = new wxBoxSizer(wxHORIZONTAL);
|
||||
sOptionsBox->Add(sActions, 1, wxEXPAND | wxRIGHT | wxTOP | wxBOTTOM, 5);
|
||||
sOptionsBox->Add(sFlags, 1, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 5);
|
||||
sOptionsBox->Add(sActions, 1, wxEXPAND, space5);
|
||||
sOptionsBox->Add(sFlags, 1, wxEXPAND | wxLEFT, space5);
|
||||
|
||||
auto* sControls = new wxBoxSizer(wxVERTICAL);
|
||||
sControls->Add(m_radioAddress, 0, wxEXPAND);
|
||||
sControls->AddSpacer(5);
|
||||
sControls->Add(sAddressBox, 0, wxEXPAND);
|
||||
sControls->AddSpacer(5);
|
||||
sControls->Add(m_radioRange, 0, wxEXPAND);
|
||||
sControls->AddSpacer(5);
|
||||
sControls->Add(sAddressRangeBox, 0, wxEXPAND);
|
||||
sControls->AddSpacer(5);
|
||||
sControls->Add(sOptionsBox, 0, wxEXPAND);
|
||||
|
||||
auto* sMainSizer = new wxBoxSizer(wxVERTICAL);
|
||||
sMainSizer->Add(sControls, 0, wxEXPAND | wxTOP | wxRIGHT | wxLEFT, 5);
|
||||
sMainSizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
sMainSizer->AddSpacer(space5);
|
||||
sMainSizer->Add(sControls, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMainSizer->AddSpacer(space5);
|
||||
sMainSizer->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMainSizer->AddSpacer(space5);
|
||||
|
||||
SetSizerAndFit(sMainSizer);
|
||||
SetFocus();
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cctype>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <wx/brush.h>
|
||||
@ -17,6 +19,7 @@
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/DebugInterface.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "DolphinWX/Debugger/CodeWindow.h"
|
||||
@ -25,6 +28,7 @@
|
||||
#include "DolphinWX/Debugger/WatchWindow.h"
|
||||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
#include "DolphinWX/Main.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
enum
|
||||
@ -42,11 +46,12 @@ enum
|
||||
IDM_VIEWASHEX,
|
||||
};
|
||||
|
||||
wxDEFINE_EVENT(DOLPHIN_EVT_MEMORY_VIEW_DATA_TYPE_CHANGED, wxCommandEvent);
|
||||
|
||||
CMemoryView::CMemoryView(DebugInterface* debuginterface, wxWindow* parent)
|
||||
: wxControl(parent, wxID_ANY), debugger(debuginterface),
|
||||
align(debuginterface->GetInstructionSize(0)), rowHeight(13), selection(0), oldSelection(0),
|
||||
selecting(false), memory(0), curAddress(debuginterface->GetPC()),
|
||||
dataType(MemoryDataType::U8), viewAsType(VIEWAS_FP)
|
||||
: wxControl(parent, wxID_ANY), debugger(debuginterface), align(0), rowHeight(FromDIP(13)),
|
||||
m_left_col_width(FromDIP(LEFT_COL_WIDTH)), selection(0), oldSelection(0), selecting(false),
|
||||
memory(0), curAddress(debuginterface->GetPC()), m_data_type(MemoryDataType::U8)
|
||||
{
|
||||
Bind(wxEVT_PAINT, &CMemoryView::OnPaint, this);
|
||||
Bind(wxEVT_LEFT_DOWN, &CMemoryView::OnMouseDownL, this);
|
||||
@ -56,6 +61,38 @@ CMemoryView::CMemoryView(DebugInterface* debuginterface, wxWindow* parent)
|
||||
Bind(wxEVT_MOUSEWHEEL, &CMemoryView::OnScrollWheel, this);
|
||||
Bind(wxEVT_MENU, &CMemoryView::OnPopupMenu, this);
|
||||
Bind(wxEVT_SIZE, &CMemoryView::OnResize, this);
|
||||
|
||||
SetDataType(MemoryDataType::FloatingPoint);
|
||||
|
||||
// Every pixel will be drawn over in the paint event so erasing will just cause flickering.
|
||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
||||
#if defined(__WXMSW__) || defined(__WXGTK__)
|
||||
SetDoubleBuffered(true);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CMemoryView::SetDataType(MemoryDataType data_type)
|
||||
{
|
||||
if (m_data_type == data_type)
|
||||
return;
|
||||
|
||||
m_data_type = data_type;
|
||||
switch (data_type)
|
||||
{
|
||||
case MemoryDataType::FloatingPoint:
|
||||
case MemoryDataType::ASCII:
|
||||
align = 4;
|
||||
break;
|
||||
default:
|
||||
align = 16;
|
||||
m_last_hex_type = data_type;
|
||||
break;
|
||||
}
|
||||
Refresh();
|
||||
|
||||
wxCommandEvent ev(DOLPHIN_EVT_MEMORY_VIEW_DATA_TYPE_CHANGED, GetId());
|
||||
ev.SetInt(static_cast<int>(data_type));
|
||||
GetEventHandler()->ProcessEvent(ev);
|
||||
}
|
||||
|
||||
int CMemoryView::YToAddress(int y)
|
||||
@ -68,10 +105,10 @@ int CMemoryView::YToAddress(int y)
|
||||
|
||||
void CMemoryView::OnMouseDownL(wxMouseEvent& event)
|
||||
{
|
||||
int x = event.m_x;
|
||||
int y = event.m_y;
|
||||
int x = event.GetX();
|
||||
int y = event.GetY();
|
||||
|
||||
if (x > 16)
|
||||
if (x > m_left_col_width)
|
||||
{
|
||||
oldSelection = selection;
|
||||
selection = YToAddress(y);
|
||||
@ -99,7 +136,7 @@ void CMemoryView::OnMouseMove(wxMouseEvent& event)
|
||||
{
|
||||
wxRect rc = GetClientRect();
|
||||
|
||||
if (event.m_leftDown && event.m_x > 16)
|
||||
if (event.m_leftDown && event.m_x > m_left_col_width)
|
||||
{
|
||||
if (event.m_y < 0)
|
||||
{
|
||||
@ -120,7 +157,7 @@ void CMemoryView::OnMouseMove(wxMouseEvent& event)
|
||||
|
||||
void CMemoryView::OnMouseUpL(wxMouseEvent& event)
|
||||
{
|
||||
if (event.m_x > 16)
|
||||
if (event.m_x > m_left_col_width)
|
||||
{
|
||||
curAddress = YToAddress(event.m_y);
|
||||
selecting = false;
|
||||
@ -137,11 +174,11 @@ void CMemoryView::OnScrollWheel(wxMouseEvent& event)
|
||||
|
||||
if (scroll_down)
|
||||
{
|
||||
curAddress += num_lines * 4;
|
||||
curAddress += num_lines * align;
|
||||
}
|
||||
else
|
||||
{
|
||||
curAddress -= num_lines * 4;
|
||||
curAddress -= num_lines * align;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
@ -150,25 +187,26 @@ void CMemoryView::OnScrollWheel(wxMouseEvent& event)
|
||||
|
||||
void CMemoryView::OnPopupMenu(wxCommandEvent& event)
|
||||
{
|
||||
CFrame* main_frame = static_cast<CFrame*>(GetGrandParent()->GetParent());
|
||||
CCodeWindow* code_window = main_frame->g_pCodeWindow;
|
||||
CWatchWindow* watch_window = code_window->m_WatchWindow;
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
wxTheClipboard->Open();
|
||||
#endif
|
||||
// FIXME: This is terrible. Generate events instead.
|
||||
CFrame* cframe = wxGetApp().GetCFrame();
|
||||
CCodeWindow* code_window = cframe->g_pCodeWindow;
|
||||
CWatchWindow* watch_window = code_window->GetPanel<CWatchWindow>();
|
||||
|
||||
switch (event.GetId())
|
||||
{
|
||||
#if wxUSE_CLIPBOARD
|
||||
case IDM_COPYADDRESS:
|
||||
{
|
||||
wxClipboardLocker clipboard_lock;
|
||||
wxTheClipboard->SetData(new wxTextDataObject(wxString::Format("%08x", selection)));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case IDM_COPYHEX:
|
||||
{
|
||||
std::string temp = StringFromFormat("%08x", debugger->ReadExtraMemory(memory, selection));
|
||||
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
|
||||
wxClipboardLocker clipboard_lock;
|
||||
wxTheClipboard->SetData(new wxTextDataObject(
|
||||
wxString::Format("%08x", debugger->ReadExtraMemory(memory, selection))));
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
@ -186,24 +224,21 @@ void CMemoryView::OnPopupMenu(wxCommandEvent& event)
|
||||
break;
|
||||
|
||||
case IDM_VIEWASFP:
|
||||
viewAsType = VIEWAS_FP;
|
||||
Refresh();
|
||||
SetDataType(MemoryDataType::FloatingPoint);
|
||||
break;
|
||||
|
||||
case IDM_VIEWASASCII:
|
||||
viewAsType = VIEWAS_ASCII;
|
||||
Refresh();
|
||||
SetDataType(MemoryDataType::ASCII);
|
||||
break;
|
||||
|
||||
case IDM_VIEWASHEX:
|
||||
viewAsType = VIEWAS_HEX;
|
||||
Refresh();
|
||||
SetDataType(m_last_hex_type);
|
||||
break;
|
||||
|
||||
default:
|
||||
event.Skip();
|
||||
break;
|
||||
}
|
||||
|
||||
#if wxUSE_CLIPBOARD
|
||||
wxTheClipboard->Close();
|
||||
#endif
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void CMemoryView::OnMouseDownR(wxMouseEvent& event)
|
||||
@ -216,12 +251,14 @@ void CMemoryView::OnMouseDownR(wxMouseEvent& event)
|
||||
menu.Append(IDM_COPYHEX, _("Copy &hex"));
|
||||
#endif
|
||||
menu.Append(IDM_WATCHADDRESS, _("Add to &watch"));
|
||||
menu.Append(IDM_TOGGLEMEMORY, _("Toggle &memory"));
|
||||
menu.AppendCheckItem(IDM_TOGGLEMEMORY, _("Toggle &memory"))->Check(memory != 0);
|
||||
|
||||
wxMenu* viewAsSubMenu = new wxMenu;
|
||||
viewAsSubMenu->Append(IDM_VIEWASFP, _("FP value"));
|
||||
viewAsSubMenu->Append(IDM_VIEWASASCII, "ASCII");
|
||||
viewAsSubMenu->Append(IDM_VIEWASHEX, _("Hex"));
|
||||
viewAsSubMenu->AppendRadioItem(IDM_VIEWASFP, _("FP value"))
|
||||
->Check(m_data_type == MemoryDataType::FloatingPoint);
|
||||
viewAsSubMenu->AppendRadioItem(IDM_VIEWASASCII, "ASCII")
|
||||
->Check(m_data_type == MemoryDataType::ASCII);
|
||||
viewAsSubMenu->AppendRadioItem(IDM_VIEWASHEX, _("Hex"))->Check(IsHexMode());
|
||||
menu.AppendSubMenu(viewAsSubMenu, _("View As:"));
|
||||
|
||||
PopupMenu(&menu);
|
||||
@ -231,176 +268,160 @@ void CMemoryView::OnPaint(wxPaintEvent& event)
|
||||
{
|
||||
wxPaintDC dc(this);
|
||||
wxRect rc = GetClientRect();
|
||||
wxFont hFont("Courier");
|
||||
hFont.SetFamily(wxFONTFAMILY_TELETYPE);
|
||||
|
||||
wxCoord w, h;
|
||||
dc.GetTextExtent("0WJyq", &w, &h, nullptr, nullptr, &hFont);
|
||||
if (h > rowHeight)
|
||||
rowHeight = h;
|
||||
dc.GetTextExtent("0WJyq", &w, &h, nullptr, nullptr, &DebuggerFont);
|
||||
if (h > rowHeight)
|
||||
rowHeight = h;
|
||||
|
||||
if (viewAsType == VIEWAS_HEX)
|
||||
dc.SetFont(hFont);
|
||||
else
|
||||
if (DebuggerFont.IsFixedWidth())
|
||||
{
|
||||
dc.SetFont(DebuggerFont);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetFont(wxFont(DebuggerFont.GetPointSize(), wxFONTFAMILY_TELETYPE, wxFONTSTYLE_NORMAL,
|
||||
wxFONTWEIGHT_NORMAL, false, "Courier"));
|
||||
}
|
||||
|
||||
dc.GetTextExtent("W", &w, &h);
|
||||
int fontSize = w;
|
||||
int textPlacement = 17 + 9 * fontSize;
|
||||
int font_width;
|
||||
{
|
||||
wxFontMetrics metrics = dc.GetFontMetrics();
|
||||
font_width = metrics.averageWidth;
|
||||
if (metrics.height > rowHeight)
|
||||
rowHeight = metrics.height;
|
||||
}
|
||||
|
||||
// TODO: Add any drawing code here...
|
||||
int width = rc.width;
|
||||
int numRows = (rc.height / rowHeight) / 2 + 2;
|
||||
dc.SetBackgroundMode(wxPENSTYLE_TRANSPARENT);
|
||||
const wxColour bgColor = *wxWHITE;
|
||||
wxPen nullPen(bgColor);
|
||||
wxPen currentPen(*wxBLACK_PEN);
|
||||
wxPen selPen(*wxGREY_PEN);
|
||||
nullPen.SetStyle(wxPENSTYLE_TRANSPARENT);
|
||||
const int row_start_x = m_left_col_width + 1;
|
||||
const int mchk_x = FromDIP(LEFT_COL_WIDTH / 8);
|
||||
const wxSize mchk_size = FromDIP(wxSize(LEFT_COL_WIDTH * 3 / 4, LEFT_COL_WIDTH * 3 / 4));
|
||||
const int mchk_offset_y = (rowHeight - mchk_size.GetHeight()) / 2;
|
||||
|
||||
wxBrush currentBrush(*wxLIGHT_GREY_BRUSH);
|
||||
wxBrush pcBrush(*wxGREEN_BRUSH);
|
||||
wxBrush mcBrush(*wxBLUE_BRUSH);
|
||||
wxBrush bgBrush(bgColor);
|
||||
wxBrush nullBrush(bgColor);
|
||||
nullBrush.SetStyle(wxBRUSHSTYLE_TRANSPARENT);
|
||||
int col_width = rc.width - m_left_col_width;
|
||||
int num_rows = (rc.height / rowHeight) / 2 + 2;
|
||||
const wxColour navy_color = wxTheColourDatabase->Find("NAVY");
|
||||
|
||||
dc.SetPen(nullPen);
|
||||
dc.SetBrush(bgBrush);
|
||||
dc.DrawRectangle(0, 0, 16, rc.height);
|
||||
dc.DrawRectangle(0, 0, rc.width, 5 + 8);
|
||||
const int pen_width = FromDIP(1);
|
||||
wxPen focus_pen(*wxBLACK, pen_width);
|
||||
wxPen selection_pen(*wxLIGHT_GREY, pen_width);
|
||||
wxBrush pc_brush(*wxGREEN_BRUSH);
|
||||
wxBrush mc_brush(*wxBLUE_BRUSH);
|
||||
wxBrush bg_brush(*wxWHITE_BRUSH);
|
||||
|
||||
// TODO - clean up this freaking mess!!!!!
|
||||
for (int row = -numRows; row <= numRows; row++)
|
||||
for (int row = -num_rows; row <= num_rows; ++row)
|
||||
{
|
||||
unsigned int address = curAddress + row * align;
|
||||
u32 address = curAddress + row * align;
|
||||
|
||||
int rowY1 = rc.height / 2 + rowHeight * row - rowHeight / 2;
|
||||
int rowY2 = rc.height / 2 + rowHeight * row + rowHeight / 2;
|
||||
int row_y = rc.height / 2 + rowHeight * row - rowHeight / 2;
|
||||
int row_x = row_start_x;
|
||||
|
||||
auto draw_text = [&](const wxString& s, int offset_chars = 0, int min_length = 0) -> void {
|
||||
dc.DrawText(s, row_x + font_width * offset_chars, row_y);
|
||||
row_x += font_width * (std::max(static_cast<int>(s.size()), min_length) + offset_chars);
|
||||
};
|
||||
|
||||
wxString temp = wxString::Format("%08x", address);
|
||||
u32 col = debugger->GetColor(address);
|
||||
wxBrush rowBrush(wxColour(col >> 16, col >> 8, col));
|
||||
dc.SetBrush(nullBrush);
|
||||
dc.SetPen(nullPen);
|
||||
dc.DrawRectangle(0, rowY1, 16, rowY2);
|
||||
dc.SetBrush(bg_brush);
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.DrawRectangle(0, row_y, m_left_col_width, rowHeight);
|
||||
|
||||
if (selecting && (address == selection))
|
||||
dc.SetPen(selPen);
|
||||
dc.SetPen(selection_pen);
|
||||
else
|
||||
dc.SetPen(row == 0 ? currentPen : nullPen);
|
||||
dc.SetPen(row == 0 ? focus_pen : *wxTRANSPARENT_PEN);
|
||||
|
||||
if (address == debugger->GetPC())
|
||||
dc.SetBrush(pcBrush);
|
||||
dc.SetBrush(pc_brush);
|
||||
else
|
||||
dc.SetBrush(rowBrush);
|
||||
|
||||
dc.DrawRectangle(16, rowY1, width, rowY2 - 1);
|
||||
dc.SetBrush(currentBrush);
|
||||
dc.SetTextForeground("#600000"); // Dark red
|
||||
dc.DrawText(temp, 17, rowY1);
|
||||
dc.DrawRectangle(m_left_col_width, row_y, col_width, rowHeight);
|
||||
dc.SetTextForeground(wxColour(0x60, 0x00, 0x00)); // Dark red
|
||||
draw_text(temp);
|
||||
|
||||
if (viewAsType != VIEWAS_HEX)
|
||||
if (!IsHexMode())
|
||||
{
|
||||
char mem[256];
|
||||
debugger->GetRawMemoryString(memory, address, mem, 256);
|
||||
dc.SetTextForeground(wxTheColourDatabase->Find("NAVY"));
|
||||
dc.DrawText(StrToWxStr(mem), 17 + fontSize * (8), rowY1);
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
dc.SetTextForeground(navy_color);
|
||||
draw_text(StrToWxStr(mem), 2);
|
||||
}
|
||||
dc.SetTextForeground(*wxBLACK);
|
||||
|
||||
// NOTE: We can trigger a segfault inside HostIsRAMAddress (nullptr) during shutdown
|
||||
// because we still get paint events even though the core is being deleted so we
|
||||
// need to make sure the Memory still exists.
|
||||
// FIXME: This isn't relevant to the DSP Memory View
|
||||
if (!debugger->IsAlive() || !Memory::IsInitialized() || !PowerPC::HostIsRAMAddress(address))
|
||||
continue;
|
||||
|
||||
std::string dis;
|
||||
// FIXME: This doesn't work with the DSP Debugger
|
||||
u32 mem_data = debugger->ReadExtraMemory(memory, address);
|
||||
|
||||
if (m_data_type == MemoryDataType::FloatingPoint)
|
||||
{
|
||||
float& flt = reinterpret_cast<float&>(mem_data);
|
||||
dis = StringFromFormat("f: %f", flt);
|
||||
}
|
||||
else if (m_data_type == MemoryDataType::ASCII)
|
||||
{
|
||||
dis.reserve(4);
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
u8 byte = static_cast<u8>(mem_data >> (24 - i * 8));
|
||||
if (std::isprint(byte))
|
||||
dis += static_cast<char>(byte);
|
||||
else
|
||||
dis += ' ';
|
||||
}
|
||||
|
||||
Symbol* sym = g_symbolDB.GetSymbolFromAddr(mem_data);
|
||||
if (sym)
|
||||
{
|
||||
dis += StringFromFormat(" # -> %s", sym->name.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dis.reserve(48);
|
||||
for (unsigned int i = 0; i < align; i += sizeof(u32))
|
||||
{
|
||||
if (!PowerPC::HostIsRAMAddress(address + i))
|
||||
break;
|
||||
u32 word = debugger->ReadExtraMemory(memory, address + i);
|
||||
switch (m_data_type)
|
||||
{
|
||||
case MemoryDataType::U8:
|
||||
default:
|
||||
dis += StringFromFormat(" %02X %02X %02X %02X", (word >> 24) & 0xFF, (word >> 16) & 0xFF,
|
||||
(word >> 8) & 0xFF, word & 0xFF);
|
||||
break;
|
||||
case MemoryDataType::U16:
|
||||
dis += StringFromFormat(" %04X %04X", (word >> 16) & 0xFFFF, word & 0xFFFF);
|
||||
break;
|
||||
case MemoryDataType::U32:
|
||||
dis += StringFromFormat(" %08X", word);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (debugger->IsAlive())
|
||||
// Pad to a minimum of 48 characters for full fixed point float width
|
||||
draw_text(StrToWxStr(dis), 2, 48);
|
||||
|
||||
dc.SetTextForeground(*wxBLUE);
|
||||
|
||||
std::string desc = debugger->GetDescription(address);
|
||||
if (!desc.empty())
|
||||
draw_text(StrToWxStr(desc), 2);
|
||||
|
||||
// Show blue memory check dot
|
||||
if (debugger->IsMemCheck(address))
|
||||
{
|
||||
if (!PowerPC::HostIsRAMAddress(address))
|
||||
continue;
|
||||
|
||||
std::string dis;
|
||||
u32 mem_data = debugger->ReadExtraMemory(memory, address);
|
||||
|
||||
if (viewAsType == VIEWAS_FP)
|
||||
{
|
||||
float flt = *(float*)(&mem_data);
|
||||
dis = StringFromFormat("f: %f", flt);
|
||||
}
|
||||
else if (viewAsType == VIEWAS_ASCII)
|
||||
{
|
||||
u32 a[4] = {(mem_data & 0xff000000) >> 24, (mem_data & 0xff0000) >> 16,
|
||||
(mem_data & 0xff00) >> 8, (mem_data & 0xff)};
|
||||
|
||||
for (auto& word : a)
|
||||
{
|
||||
if (word == '\0')
|
||||
word = ' ';
|
||||
}
|
||||
|
||||
Symbol* sym = g_symbolDB.GetSymbolFromAddr(mem_data);
|
||||
if (sym == nullptr)
|
||||
dis = StringFromFormat("%c%c%c%c", a[0], a[1], a[2], a[3]);
|
||||
else
|
||||
dis = StringFromFormat("# -> %s", sym->name.c_str());
|
||||
}
|
||||
else if (viewAsType == VIEWAS_HEX)
|
||||
{
|
||||
u32 mema[8] = {debugger->ReadExtraMemory(memory, address),
|
||||
debugger->ReadExtraMemory(memory, address + 4),
|
||||
debugger->ReadExtraMemory(memory, address + 8),
|
||||
debugger->ReadExtraMemory(memory, address + 12),
|
||||
debugger->ReadExtraMemory(memory, address + 16),
|
||||
debugger->ReadExtraMemory(memory, address + 20),
|
||||
debugger->ReadExtraMemory(memory, address + 24),
|
||||
debugger->ReadExtraMemory(memory, address + 28)};
|
||||
|
||||
for (auto& word : mema)
|
||||
{
|
||||
switch (dataType)
|
||||
{
|
||||
case MemoryDataType::U8:
|
||||
dis += StringFromFormat(" %02X %02X %02X %02X", ((word & 0xff000000) >> 24) & 0xFF,
|
||||
((word & 0xff0000) >> 16) & 0xFF, ((word & 0xff00) >> 8) & 0xFF,
|
||||
word & 0xff);
|
||||
break;
|
||||
case MemoryDataType::U16:
|
||||
dis += StringFromFormat(" %02X%02X %02X%02X", ((word & 0xff000000) >> 24) & 0xFF,
|
||||
((word & 0xff0000) >> 16) & 0xFF, ((word & 0xff00) >> 8) & 0xFF,
|
||||
word & 0xff);
|
||||
break;
|
||||
case MemoryDataType::U32:
|
||||
dis += StringFromFormat(" %02X%02X%02X%02X", ((word & 0xff000000) >> 24) & 0xFF,
|
||||
((word & 0xff0000) >> 16) & 0xFF, ((word & 0xff00) >> 8) & 0xFF,
|
||||
word & 0xff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
dis = "INVALID VIEWAS TYPE";
|
||||
}
|
||||
|
||||
if (viewAsType != VIEWAS_HEX)
|
||||
dc.DrawText(StrToWxStr(dis), textPlacement + fontSize * (8 + 8), rowY1);
|
||||
else
|
||||
dc.DrawText(StrToWxStr(dis), textPlacement, rowY1);
|
||||
|
||||
dc.SetTextForeground(*wxBLUE);
|
||||
|
||||
std::string desc = debugger->GetDescription(address);
|
||||
if (!desc.empty())
|
||||
dc.DrawText(StrToWxStr(desc), 17 + fontSize * ((8 + 8 + 8 + 30) * 2), rowY1);
|
||||
|
||||
// Show blue memory check dot
|
||||
if (debugger->IsMemCheck(address))
|
||||
{
|
||||
dc.SetBrush(mcBrush);
|
||||
dc.DrawRectangle(8, rowY1 + 1, 11, 11);
|
||||
}
|
||||
dc.SetPen(*wxTRANSPARENT_PEN);
|
||||
dc.SetBrush(mc_brush);
|
||||
dc.DrawEllipse(mchk_x, row_y + mchk_offset_y, mchk_size.GetWidth(), mchk_size.GetHeight());
|
||||
}
|
||||
}
|
||||
|
||||
dc.SetPen(currentPen);
|
||||
}
|
||||
|
||||
void CMemoryView::OnResize(wxSizeEvent& event)
|
||||
|
@ -13,9 +13,13 @@ enum class MemoryDataType
|
||||
{
|
||||
U8,
|
||||
U16,
|
||||
U32
|
||||
U32,
|
||||
ASCII,
|
||||
FloatingPoint
|
||||
};
|
||||
|
||||
wxDECLARE_EVENT(DOLPHIN_EVT_MEMORY_VIEW_DATA_TYPE_CHANGED, wxCommandEvent);
|
||||
|
||||
class CMemoryView : public wxControl
|
||||
{
|
||||
public:
|
||||
@ -29,12 +33,8 @@ public:
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SetDataType(MemoryDataType data_type)
|
||||
{
|
||||
dataType = data_type;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void SetDataType(MemoryDataType data_type);
|
||||
MemoryDataType GetDataType() const { return m_data_type; }
|
||||
void SetMemCheckOptions(bool read, bool write, bool log)
|
||||
{
|
||||
memCheckRead = read;
|
||||
@ -43,6 +43,12 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
int YToAddress(int y);
|
||||
bool IsHexMode() const
|
||||
{
|
||||
return m_data_type != MemoryDataType::ASCII && m_data_type != MemoryDataType::FloatingPoint;
|
||||
}
|
||||
|
||||
void OnPaint(wxPaintEvent& event);
|
||||
void OnMouseDownL(wxMouseEvent& event);
|
||||
void OnMouseMove(wxMouseEvent& event);
|
||||
@ -50,14 +56,15 @@ private:
|
||||
void OnMouseDownR(wxMouseEvent& event);
|
||||
void OnScrollWheel(wxMouseEvent& event);
|
||||
void OnPopupMenu(wxCommandEvent& event);
|
||||
|
||||
int YToAddress(int y);
|
||||
void OnResize(wxSizeEvent& event);
|
||||
|
||||
static constexpr int LEFT_COL_WIDTH = 16;
|
||||
|
||||
DebugInterface* debugger;
|
||||
|
||||
int align;
|
||||
unsigned int align;
|
||||
int rowHeight;
|
||||
int m_left_col_width;
|
||||
|
||||
u32 selection;
|
||||
u32 oldSelection;
|
||||
@ -65,18 +72,11 @@ private:
|
||||
|
||||
int memory;
|
||||
int curAddress;
|
||||
MemoryDataType dataType;
|
||||
|
||||
bool memCheckRead;
|
||||
bool memCheckWrite;
|
||||
bool memCheckLog;
|
||||
|
||||
enum EViewAsType
|
||||
{
|
||||
VIEWAS_ASCII = 0,
|
||||
VIEWAS_FP,
|
||||
VIEWAS_HEX,
|
||||
};
|
||||
|
||||
EViewAsType viewAsType;
|
||||
MemoryDataType m_data_type;
|
||||
MemoryDataType m_last_hex_type = MemoryDataType::U8;
|
||||
};
|
||||
|
@ -2,9 +2,10 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <wx/button.h>
|
||||
@ -12,10 +13,13 @@
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/radiobox.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/srchctrl.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
@ -43,9 +47,7 @@ enum
|
||||
IDM_DUMP_MEM2,
|
||||
IDM_DUMP_FAKEVMEM,
|
||||
IDM_VALBOX,
|
||||
IDM_U8,
|
||||
IDM_U16,
|
||||
IDM_U32,
|
||||
IDM_DATA_TYPE_RBOX,
|
||||
IDM_SEARCH,
|
||||
IDM_ASCII,
|
||||
IDM_HEX,
|
||||
@ -53,30 +55,24 @@ enum
|
||||
};
|
||||
|
||||
BEGIN_EVENT_TABLE(CMemoryWindow, wxPanel)
|
||||
EVT_LISTBOX(IDM_SYMBOLLIST, CMemoryWindow::OnSymbolListChange)
|
||||
EVT_HOST_COMMAND(wxID_ANY, CMemoryWindow::OnHostMessage)
|
||||
EVT_BUTTON(IDM_SETVALBUTTON, CMemoryWindow::SetMemoryValue)
|
||||
EVT_BUTTON(IDM_DUMP_MEMORY, CMemoryWindow::OnDumpMemory)
|
||||
EVT_BUTTON(IDM_DUMP_MEM2, CMemoryWindow::OnDumpMem2)
|
||||
EVT_BUTTON(IDM_DUMP_FAKEVMEM, CMemoryWindow::OnDumpFakeVMEM)
|
||||
EVT_CHECKBOX(IDM_U8, CMemoryWindow::U8)
|
||||
EVT_CHECKBOX(IDM_U16, CMemoryWindow::U16)
|
||||
EVT_CHECKBOX(IDM_U32, CMemoryWindow::U32)
|
||||
EVT_BUTTON(IDM_SEARCH, CMemoryWindow::onSearch)
|
||||
EVT_CHECKBOX(IDM_ASCII, CMemoryWindow::onAscii)
|
||||
EVT_CHECKBOX(IDM_HEX, CMemoryWindow::onHex)
|
||||
EVT_RADIOBUTTON(IDM_MEMCHECK_OPTIONS_CHANGE, CMemoryWindow::onMemCheckOptionChange)
|
||||
EVT_CHECKBOX(IDM_MEMCHECK_OPTIONS_CHANGE, CMemoryWindow::onMemCheckOptionChange)
|
||||
EVT_RADIOBOX(IDM_DATA_TYPE_RBOX, CMemoryWindow::OnDataTypeChanged)
|
||||
EVT_BUTTON(IDM_SEARCH, CMemoryWindow::OnSearch)
|
||||
EVT_RADIOBUTTON(IDM_MEMCHECK_OPTIONS_CHANGE, CMemoryWindow::OnMemCheckOptionChange)
|
||||
EVT_CHECKBOX(IDM_MEMCHECK_OPTIONS_CHANGE, CMemoryWindow::OnMemCheckOptionChange)
|
||||
END_EVENT_TABLE()
|
||||
|
||||
CMemoryWindow::CMemoryWindow(CCodeWindow* code_window, wxWindow* parent, wxWindowID id,
|
||||
const wxPoint& pos, const wxSize& size, long style,
|
||||
const wxString& name)
|
||||
: wxPanel(parent, id, pos, size, style, name), m_code_window(code_window)
|
||||
CMemoryWindow::CMemoryWindow(wxWindow* parent, wxWindowID id, const wxPoint& pos,
|
||||
const wxSize& size, long style, const wxString& name)
|
||||
: wxPanel(parent, id, pos, size, style, name)
|
||||
{
|
||||
DebugInterface* di = &PowerPC::debug_interface;
|
||||
|
||||
memview = new CMemoryView(di, this);
|
||||
memview->Bind(DOLPHIN_EVT_MEMORY_VIEW_DATA_TYPE_CHANGED, &CMemoryWindow::OnDataTypeChanged, this);
|
||||
|
||||
addrbox = new wxSearchCtrl(this, IDM_MEM_ADDRBOX);
|
||||
addrbox->Bind(wxEVT_TEXT, &CMemoryWindow::OnAddrBoxChange, this);
|
||||
@ -85,13 +81,17 @@ CMemoryWindow::CMemoryWindow(CCodeWindow* code_window, wxWindow* parent, wxWindo
|
||||
valbox =
|
||||
new wxTextCtrl(this, IDM_VALBOX, "", wxDefaultPosition, wxDefaultSize, wxTE_PROCESS_ENTER);
|
||||
valbox->Bind(wxEVT_TEXT_ENTER, &CMemoryWindow::SetMemoryValueFromValBox, this);
|
||||
valbox->Bind(wxEVT_TEXT, &CMemoryWindow::OnValueChanged, this);
|
||||
|
||||
wxGridSizer* const search_sizer = new wxGridSizer(1);
|
||||
search_sizer->Add(addrbox);
|
||||
const int space3 = FromDIP(3);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const search_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
search_sizer->Add(addrbox, 0, wxEXPAND);
|
||||
search_sizer->Add(valbox, 0, wxEXPAND);
|
||||
search_sizer->Add(new wxButton(this, IDM_SETVALBUTTON, _("Set Value")));
|
||||
|
||||
wxGridSizer* const dump_sizer = new wxGridSizer(1);
|
||||
wxBoxSizer* const dump_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
dump_sizer->Add(new wxButton(this, IDM_DUMP_MEMORY, _("Dump MRAM")), 0, wxEXPAND);
|
||||
dump_sizer->Add(new wxButton(this, IDM_DUMP_MEM2, _("Dump EXRAM")), 0, wxEXPAND);
|
||||
if (!SConfig::GetInstance().bMMU)
|
||||
@ -99,73 +99,57 @@ CMemoryWindow::CMemoryWindow(CCodeWindow* code_window, wxWindow* parent, wxWindo
|
||||
|
||||
wxStaticBoxSizer* const sizerSearchType = new wxStaticBoxSizer(wxVERTICAL, this, _("Search"));
|
||||
sizerSearchType->Add(btnSearch = new wxButton(this, IDM_SEARCH, _("Search")));
|
||||
sizerSearchType->Add(chkAscii = new wxCheckBox(this, IDM_ASCII, "Ascii "));
|
||||
sizerSearchType->Add(chkHex = new wxCheckBox(this, IDM_HEX, _("Hex")));
|
||||
sizerSearchType->Add(m_rb_ascii = new wxRadioButton(this, IDM_ASCII, "Ascii", wxDefaultPosition,
|
||||
wxDefaultSize, wxRB_GROUP));
|
||||
sizerSearchType->Add(m_rb_hex = new wxRadioButton(this, IDM_HEX, _("Hex")));
|
||||
m_search_result_msg =
|
||||
new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxST_NO_AUTORESIZE | wxALIGN_CENTER_HORIZONTAL);
|
||||
sizerSearchType->Add(m_search_result_msg, 0, wxEXPAND);
|
||||
|
||||
wxStaticBoxSizer* const sizerDataTypes = new wxStaticBoxSizer(wxVERTICAL, this, _("Data Type"));
|
||||
sizerDataTypes->SetMinSize(74, 40);
|
||||
sizerDataTypes->Add(chk8 = new wxCheckBox(this, IDM_U8, "U8"));
|
||||
sizerDataTypes->Add(chk16 = new wxCheckBox(this, IDM_U16, "U16"));
|
||||
sizerDataTypes->Add(chk32 = new wxCheckBox(this, IDM_U32, "U32"));
|
||||
wxArrayString data_type_options;
|
||||
data_type_options.Add("U8");
|
||||
data_type_options.Add("U16");
|
||||
data_type_options.Add("U32");
|
||||
data_type_options.Add("ASCII");
|
||||
data_type_options.Add("Float32");
|
||||
m_rbox_data_type = new wxRadioBox(this, IDM_DATA_TYPE_RBOX, _("Data Type"), wxDefaultPosition,
|
||||
wxDefaultSize, data_type_options, 1);
|
||||
|
||||
wxStaticBoxSizer* const sizerMemCheckOptions =
|
||||
wxStaticBoxSizer* const memcheck_options_sizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, this, "Memory check options");
|
||||
sizerMemCheckOptions->Add(rdbReadWrite = new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE,
|
||||
"Read and Write", wxDefaultPosition,
|
||||
wxDefaultSize, wxRB_GROUP));
|
||||
sizerMemCheckOptions->Add(rdbRead =
|
||||
new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE, "Read only"));
|
||||
sizerMemCheckOptions->Add(rdbWrite =
|
||||
new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE, "Write only"));
|
||||
sizerMemCheckOptions->Add(chkLog = new wxCheckBox(this, IDM_MEMCHECK_OPTIONS_CHANGE, "Log"));
|
||||
memcheck_options_sizer->Add(rdbReadWrite = new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE,
|
||||
"Read and Write", wxDefaultPosition,
|
||||
wxDefaultSize, wxRB_GROUP));
|
||||
memcheck_options_sizer->Add(
|
||||
rdbRead = new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE, "Read only"));
|
||||
memcheck_options_sizer->Add(
|
||||
rdbWrite = new wxRadioButton(this, IDM_MEMCHECK_OPTIONS_CHANGE, "Write only"));
|
||||
memcheck_options_sizer->Add(chkLog = new wxCheckBox(this, IDM_MEMCHECK_OPTIONS_CHANGE, "Log"));
|
||||
|
||||
wxBoxSizer* const sizerRight = new wxBoxSizer(wxVERTICAL);
|
||||
sizerRight->Add(search_sizer);
|
||||
sizerRight->AddSpacer(5);
|
||||
sizerRight->Add(dump_sizer);
|
||||
sizerRight->Add(sizerSearchType);
|
||||
sizerRight->Add(sizerDataTypes);
|
||||
sizerRight->Add(sizerMemCheckOptions);
|
||||
sizerRight->AddSpacer(space5);
|
||||
sizerRight->Add(dump_sizer, 0, wxEXPAND);
|
||||
sizerRight->Add(sizerSearchType, 0, wxEXPAND);
|
||||
sizerRight->Add(m_rbox_data_type, 0, wxEXPAND);
|
||||
sizerRight->Add(memcheck_options_sizer, 0, wxEXPAND);
|
||||
|
||||
wxBoxSizer* const sizerBig = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizerBig->Add(memview, 20, wxEXPAND);
|
||||
sizerBig->Add(sizerRight, 0, wxEXPAND | wxALL, 3);
|
||||
sizerBig->AddSpacer(space3);
|
||||
sizerBig->Add(sizerRight, 0, wxEXPAND | wxTOP | wxBOTTOM, space3);
|
||||
sizerBig->AddSpacer(space3);
|
||||
|
||||
SetSizer(sizerBig);
|
||||
chkHex->SetValue(1); // Set defaults
|
||||
chk8->SetValue(1);
|
||||
chkLog->SetValue(1);
|
||||
m_rb_hex->SetValue(true); // Set defaults
|
||||
chkLog->SetValue(true);
|
||||
m_rbox_data_type->SetSelection(static_cast<int>(memview->GetDataType()));
|
||||
|
||||
sizerRight->Fit(this);
|
||||
sizerBig->Fit(this);
|
||||
}
|
||||
|
||||
void CMemoryWindow::Save(IniFile& ini) const
|
||||
{
|
||||
// Prevent these bad values that can happen after a crash or hanging
|
||||
if (GetPosition().x != -32000 && GetPosition().y != -32000)
|
||||
{
|
||||
IniFile::Section* mem_window = ini.GetOrCreateSection("MemoryWindow");
|
||||
mem_window->Set("x", GetPosition().x);
|
||||
mem_window->Set("y", GetPosition().y);
|
||||
mem_window->Set("w", GetSize().GetWidth());
|
||||
mem_window->Set("h", GetSize().GetHeight());
|
||||
}
|
||||
}
|
||||
|
||||
void CMemoryWindow::Load(IniFile& ini)
|
||||
{
|
||||
int x, y, w, h;
|
||||
|
||||
IniFile::Section* mem_window = ini.GetOrCreateSection("MemoryWindow");
|
||||
mem_window->Get("x", &x, GetPosition().x);
|
||||
mem_window->Get("y", &y, GetPosition().y);
|
||||
mem_window->Get("w", &w, GetSize().GetWidth());
|
||||
mem_window->Get("h", &h, GetSize().GetHeight());
|
||||
|
||||
SetSize(x, y, w, h);
|
||||
}
|
||||
|
||||
void CMemoryWindow::JumpToAddress(u32 _Address)
|
||||
{
|
||||
memview->Center(_Address);
|
||||
@ -219,55 +203,14 @@ void CMemoryWindow::OnAddrBoxChange(wxCommandEvent& event)
|
||||
event.Skip();
|
||||
}
|
||||
|
||||
void CMemoryWindow::Update()
|
||||
void CMemoryWindow::Repopulate()
|
||||
{
|
||||
memview->Refresh();
|
||||
memview->Center(PC);
|
||||
}
|
||||
|
||||
void CMemoryWindow::NotifyMapLoaded()
|
||||
void CMemoryWindow::OnValueChanged(wxCommandEvent&)
|
||||
{
|
||||
symbols->Show(false); // hide it for faster filling
|
||||
symbols->Clear();
|
||||
#if 0
|
||||
#ifdef _WIN32
|
||||
const FunctionDB::XFuncMap &syms = g_symbolDB.Symbols();
|
||||
for (FuntionDB::XFuncMap::iterator iter = syms.begin(); iter != syms.end(); ++iter)
|
||||
{
|
||||
int idx = symbols->Append(iter->second.name.c_str());
|
||||
symbols->SetClientData(idx, (void*)&iter->second);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
symbols->Show(true);
|
||||
Update();
|
||||
}
|
||||
|
||||
void CMemoryWindow::OnSymbolListChange(wxCommandEvent& event)
|
||||
{
|
||||
int index = symbols->GetSelection();
|
||||
if (index >= 0)
|
||||
{
|
||||
Symbol* pSymbol = static_cast<Symbol*>(symbols->GetClientData(index));
|
||||
if (pSymbol != nullptr)
|
||||
{
|
||||
memview->Center(pSymbol->address);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CMemoryWindow::OnHostMessage(wxCommandEvent& event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case IDM_NOTIFY_MAP_LOADED:
|
||||
NotifyMapLoaded();
|
||||
break;
|
||||
case IDM_UPDATE_BREAKPOINTS:
|
||||
if (m_code_window->m_BreakpointWindow)
|
||||
m_code_window->m_BreakpointWindow->NotifyUpdate();
|
||||
break;
|
||||
}
|
||||
m_continue_search = false;
|
||||
}
|
||||
|
||||
static void DumpArray(const std::string& filename, const u8* data, size_t length)
|
||||
@ -304,39 +247,40 @@ void CMemoryWindow::OnDumpFakeVMEM(wxCommandEvent& event)
|
||||
DumpArray(File::GetUserPath(F_FAKEVMEMDUMP_IDX), Memory::m_pFakeVMEM, Memory::FAKEVMEM_SIZE);
|
||||
}
|
||||
|
||||
void CMemoryWindow::U8(wxCommandEvent& event)
|
||||
void CMemoryWindow::OnDataTypeChanged(wxCommandEvent& ev)
|
||||
{
|
||||
chk16->SetValue(0);
|
||||
chk32->SetValue(0);
|
||||
memview->SetDataType(MemoryDataType::U8);
|
||||
static constexpr std::array<MemoryDataType, 5> map{{MemoryDataType::U8, MemoryDataType::U16,
|
||||
MemoryDataType::U32, MemoryDataType::ASCII,
|
||||
MemoryDataType::FloatingPoint}};
|
||||
if (ev.GetId() == IDM_DATA_TYPE_RBOX)
|
||||
{
|
||||
memview->SetDataType(map.at(ev.GetSelection()));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Event from the CMemoryView indicating type was changed.
|
||||
auto itr = std::find(map.begin(), map.end(), static_cast<MemoryDataType>(ev.GetInt()));
|
||||
int idx = -1;
|
||||
if (itr != map.end())
|
||||
idx = static_cast<int>(itr - map.begin());
|
||||
m_rbox_data_type->SetSelection(idx);
|
||||
}
|
||||
}
|
||||
|
||||
void CMemoryWindow::U16(wxCommandEvent& event)
|
||||
void CMemoryWindow::OnSearch(wxCommandEvent& event)
|
||||
{
|
||||
chk8->SetValue(0);
|
||||
chk32->SetValue(0);
|
||||
memview->SetDataType(MemoryDataType::U16);
|
||||
}
|
||||
|
||||
void CMemoryWindow::U32(wxCommandEvent& event)
|
||||
{
|
||||
chk16->SetValue(0);
|
||||
chk8->SetValue(0);
|
||||
memview->SetDataType(MemoryDataType::U32);
|
||||
}
|
||||
|
||||
void CMemoryWindow::onSearch(wxCommandEvent& event)
|
||||
{
|
||||
u8* TheRAM = nullptr;
|
||||
u32 szRAM = 0;
|
||||
wxBusyCursor hourglass_cursor;
|
||||
u8* ram_ptr = nullptr;
|
||||
u32 ram_size = 0;
|
||||
// NOTE: We're assuming the base address is zero.
|
||||
switch (memview->GetMemoryType())
|
||||
{
|
||||
case 0:
|
||||
default:
|
||||
if (Memory::m_pRAM)
|
||||
{
|
||||
TheRAM = Memory::m_pRAM;
|
||||
szRAM = Memory::REALRAM_SIZE;
|
||||
ram_ptr = Memory::m_pRAM;
|
||||
ram_size = Memory::REALRAM_SIZE;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
@ -344,131 +288,115 @@ void CMemoryWindow::onSearch(wxCommandEvent& event)
|
||||
u8* aram = DSP::GetARAMPtr();
|
||||
if (aram)
|
||||
{
|
||||
TheRAM = aram;
|
||||
szRAM = DSP::ARAM_SIZE;
|
||||
ram_ptr = aram;
|
||||
ram_size = DSP::ARAM_SIZE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
// Now we have memory to look in
|
||||
// Are we looking for ASCII string, or hex?
|
||||
// memview->cu
|
||||
wxString rawData = valbox->GetValue();
|
||||
std::vector<u8> Dest; // May need a better name
|
||||
u32 size = 0;
|
||||
int pad = rawData.size() % 2; // If it's uneven
|
||||
unsigned int i = 0;
|
||||
long count = 0;
|
||||
char copy[3] = {0};
|
||||
long newsize = 0;
|
||||
unsigned char* tmp2 = nullptr;
|
||||
char* tmpstr = nullptr;
|
||||
|
||||
if (chkHex->GetValue())
|
||||
if (!ram_ptr)
|
||||
{
|
||||
// We are looking for hex
|
||||
// If it's uneven
|
||||
size = (rawData.size() / 2) + pad;
|
||||
Dest.resize(size + 32);
|
||||
newsize = rawData.size();
|
||||
m_search_result_msg->SetLabel(_("Memory Not Ready"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (pad)
|
||||
std::vector<u8> search_bytes;
|
||||
wxString search_val = valbox->GetValue();
|
||||
|
||||
if (m_rb_hex->GetValue())
|
||||
{
|
||||
search_val.Trim(true).Trim(false);
|
||||
// If there's a trailing nybble, stick a zero in front to make it a byte
|
||||
if (search_val.size() & 1)
|
||||
search_val.insert(0, 1, '0');
|
||||
search_bytes.reserve(search_val.size() / 2);
|
||||
|
||||
wxString conversion_buffer(2, ' ');
|
||||
for (std::size_t i = 0; i < search_val.size(); i += 2)
|
||||
{
|
||||
tmpstr = new char[newsize + 2];
|
||||
memset(tmpstr, 0, newsize + 2);
|
||||
tmpstr[0] = '0';
|
||||
unsigned long byte = 0;
|
||||
conversion_buffer[0] = search_val[i];
|
||||
conversion_buffer[1] = search_val[i + 1];
|
||||
if (!conversion_buffer.ToULong(&byte, 16))
|
||||
{
|
||||
m_search_result_msg->SetLabel(_("Not Valid Hex"));
|
||||
return;
|
||||
}
|
||||
search_bytes.push_back(static_cast<u8>(byte));
|
||||
}
|
||||
else
|
||||
{
|
||||
tmpstr = new char[newsize + 1];
|
||||
memset(tmpstr, 0, newsize + 1);
|
||||
}
|
||||
strcat(tmpstr, WxStrToStr(rawData).c_str());
|
||||
tmp2 = &Dest.front();
|
||||
count = 0;
|
||||
for (i = 0; i < strlen(tmpstr); i++)
|
||||
{
|
||||
copy[0] = tmpstr[i];
|
||||
copy[1] = tmpstr[i + 1];
|
||||
copy[2] = 0;
|
||||
int tmpint;
|
||||
sscanf(copy, "%02x", &tmpint);
|
||||
tmp2[count++] = tmpint;
|
||||
// Dest[count] should now be the hex of what the two chars were!
|
||||
// Also should add a check to make sure it's A-F only
|
||||
// sscanf(copy, "%02x", &tmp2[count++]);
|
||||
i += 1;
|
||||
}
|
||||
delete[] tmpstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Looking for an ascii string
|
||||
size = rawData.size();
|
||||
Dest.resize(size + 1);
|
||||
tmpstr = new char[size + 1];
|
||||
|
||||
tmp2 = &Dest.front();
|
||||
sprintf(tmpstr, "%s", WxStrToStr(rawData).c_str());
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
tmp2[i] = tmpstr[i];
|
||||
|
||||
delete[] tmpstr;
|
||||
const auto& bytes = search_val.ToUTF8();
|
||||
search_bytes.assign(bytes.data(), bytes.data() + bytes.length());
|
||||
}
|
||||
search_val.Clear();
|
||||
|
||||
if (size)
|
||||
// For completeness
|
||||
if (search_bytes.size() > ram_size)
|
||||
{
|
||||
unsigned char* pnt = &Dest.front();
|
||||
unsigned int k = 0;
|
||||
// grab
|
||||
wxString txt = addrbox->GetValue();
|
||||
u32 addr = 0;
|
||||
if (txt.size())
|
||||
m_search_result_msg->SetLabel(_("Value Too Large"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (search_bytes.empty())
|
||||
{
|
||||
m_search_result_msg->SetLabel(_("No Value Given"));
|
||||
return;
|
||||
}
|
||||
|
||||
// Search starting from specified address if there is one.
|
||||
u32 addr = 0; // Base address
|
||||
{
|
||||
wxString addr_val = addrbox->GetValue();
|
||||
addr_val.Trim(true).Trim(false);
|
||||
if (!addr_val.empty())
|
||||
{
|
||||
sscanf(WxStrToStr(txt).c_str(), "%08x", &addr);
|
||||
}
|
||||
i = addr + 4;
|
||||
for (; i < szRAM; ++i)
|
||||
{
|
||||
for (k = 0; k < size; ++k)
|
||||
unsigned long addr_ul = 0;
|
||||
if (addr_val.ToULong(&addr_ul, 16))
|
||||
{
|
||||
if (i + k > szRAM)
|
||||
break;
|
||||
if (k > size)
|
||||
break;
|
||||
if (pnt[k] != TheRAM[i + k])
|
||||
{
|
||||
k = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (k == size)
|
||||
{
|
||||
// Match was found
|
||||
wxMessageBox(_("A match was found. Placing viewer at the offset."));
|
||||
addrbox->SetValue(wxString::Format("%08x", i));
|
||||
// memview->curAddress = i;
|
||||
// memview->Refresh();
|
||||
OnAddrBoxChange(event);
|
||||
return;
|
||||
addr = static_cast<u32>(addr_ul);
|
||||
// Don't find the result we're already looking at
|
||||
if (m_continue_search && addr == m_last_search_address)
|
||||
addr += 1;
|
||||
}
|
||||
}
|
||||
wxMessageBox(_("No match was found."));
|
||||
}
|
||||
|
||||
// If the current address doesn't leave enough bytes to search then we're done.
|
||||
if (addr >= ram_size - search_bytes.size())
|
||||
{
|
||||
m_search_result_msg->SetLabel(_("Address Out of Range"));
|
||||
return;
|
||||
}
|
||||
|
||||
u8* end = &ram_ptr[ram_size - search_bytes.size() + 1];
|
||||
u8* ptr = &ram_ptr[addr];
|
||||
while (true)
|
||||
{
|
||||
ptr = std::find(ptr, end, search_bytes[0]);
|
||||
if (ptr == end)
|
||||
{
|
||||
m_search_result_msg->SetLabel(_("No Match"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (std::equal(search_bytes.begin(), search_bytes.end(), ptr))
|
||||
{
|
||||
m_search_result_msg->SetLabel(_("Match Found"));
|
||||
u32 offset = static_cast<u32>(ptr - ram_ptr);
|
||||
// NOTE: SetValue() generates a synthetic wxEVT_TEXT
|
||||
addrbox->SetValue(wxString::Format("%08x", offset));
|
||||
m_last_search_address = offset;
|
||||
m_continue_search = true;
|
||||
break;
|
||||
}
|
||||
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
|
||||
void CMemoryWindow::onAscii(wxCommandEvent& event)
|
||||
{
|
||||
chkHex->SetValue(0);
|
||||
}
|
||||
|
||||
void CMemoryWindow::onHex(wxCommandEvent& event)
|
||||
{
|
||||
chkAscii->SetValue(0);
|
||||
}
|
||||
|
||||
void CMemoryWindow::onMemCheckOptionChange(wxCommandEvent& event)
|
||||
void CMemoryWindow::OnMemCheckOptionChange(wxCommandEvent& event)
|
||||
{
|
||||
if (rdbReadWrite->GetValue())
|
||||
memview->SetMemCheckOptions(true, true, chkLog->GetValue());
|
||||
|
@ -12,51 +12,46 @@ class CCodeWindow;
|
||||
class IniFile;
|
||||
class wxButton;
|
||||
class wxCheckBox;
|
||||
class wxRadioBox;
|
||||
class wxRadioButton;
|
||||
class wxListBox;
|
||||
class wxSearchCtrl;
|
||||
class wxStaticText;
|
||||
class wxTextCtrl;
|
||||
class wxRadioButton;
|
||||
|
||||
class CMemoryWindow : public wxPanel
|
||||
{
|
||||
public:
|
||||
CMemoryWindow(CCodeWindow* code_window, wxWindow* parent, wxWindowID id = wxID_ANY,
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||
long style = wxTAB_TRAVERSAL | wxBORDER_NONE, const wxString& name = _("Memory"));
|
||||
CMemoryWindow(wxWindow* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL | wxBORDER_NONE,
|
||||
const wxString& name = _("Memory"));
|
||||
|
||||
void Save(IniFile& _IniFile) const;
|
||||
void Load(IniFile& _IniFile);
|
||||
|
||||
void Update() override;
|
||||
void NotifyMapLoaded();
|
||||
void Repopulate();
|
||||
|
||||
void JumpToAddress(u32 _Address);
|
||||
|
||||
private:
|
||||
DECLARE_EVENT_TABLE()
|
||||
|
||||
void U8(wxCommandEvent& event);
|
||||
void U16(wxCommandEvent& event);
|
||||
void U32(wxCommandEvent& event);
|
||||
void onSearch(wxCommandEvent& event);
|
||||
void onAscii(wxCommandEvent& event);
|
||||
void onHex(wxCommandEvent& event);
|
||||
void OnSymbolListChange(wxCommandEvent& event);
|
||||
void OnDataTypeChanged(wxCommandEvent& event);
|
||||
void OnSearch(wxCommandEvent& event);
|
||||
void OnAddrBoxChange(wxCommandEvent& event);
|
||||
void OnHostMessage(wxCommandEvent& event);
|
||||
void OnValueChanged(wxCommandEvent&);
|
||||
void SetMemoryValueFromValBox(wxCommandEvent& event);
|
||||
void SetMemoryValue(wxCommandEvent& event);
|
||||
void OnDumpMemory(wxCommandEvent& event);
|
||||
void OnDumpMem2(wxCommandEvent& event);
|
||||
void OnDumpFakeVMEM(wxCommandEvent& event);
|
||||
void onMemCheckOptionChange(wxCommandEvent& event);
|
||||
void OnMemCheckOptionChange(wxCommandEvent& event);
|
||||
|
||||
wxCheckBox* chk8;
|
||||
wxCheckBox* chk16;
|
||||
wxCheckBox* chk32;
|
||||
wxButton* btnSearch;
|
||||
wxCheckBox* chkAscii;
|
||||
wxCheckBox* chkHex;
|
||||
wxRadioButton* m_rb_ascii;
|
||||
wxRadioButton* m_rb_hex;
|
||||
|
||||
wxRadioBox* m_rbox_data_type;
|
||||
wxStaticText* m_search_result_msg;
|
||||
|
||||
wxCheckBox* chkLog;
|
||||
wxRadioButton* rdbRead;
|
||||
wxRadioButton* rdbWrite;
|
||||
@ -65,8 +60,10 @@ private:
|
||||
CCodeWindow* m_code_window;
|
||||
|
||||
CMemoryView* memview;
|
||||
wxListBox* symbols;
|
||||
|
||||
wxSearchCtrl* addrbox;
|
||||
wxTextCtrl* valbox;
|
||||
|
||||
u32 m_last_search_address = 0;
|
||||
bool m_continue_search = false;
|
||||
};
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "DolphinWX/Debugger/WatchWindow.h"
|
||||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
#include "DolphinWX/Main.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
// F-zero 80005e60 wtf??
|
||||
@ -466,7 +467,7 @@ CRegisterView::CRegisterView(wxWindow* parent, wxWindowID id) : wxGrid(parent, i
|
||||
AutoSizeColumns();
|
||||
}
|
||||
|
||||
void CRegisterView::Update()
|
||||
void CRegisterView::Repopulate()
|
||||
{
|
||||
m_register_table->UpdateCachedRegs();
|
||||
ForceRefresh();
|
||||
@ -507,10 +508,11 @@ void CRegisterView::OnMouseDownR(wxGridEvent& event)
|
||||
|
||||
void CRegisterView::OnPopupMenu(wxCommandEvent& event)
|
||||
{
|
||||
CFrame* main_frame = static_cast<CFrame*>(GetGrandParent()->GetParent());
|
||||
CCodeWindow* code_window = main_frame->g_pCodeWindow;
|
||||
CWatchWindow* watch_window = code_window->m_WatchWindow;
|
||||
CMemoryWindow* memory_window = code_window->m_MemoryWindow;
|
||||
// FIXME: This is terrible. Generate events instead.
|
||||
CFrame* cframe = wxGetApp().GetCFrame();
|
||||
CCodeWindow* code_window = cframe->g_pCodeWindow;
|
||||
CWatchWindow* watch_window = code_window->GetPanel<CWatchWindow>();
|
||||
CMemoryWindow* memory_window = code_window->GetPanel<CMemoryWindow>();
|
||||
|
||||
switch (event.GetId())
|
||||
{
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
void UpdateCachedRegs();
|
||||
|
||||
private:
|
||||
static constexpr size_t NUM_SPECIALS = 14;
|
||||
static constexpr int NUM_SPECIALS = 14;
|
||||
|
||||
std::array<u32, 32> m_CachedRegs{};
|
||||
std::array<u32, NUM_SPECIALS> m_CachedSpecialRegs{};
|
||||
@ -72,7 +72,7 @@ class CRegisterView : public wxGrid
|
||||
{
|
||||
public:
|
||||
CRegisterView(wxWindow* parent, wxWindowID id = wxID_ANY);
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
|
||||
private:
|
||||
void OnMouseDownR(wxGridEvent& event);
|
||||
|
@ -21,7 +21,7 @@ void CRegisterWindow::CreateGUIControls()
|
||||
{
|
||||
wxBoxSizer* sGrid = new wxBoxSizer(wxVERTICAL);
|
||||
m_GPRGridView = new CRegisterView(this);
|
||||
sGrid->Add(m_GPRGridView, 1, wxGROW);
|
||||
sGrid->Add(m_GPRGridView, 1, wxEXPAND);
|
||||
SetSizer(sGrid);
|
||||
|
||||
NotifyUpdate();
|
||||
@ -30,5 +30,5 @@ void CRegisterWindow::CreateGUIControls()
|
||||
void CRegisterWindow::NotifyUpdate()
|
||||
{
|
||||
if (m_GPRGridView != nullptr)
|
||||
m_GPRGridView->Update();
|
||||
m_GPRGridView->Repopulate();
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "DolphinWX/Debugger/WatchView.h"
|
||||
#include "DolphinWX/Debugger/WatchWindow.h"
|
||||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Main.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
enum
|
||||
@ -232,7 +233,7 @@ CWatchView::CWatchView(wxWindow* parent, wxWindowID id) : wxGrid(parent, id)
|
||||
Bind(wxEVT_MENU, &CWatchView::OnPopupMenu, this);
|
||||
}
|
||||
|
||||
void CWatchView::Update()
|
||||
void CWatchView::Repopulate()
|
||||
{
|
||||
if (Core::IsRunning())
|
||||
{
|
||||
@ -269,11 +270,12 @@ void CWatchView::OnMouseDownR(wxGridEvent& event)
|
||||
|
||||
void CWatchView::OnPopupMenu(wxCommandEvent& event)
|
||||
{
|
||||
CFrame* main_frame = static_cast<CFrame*>(GetGrandParent()->GetParent());
|
||||
CCodeWindow* code_window = main_frame->g_pCodeWindow;
|
||||
CWatchWindow* watch_window = code_window->m_WatchWindow;
|
||||
CMemoryWindow* memory_window = code_window->m_MemoryWindow;
|
||||
CBreakPointWindow* breakpoint_window = code_window->m_BreakpointWindow;
|
||||
// FIXME: This is terrible. Generate events instead.
|
||||
CFrame* cframe = wxGetApp().GetCFrame();
|
||||
CCodeWindow* code_window = cframe->g_pCodeWindow;
|
||||
CWatchWindow* watch_window = code_window->GetPanel<CWatchWindow>();
|
||||
CMemoryWindow* memory_window = code_window->GetPanel<CMemoryWindow>();
|
||||
CBreakPointWindow* breakpoint_window = code_window->GetPanel<CBreakPointWindow>();
|
||||
|
||||
wxString strNewVal;
|
||||
TMemCheck MemCheck;
|
||||
|
@ -37,7 +37,7 @@ class CWatchView : public wxGrid
|
||||
{
|
||||
public:
|
||||
CWatchView(wxWindow* parent, wxWindowID id = wxID_ANY);
|
||||
void Update() override;
|
||||
void Repopulate();
|
||||
|
||||
private:
|
||||
void OnMouseDownR(wxGridEvent& event);
|
||||
|
@ -25,9 +25,12 @@ public:
|
||||
: DolphinAuiToolBar(parent, id, wxDefaultPosition, wxDefaultSize,
|
||||
wxAUI_TB_DEFAULT_STYLE | wxAUI_TB_TEXT)
|
||||
{
|
||||
SetToolBitmapSize(wxSize(16, 16));
|
||||
wxSize bitmap_size = FromDIP(wxSize(16, 16));
|
||||
SetToolBitmapSize(bitmap_size);
|
||||
|
||||
m_Bitmaps[Toolbar_File] = WxUtils::LoadResourceBitmap("toolbar_debugger_delete");
|
||||
m_Bitmaps[Toolbar_File] = WxUtils::LoadScaledResourceBitmap(
|
||||
"toolbar_debugger_delete", this, bitmap_size, wxDefaultSize,
|
||||
WxUtils::LSI_SCALE_DOWN | WxUtils::LSI_ALIGN_CENTER);
|
||||
|
||||
AddTool(ID_LOAD, _("Load"), m_Bitmaps[Toolbar_File]);
|
||||
Bind(wxEVT_TOOL, &CWatchWindow::Event_LoadAll, parent, ID_LOAD);
|
||||
@ -80,7 +83,7 @@ CWatchWindow::~CWatchWindow()
|
||||
void CWatchWindow::NotifyUpdate()
|
||||
{
|
||||
if (m_GPRGridView != nullptr)
|
||||
m_GPRGridView->Update();
|
||||
m_GPRGridView->Repopulate();
|
||||
}
|
||||
|
||||
void CWatchWindow::Event_SaveAll(wxCommandEvent& WXUNUSED(event))
|
||||
|
126
Source/Core/DolphinWX/DolphinSlider.cpp
Normal file
126
Source/Core/DolphinWX/DolphinSlider.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <wx/utils.h>
|
||||
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
|
||||
#ifdef __WXMSW__
|
||||
#define WIN32_LEAN_AND_MEAN 1
|
||||
// clang-format off
|
||||
#include <Windows.h>
|
||||
#include <CommCtrl.h>
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
static constexpr int SLIDER_MIN_LENGTH = 100;
|
||||
|
||||
DolphinSlider::DolphinSlider() = default;
|
||||
DolphinSlider::~DolphinSlider() = default;
|
||||
|
||||
bool DolphinSlider::Create(wxWindow* parent, wxWindowID id, int value, int min_val, int max_val,
|
||||
const wxPoint& pos, const wxSize& size, long style,
|
||||
const wxValidator& validator, const wxString& name)
|
||||
{
|
||||
// Sanitize the style flags.
|
||||
// We don't want any label flags because those break DPI scaling on wxMSW,
|
||||
// wxWidgets will internally lock the height of the slider to 32 pixels.
|
||||
style &= ~wxSL_LABELS;
|
||||
|
||||
return wxSlider::Create(parent, id, value, min_val, max_val, pos, size, style, validator, name);
|
||||
}
|
||||
|
||||
wxSize DolphinSlider::DoGetBestClientSize() const
|
||||
{
|
||||
#ifdef __WXMSW__
|
||||
int ticks = 0;
|
||||
int default_length = FromDIP(SLIDER_MIN_LENGTH);
|
||||
if (HasFlag(wxSL_TICKS))
|
||||
{
|
||||
// NOTE: Ticks do not scale at all (on Win7)
|
||||
default_length += 4;
|
||||
ticks = 6;
|
||||
}
|
||||
|
||||
int metric = 0;
|
||||
{
|
||||
// We need to determine the maximum thumb size because unfortunately the thumb size
|
||||
// is controlled by the theme so may have a varying maximum size limit.
|
||||
// NOTE: We can't use ourself because we're const so we can't change our size.
|
||||
// NOTE: This is less inefficient then it seems, DoGetBestSize() is only called once
|
||||
// per instance and cached until InvalidateBestSize() is called.
|
||||
wxSlider* helper = new wxSlider(GetParent(), wxID_ANY, GetValue(), GetMin(), GetMax(),
|
||||
wxDefaultPosition, FromDIP(wxSize(100, 100)), GetWindowStyle());
|
||||
::RECT r{};
|
||||
::SendMessageW(reinterpret_cast<HWND>(helper->GetHWND()), TBM_GETTHUMBRECT, 0,
|
||||
reinterpret_cast<LPARAM>(&r));
|
||||
helper->Destroy();
|
||||
|
||||
// Breakdown metrics
|
||||
int computed_size;
|
||||
int scroll_size;
|
||||
if (HasFlag(wxSL_VERTICAL))
|
||||
{
|
||||
// Trackbar thumb does not directly touch the edge, we add the padding
|
||||
// a second time to pad the other edge to make it symmetric.
|
||||
computed_size = static_cast<int>(r.right + r.left);
|
||||
scroll_size = ::GetSystemMetrics(SM_CXVSCROLL);
|
||||
}
|
||||
else
|
||||
{
|
||||
computed_size = static_cast<int>(r.bottom + r.top);
|
||||
scroll_size = ::GetSystemMetrics(SM_CYHSCROLL);
|
||||
}
|
||||
|
||||
// This is based on how Microsoft calculates trackbar sizes in the .Net Framework
|
||||
// when using automatic sizing in WinForms.
|
||||
int max = scroll_size * 2;
|
||||
|
||||
metric = wxClip(computed_size, scroll_size, max);
|
||||
}
|
||||
|
||||
if (HasFlag(wxSL_VERTICAL))
|
||||
return wxSize(metric + ticks, default_length);
|
||||
return wxSize(default_length, metric + ticks);
|
||||
#else
|
||||
wxSize base_size = wxSlider::DoGetBestClientSize();
|
||||
// If the base class is not using DoGetBestClientSize(), fallback to DoGetBestSize()
|
||||
if (base_size == wxDefaultSize)
|
||||
return wxDefaultSize;
|
||||
return CorrectMinSize(base_size);
|
||||
#endif
|
||||
}
|
||||
|
||||
wxSize DolphinSlider::DoGetBestSize() const
|
||||
{
|
||||
return CorrectMinSize(wxSlider::DoGetBestSize());
|
||||
}
|
||||
|
||||
wxSize DolphinSlider::CorrectMinSize(wxSize size) const
|
||||
{
|
||||
wxSize default_length = FromDIP(wxSize(SLIDER_MIN_LENGTH, SLIDER_MIN_LENGTH));
|
||||
// GTK Styles sometimes don't return a default length.
|
||||
// NOTE: Vertical is the dominant flag if both are set.
|
||||
if (HasFlag(wxSL_VERTICAL))
|
||||
{
|
||||
if (size.GetHeight() < default_length.GetHeight())
|
||||
{
|
||||
size.SetHeight(default_length.GetHeight());
|
||||
}
|
||||
}
|
||||
else if (size.GetWidth() < default_length.GetWidth())
|
||||
{
|
||||
size.SetWidth(default_length.GetWidth());
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
#ifdef __WXMSW__
|
||||
WXLRESULT DolphinSlider::MSWWindowProc(WXUINT msg, WXWPARAM wp, WXLPARAM lp)
|
||||
{
|
||||
if (msg == WM_THEMECHANGED)
|
||||
InvalidateBestSize();
|
||||
return wxSlider::MSWWindowProc(msg, wp, lp);
|
||||
}
|
||||
#endif
|
51
Source/Core/DolphinWX/DolphinSlider.h
Normal file
51
Source/Core/DolphinWX/DolphinSlider.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2016 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <wx/slider.h>
|
||||
|
||||
// wxSlider has several bugs, including not scaling with DPI.
|
||||
// This extended slider class tries to paper over the flaws.
|
||||
// NOTE: wxSL_LABELS is not supported because it doesn't work correctly.
|
||||
class DolphinSlider : public wxSlider
|
||||
{
|
||||
public:
|
||||
DolphinSlider();
|
||||
~DolphinSlider() override;
|
||||
DolphinSlider(const DolphinSlider&) = delete;
|
||||
|
||||
DolphinSlider(wxWindow* parent, wxWindowID id, int value, int min_value, int max_value,
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||
long style = wxSL_HORIZONTAL, const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxSliderNameStr)
|
||||
{
|
||||
Create(parent, id, value, min_value, max_value, pos, size, style, validator, name);
|
||||
}
|
||||
|
||||
DolphinSlider& operator=(const DolphinSlider&) = delete;
|
||||
|
||||
bool Create(wxWindow* parent, wxWindowID id, int value, int min_value, int max_value,
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||
long style = wxSL_HORIZONTAL, const wxValidator& validator = wxDefaultValidator,
|
||||
const wxString& name = wxSliderNameStr);
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// For WM_THEMECHANGED to regenerate metrics
|
||||
WXLRESULT MSWWindowProc(WXUINT msg, WXWPARAM wp, WXLPARAM lp) override;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
// DoGetBestSize() in wxMSW::wxSlider is borked.
|
||||
// This is called by GetEffectiveMinSize() which is used by
|
||||
// wxSizers to decide the size of the widget for generating layout.
|
||||
wxSize DoGetBestClientSize() const override;
|
||||
|
||||
// GTK Themes sometimes don't provide a default min size.
|
||||
// Make other platforms consistent with Windows (i.e. min length = 100px)
|
||||
wxSize DoGetBestSize() const override;
|
||||
|
||||
private:
|
||||
wxSize CorrectMinSize(wxSize size) const;
|
||||
};
|
@ -89,6 +89,7 @@
|
||||
<ClCompile Include="Debugger\RegisterWindow.cpp" />
|
||||
<ClCompile Include="Debugger\WatchView.cpp" />
|
||||
<ClCompile Include="Debugger\WatchWindow.cpp" />
|
||||
<ClCompile Include="DolphinSlider.cpp" />
|
||||
<ClCompile Include="NetPlay\ChangeGameDialog.cpp" />
|
||||
<ClCompile Include="NetPlay\MD5Dialog.cpp" />
|
||||
<ClCompile Include="NetPlay\NetPlayLauncher.cpp" />
|
||||
@ -131,6 +132,7 @@
|
||||
<ClInclude Include="Config\InterfaceConfigPane.h" />
|
||||
<ClInclude Include="Config\PathConfigPane.h" />
|
||||
<ClInclude Include="Config\WiiConfigPane.h" />
|
||||
<ClInclude Include="DolphinSlider.h" />
|
||||
<ClInclude Include="NetPlay\ChangeGameDialog.h" />
|
||||
<ClInclude Include="NetPlay\MD5Dialog.h" />
|
||||
<ClInclude Include="NetPlay\NetPlayLauncher.h" />
|
||||
|
@ -28,6 +28,9 @@
|
||||
<Filter Include="GUI\Config">
|
||||
<UniqueIdentifier>{9d8b4144-f335-4fa4-b995-852533298474}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="GUI\Widgets">
|
||||
<UniqueIdentifier>{a894e2e3-e577-4b65-8572-055699f23a49}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Main.cpp" />
|
||||
@ -208,6 +211,9 @@
|
||||
<ClCompile Include="NetPlay\NetPlayLauncher.cpp">
|
||||
<Filter>GUI\NetPlay</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DolphinSlider.cpp">
|
||||
<Filter>GUI\Widgets</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Main.h" />
|
||||
@ -381,6 +387,9 @@
|
||||
<ClInclude Include="NetPlay\NetPlayLauncher.h">
|
||||
<Filter>GUI\NetPlay</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DolphinSlider.h">
|
||||
<Filter>GUI\Widgets</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
@ -393,4 +402,4 @@
|
||||
<ItemGroup>
|
||||
<Image Include="$(CoreDir)..\..\Installer\Dolphin.ico" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
</Project>
|
||||
|
@ -66,149 +66,139 @@ FifoPlayerDlg::~FifoPlayerDlg()
|
||||
|
||||
void FifoPlayerDlg::CreateGUIControls()
|
||||
{
|
||||
wxBoxSizer* sMain;
|
||||
sMain = new wxBoxSizer(wxVERTICAL);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
m_Notebook = new wxNotebook(this, wxID_ANY);
|
||||
|
||||
{
|
||||
m_PlayPage =
|
||||
new wxPanel(m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
wxBoxSizer* sPlayPage;
|
||||
sPlayPage = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticBoxSizer* sPlayInfo;
|
||||
sPlayInfo =
|
||||
new wxStaticBoxSizer(new wxStaticBox(m_PlayPage, wxID_ANY, _("File Info")), wxVERTICAL);
|
||||
|
||||
// File Info
|
||||
m_NumFramesLabel = new wxStaticText(m_PlayPage, wxID_ANY, wxEmptyString);
|
||||
m_NumFramesLabel->Wrap(-1);
|
||||
sPlayInfo->Add(m_NumFramesLabel, 0, wxALL, 5);
|
||||
|
||||
m_CurrentFrameLabel = new wxStaticText(m_PlayPage, wxID_ANY, wxEmptyString);
|
||||
m_CurrentFrameLabel->Wrap(-1);
|
||||
sPlayInfo->Add(m_CurrentFrameLabel, 0, wxALL, 5);
|
||||
|
||||
m_NumObjectsLabel = new wxStaticText(m_PlayPage, wxID_ANY, wxEmptyString);
|
||||
m_NumObjectsLabel->Wrap(-1);
|
||||
sPlayInfo->Add(m_NumObjectsLabel, 0, wxALL, 5);
|
||||
|
||||
sPlayPage->Add(sPlayInfo, 1, wxEXPAND, 5);
|
||||
|
||||
wxStaticBoxSizer* sFrameRange;
|
||||
sFrameRange =
|
||||
new wxStaticBoxSizer(new wxStaticBox(m_PlayPage, wxID_ANY, _("Frame Range")), wxHORIZONTAL);
|
||||
|
||||
// Frame Range
|
||||
m_FrameFromLabel = new wxStaticText(m_PlayPage, wxID_ANY, _("From"));
|
||||
m_FrameFromLabel->Wrap(-1);
|
||||
sFrameRange->Add(m_FrameFromLabel, 0, wxALL, 5);
|
||||
|
||||
m_FrameFromCtrl = new wxSpinCtrl(m_PlayPage, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 10, 0);
|
||||
sFrameRange->Add(m_FrameFromCtrl, 0, wxALL, 5);
|
||||
|
||||
m_FrameToLabel = new wxStaticText(m_PlayPage, wxID_ANY, _("To"));
|
||||
m_FrameToLabel->Wrap(-1);
|
||||
sFrameRange->Add(m_FrameToLabel, 0, wxALL, 5);
|
||||
|
||||
m_FrameToCtrl = new wxSpinCtrl(m_PlayPage, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(-1, -1), wxSP_ARROW_KEYS, 0, 10, 0);
|
||||
sFrameRange->Add(m_FrameToCtrl, 0, wxALL, 5);
|
||||
|
||||
sPlayPage->Add(sFrameRange, 0, wxEXPAND, 5);
|
||||
|
||||
wxStaticBoxSizer* sObjectRange;
|
||||
sObjectRange = new wxStaticBoxSizer(new wxStaticBox(m_PlayPage, wxID_ANY, _("Object Range")),
|
||||
wxHORIZONTAL);
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 10, 0);
|
||||
|
||||
// Object Range
|
||||
m_ObjectFromLabel = new wxStaticText(m_PlayPage, wxID_ANY, _("From"));
|
||||
m_ObjectFromLabel->Wrap(-1);
|
||||
sObjectRange->Add(m_ObjectFromLabel, 0, wxALL, 5);
|
||||
|
||||
m_ObjectFromCtrl = new wxSpinCtrl(m_PlayPage, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 10000, 0);
|
||||
sObjectRange->Add(m_ObjectFromCtrl, 0, wxALL, 5);
|
||||
|
||||
m_ObjectToLabel = new wxStaticText(m_PlayPage, wxID_ANY, _("To"));
|
||||
m_ObjectToLabel->Wrap(-1);
|
||||
sObjectRange->Add(m_ObjectToLabel, 0, wxALL, 5);
|
||||
|
||||
m_ObjectToCtrl = new wxSpinCtrl(m_PlayPage, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 10000, 0);
|
||||
sObjectRange->Add(m_ObjectToCtrl, 0, wxALL, 5);
|
||||
|
||||
sPlayPage->Add(sObjectRange, 0, wxEXPAND, 5);
|
||||
|
||||
wxStaticBoxSizer* sPlayOptions;
|
||||
sPlayOptions = new wxStaticBoxSizer(
|
||||
new wxStaticBox(m_PlayPage, wxID_ANY, _("Playback Options")), wxVERTICAL);
|
||||
|
||||
// Playback Options
|
||||
m_EarlyMemoryUpdates = new wxCheckBox(m_PlayPage, wxID_ANY, _("Early Memory Updates"));
|
||||
sPlayOptions->Add(m_EarlyMemoryUpdates, 0, wxALL, 5);
|
||||
|
||||
sPlayPage->Add(sPlayOptions, 0, wxEXPAND, 5);
|
||||
wxStaticBoxSizer* sPlayInfo = new wxStaticBoxSizer(wxVERTICAL, m_PlayPage, _("File Info"));
|
||||
sPlayInfo->AddSpacer(space5);
|
||||
sPlayInfo->Add(m_NumFramesLabel, 0, wxLEFT | wxRIGHT, space5);
|
||||
sPlayInfo->AddSpacer(space5);
|
||||
sPlayInfo->Add(m_CurrentFrameLabel, 0, wxLEFT | wxRIGHT, space5);
|
||||
sPlayInfo->AddSpacer(space5);
|
||||
sPlayInfo->Add(m_NumObjectsLabel, 0, wxLEFT | wxRIGHT, space5);
|
||||
sPlayInfo->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* sFrameRange =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, m_PlayPage, _("Frame Range"));
|
||||
sFrameRange->AddSpacer(space5);
|
||||
sFrameRange->Add(m_FrameFromLabel, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sFrameRange->AddSpacer(space5);
|
||||
sFrameRange->Add(m_FrameFromCtrl, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sFrameRange->AddSpacer(space5);
|
||||
sFrameRange->Add(m_FrameToLabel, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sFrameRange->AddSpacer(space5);
|
||||
sFrameRange->Add(m_FrameToCtrl, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sFrameRange->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* sObjectRange =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, m_PlayPage, _("Object Range"));
|
||||
sObjectRange->AddSpacer(space5);
|
||||
sObjectRange->Add(m_ObjectFromLabel, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sObjectRange->AddSpacer(space5);
|
||||
sObjectRange->Add(m_ObjectFromCtrl, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sObjectRange->AddSpacer(space5);
|
||||
sObjectRange->Add(m_ObjectToLabel, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sObjectRange->AddSpacer(space5);
|
||||
sObjectRange->Add(m_ObjectToCtrl, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space5);
|
||||
sObjectRange->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* sPlayOptions =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_PlayPage, _("Playback Options"));
|
||||
sPlayOptions->AddSpacer(space5);
|
||||
sPlayOptions->Add(m_EarlyMemoryUpdates, 0, wxLEFT | wxRIGHT, space5);
|
||||
sPlayOptions->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* sPlayPage = new wxBoxSizer(wxVERTICAL);
|
||||
sPlayPage->Add(sPlayInfo, 1, wxEXPAND);
|
||||
sPlayPage->Add(sFrameRange, 0, wxEXPAND);
|
||||
sPlayPage->Add(sObjectRange, 0, wxEXPAND);
|
||||
sPlayPage->Add(sPlayOptions, 0, wxEXPAND);
|
||||
sPlayPage->AddStretchSpacer();
|
||||
|
||||
m_PlayPage->SetSizer(sPlayPage);
|
||||
m_PlayPage->Layout();
|
||||
sPlayPage->Fit(m_PlayPage);
|
||||
m_Notebook->AddPage(m_PlayPage, _("Play"), true);
|
||||
}
|
||||
|
||||
{
|
||||
m_RecordPage =
|
||||
new wxPanel(m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
wxBoxSizer* sRecordPage;
|
||||
sRecordPage = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticBoxSizer* sRecordInfo;
|
||||
sRecordInfo = new wxStaticBoxSizer(new wxStaticBox(m_RecordPage, wxID_ANY, _("Recording Info")),
|
||||
wxVERTICAL);
|
||||
|
||||
// Recording Info
|
||||
m_RecordingFifoSizeLabel = new wxStaticText(m_RecordPage, wxID_ANY, wxEmptyString);
|
||||
m_RecordingFifoSizeLabel->Wrap(-1);
|
||||
sRecordInfo->Add(m_RecordingFifoSizeLabel, 0, wxALL, 5);
|
||||
|
||||
m_RecordingMemSizeLabel = new wxStaticText(m_RecordPage, wxID_ANY, wxEmptyString);
|
||||
m_RecordingMemSizeLabel->Wrap(-1);
|
||||
sRecordInfo->Add(m_RecordingMemSizeLabel, 0, wxALL, 5);
|
||||
|
||||
m_RecordingFramesLabel = new wxStaticText(m_RecordPage, wxID_ANY, wxEmptyString);
|
||||
m_RecordingFramesLabel->Wrap(-1);
|
||||
sRecordInfo->Add(m_RecordingFramesLabel, 0, wxALL, 5);
|
||||
|
||||
sRecordPage->Add(sRecordInfo, 0, wxEXPAND, 5);
|
||||
|
||||
wxBoxSizer* sRecordButtons;
|
||||
sRecordButtons = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
// Recording Buttons
|
||||
m_RecordStop = new wxButton(m_RecordPage, wxID_ANY, _("Record"));
|
||||
sRecordButtons->Add(m_RecordStop, 0, wxALL, 5);
|
||||
|
||||
m_Save = new wxButton(m_RecordPage, wxID_ANY, _("Save"));
|
||||
sRecordButtons->Add(m_Save, 0, wxALL, 5);
|
||||
|
||||
sRecordPage->Add(sRecordButtons, 0, wxEXPAND, 5);
|
||||
|
||||
wxStaticBoxSizer* sRecordingOptions;
|
||||
sRecordingOptions = new wxStaticBoxSizer(
|
||||
new wxStaticBox(m_RecordPage, wxID_ANY, _("Recording Options")), wxHORIZONTAL);
|
||||
|
||||
// Recording Options
|
||||
m_FramesToRecordLabel = new wxStaticText(m_RecordPage, wxID_ANY, _("Frames To Record"));
|
||||
m_FramesToRecordLabel->Wrap(-1);
|
||||
sRecordingOptions->Add(m_FramesToRecordLabel, 0, wxALL, 5);
|
||||
m_FramesToRecordCtrl =
|
||||
new wxSpinCtrl(m_RecordPage, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS, 0, 10000, m_FramesToRecord);
|
||||
|
||||
wxString initialNum = wxString::Format("%d", m_FramesToRecord);
|
||||
m_FramesToRecordCtrl = new wxSpinCtrl(m_RecordPage, wxID_ANY, initialNum, wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 10000, 1);
|
||||
sRecordingOptions->Add(m_FramesToRecordCtrl, 0, wxALL, 5);
|
||||
wxStaticBoxSizer* sRecordInfo =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_RecordPage, _("Recording Info"));
|
||||
sRecordInfo->AddSpacer(space5);
|
||||
sRecordInfo->Add(m_RecordingFifoSizeLabel, 0, wxLEFT | wxRIGHT, space5);
|
||||
sRecordInfo->AddSpacer(space5);
|
||||
sRecordInfo->Add(m_RecordingMemSizeLabel, 0, wxLEFT | wxRIGHT, space5);
|
||||
sRecordInfo->AddSpacer(space5);
|
||||
sRecordInfo->Add(m_RecordingFramesLabel, 0, wxLEFT | wxRIGHT, space5);
|
||||
sRecordInfo->AddSpacer(space5);
|
||||
|
||||
sRecordPage->Add(sRecordingOptions, 0, wxEXPAND, 5);
|
||||
sRecordPage->AddStretchSpacer();
|
||||
wxBoxSizer* sRecordButtons = new wxBoxSizer(wxHORIZONTAL);
|
||||
sRecordButtons->Add(m_RecordStop);
|
||||
sRecordButtons->Add(m_Save, 0, wxLEFT, space5);
|
||||
|
||||
wxStaticBoxSizer* sRecordingOptions =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, m_RecordPage, _("Recording Options"));
|
||||
sRecordingOptions->AddSpacer(space5);
|
||||
sRecordingOptions->Add(m_FramesToRecordLabel, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM,
|
||||
space5);
|
||||
sRecordingOptions->AddSpacer(space5);
|
||||
sRecordingOptions->Add(m_FramesToRecordCtrl, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM,
|
||||
space5);
|
||||
sRecordingOptions->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* sRecordPage = new wxBoxSizer(wxVERTICAL);
|
||||
sRecordPage->Add(sRecordInfo, 0, wxEXPAND);
|
||||
sRecordPage->AddSpacer(space5);
|
||||
sRecordPage->Add(sRecordButtons, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sRecordPage->AddSpacer(space5);
|
||||
sRecordPage->Add(sRecordingOptions, 0, wxEXPAND);
|
||||
|
||||
m_RecordPage->SetSizer(sRecordPage);
|
||||
m_RecordPage->Layout();
|
||||
sRecordPage->Fit(m_RecordPage);
|
||||
m_Notebook->AddPage(m_RecordPage, _("Record"), false);
|
||||
}
|
||||
|
||||
@ -216,81 +206,86 @@ void FifoPlayerDlg::CreateGUIControls()
|
||||
{
|
||||
m_AnalyzePage =
|
||||
new wxPanel(m_Notebook, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL);
|
||||
wxBoxSizer* sAnalyzePage;
|
||||
sAnalyzePage = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
wxStaticBoxSizer* sFrameInfoSizer;
|
||||
sFrameInfoSizer =
|
||||
new wxStaticBoxSizer(new wxStaticBox(m_AnalyzePage, wxID_ANY, _("Frame Info")), wxVERTICAL);
|
||||
// FIFO Content Lists
|
||||
m_framesList = new wxListBox(m_AnalyzePage, wxID_ANY, wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(72, 185)));
|
||||
m_objectsList = new wxListBox(m_AnalyzePage, wxID_ANY, wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(72, 185)));
|
||||
m_objectCmdList =
|
||||
new wxListBox(m_AnalyzePage, wxID_ANY, wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(144, 185)), wxArrayString(), wxLB_HSCROLL);
|
||||
|
||||
wxBoxSizer* sListsSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
// Selected command breakdown
|
||||
m_objectCmdInfo = new wxStaticText(m_AnalyzePage, wxID_ANY, wxEmptyString);
|
||||
|
||||
m_framesList = new wxListBox(m_AnalyzePage, wxID_ANY);
|
||||
m_framesList->SetMinSize(wxSize(100, 250));
|
||||
sListsSizer->Add(m_framesList, 0, wxALL, 5);
|
||||
|
||||
m_objectsList = new wxListBox(m_AnalyzePage, wxID_ANY);
|
||||
m_objectsList->SetMinSize(wxSize(110, 250));
|
||||
sListsSizer->Add(m_objectsList, 0, wxALL, 5);
|
||||
|
||||
m_objectCmdList = new wxListBox(m_AnalyzePage, wxID_ANY);
|
||||
m_objectCmdList->SetMinSize(wxSize(175, 250));
|
||||
sListsSizer->Add(m_objectCmdList, 0, wxALL, 5);
|
||||
|
||||
sFrameInfoSizer->Add(sListsSizer, 0, wxALL, 5);
|
||||
|
||||
m_objectCmdInfo = new wxStaticText(m_AnalyzePage, wxID_ANY, wxString());
|
||||
sFrameInfoSizer->Add(m_objectCmdInfo, 0, wxALL, 5);
|
||||
|
||||
sAnalyzePage->Add(sFrameInfoSizer, 0, wxEXPAND, 5);
|
||||
|
||||
wxStaticBoxSizer* sSearchSizer = new wxStaticBoxSizer(
|
||||
new wxStaticBox(m_AnalyzePage, wxID_ANY, _("Search current Object")), wxVERTICAL);
|
||||
|
||||
wxBoxSizer* sSearchField = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
sSearchField->Add(new wxStaticText(m_AnalyzePage, wxID_ANY, _("Search for hex Value:")), 0,
|
||||
wxALIGN_CENTER_VERTICAL, 5);
|
||||
// Search box
|
||||
wxStaticText* search_label =
|
||||
new wxStaticText(m_AnalyzePage, wxID_ANY, _("Search for hex Value:"));
|
||||
// TODO: ugh, wxValidator sucks - but we should use it anyway.
|
||||
m_searchField = new wxTextCtrl(m_AnalyzePage, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxTE_PROCESS_ENTER);
|
||||
m_numResultsText = new wxStaticText(m_AnalyzePage, wxID_ANY, wxEmptyString);
|
||||
|
||||
sSearchField->Add(m_searchField, 0, wxALL, 5);
|
||||
sSearchField->Add(m_numResultsText, 0, wxALIGN_CENTER_VERTICAL, 5);
|
||||
|
||||
wxBoxSizer* sSearchButtons = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
// Search buttons
|
||||
m_beginSearch = new wxButton(m_AnalyzePage, wxID_ANY, _("Search"));
|
||||
m_findNext = new wxButton(m_AnalyzePage, wxID_ANY, _("Find next"));
|
||||
m_findPrevious = new wxButton(m_AnalyzePage, wxID_ANY, _("Find previous"));
|
||||
|
||||
ResetSearch();
|
||||
|
||||
sSearchButtons->Add(m_beginSearch, 0, wxALL, 5);
|
||||
sSearchButtons->Add(m_findNext, 0, wxALL, 5);
|
||||
sSearchButtons->Add(m_findPrevious, 0, wxALL, 5);
|
||||
wxBoxSizer* sListsSizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sListsSizer->Add(m_framesList);
|
||||
sListsSizer->Add(m_objectsList, 0, wxLEFT, space5);
|
||||
sListsSizer->Add(m_objectCmdList, 1, wxLEFT, space5);
|
||||
|
||||
sSearchSizer->Add(sSearchField, 0, wxEXPAND, 5);
|
||||
sSearchSizer->Add(sSearchButtons, 0, wxEXPAND, 5);
|
||||
wxStaticBoxSizer* sFrameInfoSizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_AnalyzePage, _("Frame Info"));
|
||||
sFrameInfoSizer->AddSpacer(space5);
|
||||
sFrameInfoSizer->Add(sListsSizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sFrameInfoSizer->AddSpacer(space5);
|
||||
sFrameInfoSizer->Add(m_objectCmdInfo, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sFrameInfoSizer->AddSpacer(space5);
|
||||
|
||||
sAnalyzePage->Add(sSearchSizer, 0, wxEXPAND, 5);
|
||||
sAnalyzePage->AddStretchSpacer();
|
||||
wxBoxSizer* sSearchField = new wxBoxSizer(wxHORIZONTAL);
|
||||
sSearchField->Add(search_label, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sSearchField->Add(m_searchField, 0, wxLEFT, space5);
|
||||
sSearchField->Add(m_numResultsText, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
|
||||
wxBoxSizer* sSearchButtons = new wxBoxSizer(wxHORIZONTAL);
|
||||
sSearchButtons->Add(m_beginSearch);
|
||||
sSearchButtons->Add(m_findNext, 0, wxLEFT, space5);
|
||||
sSearchButtons->Add(m_findPrevious, 0, wxLEFT, space5);
|
||||
|
||||
wxStaticBoxSizer* sSearchSizer =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_AnalyzePage, _("Search current Object"));
|
||||
sSearchSizer->Add(sSearchField, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sSearchSizer->AddSpacer(space5);
|
||||
sSearchSizer->Add(sSearchButtons, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sSearchSizer->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* sAnalyzePage = new wxBoxSizer(wxVERTICAL);
|
||||
sAnalyzePage->Add(sFrameInfoSizer, 0, wxEXPAND);
|
||||
sAnalyzePage->Add(sSearchSizer, 0, wxEXPAND);
|
||||
|
||||
m_AnalyzePage->SetSizer(sAnalyzePage);
|
||||
m_AnalyzePage->Layout();
|
||||
sAnalyzePage->Fit(m_AnalyzePage);
|
||||
m_Notebook->AddPage(m_AnalyzePage, _("Analyze"), false);
|
||||
}
|
||||
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND | wxALL, 5);
|
||||
sMain->Add(CreateButtonSizer(wxCLOSE), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxStdDialogButtonSizer* close_btn_sizer = CreateStdDialogButtonSizer(wxCLOSE);
|
||||
close_btn_sizer->GetCancelButton()->SetLabel(_("Close"));
|
||||
|
||||
SetSizer(sMain);
|
||||
Layout();
|
||||
sMain->Fit(this);
|
||||
wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(close_btn_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
|
||||
Center(wxBOTH);
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(sMain);
|
||||
Center();
|
||||
|
||||
// Connect Events
|
||||
Bind(wxEVT_PAINT, &FifoPlayerDlg::OnPaint, this);
|
||||
@ -302,7 +297,6 @@ void FifoPlayerDlg::CreateGUIControls()
|
||||
m_RecordStop->Bind(wxEVT_BUTTON, &FifoPlayerDlg::OnRecordStop, this);
|
||||
m_Save->Bind(wxEVT_BUTTON, &FifoPlayerDlg::OnSaveFile, this);
|
||||
m_FramesToRecordCtrl->Bind(wxEVT_SPINCTRL, &FifoPlayerDlg::OnNumFramesToRecord, this);
|
||||
Bind(wxEVT_BUTTON, &FifoPlayerDlg::OnCloseClick, this);
|
||||
|
||||
m_framesList->Bind(wxEVT_LISTBOX, &FifoPlayerDlg::OnFrameListSelectionChanged, this);
|
||||
m_objectsList->Bind(wxEVT_LISTBOX, &FifoPlayerDlg::OnObjectListSelectionChanged, this);
|
||||
@ -808,11 +802,6 @@ void FifoPlayerDlg::OnObjectCmdListSelectionCopy(wxCommandEvent& WXUNUSED(event)
|
||||
}
|
||||
}
|
||||
|
||||
void FifoPlayerDlg::OnCloseClick(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
Hide();
|
||||
}
|
||||
|
||||
void FifoPlayerDlg::OnRecordingFinished(wxEvent&)
|
||||
{
|
||||
m_RecordStop->SetLabel(_("Record"));
|
||||
|
@ -39,7 +39,6 @@ private:
|
||||
void OnRecordStop(wxCommandEvent& event);
|
||||
void OnSaveFile(wxCommandEvent& event);
|
||||
void OnNumFramesToRecord(wxSpinEvent& event);
|
||||
void OnCloseClick(wxCommandEvent& event);
|
||||
|
||||
void OnBeginSearch(wxCommandEvent& event);
|
||||
void OnFindNextClick(wxCommandEvent& event);
|
||||
|
@ -85,9 +85,7 @@ CRenderFrame::CRenderFrame(wxFrame* parent, wxWindowID id, const wxString& title
|
||||
: wxFrame(parent, id, title, pos, size, style)
|
||||
{
|
||||
// Give it an icon
|
||||
wxIcon IconTemp;
|
||||
IconTemp.CopyFromBitmap(WxUtils::LoadResourceBitmap("Dolphin"));
|
||||
SetIcon(IconTemp);
|
||||
SetIcons(WxUtils::GetDolphinIconBundle());
|
||||
|
||||
DragAcceptFiles(true);
|
||||
Bind(wxEVT_DROP_FILES, &CRenderFrame::OnDropFiles, this);
|
||||
@ -323,14 +321,9 @@ EVT_MOVE(CFrame::OnMove)
|
||||
EVT_HOST_COMMAND(wxID_ANY, CFrame::OnHostMessage)
|
||||
|
||||
EVT_AUI_PANE_CLOSE(CFrame::OnPaneClose)
|
||||
EVT_AUINOTEBOOK_PAGE_CLOSE(wxID_ANY, CFrame::OnNotebookPageClose)
|
||||
EVT_AUINOTEBOOK_ALLOW_DND(wxID_ANY, CFrame::OnAllowNotebookDnD)
|
||||
EVT_AUINOTEBOOK_PAGE_CHANGED(wxID_ANY, CFrame::OnNotebookPageChanged)
|
||||
EVT_AUINOTEBOOK_TAB_RIGHT_UP(wxID_ANY, CFrame::OnTab)
|
||||
|
||||
// Post events to child panels
|
||||
EVT_MENU_RANGE(IDM_INTERPRETER, IDM_ADDRBOX, CFrame::PostEvent)
|
||||
EVT_TEXT(IDM_ADDRBOX, CFrame::PostEvent)
|
||||
|
||||
END_EVENT_TABLE()
|
||||
|
||||
@ -381,22 +374,18 @@ static BOOL WINAPI s_ctrl_handler(DWORD fdwCtrlType)
|
||||
}
|
||||
#endif
|
||||
|
||||
CFrame::CFrame(wxFrame* parent, wxWindowID id, const wxString& title, const wxPoint& pos,
|
||||
const wxSize& size, bool _UseDebugger, bool _BatchMode, bool ShowLogWindow,
|
||||
long style)
|
||||
: CRenderFrame(parent, id, title, pos, size, style), UseDebugger(_UseDebugger),
|
||||
m_bBatchMode(_BatchMode)
|
||||
CFrame::CFrame(wxFrame* parent, wxWindowID id, const wxString& title, wxRect geometry,
|
||||
bool use_debugger, bool batch_mode, bool show_log_window, long style)
|
||||
: CRenderFrame(parent, id, title, wxDefaultPosition, wxSize(800, 600), style),
|
||||
UseDebugger(use_debugger), m_bBatchMode(batch_mode),
|
||||
m_toolbar_bitmap_size(FromDIP(wxSize(32, 32)))
|
||||
{
|
||||
for (int i = 0; i <= IDM_CODE_WINDOW - IDM_LOG_WINDOW; i++)
|
||||
bFloatWindow[i] = false;
|
||||
|
||||
if (ShowLogWindow)
|
||||
if (show_log_window)
|
||||
SConfig::GetInstance().m_InterfaceLogWindow = true;
|
||||
|
||||
// Start debugging maximized
|
||||
if (UseDebugger)
|
||||
this->Maximize(true);
|
||||
|
||||
// Debugger class
|
||||
if (UseDebugger)
|
||||
{
|
||||
@ -487,15 +476,23 @@ CFrame::CFrame(wxFrame* parent, wxWindowID id, const wxString& title, const wxPo
|
||||
ToggleLogConfigWindow(true);
|
||||
}
|
||||
|
||||
// Set the size of the window after the UI has been built, but before we show it
|
||||
SetSize(size);
|
||||
// Setup the window size.
|
||||
// This has to be done here instead of in Main because the Show() happens here.
|
||||
SetMinSize(FromDIP(wxSize(400, 300)));
|
||||
WxUtils::SetWindowSizeAndFitToScreen(this, geometry.GetPosition(), geometry.GetSize(),
|
||||
FromDIP(wxSize(800, 600)));
|
||||
|
||||
// Show window
|
||||
Show();
|
||||
// Start debugging maximized (Must be after the window has been positioned)
|
||||
if (UseDebugger)
|
||||
Maximize(true);
|
||||
|
||||
// Commit
|
||||
m_Mgr->Update();
|
||||
|
||||
// The window must be shown for m_XRRConfig to be created (wxGTK will not allocate X11
|
||||
// resources until the window is shown for the first time).
|
||||
Show();
|
||||
|
||||
#ifdef _WIN32
|
||||
SetToolTip("");
|
||||
GetToolTip()->SetAutoPop(25000);
|
||||
@ -639,11 +636,10 @@ void CFrame::OnClose(wxCloseEvent& event)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Close the log window now so that its settings are saved
|
||||
if (m_LogWindow)
|
||||
m_LogWindow->Close();
|
||||
m_LogWindow = nullptr;
|
||||
m_LogWindow->SaveSettings();
|
||||
}
|
||||
if (m_LogWindow)
|
||||
m_LogWindow->RemoveAllListeners();
|
||||
|
||||
// Uninit
|
||||
m_Mgr->UnInit();
|
||||
@ -680,7 +676,8 @@ void CFrame::OnResize(wxSizeEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
|
||||
if (!IsMaximized() && !(SConfig::GetInstance().bRenderToMain && RendererIsFullscreen()) &&
|
||||
if (!IsMaximized() && !IsIconized() &&
|
||||
!(SConfig::GetInstance().bRenderToMain && RendererIsFullscreen()) &&
|
||||
!(Core::GetState() != Core::CORE_UNINITIALIZED && SConfig::GetInstance().bRenderToMain &&
|
||||
SConfig::GetInstance().bRenderWindowAutoSize))
|
||||
{
|
||||
@ -740,6 +737,11 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
|
||||
{
|
||||
switch (event.GetId())
|
||||
{
|
||||
case IDM_UPDATE_DISASM_DIALOG: // For breakpoints causing pausing
|
||||
if (!g_pCodeWindow || Core::GetState() != Core::CORE_PAUSE)
|
||||
return;
|
||||
// fallthrough
|
||||
|
||||
case IDM_UPDATE_GUI:
|
||||
UpdateGUI();
|
||||
break;
|
||||
@ -821,33 +823,29 @@ void CFrame::OnHostMessage(wxCommandEvent& event)
|
||||
|
||||
void CFrame::OnRenderWindowSizeRequest(int width, int height)
|
||||
{
|
||||
if (!Core::IsRunning() || !SConfig::GetInstance().bRenderWindowAutoSize ||
|
||||
if (!SConfig::GetInstance().bRenderWindowAutoSize || !Core::IsRunning() ||
|
||||
RendererIsFullscreen() || m_RenderFrame->IsMaximized())
|
||||
return;
|
||||
|
||||
int old_width, old_height, log_width = 0, log_height = 0;
|
||||
m_RenderFrame->GetClientSize(&old_width, &old_height);
|
||||
wxSize requested_size(width, height);
|
||||
// Convert to window pixels, since the size is from the backend it will be in framebuffer px.
|
||||
requested_size *= 1.0 / m_RenderFrame->GetContentScaleFactor();
|
||||
wxSize old_size;
|
||||
|
||||
// Add space for the log/console/debugger window
|
||||
if (SConfig::GetInstance().bRenderToMain && (SConfig::GetInstance().m_InterfaceLogWindow ||
|
||||
SConfig::GetInstance().m_InterfaceLogConfigWindow) &&
|
||||
!m_Mgr->GetPane("Pane 1").IsFloating())
|
||||
if (!SConfig::GetInstance().bRenderToMain)
|
||||
{
|
||||
switch (m_Mgr->GetPane("Pane 1").dock_direction)
|
||||
{
|
||||
case wxAUI_DOCK_LEFT:
|
||||
case wxAUI_DOCK_RIGHT:
|
||||
log_width = m_Mgr->GetPane("Pane 1").rect.GetWidth();
|
||||
break;
|
||||
case wxAUI_DOCK_TOP:
|
||||
case wxAUI_DOCK_BOTTOM:
|
||||
log_height = m_Mgr->GetPane("Pane 1").rect.GetHeight();
|
||||
break;
|
||||
}
|
||||
old_size = m_RenderFrame->GetClientSize();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Resize for the render panel only, this implicitly retains space for everything else
|
||||
// (i.e. log panel, toolbar, statusbar, etc) without needing to compute for them.
|
||||
old_size = m_RenderParent->GetSize();
|
||||
}
|
||||
|
||||
if (old_width != width + log_width || old_height != height + log_height)
|
||||
m_RenderFrame->SetClientSize(width + log_width, height + log_height);
|
||||
wxSize diff = requested_size - old_size;
|
||||
if (diff != wxSize())
|
||||
m_RenderFrame->SetSize(m_RenderFrame->GetSize() + diff);
|
||||
}
|
||||
|
||||
bool CFrame::RendererHasFocus()
|
||||
@ -930,7 +928,7 @@ void CFrame::OnGameListCtrlItemActivated(wxListEvent& WXUNUSED(event))
|
||||
GetMenuBar()->FindItem(IDM_LIST_WORLD)->Check(true);
|
||||
GetMenuBar()->FindItem(IDM_LIST_UNKNOWN)->Check(true);
|
||||
|
||||
m_GameListCtrl->Update();
|
||||
UpdateGameList();
|
||||
}
|
||||
else if (!m_GameListCtrl->GetISO(0))
|
||||
{
|
||||
|
@ -46,7 +46,7 @@ class CRenderFrame : public wxFrame
|
||||
public:
|
||||
CRenderFrame(wxFrame* parent, wxWindowID id = wxID_ANY, const wxString& title = "Dolphin",
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||
long style = wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE);
|
||||
long style = wxDEFAULT_FRAME_STYLE);
|
||||
|
||||
bool ShowFullScreen(bool show, long style = wxFULLSCREEN_ALL) override;
|
||||
|
||||
@ -63,8 +63,8 @@ class CFrame : public CRenderFrame
|
||||
{
|
||||
public:
|
||||
CFrame(wxFrame* parent, wxWindowID id = wxID_ANY, const wxString& title = "Dolphin",
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||
bool _UseDebugger = false, bool _BatchMode = false, bool ShowLogWindow = false,
|
||||
wxRect geometry = wxDefaultSize, bool use_debugger = false, bool batch_mode = false,
|
||||
bool show_log_window = false,
|
||||
long style = wxDEFAULT_FRAME_STYLE | wxNO_FULL_REPAINT_ON_RESIZE);
|
||||
|
||||
virtual ~CFrame();
|
||||
@ -113,6 +113,7 @@ public:
|
||||
|
||||
const CGameListCtrl* GetGameListCtrl() const;
|
||||
wxMenuBar* GetMenuBar() const override;
|
||||
const wxSize& GetToolbarBitmapSize() const; // Needed before the toolbar exists
|
||||
|
||||
#ifdef __WXGTK__
|
||||
Common::Event panic_event;
|
||||
@ -129,7 +130,7 @@ public:
|
||||
wxToolBar* m_ToolBar = nullptr;
|
||||
// AUI
|
||||
wxAuiManager* m_Mgr = nullptr;
|
||||
bool bFloatWindow[IDM_CODE_WINDOW - IDM_LOG_WINDOW + 1];
|
||||
bool bFloatWindow[IDM_DEBUG_WINDOW_LIST_END - IDM_DEBUG_WINDOW_LIST_START] = {};
|
||||
|
||||
// Perspectives (Should find a way to make all of this private)
|
||||
void DoAddPage(wxWindow* Win, int i, bool Float);
|
||||
@ -191,6 +192,7 @@ private:
|
||||
wxTimer m_poll_hotkey_timer;
|
||||
wxTimer m_handle_signal_timer;
|
||||
|
||||
wxSize m_toolbar_bitmap_size;
|
||||
wxBitmap m_Bitmaps[EToolbar_Max];
|
||||
|
||||
wxMenuBar* m_menubar_shadow = nullptr;
|
||||
@ -209,12 +211,12 @@ private:
|
||||
|
||||
// Perspectives
|
||||
void AddRemoveBlankPage();
|
||||
void OnNotebookPageClose(wxAuiNotebookEvent& event);
|
||||
void OnAllowNotebookDnD(wxAuiNotebookEvent& event);
|
||||
void OnNotebookAllowDnD(wxAuiNotebookEvent& event);
|
||||
void OnNotebookPageChanged(wxAuiNotebookEvent& event);
|
||||
void OnNotebookPageClose(wxAuiNotebookEvent& event);
|
||||
void OnNotebookTabRightUp(wxAuiNotebookEvent& event);
|
||||
void OnFloatWindow(wxCommandEvent& event);
|
||||
void ToggleFloatWindow(int Id);
|
||||
void OnTab(wxAuiNotebookEvent& event);
|
||||
int GetNotebookAffiliation(wxWindowID Id);
|
||||
void ClosePages();
|
||||
void CloseAllNotebooks();
|
||||
@ -226,7 +228,6 @@ private:
|
||||
// Float window
|
||||
void DoUnfloatPage(int Id);
|
||||
void OnFloatingPageClosed(wxCloseEvent& event);
|
||||
void OnFloatingPageSize(wxSizeEvent& event);
|
||||
void DoFloatNotebookPage(wxWindowID Id);
|
||||
wxFrame* CreateParentFrame(wxWindowID Id = wxID_ANY, const wxString& title = "",
|
||||
wxWindow* = nullptr);
|
||||
|
@ -152,41 +152,22 @@ void CFrame::ToggleLogConfigWindow(bool bShow)
|
||||
|
||||
void CFrame::OnToggleWindow(wxCommandEvent& event)
|
||||
{
|
||||
bool bShow = GetMenuBar()->IsChecked(event.GetId());
|
||||
bool show = GetMenuBar()->IsChecked(event.GetId());
|
||||
|
||||
switch (event.GetId())
|
||||
{
|
||||
case IDM_LOG_WINDOW:
|
||||
if (!g_pCodeWindow)
|
||||
SConfig::GetInstance().m_InterfaceLogWindow = bShow;
|
||||
ToggleLogWindow(bShow);
|
||||
SConfig::GetInstance().m_InterfaceLogWindow = show;
|
||||
ToggleLogWindow(show);
|
||||
break;
|
||||
case IDM_LOG_CONFIG_WINDOW:
|
||||
if (!g_pCodeWindow)
|
||||
SConfig::GetInstance().m_InterfaceLogConfigWindow = bShow;
|
||||
ToggleLogConfigWindow(bShow);
|
||||
break;
|
||||
case IDM_REGISTER_WINDOW:
|
||||
g_pCodeWindow->ToggleRegisterWindow(bShow);
|
||||
break;
|
||||
case IDM_WATCH_WINDOW:
|
||||
g_pCodeWindow->ToggleWatchWindow(bShow);
|
||||
break;
|
||||
case IDM_BREAKPOINT_WINDOW:
|
||||
g_pCodeWindow->ToggleBreakPointWindow(bShow);
|
||||
break;
|
||||
case IDM_MEMORY_WINDOW:
|
||||
g_pCodeWindow->ToggleMemoryWindow(bShow);
|
||||
break;
|
||||
case IDM_JIT_WINDOW:
|
||||
g_pCodeWindow->ToggleJitWindow(bShow);
|
||||
break;
|
||||
case IDM_SOUND_WINDOW:
|
||||
g_pCodeWindow->ToggleSoundWindow(bShow);
|
||||
break;
|
||||
case IDM_VIDEO_WINDOW:
|
||||
g_pCodeWindow->ToggleVideoWindow(bShow);
|
||||
SConfig::GetInstance().m_InterfaceLogConfigWindow = show;
|
||||
ToggleLogConfigWindow(show);
|
||||
break;
|
||||
default:
|
||||
g_pCodeWindow->TogglePanel(event.GetId(), show);
|
||||
}
|
||||
}
|
||||
|
||||
@ -199,20 +180,21 @@ void CFrame::ClosePages()
|
||||
|
||||
if (g_pCodeWindow)
|
||||
{
|
||||
g_pCodeWindow->ToggleCodeWindow(false);
|
||||
g_pCodeWindow->ToggleRegisterWindow(false);
|
||||
g_pCodeWindow->ToggleWatchWindow(false);
|
||||
g_pCodeWindow->ToggleBreakPointWindow(false);
|
||||
g_pCodeWindow->ToggleMemoryWindow(false);
|
||||
g_pCodeWindow->ToggleJitWindow(false);
|
||||
g_pCodeWindow->ToggleSoundWindow(false);
|
||||
g_pCodeWindow->ToggleVideoWindow(false);
|
||||
for (int i = IDM_REGISTER_WINDOW; i < IDM_DEBUG_WINDOW_LIST_END; ++i)
|
||||
{
|
||||
g_pCodeWindow->TogglePanel(i, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CFrame::OnNotebookPageChanged(wxAuiNotebookEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
// Event is intended for someone else
|
||||
if (event.GetPropagatedFrom() != nullptr)
|
||||
{
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pCodeWindow)
|
||||
return;
|
||||
@ -230,39 +212,45 @@ void CFrame::OnNotebookPageChanged(wxAuiNotebookEvent& event)
|
||||
|
||||
void CFrame::OnNotebookPageClose(wxAuiNotebookEvent& event)
|
||||
{
|
||||
// Event is intended for someone else
|
||||
if (event.GetPropagatedFrom() != nullptr)
|
||||
{
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
// Override event
|
||||
event.Veto();
|
||||
|
||||
wxAuiNotebook* Ctrl = (wxAuiNotebook*)event.GetEventObject();
|
||||
wxAuiNotebook* nb = static_cast<wxAuiNotebook*>(event.GetEventObject());
|
||||
int page_id = nb->GetPage(event.GetSelection())->GetId();
|
||||
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_LOG_WINDOW)
|
||||
ToggleLogWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_LOG_CONFIG_WINDOW)
|
||||
ToggleLogConfigWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_REGISTER_WINDOW)
|
||||
g_pCodeWindow->ToggleRegisterWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_WATCH_WINDOW)
|
||||
g_pCodeWindow->ToggleWatchWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_BREAKPOINT_WINDOW)
|
||||
g_pCodeWindow->ToggleBreakPointWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_JIT_WINDOW)
|
||||
g_pCodeWindow->ToggleJitWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_MEMORY_WINDOW)
|
||||
g_pCodeWindow->ToggleMemoryWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_SOUND_WINDOW)
|
||||
g_pCodeWindow->ToggleSoundWindow(false);
|
||||
if (Ctrl->GetPage(event.GetSelection())->GetId() == IDM_VIDEO_WINDOW)
|
||||
g_pCodeWindow->ToggleVideoWindow(false);
|
||||
switch (page_id)
|
||||
{
|
||||
case IDM_LOG_WINDOW:
|
||||
case IDM_LOG_CONFIG_WINDOW:
|
||||
{
|
||||
GetMenuBar()->Check(page_id, !GetMenuBar()->IsChecked(page_id));
|
||||
wxCommandEvent ev(wxEVT_MENU, page_id);
|
||||
OnToggleWindow(ev);
|
||||
break;
|
||||
}
|
||||
case IDM_CODE_WINDOW:
|
||||
break; // Code Window is not allowed to be closed
|
||||
default:
|
||||
// Check for the magic empty panel.
|
||||
if (nb->GetPageText(event.GetSelection()).IsSameAs("<>"))
|
||||
break;
|
||||
|
||||
g_pCodeWindow->TogglePanel(page_id, false);
|
||||
}
|
||||
}
|
||||
|
||||
void CFrame::OnFloatingPageClosed(wxCloseEvent& event)
|
||||
{
|
||||
ToggleFloatWindow(event.GetId() - IDM_LOG_WINDOW_PARENT + IDM_FLOAT_LOG_WINDOW);
|
||||
}
|
||||
// TODO: This is a good place to save the window size and position to an INI
|
||||
|
||||
void CFrame::OnFloatingPageSize(wxSizeEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
ToggleFloatWindow(event.GetId() - IDM_LOG_WINDOW_PARENT + IDM_FLOAT_LOG_WINDOW);
|
||||
}
|
||||
|
||||
void CFrame::OnFloatWindow(wxCommandEvent& event)
|
||||
@ -320,9 +308,15 @@ void CFrame::DoUnfloatPage(int Id)
|
||||
Win->Destroy();
|
||||
}
|
||||
|
||||
void CFrame::OnTab(wxAuiNotebookEvent& event)
|
||||
void CFrame::OnNotebookTabRightUp(wxAuiNotebookEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
// Event is intended for someone else
|
||||
if (event.GetPropagatedFrom() != nullptr)
|
||||
{
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!g_pCodeWindow)
|
||||
return;
|
||||
|
||||
@ -354,10 +348,21 @@ void CFrame::OnTab(wxAuiNotebookEvent& event)
|
||||
PopupMenu(&MenuPopup, Pt);
|
||||
}
|
||||
|
||||
void CFrame::OnAllowNotebookDnD(wxAuiNotebookEvent& event)
|
||||
void CFrame::OnNotebookAllowDnD(wxAuiNotebookEvent& event)
|
||||
{
|
||||
event.Skip();
|
||||
event.Allow();
|
||||
// NOTE: This event was sent FROM the source notebook TO the destination notebook so
|
||||
// all the member variables are related to the source, we can't get the drop target.
|
||||
// NOTE: This function is "part of the internal interface" but there's no clean alternative.
|
||||
if (event.GetPropagatedFrom() != nullptr)
|
||||
{
|
||||
// Drop target was one of the notebook's children, we don't care about this event.
|
||||
event.Skip();
|
||||
return;
|
||||
}
|
||||
// Since the destination is one of our own notebooks, make sure the source is as well.
|
||||
// If the source is some other panel, leave the event in the default reject state.
|
||||
if (m_Mgr->GetPane(event.GetDragSource()).window)
|
||||
event.Allow();
|
||||
}
|
||||
|
||||
void CFrame::ShowResizePane()
|
||||
@ -391,12 +396,7 @@ void CFrame::ShowResizePane()
|
||||
void CFrame::TogglePane()
|
||||
{
|
||||
// Get the first notebook
|
||||
wxAuiNotebook* NB = nullptr;
|
||||
for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++)
|
||||
{
|
||||
if (m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiNotebook)))
|
||||
NB = (wxAuiNotebook*)m_Mgr->GetAllPanes()[i].window;
|
||||
}
|
||||
wxAuiNotebook* NB = GetNotebookFromId(0);
|
||||
|
||||
if (NB)
|
||||
{
|
||||
@ -450,6 +450,7 @@ void CFrame::DoRemovePage(wxWindow* Win, bool bHide)
|
||||
{
|
||||
Win->Destroy();
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -468,13 +469,17 @@ void CFrame::DoAddPage(wxWindow* Win, int i, bool Float)
|
||||
i = 0;
|
||||
|
||||
// The page was already previously added, no need to add it again.
|
||||
if (Win && GetNotebookFromId(i)->GetPageIndex(Win) != wxNOT_FOUND)
|
||||
if (GetNotebookFromId(i)->GetPageIndex(Win) != wxNOT_FOUND)
|
||||
return;
|
||||
|
||||
if (!Float)
|
||||
{
|
||||
GetNotebookFromId(i)->AddPage(Win, Win->GetName(), true);
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateParentFrame(Win->GetId() + IDM_LOG_WINDOW_PARENT - IDM_LOG_WINDOW, Win->GetName(), Win);
|
||||
}
|
||||
}
|
||||
|
||||
void CFrame::PopulateSavedPerspectives()
|
||||
@ -664,8 +669,7 @@ void CFrame::SetPaneSize()
|
||||
if (Perspectives.size() <= ActivePerspective)
|
||||
return;
|
||||
|
||||
int iClientX = GetSize().GetX();
|
||||
int iClientY = GetSize().GetY();
|
||||
wxSize client_size = GetClientSize();
|
||||
|
||||
for (u32 i = 0, j = 0; i < m_Mgr->GetAllPanes().GetCount(); i++)
|
||||
{
|
||||
@ -687,8 +691,8 @@ void CFrame::SetPaneSize()
|
||||
H = MathUtil::Clamp<u32>(H, 5, 95);
|
||||
|
||||
// Convert percentages to pixel lengths
|
||||
W = (W * iClientX) / 100;
|
||||
H = (H * iClientY) / 100;
|
||||
W = (W * client_size.GetWidth()) / 100;
|
||||
H = (H * client_size.GetHeight()) / 100;
|
||||
m_Mgr->GetAllPanes()[i].BestSize(W, H).MinSize(W, H);
|
||||
|
||||
j++;
|
||||
@ -815,7 +819,7 @@ void CFrame::UpdateCurrentPerspective()
|
||||
current->Perspective = m_Mgr->SavePerspective();
|
||||
|
||||
// Get client size
|
||||
int iClientX = GetSize().GetX(), iClientY = GetSize().GetY();
|
||||
wxSize client_size = GetClientSize();
|
||||
current->Width.clear();
|
||||
current->Height.clear();
|
||||
for (u32 i = 0; i < m_Mgr->GetAllPanes().GetCount(); i++)
|
||||
@ -823,10 +827,10 @@ void CFrame::UpdateCurrentPerspective()
|
||||
if (!m_Mgr->GetAllPanes()[i].window->IsKindOf(CLASSINFO(wxAuiToolBar)))
|
||||
{
|
||||
// Save width and height as a percentage of the client width and height
|
||||
current->Width.push_back((m_Mgr->GetAllPanes()[i].window->GetClientSize().GetX() * 100) /
|
||||
iClientX);
|
||||
current->Height.push_back((m_Mgr->GetAllPanes()[i].window->GetClientSize().GetY() * 100) /
|
||||
iClientY);
|
||||
current->Width.push_back((m_Mgr->GetAllPanes()[i].window->GetSize().GetX() * 100) /
|
||||
client_size.GetWidth());
|
||||
current->Height.push_back((m_Mgr->GetAllPanes()[i].window->GetSize().GetY() * 100) /
|
||||
client_size.GetHeight());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -952,23 +956,40 @@ wxFrame* CFrame::CreateParentFrame(wxWindowID Id, const wxString& Title, wxWindo
|
||||
|
||||
m_MainSizer->Add(Child, 1, wxEXPAND);
|
||||
|
||||
// If the tab is not the one currently being shown to the user then it will
|
||||
// be hidden. Make sure it is being shown.
|
||||
Child->Show();
|
||||
|
||||
Frame->Bind(wxEVT_CLOSE_WINDOW, &CFrame::OnFloatingPageClosed, this);
|
||||
|
||||
// TODO: This is a good place to load window position and size settings from an INI
|
||||
|
||||
// Main sizer
|
||||
Frame->SetSizer(m_MainSizer);
|
||||
// Minimum frame size
|
||||
Frame->SetMinSize(wxSize(200, 200));
|
||||
Frame->SetSizerAndFit(m_MainSizer);
|
||||
Frame->Show();
|
||||
return Frame;
|
||||
}
|
||||
|
||||
wxAuiNotebook* CFrame::CreateEmptyNotebook()
|
||||
{
|
||||
const long NOTEBOOK_STYLE = wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE |
|
||||
wxAUI_NB_TAB_EXTERNAL_MOVE | wxAUI_NB_SCROLL_BUTTONS |
|
||||
wxAUI_NB_WINDOWLIST_BUTTON | wxNO_BORDER;
|
||||
static constexpr long NOTEBOOK_STYLE = wxAUI_NB_TOP | wxAUI_NB_TAB_SPLIT | wxAUI_NB_TAB_MOVE |
|
||||
wxAUI_NB_CLOSE_BUTTON | wxAUI_NB_TAB_EXTERNAL_MOVE |
|
||||
wxAUI_NB_SCROLL_BUTTONS | wxAUI_NB_WINDOWLIST_BUTTON |
|
||||
wxNO_BORDER;
|
||||
|
||||
return new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, NOTEBOOK_STYLE);
|
||||
auto* nb = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, NOTEBOOK_STYLE);
|
||||
|
||||
// wxAuiNotebookEvent is derived from wxCommandEvent so they bubble up from child panels.
|
||||
// This is a problem if the panels contain their own AUI Notebooks like DSPDebuggerLLE
|
||||
// since we receive its events as though they came from our own children which we do
|
||||
// not want to deal with. Binding directly to our notebooks and ignoring any event that
|
||||
// has been propagated from somewhere else resolves it.
|
||||
nb->Bind(wxEVT_AUINOTEBOOK_ALLOW_DND, &CFrame::OnNotebookAllowDnD, this);
|
||||
nb->Bind(wxEVT_AUINOTEBOOK_PAGE_CHANGED, &CFrame::OnNotebookPageChanged, this);
|
||||
nb->Bind(wxEVT_AUINOTEBOOK_PAGE_CLOSE, &CFrame::OnNotebookPageClose, this);
|
||||
nb->Bind(wxEVT_AUINOTEBOOK_TAB_RIGHT_UP, &CFrame::OnNotebookTabRightUp, this);
|
||||
|
||||
return nb;
|
||||
}
|
||||
|
||||
void CFrame::AddRemoveBlankPage()
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
#include <mutex>
|
||||
@ -77,21 +78,6 @@
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef SM_XVIRTUALSCREEN
|
||||
#define SM_XVIRTUALSCREEN 76
|
||||
#endif
|
||||
#ifndef SM_YVIRTUALSCREEN
|
||||
#define SM_YVIRTUALSCREEN 77
|
||||
#endif
|
||||
#ifndef SM_CXVIRTUALSCREEN
|
||||
#define SM_CXVIRTUALSCREEN 78
|
||||
#endif
|
||||
#ifndef SM_CYVIRTUALSCREEN
|
||||
#define SM_CYVIRTUALSCREEN 79
|
||||
#endif
|
||||
#endif
|
||||
|
||||
class InputConfig;
|
||||
class wxFrame;
|
||||
|
||||
@ -108,6 +94,11 @@ wxMenuBar* CFrame::GetMenuBar() const
|
||||
}
|
||||
}
|
||||
|
||||
const wxSize& CFrame::GetToolbarBitmapSize() const
|
||||
{
|
||||
return m_toolbar_bitmap_size;
|
||||
}
|
||||
|
||||
// Create menu items
|
||||
// ---------------------
|
||||
wxMenuBar* CFrame::CreateMenu()
|
||||
@ -528,9 +519,6 @@ wxString CFrame::GetMenuLabel(int Id)
|
||||
// ---------------------
|
||||
void CFrame::PopulateToolbar(wxToolBar* ToolBar)
|
||||
{
|
||||
int w = m_Bitmaps[Toolbar_FileOpen].GetWidth(), h = m_Bitmaps[Toolbar_FileOpen].GetHeight();
|
||||
ToolBar->SetToolBitmapSize(wxSize(w, h));
|
||||
|
||||
WxUtils::AddToolbarButton(ToolBar, wxID_OPEN, _("Open"), m_Bitmaps[Toolbar_FileOpen],
|
||||
_("Open file..."));
|
||||
WxUtils::AddToolbarButton(ToolBar, wxID_REFRESH, _("Refresh"), m_Bitmaps[Toolbar_Refresh],
|
||||
@ -554,7 +542,7 @@ void CFrame::PopulateToolbar(wxToolBar* ToolBar)
|
||||
// Delete and recreate the toolbar
|
||||
void CFrame::RecreateToolbar()
|
||||
{
|
||||
static const long TOOLBAR_STYLE = wxTB_DEFAULT_STYLE | wxTB_TEXT | wxTB_FLAT;
|
||||
static constexpr long TOOLBAR_STYLE = wxTB_DEFAULT_STYLE | wxTB_TEXT | wxTB_FLAT;
|
||||
|
||||
if (m_ToolBar != nullptr)
|
||||
{
|
||||
@ -563,6 +551,7 @@ void CFrame::RecreateToolbar()
|
||||
}
|
||||
|
||||
m_ToolBar = CreateToolBar(TOOLBAR_STYLE, wxID_ANY);
|
||||
m_ToolBar->SetToolBitmapSize(m_toolbar_bitmap_size);
|
||||
|
||||
if (g_pCodeWindow)
|
||||
{
|
||||
@ -580,18 +569,11 @@ void CFrame::RecreateToolbar()
|
||||
|
||||
void CFrame::InitBitmaps()
|
||||
{
|
||||
auto const dir = StrToWxStr(File::GetThemeDir(SConfig::GetInstance().theme_name));
|
||||
|
||||
m_Bitmaps[Toolbar_FileOpen].LoadFile(dir + "open.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_Refresh].LoadFile(dir + "refresh.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_Play].LoadFile(dir + "play.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_Stop].LoadFile(dir + "stop.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_Pause].LoadFile(dir + "pause.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_ConfigMain].LoadFile(dir + "config.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_ConfigGFX].LoadFile(dir + "graphics.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_Controller].LoadFile(dir + "classic.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_Screenshot].LoadFile(dir + "screenshot.png", wxBITMAP_TYPE_PNG);
|
||||
m_Bitmaps[Toolbar_FullScreen].LoadFile(dir + "fullscreen.png", wxBITMAP_TYPE_PNG);
|
||||
static constexpr std::array<const char* const, EToolbar_Max> s_image_names{
|
||||
{"open", "refresh", "play", "stop", "pause", "screenshot", "fullscreen", "config", "graphics",
|
||||
"classic"}};
|
||||
for (std::size_t i = 0; i < s_image_names.size(); ++i)
|
||||
m_Bitmaps[i] = WxUtils::LoadScaledThemeBitmap(s_image_names[i], this, m_toolbar_bitmap_size);
|
||||
|
||||
// Update in case the bitmap has been updated
|
||||
if (m_ToolBar != nullptr)
|
||||
@ -606,7 +588,7 @@ void CFrame::OpenGeneralConfiguration(int tab)
|
||||
|
||||
HotkeyManagerEmu::Enable(false);
|
||||
if (config_main.ShowModal() == wxID_OK)
|
||||
m_GameListCtrl->Update();
|
||||
UpdateGameList();
|
||||
HotkeyManagerEmu::Enable(true);
|
||||
|
||||
UpdateGUI();
|
||||
@ -660,10 +642,10 @@ void CFrame::BootGame(const std::string& filename)
|
||||
StartGame(bootfile);
|
||||
if (UseDebugger && g_pCodeWindow)
|
||||
{
|
||||
if (g_pCodeWindow->m_WatchWindow)
|
||||
g_pCodeWindow->m_WatchWindow->LoadAll();
|
||||
if (g_pCodeWindow->m_BreakpointWindow)
|
||||
g_pCodeWindow->m_BreakpointWindow->LoadAll();
|
||||
if (g_pCodeWindow->HasPanel<CWatchWindow>())
|
||||
g_pCodeWindow->GetPanel<CWatchWindow>()->LoadAll();
|
||||
if (g_pCodeWindow->HasPanel<CBreakPointWindow>())
|
||||
g_pCodeWindow->GetPanel<CBreakPointWindow>()->LoadAll();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -860,7 +842,7 @@ void CFrame::OnPlay(wxCommandEvent& WXUNUSED(event))
|
||||
|
||||
wxThread::Sleep(20);
|
||||
g_pCodeWindow->JumpToAddress(PC);
|
||||
g_pCodeWindow->Update();
|
||||
g_pCodeWindow->Repopulate();
|
||||
// Update toolbar with Play/Pause status
|
||||
UpdateGUI();
|
||||
}
|
||||
@ -987,36 +969,29 @@ void CFrame::StartGame(const std::string& filename)
|
||||
}
|
||||
else
|
||||
{
|
||||
wxPoint position(SConfig::GetInstance().iRenderWindowXPos,
|
||||
SConfig::GetInstance().iRenderWindowYPos);
|
||||
#ifdef __APPLE__
|
||||
// On OS X, the render window's title bar is not visible,
|
||||
// and the window therefore not easily moved, when the
|
||||
// position is 0,0. Weed out the 0's from existing configs.
|
||||
if (position == wxPoint(0, 0))
|
||||
position = wxDefaultPosition;
|
||||
#endif
|
||||
wxRect window_geometry(
|
||||
SConfig::GetInstance().iRenderWindowXPos, SConfig::GetInstance().iRenderWindowYPos,
|
||||
SConfig::GetInstance().iRenderWindowWidth, SConfig::GetInstance().iRenderWindowHeight);
|
||||
// Set window size in framebuffer pixels since the 3D rendering will be operating at
|
||||
// that level.
|
||||
wxSize default_size{wxSize(640, 480) * (1.0 / GetContentScaleFactor())};
|
||||
m_RenderFrame = new CRenderFrame(this, wxID_ANY, _("Dolphin"), wxDefaultPosition, default_size);
|
||||
|
||||
// Convert ClientSize coordinates to frame sizes.
|
||||
wxSize decoration_fudge = m_RenderFrame->GetSize() - m_RenderFrame->GetClientSize();
|
||||
default_size += decoration_fudge;
|
||||
if (!window_geometry.IsEmpty())
|
||||
window_geometry.SetSize(window_geometry.GetSize() + decoration_fudge);
|
||||
|
||||
WxUtils::SetWindowSizeAndFitToScreen(m_RenderFrame, window_geometry.GetPosition(),
|
||||
window_geometry.GetSize(), default_size);
|
||||
|
||||
wxSize size(SConfig::GetInstance().iRenderWindowWidth,
|
||||
SConfig::GetInstance().iRenderWindowHeight);
|
||||
#ifdef _WIN32
|
||||
// Out of desktop check
|
||||
int leftPos = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
int topPos = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||
int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
if ((leftPos + width) < (position.x + size.GetWidth()) || leftPos > position.x ||
|
||||
(topPos + height) < (position.y + size.GetHeight()) || topPos > position.y)
|
||||
position.x = position.y = wxDefaultCoord;
|
||||
#endif
|
||||
m_RenderFrame = new CRenderFrame((wxFrame*)this, wxID_ANY, _("Dolphin"), position);
|
||||
if (SConfig::GetInstance().bKeepWindowOnTop)
|
||||
m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() | wxSTAY_ON_TOP);
|
||||
else
|
||||
m_RenderFrame->SetWindowStyle(m_RenderFrame->GetWindowStyle() & ~wxSTAY_ON_TOP);
|
||||
|
||||
m_RenderFrame->SetBackgroundColour(*wxBLACK);
|
||||
m_RenderFrame->SetClientSize(size.GetWidth(), size.GetHeight());
|
||||
m_RenderFrame->Bind(wxEVT_CLOSE_WINDOW, &CFrame::OnRenderParentClose, this);
|
||||
m_RenderFrame->Bind(wxEVT_ACTIVATE, &CFrame::OnActive, this);
|
||||
m_RenderFrame->Bind(wxEVT_MOVE, &CFrame::OnRenderParentMove, this);
|
||||
@ -1035,7 +1010,7 @@ void CFrame::StartGame(const std::string& filename)
|
||||
m_RenderFrame->EnableFullScreenView(true);
|
||||
#endif
|
||||
|
||||
wxBeginBusyCursor();
|
||||
wxBusyCursor hourglass;
|
||||
|
||||
DoFullscreen(SConfig::GetInstance().bFullscreen);
|
||||
|
||||
@ -1045,6 +1020,7 @@ void CFrame::StartGame(const std::string& filename)
|
||||
// Destroy the renderer frame when not rendering to main
|
||||
if (!SConfig::GetInstance().bRenderToMain)
|
||||
m_RenderFrame->Destroy();
|
||||
m_RenderFrame = nullptr;
|
||||
m_RenderParent = nullptr;
|
||||
m_bGameLoading = false;
|
||||
UpdateGUI();
|
||||
@ -1076,8 +1052,6 @@ void CFrame::StartGame(const std::string& filename)
|
||||
wxTheApp->Bind(wxEVT_KILL_FOCUS, &CFrame::OnFocusChange, this);
|
||||
m_RenderParent->Bind(wxEVT_SIZE, &CFrame::OnRenderParentResize, this);
|
||||
}
|
||||
|
||||
wxEndBusyCursor();
|
||||
}
|
||||
|
||||
void CFrame::OnBootDrive(wxCommandEvent& event)
|
||||
@ -1088,10 +1062,7 @@ void CFrame::OnBootDrive(wxCommandEvent& event)
|
||||
// Refresh the file list and browse for a favorites directory
|
||||
void CFrame::OnRefresh(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
if (m_GameListCtrl)
|
||||
{
|
||||
m_GameListCtrl->Update();
|
||||
}
|
||||
UpdateGameList();
|
||||
}
|
||||
|
||||
// Create screenshot
|
||||
@ -1194,18 +1165,15 @@ void CFrame::DoStop()
|
||||
|
||||
if (UseDebugger && g_pCodeWindow)
|
||||
{
|
||||
if (g_pCodeWindow->m_WatchWindow)
|
||||
{
|
||||
g_pCodeWindow->m_WatchWindow->SaveAll();
|
||||
PowerPC::watches.Clear();
|
||||
}
|
||||
if (g_pCodeWindow->m_BreakpointWindow)
|
||||
{
|
||||
g_pCodeWindow->m_BreakpointWindow->SaveAll();
|
||||
PowerPC::breakpoints.Clear();
|
||||
PowerPC::memchecks.Clear();
|
||||
g_pCodeWindow->m_BreakpointWindow->NotifyUpdate();
|
||||
}
|
||||
if (g_pCodeWindow->HasPanel<CWatchWindow>())
|
||||
g_pCodeWindow->GetPanel<CWatchWindow>()->SaveAll();
|
||||
PowerPC::watches.Clear();
|
||||
if (g_pCodeWindow->HasPanel<CBreakPointWindow>())
|
||||
g_pCodeWindow->GetPanel<CBreakPointWindow>()->SaveAll();
|
||||
PowerPC::breakpoints.Clear();
|
||||
PowerPC::memchecks.Clear();
|
||||
if (g_pCodeWindow->HasPanel<CBreakPointWindow>())
|
||||
g_pCodeWindow->GetPanel<CBreakPointWindow>()->NotifyUpdate();
|
||||
g_symbolDB.Clear();
|
||||
Host_NotifyMapLoaded();
|
||||
}
|
||||
@ -1912,7 +1880,8 @@ void CFrame::UpdateGUI()
|
||||
|
||||
void CFrame::UpdateGameList()
|
||||
{
|
||||
m_GameListCtrl->Update();
|
||||
if (m_GameListCtrl)
|
||||
m_GameListCtrl->ReloadList();
|
||||
}
|
||||
|
||||
void CFrame::GameListChanged(wxCommandEvent& event)
|
||||
@ -1987,11 +1956,7 @@ void CFrame::GameListChanged(wxCommandEvent& event)
|
||||
break;
|
||||
}
|
||||
|
||||
// Update gamelist
|
||||
if (m_GameListCtrl)
|
||||
{
|
||||
m_GameListCtrl->Update();
|
||||
}
|
||||
UpdateGameList();
|
||||
}
|
||||
|
||||
// Enable and disable the toolbar
|
||||
@ -2047,6 +2012,6 @@ void CFrame::OnChangeColumnsVisible(wxCommandEvent& event)
|
||||
default:
|
||||
return;
|
||||
}
|
||||
m_GameListCtrl->Update();
|
||||
UpdateGameList();
|
||||
SConfig::GetInstance().SaveSettings();
|
||||
}
|
||||
|
@ -11,6 +11,7 @@
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <wx/app.h>
|
||||
#include <wx/bitmap.h>
|
||||
@ -187,47 +188,73 @@ CGameListCtrl::~CGameListCtrl()
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void InitBitmap(wxImageList* img_list, std::vector<int>* vector, T index,
|
||||
const std::string& name)
|
||||
static void InitBitmap(wxImageList* img_list, std::vector<int>* vector, wxWindow* context,
|
||||
const wxSize& usable_size, T index, const std::string& name)
|
||||
{
|
||||
wxSize size(96, 32);
|
||||
(*vector)[static_cast<size_t>(index)] = img_list->Add(WxUtils::LoadResourceBitmap(name, size));
|
||||
wxSize size = img_list->GetSize();
|
||||
(*vector)[static_cast<size_t>(index)] = img_list->Add(WxUtils::LoadScaledResourceBitmap(
|
||||
name, context, size, usable_size, WxUtils::LSI_SCALE | WxUtils::LSI_ALIGN_VCENTER));
|
||||
}
|
||||
|
||||
void CGameListCtrl::InitBitmaps()
|
||||
{
|
||||
wxImageList* img_list = new wxImageList(96, 32);
|
||||
const wxSize size = FromDIP(wxSize(96, 32));
|
||||
const wxSize flag_bmp_size = FromDIP(wxSize(32, 32));
|
||||
const wxSize platform_bmp_size = flag_bmp_size;
|
||||
const wxSize rating_bmp_size = FromDIP(wxSize(48, 32));
|
||||
wxImageList* img_list = new wxImageList(size.GetWidth(), size.GetHeight());
|
||||
AssignImageList(img_list, wxIMAGE_LIST_SMALL);
|
||||
|
||||
m_FlagImageIndex.resize(static_cast<size_t>(DiscIO::Country::NUMBER_OF_COUNTRIES));
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_JAPAN, "Flag_Japan");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_EUROPE, "Flag_Europe");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_USA, "Flag_USA");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_AUSTRALIA, "Flag_Australia");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_FRANCE, "Flag_France");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_GERMANY, "Flag_Germany");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_ITALY, "Flag_Italy");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_KOREA, "Flag_Korea");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_NETHERLANDS, "Flag_Netherlands");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_RUSSIA, "Flag_Russia");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_SPAIN, "Flag_Spain");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_TAIWAN, "Flag_Taiwan");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_WORLD, "Flag_International");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, DiscIO::Country::COUNTRY_UNKNOWN, "Flag_Unknown");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_JAPAN,
|
||||
"Flag_Japan");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_EUROPE,
|
||||
"Flag_Europe");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_USA,
|
||||
"Flag_USA");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_AUSTRALIA,
|
||||
"Flag_Australia");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_FRANCE,
|
||||
"Flag_France");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_GERMANY,
|
||||
"Flag_Germany");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_ITALY,
|
||||
"Flag_Italy");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_KOREA,
|
||||
"Flag_Korea");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_NETHERLANDS,
|
||||
"Flag_Netherlands");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_RUSSIA,
|
||||
"Flag_Russia");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_SPAIN,
|
||||
"Flag_Spain");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_TAIWAN,
|
||||
"Flag_Taiwan");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_WORLD,
|
||||
"Flag_International");
|
||||
InitBitmap(img_list, &m_FlagImageIndex, this, flag_bmp_size, DiscIO::Country::COUNTRY_UNKNOWN,
|
||||
"Flag_Unknown");
|
||||
|
||||
m_PlatformImageIndex.resize(static_cast<size_t>(DiscIO::Platform::NUMBER_OF_PLATFORMS));
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, DiscIO::Platform::GAMECUBE_DISC, "Platform_Gamecube");
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, DiscIO::Platform::WII_DISC, "Platform_Wii");
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, DiscIO::Platform::WII_WAD, "Platform_Wad");
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, DiscIO::Platform::ELF_DOL, "Platform_File");
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, this, platform_bmp_size,
|
||||
DiscIO::Platform::GAMECUBE_DISC, "Platform_Gamecube");
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, this, platform_bmp_size, DiscIO::Platform::WII_DISC,
|
||||
"Platform_Wii");
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, this, platform_bmp_size, DiscIO::Platform::WII_WAD,
|
||||
"Platform_Wad");
|
||||
InitBitmap(img_list, &m_PlatformImageIndex, this, platform_bmp_size, DiscIO::Platform::ELF_DOL,
|
||||
"Platform_File");
|
||||
|
||||
m_EmuStateImageIndex.resize(6);
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, 0, "rating0");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, 1, "rating1");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, 2, "rating2");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, 3, "rating3");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, 4, "rating4");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, 5, "rating5");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, this, rating_bmp_size, 0, "rating0");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, this, rating_bmp_size, 1, "rating1");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, this, rating_bmp_size, 2, "rating2");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, this, rating_bmp_size, 3, "rating3");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, this, rating_bmp_size, 4, "rating4");
|
||||
InitBitmap(img_list, &m_EmuStateImageIndex, this, rating_bmp_size, 5, "rating5");
|
||||
|
||||
m_utility_game_banners.resize(1);
|
||||
InitBitmap(img_list, &m_utility_game_banners, this, size, 0, "nobanner");
|
||||
}
|
||||
|
||||
void CGameListCtrl::BrowseForDirectory()
|
||||
@ -252,11 +279,11 @@ void CGameListCtrl::BrowseForDirectory()
|
||||
SConfig::GetInstance().SaveSettings();
|
||||
}
|
||||
|
||||
Update();
|
||||
ReloadList();
|
||||
}
|
||||
}
|
||||
|
||||
void CGameListCtrl::Update()
|
||||
void CGameListCtrl::ReloadList()
|
||||
{
|
||||
int scrollPos = wxWindow::GetScrollPos(wxVERTICAL);
|
||||
// Don't let the user refresh it while a game is running
|
||||
@ -297,20 +324,22 @@ void CGameListCtrl::Update()
|
||||
// set initial sizes for columns
|
||||
SetColumnWidth(COLUMN_DUMMY, 0);
|
||||
SetColumnWidth(COLUMN_PLATFORM, SConfig::GetInstance().m_showSystemColumn ?
|
||||
32 + platform_icon_padding + platform_padding :
|
||||
FromDIP(32 + platform_icon_padding + platform_padding) :
|
||||
0);
|
||||
SetColumnWidth(COLUMN_BANNER,
|
||||
SConfig::GetInstance().m_showBannerColumn ? 96 + platform_padding : 0);
|
||||
SetColumnWidth(COLUMN_TITLE, 175 + platform_padding);
|
||||
SConfig::GetInstance().m_showBannerColumn ? FromDIP(96 + platform_padding) : 0);
|
||||
SetColumnWidth(COLUMN_TITLE, FromDIP(175 + platform_padding));
|
||||
SetColumnWidth(COLUMN_MAKER,
|
||||
SConfig::GetInstance().m_showMakerColumn ? 150 + platform_padding : 0);
|
||||
SetColumnWidth(COLUMN_FILENAME,
|
||||
SConfig::GetInstance().m_showFileNameColumn ? 100 + platform_padding : 0);
|
||||
SetColumnWidth(COLUMN_ID, SConfig::GetInstance().m_showIDColumn ? 75 + platform_padding : 0);
|
||||
SConfig::GetInstance().m_showMakerColumn ? FromDIP(150 + platform_padding) : 0);
|
||||
SetColumnWidth(COLUMN_FILENAME, SConfig::GetInstance().m_showFileNameColumn ?
|
||||
FromDIP(100 + platform_padding) :
|
||||
0);
|
||||
SetColumnWidth(COLUMN_ID,
|
||||
SConfig::GetInstance().m_showIDColumn ? FromDIP(75 + platform_padding) : 0);
|
||||
SetColumnWidth(COLUMN_COUNTRY,
|
||||
SConfig::GetInstance().m_showRegionColumn ? 32 + platform_padding : 0);
|
||||
SConfig::GetInstance().m_showRegionColumn ? FromDIP(32 + platform_padding) : 0);
|
||||
SetColumnWidth(COLUMN_EMULATION_STATE,
|
||||
SConfig::GetInstance().m_showStateColumn ? 48 + platform_padding : 0);
|
||||
SConfig::GetInstance().m_showStateColumn ? FromDIP(48 + platform_padding) : 0);
|
||||
|
||||
// add all items
|
||||
for (int i = 0; i < (int)m_ISOFiles.size(); i++)
|
||||
@ -405,10 +434,14 @@ void CGameListCtrl::UpdateItemAtColumn(long _Index, int column)
|
||||
}
|
||||
case COLUMN_BANNER:
|
||||
{
|
||||
int ImageIndex = -1;
|
||||
int ImageIndex = m_utility_game_banners[0]; // nobanner
|
||||
|
||||
if (rISOFile.GetBitmap().IsOk())
|
||||
ImageIndex = GetImageList(wxIMAGE_LIST_SMALL)->Add(rISOFile.GetBitmap());
|
||||
if (rISOFile.GetBannerImage().IsOk())
|
||||
{
|
||||
wxImageList* img_list = GetImageList(wxIMAGE_LIST_SMALL);
|
||||
ImageIndex = img_list->Add(
|
||||
WxUtils::ScaleImageToBitmap(rISOFile.GetBannerImage(), this, img_list->GetSize()));
|
||||
}
|
||||
|
||||
SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex);
|
||||
break;
|
||||
@ -502,7 +535,7 @@ void CGameListCtrl::SetBackgroundColor()
|
||||
|
||||
void CGameListCtrl::ScanForISOs()
|
||||
{
|
||||
ClearIsoFiles();
|
||||
m_ISOFiles.clear();
|
||||
|
||||
// Load custom game titles from titles.txt
|
||||
// http://www.gametdb.com/Wii/Downloads
|
||||
@ -1098,7 +1131,7 @@ void CGameListCtrl::OnDeleteISO(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
for (const GameListItem* iso : GetAllSelectedISOs())
|
||||
File::Delete(iso->GetFileName());
|
||||
Update();
|
||||
ReloadList();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1269,7 +1302,7 @@ void CGameListCtrl::CompressSelection(bool _compress)
|
||||
if (!all_good)
|
||||
WxUtils::ShowErrorDialog(_("Dolphin was unable to complete the requested action."));
|
||||
|
||||
Update();
|
||||
ReloadList();
|
||||
}
|
||||
|
||||
bool CGameListCtrl::CompressCB(const std::string& text, float percent, void* arg)
|
||||
@ -1342,7 +1375,7 @@ void CGameListCtrl::OnCompressISO(wxCommandEvent& WXUNUSED(event))
|
||||
if (!all_good)
|
||||
WxUtils::ShowErrorDialog(_("Dolphin was unable to complete the requested action."));
|
||||
|
||||
Update();
|
||||
ReloadList();
|
||||
}
|
||||
|
||||
void CGameListCtrl::OnChangeDisc(wxCommandEvent& WXUNUSED(event))
|
||||
|
@ -38,7 +38,7 @@ public:
|
||||
long style);
|
||||
~CGameListCtrl();
|
||||
|
||||
void Update() override;
|
||||
void ReloadList();
|
||||
|
||||
void BrowseForDirectory();
|
||||
const GameListItem* GetISO(size_t index) const;
|
||||
@ -70,6 +70,7 @@ private:
|
||||
std::vector<int> m_FlagImageIndex;
|
||||
std::vector<int> m_PlatformImageIndex;
|
||||
std::vector<int> m_EmuStateImageIndex;
|
||||
std::vector<int> m_utility_game_banners;
|
||||
std::vector<std::unique_ptr<GameListItem>> m_ISOFiles;
|
||||
|
||||
void ClearIsoFiles() { m_ISOFiles.clear(); }
|
||||
|
@ -163,7 +163,9 @@ enum
|
||||
IDM_CONFIG_LOGGER,
|
||||
|
||||
// Views
|
||||
IDM_LOG_WINDOW,
|
||||
// IMPORTANT: Make sure IDM_FLOAT_xxx and IDM_xxx_PARENT are kept in sync!
|
||||
IDM_DEBUG_WINDOW_LIST_START, // Bookend for doing array lookups
|
||||
IDM_LOG_WINDOW = IDM_DEBUG_WINDOW_LIST_START,
|
||||
IDM_LOG_CONFIG_WINDOW,
|
||||
IDM_REGISTER_WINDOW,
|
||||
IDM_WATCH_WINDOW,
|
||||
@ -173,9 +175,10 @@ enum
|
||||
IDM_SOUND_WINDOW,
|
||||
IDM_VIDEO_WINDOW,
|
||||
IDM_CODE_WINDOW,
|
||||
IDM_DEBUG_WINDOW_LIST_END, // Bookend for doing array lookups
|
||||
|
||||
// List Column Title Toggles
|
||||
IDM_SHOW_SYSTEM,
|
||||
IDM_SHOW_SYSTEM = IDM_DEBUG_WINDOW_LIST_END,
|
||||
IDM_SHOW_BANNER,
|
||||
IDM_SHOW_MAKER,
|
||||
IDM_SHOW_FILENAME,
|
||||
@ -345,6 +348,7 @@ enum
|
||||
// custom message macro
|
||||
#define EVT_HOST_COMMAND(id, fn) EVT_COMMAND(id, wxEVT_HOST_COMMAND, fn)
|
||||
|
||||
// FIXME: This should be changed to wxThreadEvent
|
||||
wxDECLARE_EVENT(wxEVT_HOST_COMMAND, wxCommandEvent);
|
||||
|
||||
// Sent to wxTheApp
|
||||
|
@ -38,9 +38,6 @@
|
||||
|
||||
static const u32 CACHE_REVISION = 0x127; // Last changed in PR 3309
|
||||
|
||||
#define DVD_BANNER_WIDTH 96
|
||||
#define DVD_BANNER_HEIGHT 32
|
||||
|
||||
static std::string GetLanguageString(DiscIO::Language language,
|
||||
std::map<DiscIO::Language, std::string> strings)
|
||||
{
|
||||
@ -165,13 +162,12 @@ GameListItem::GameListItem(const std::string& _rFileName,
|
||||
// Volume banner. Typical for everything that isn't a DOL or ELF.
|
||||
if (!m_pImage.empty())
|
||||
{
|
||||
wxImage image(m_ImageWidth, m_ImageHeight, &m_pImage[0], true);
|
||||
m_Bitmap = ScaleBanner(&image);
|
||||
// Need to make explicit copy as wxImage uses reference counting for copies combined with only
|
||||
// taking a pointer, not the content, when given a buffer to its constructor.
|
||||
m_image.Create(m_ImageWidth, m_ImageHeight, false);
|
||||
std::memcpy(m_image.GetData(), m_pImage.data(), m_pImage.size());
|
||||
return;
|
||||
}
|
||||
|
||||
// Fallback in case no banner is available.
|
||||
ReadPNGBanner(File::GetSysDirectory() + RESOURCES_DIR + DIR_SEP + "nobanner.png");
|
||||
}
|
||||
|
||||
GameListItem::~GameListItem()
|
||||
@ -277,25 +273,11 @@ bool GameListItem::ReadPNGBanner(const std::string& path)
|
||||
return false;
|
||||
|
||||
wxImage image(StrToWxStr(path), wxBITMAP_TYPE_PNG);
|
||||
m_Bitmap = ScaleBanner(&image);
|
||||
return true;
|
||||
}
|
||||
if (!image.IsOk())
|
||||
return false;
|
||||
|
||||
wxBitmap GameListItem::ScaleBanner(wxImage* image)
|
||||
{
|
||||
const double gui_scale = wxTheApp->GetTopWindow()->GetContentScaleFactor();
|
||||
const double target_width = DVD_BANNER_WIDTH * gui_scale;
|
||||
const double target_height = DVD_BANNER_HEIGHT * gui_scale;
|
||||
const double banner_scale =
|
||||
std::min(target_width / image->GetWidth(), target_height / image->GetHeight());
|
||||
image->Rescale(image->GetWidth() * banner_scale, image->GetHeight() * banner_scale,
|
||||
wxIMAGE_QUALITY_HIGH);
|
||||
image->Resize(wxSize(target_width, target_height), wxPoint(), 0xFF, 0xFF, 0xFF);
|
||||
#ifdef __APPLE__
|
||||
return wxBitmap(*image, -1, gui_scale);
|
||||
#else
|
||||
return wxBitmap(*image, -1);
|
||||
#endif
|
||||
m_image = image;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string GameListItem::GetDescription(DiscIO::Language language) const
|
||||
|
@ -59,7 +59,9 @@ public:
|
||||
// 0 is the first disc, 1 is the second disc
|
||||
u8 GetDiscNumber() const { return m_disc_number; }
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
const wxBitmap& GetBitmap() const { return m_Bitmap; }
|
||||
// NOTE: Banner image is at the original resolution, use WxUtils::ScaleImageToBitmap
|
||||
// to display it
|
||||
const wxImage& GetBannerImage() const { return m_image; }
|
||||
#endif
|
||||
|
||||
void DoState(PointerWrap& p);
|
||||
@ -86,7 +88,7 @@ private:
|
||||
u16 m_Revision;
|
||||
|
||||
#if defined(HAVE_WX) && HAVE_WX
|
||||
wxBitmap m_Bitmap;
|
||||
wxImage m_image;
|
||||
#endif
|
||||
bool m_Valid;
|
||||
std::vector<u8> m_pImage;
|
||||
@ -107,6 +109,4 @@ private:
|
||||
void ReadVolumeBanner(const std::vector<u32>& buffer, int width, int height);
|
||||
// Outputs to m_Bitmap
|
||||
bool ReadPNGBanner(const std::string& path);
|
||||
|
||||
static wxBitmap ScaleBanner(wxImage* image);
|
||||
};
|
||||
|
@ -2,6 +2,7 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <array>
|
||||
#include <cinttypes>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
@ -33,7 +34,6 @@
|
||||
#include <wx/panel.h>
|
||||
#include <wx/progdlg.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/stattext.h>
|
||||
@ -63,6 +63,7 @@
|
||||
#include "DiscIO/VolumeCreator.h"
|
||||
#include "DolphinWX/Cheats/ActionReplayCodesPanel.h"
|
||||
#include "DolphinWX/Cheats/GeckoCodeDiag.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "DolphinWX/Frame.h"
|
||||
#include "DolphinWX/Globals.h"
|
||||
#include "DolphinWX/ISOFile.h"
|
||||
@ -110,6 +111,9 @@ private:
|
||||
|
||||
void CreateGUI()
|
||||
{
|
||||
int space10 = FromDIP(10);
|
||||
int space15 = FromDIP(15);
|
||||
|
||||
wxStaticBitmap* icon =
|
||||
new wxStaticBitmap(this, wxID_ANY, wxArtProvider::GetMessageBoxIcon(wxICON_WARNING));
|
||||
m_message = new wxStaticText(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
@ -119,10 +123,10 @@ private:
|
||||
m_btn_configure->Bind(wxEVT_BUTTON, &CheatWarningMessage::OnConfigureClicked, this);
|
||||
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
sizer->Add(icon, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 15);
|
||||
sizer->Add(m_message, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, 15);
|
||||
sizer->Add(m_btn_configure, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, 10);
|
||||
sizer->AddSpacer(10);
|
||||
sizer->Add(icon, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space15);
|
||||
sizer->Add(m_message, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, space15);
|
||||
sizer->Add(m_btn_configure, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space10);
|
||||
sizer->AddSpacer(space10);
|
||||
|
||||
SetSizer(sizer);
|
||||
}
|
||||
@ -286,8 +290,17 @@ CISOProperties::CISOProperties(const GameListItem& game_list_item, wxWindow* par
|
||||
bool wii = m_open_iso->GetVolumeType() != DiscIO::Platform::GAMECUBE_DISC;
|
||||
ChangeBannerDetails(SConfig::GetInstance().GetCurrentLanguage(wii));
|
||||
|
||||
m_Banner->SetBitmap(OpenGameListItem.GetBitmap());
|
||||
m_Banner->Bind(wxEVT_RIGHT_DOWN, &CISOProperties::RightClickOnBanner, this);
|
||||
if (OpenGameListItem.GetBannerImage().IsOk())
|
||||
{
|
||||
m_Banner->SetBitmap(WxUtils::ScaleImageToBitmap(OpenGameListItem.GetBannerImage(), this,
|
||||
m_Banner->GetMinSize()));
|
||||
m_Banner->Bind(wxEVT_RIGHT_DOWN, &CISOProperties::RightClickOnBanner, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Banner->SetBitmap(
|
||||
WxUtils::LoadScaledResourceBitmap("nobanner", this, m_Banner->GetMinSize()));
|
||||
}
|
||||
|
||||
// Filesystem browser/dumper
|
||||
// TODO : Should we add a way to browse the wad file ?
|
||||
@ -410,6 +423,9 @@ long CISOProperties::GetElementStyle(const char* section, const char* key)
|
||||
|
||||
void CISOProperties::CreateGUIControls()
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
const int space10 = FromDIP(10);
|
||||
|
||||
wxButton* const EditConfig = new wxButton(this, ID_EDITCONFIG, _("Edit Config"));
|
||||
EditConfig->SetToolTip(_("This will let you manually edit the INI config file."));
|
||||
|
||||
@ -473,8 +489,8 @@ void CISOProperties::CreateGUIControls()
|
||||
arrayStringFor_GPUDeterminism.Add(_("fake-completion"));
|
||||
GPUDeterminism = new wxChoice(m_GameConfig, ID_GPUDETERMINISM, wxDefaultPosition, wxDefaultSize,
|
||||
arrayStringFor_GPUDeterminism);
|
||||
sGPUDeterminism->Add(GPUDeterminismText);
|
||||
sGPUDeterminism->Add(GPUDeterminism);
|
||||
sGPUDeterminism->Add(GPUDeterminismText, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sGPUDeterminism->Add(GPUDeterminism, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
// Wii Console
|
||||
EnableWideScreen =
|
||||
@ -485,7 +501,7 @@ void CISOProperties::CreateGUIControls()
|
||||
wxBoxSizer* const sDepthPercentage = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxStaticText* const DepthPercentageText =
|
||||
new wxStaticText(m_GameConfig, wxID_ANY, _("Depth Percentage: "));
|
||||
DepthPercentage = new wxSlider(m_GameConfig, ID_DEPTHPERCENTAGE, 100, 0, 200);
|
||||
DepthPercentage = new DolphinSlider(m_GameConfig, ID_DEPTHPERCENTAGE, 100, 0, 200);
|
||||
DepthPercentage->SetToolTip(
|
||||
_("This value is multiplied with the depth set in the graphics configuration."));
|
||||
sDepthPercentage->Add(DepthPercentageText);
|
||||
@ -518,19 +534,23 @@ void CISOProperties::CreateGUIControls()
|
||||
EmuState = new wxChoice(m_GameConfig, ID_EMUSTATE, wxDefaultPosition, wxDefaultSize,
|
||||
arrayStringFor_EmuState);
|
||||
EmuIssues = new wxTextCtrl(m_GameConfig, ID_EMU_ISSUES, wxEmptyString);
|
||||
sEmuState->Add(EmuStateText, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sEmuState->Add(EmuState, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sEmuState->Add(EmuIssues, 1, wxEXPAND);
|
||||
|
||||
wxBoxSizer* const sConfigPage = new wxBoxSizer(wxVERTICAL);
|
||||
wxStaticBoxSizer* const sbCoreOverrides =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Core"));
|
||||
sbCoreOverrides->Add(CPUThread, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(SkipIdle, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(MMU, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(DCBZOFF, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(FPRF, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(SyncGPU, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(FastDiscSpeed, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(DSPHLE, 0, wxLEFT, 5);
|
||||
sbCoreOverrides->Add(sGPUDeterminism, 0, wxEXPAND | wxALL, 5);
|
||||
sbCoreOverrides->Add(CPUThread, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->Add(SkipIdle, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->Add(MMU, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->Add(DCBZOFF, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->Add(FPRF, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->Add(SyncGPU, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->Add(FastDiscSpeed, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->Add(DSPHLE, 0, wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->AddSpacer(space5);
|
||||
sbCoreOverrides->Add(sGPUDeterminism, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbCoreOverrides->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const sbWiiOverrides =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Wii Console"));
|
||||
@ -539,7 +559,7 @@ void CISOProperties::CreateGUIControls()
|
||||
sbWiiOverrides->ShowItems(false);
|
||||
EnableWideScreen->Hide();
|
||||
}
|
||||
sbWiiOverrides->Add(EnableWideScreen, 0, wxLEFT, 5);
|
||||
sbWiiOverrides->Add(EnableWideScreen, 0, wxLEFT, space5);
|
||||
|
||||
wxStaticBoxSizer* const sbStereoOverrides =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Stereoscopy"));
|
||||
@ -549,15 +569,19 @@ void CISOProperties::CreateGUIControls()
|
||||
|
||||
wxStaticBoxSizer* const sbGameConfig =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_GameConfig, _("Game-Specific Settings"));
|
||||
sbGameConfig->Add(OverrideText, 0, wxEXPAND | wxALL, 5);
|
||||
sbGameConfig->AddSpacer(space5);
|
||||
sbGameConfig->Add(OverrideText, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbGameConfig->AddSpacer(space5);
|
||||
sbGameConfig->Add(sbCoreOverrides, 0, wxEXPAND);
|
||||
sbGameConfig->Add(sbWiiOverrides, 0, wxEXPAND);
|
||||
sbGameConfig->Add(sbStereoOverrides, 0, wxEXPAND);
|
||||
sConfigPage->Add(sbGameConfig, 0, wxEXPAND | wxALL, 5);
|
||||
sEmuState->Add(EmuStateText, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sEmuState->Add(EmuState, 0, wxEXPAND);
|
||||
sEmuState->Add(EmuIssues, 1, wxEXPAND);
|
||||
sConfigPage->Add(sEmuState, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
wxBoxSizer* const sConfigPage = new wxBoxSizer(wxVERTICAL);
|
||||
sConfigPage->AddSpacer(space5);
|
||||
sConfigPage->Add(sbGameConfig, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sConfigPage->AddSpacer(space5);
|
||||
sConfigPage->Add(sEmuState, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sConfigPage->AddSpacer(space5);
|
||||
m_GameConfig->SetSizer(sConfigPage);
|
||||
|
||||
// Patches
|
||||
@ -572,13 +596,15 @@ void CISOProperties::CreateGUIControls()
|
||||
RemovePatch->Disable();
|
||||
|
||||
wxBoxSizer* sPatchPage = new wxBoxSizer(wxVERTICAL);
|
||||
sPatches->Add(Patches, 1, wxEXPAND | wxALL, 0);
|
||||
sPatchButtons->Add(EditPatch, 0, wxEXPAND | wxALL, 0);
|
||||
sPatches->Add(Patches, 1, wxEXPAND);
|
||||
sPatchButtons->Add(EditPatch, 0, wxEXPAND);
|
||||
sPatchButtons->AddStretchSpacer();
|
||||
sPatchButtons->Add(AddPatch, 0, wxEXPAND | wxALL, 0);
|
||||
sPatchButtons->Add(RemovePatch, 0, wxEXPAND | wxALL, 0);
|
||||
sPatches->Add(sPatchButtons, 0, wxEXPAND | wxALL, 0);
|
||||
sPatchPage->Add(sPatches, 1, wxEXPAND | wxALL, 5);
|
||||
sPatchButtons->Add(AddPatch, 0, wxEXPAND);
|
||||
sPatchButtons->Add(RemovePatch, 0, wxEXPAND);
|
||||
sPatches->Add(sPatchButtons, 0, wxEXPAND);
|
||||
sPatchPage->AddSpacer(space5);
|
||||
sPatchPage->Add(sPatches, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sPatchPage->AddSpacer(space5);
|
||||
m_PatchPage->SetSizer(sPatchPage);
|
||||
|
||||
// Action Replay Cheats
|
||||
@ -589,8 +615,8 @@ void CISOProperties::CreateGUIControls()
|
||||
m_ar_code_panel->Bind(DOLPHIN_EVT_ARCODE_TOGGLED, &CISOProperties::OnCheatCodeToggled, this);
|
||||
|
||||
wxBoxSizer* const sCheatPage = new wxBoxSizer(wxVERTICAL);
|
||||
sCheatPage->Add(m_cheats_disabled_ar, 0, wxEXPAND | wxTOP, 5);
|
||||
sCheatPage->Add(m_ar_code_panel, 1, wxEXPAND | wxALL, 5);
|
||||
sCheatPage->Add(m_cheats_disabled_ar, 0, wxEXPAND | wxTOP, space5);
|
||||
sCheatPage->Add(m_ar_code_panel, 1, wxEXPAND | wxALL, space5);
|
||||
m_CheatPage->SetSizer(sCheatPage);
|
||||
|
||||
// Gecko Cheats
|
||||
@ -600,7 +626,7 @@ void CISOProperties::CreateGUIControls()
|
||||
m_geckocode_panel->Bind(DOLPHIN_EVT_GECKOCODE_TOGGLED, &CISOProperties::OnCheatCodeToggled, this);
|
||||
|
||||
wxBoxSizer* gecko_layout = new wxBoxSizer(wxVERTICAL);
|
||||
gecko_layout->Add(m_cheats_disabled_gecko, 0, wxEXPAND | wxTOP, 5);
|
||||
gecko_layout->Add(m_cheats_disabled_gecko, 0, wxEXPAND | wxTOP, space5);
|
||||
gecko_layout->Add(m_geckocode_panel, 1, wxEXPAND);
|
||||
gecko_cheat_page->SetSizer(gecko_layout);
|
||||
|
||||
@ -698,67 +724,63 @@ void CISOProperties::CreateGUIControls()
|
||||
m_Comment = new wxTextCtrl(m_Information, ID_COMMENT, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxTE_MULTILINE | wxTE_READONLY);
|
||||
wxStaticText* const m_BannerText = new wxStaticText(m_Information, wxID_ANY, _("Banner:"));
|
||||
m_Banner =
|
||||
new wxStaticBitmap(m_Information, ID_BANNER, wxNullBitmap, wxDefaultPosition, wxSize(96, 32));
|
||||
m_Banner = new wxStaticBitmap(m_Information, ID_BANNER, wxNullBitmap, wxDefaultPosition,
|
||||
FromDIP(wxSize(96, 32)));
|
||||
|
||||
// ISO Details
|
||||
wxGridBagSizer* const sISODetails = new wxGridBagSizer(0, 0);
|
||||
sISODetails->Add(m_InternalNameText, wxGBPosition(0, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sISODetails->Add(m_InternalName, wxGBPosition(0, 1), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sISODetails->Add(m_GameIDText, wxGBPosition(1, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sISODetails->Add(m_GameID, wxGBPosition(1, 1), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sISODetails->Add(m_CountryText, wxGBPosition(2, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sISODetails->Add(m_Country, wxGBPosition(2, 1), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sISODetails->Add(m_MakerIDText, wxGBPosition(3, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sISODetails->Add(m_MakerID, wxGBPosition(3, 1), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sISODetails->Add(m_RevisionText, wxGBPosition(4, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sISODetails->Add(m_Revision, wxGBPosition(4, 1), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sISODetails->Add(m_DateText, wxGBPosition(5, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5);
|
||||
sISODetails->Add(m_Date, wxGBPosition(5, 1), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sISODetails->Add(m_FSTText, wxGBPosition(6, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL | wxALL,
|
||||
5);
|
||||
sISODetails->Add(m_FST, wxGBPosition(6, 1), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sISODetails->Add(m_MD5SumText, wxGBPosition(7, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sISODetails->Add(m_MD5Sum, wxGBPosition(7, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
wxSizer* sMD5SumButtonSizer = CreateButtonSizer(wxNO_DEFAULT);
|
||||
sMD5SumButtonSizer->Add(m_MD5SumCompute);
|
||||
sISODetails->Add(sMD5SumButtonSizer, wxGBPosition(7, 2), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
wxGridBagSizer* const sISODetails = new wxGridBagSizer(space10, space10);
|
||||
sISODetails->Add(m_InternalNameText, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_InternalName, wxGBPosition(0, 1), wxGBSpan(1, 2), wxEXPAND);
|
||||
sISODetails->Add(m_GameIDText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_GameID, wxGBPosition(1, 1), wxGBSpan(1, 2), wxEXPAND);
|
||||
sISODetails->Add(m_CountryText, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_Country, wxGBPosition(2, 1), wxGBSpan(1, 2), wxEXPAND);
|
||||
sISODetails->Add(m_MakerIDText, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_MakerID, wxGBPosition(3, 1), wxGBSpan(1, 2), wxEXPAND);
|
||||
sISODetails->Add(m_RevisionText, wxGBPosition(4, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_Revision, wxGBPosition(4, 1), wxGBSpan(1, 2), wxEXPAND);
|
||||
sISODetails->Add(m_DateText, wxGBPosition(5, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_Date, wxGBPosition(5, 1), wxGBSpan(1, 2), wxEXPAND);
|
||||
sISODetails->Add(m_FSTText, wxGBPosition(6, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_FST, wxGBPosition(6, 1), wxGBSpan(1, 2), wxEXPAND);
|
||||
sISODetails->Add(m_MD5SumText, wxGBPosition(7, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sISODetails->Add(m_MD5Sum, wxGBPosition(7, 1), wxGBSpan(1, 1), wxEXPAND);
|
||||
sISODetails->Add(m_MD5SumCompute, wxGBPosition(7, 2), wxGBSpan(1, 1), wxEXPAND);
|
||||
|
||||
sISODetails->AddGrowableCol(1);
|
||||
wxStaticBoxSizer* const sbISODetails =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_Information, _("ISO Details"));
|
||||
sbISODetails->Add(sISODetails, 0, wxEXPAND, 5);
|
||||
sbISODetails->AddSpacer(space5);
|
||||
sbISODetails->Add(sISODetails, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbISODetails->AddSpacer(space5);
|
||||
|
||||
// Banner Details
|
||||
wxGridBagSizer* const sBannerDetails = new wxGridBagSizer(0, 0);
|
||||
sBannerDetails->Add(m_LangText, wxGBPosition(0, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sBannerDetails->Add(m_Lang, wxGBPosition(0, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
sBannerDetails->Add(m_NameText, wxGBPosition(1, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sBannerDetails->Add(m_Name, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
sBannerDetails->Add(m_MakerText, wxGBPosition(2, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sBannerDetails->Add(m_Maker, wxGBPosition(2, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
sBannerDetails->Add(m_CommentText, wxGBPosition(3, 0), wxGBSpan(1, 1), wxALL, 5);
|
||||
sBannerDetails->Add(m_Comment, wxGBPosition(3, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
sBannerDetails->Add(m_BannerText, wxGBPosition(4, 0), wxGBSpan(1, 1), wxALL, 5);
|
||||
sBannerDetails->Add(m_Banner, wxGBPosition(4, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
wxGridBagSizer* const sBannerDetails = new wxGridBagSizer(space10, space10);
|
||||
sBannerDetails->Add(m_LangText, wxGBPosition(0, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
// Comboboxes cannot be safely stretched vertically on Windows.
|
||||
sBannerDetails->Add(WxUtils::GiveMinSize(m_Lang, wxDefaultSize), wxGBPosition(0, 1),
|
||||
wxGBSpan(1, 1), wxEXPAND);
|
||||
sBannerDetails->Add(m_NameText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sBannerDetails->Add(m_Name, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND);
|
||||
sBannerDetails->Add(m_MakerText, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sBannerDetails->Add(m_Maker, wxGBPosition(2, 1), wxGBSpan(1, 1), wxEXPAND);
|
||||
sBannerDetails->Add(m_CommentText, wxGBPosition(3, 0), wxGBSpan(1, 1));
|
||||
sBannerDetails->Add(m_Comment, wxGBPosition(3, 1), wxGBSpan(1, 1), wxEXPAND);
|
||||
sBannerDetails->Add(m_BannerText, wxGBPosition(4, 0), wxGBSpan(1, 1));
|
||||
sBannerDetails->Add(m_Banner, wxGBPosition(4, 1), wxGBSpan(1, 1), wxEXPAND);
|
||||
sBannerDetails->AddGrowableCol(1);
|
||||
wxStaticBoxSizer* const sbBannerDetails =
|
||||
new wxStaticBoxSizer(wxVERTICAL, m_Information, _("Banner Details"));
|
||||
sbBannerDetails->Add(sBannerDetails, 0, wxEXPAND, 5);
|
||||
sbBannerDetails->AddSpacer(space5);
|
||||
sbBannerDetails->Add(sBannerDetails, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbBannerDetails->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const sInfoPage = new wxBoxSizer(wxVERTICAL);
|
||||
sInfoPage->Add(sbISODetails, 0, wxEXPAND | wxALL, 5);
|
||||
sInfoPage->Add(sbBannerDetails, 0, wxEXPAND | wxALL, 5);
|
||||
sInfoPage->AddSpacer(space5);
|
||||
sInfoPage->Add(sbISODetails, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sInfoPage->AddSpacer(space5);
|
||||
sInfoPage->Add(sbBannerDetails, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sInfoPage->AddSpacer(space5);
|
||||
m_Information->SetSizer(sInfoPage);
|
||||
|
||||
if (m_open_iso->GetVolumeType() != DiscIO::Platform::WII_WAD)
|
||||
@ -767,10 +789,14 @@ void CISOProperties::CreateGUIControls()
|
||||
m_Notebook->AddPage(filesystem_panel, _("Filesystem"));
|
||||
|
||||
// Filesystem icons
|
||||
wxImageList* const m_iconList = new wxImageList(16, 16);
|
||||
m_iconList->Add(WxUtils::LoadResourceBitmap("isoproperties_disc")); // 0
|
||||
m_iconList->Add(WxUtils::LoadResourceBitmap("isoproperties_folder")); // 1
|
||||
m_iconList->Add(WxUtils::LoadResourceBitmap("isoproperties_file")); // 2
|
||||
wxSize icon_size = FromDIP(wxSize(16, 16));
|
||||
wxImageList* const m_iconList = new wxImageList(icon_size.GetWidth(), icon_size.GetHeight());
|
||||
static const std::array<const char* const, 3> s_icon_names{
|
||||
{"isoproperties_disc", "isoproperties_folder", "isoproperties_file"}};
|
||||
for (const auto& name : s_icon_names)
|
||||
m_iconList->Add(
|
||||
WxUtils::LoadScaledResourceBitmap(name, this, icon_size, wxDefaultSize,
|
||||
WxUtils::LSI_SCALE_DOWN | WxUtils::LSI_ALIGN_CENTER));
|
||||
|
||||
// Filesystem tree
|
||||
m_Treectrl = new wxTreeCtrl(filesystem_panel, ID_TREECTRL);
|
||||
@ -778,14 +804,16 @@ void CISOProperties::CreateGUIControls()
|
||||
RootId = m_Treectrl->AddRoot(_("Disc"), 0, 0, nullptr);
|
||||
|
||||
wxBoxSizer* sTreePage = new wxBoxSizer(wxVERTICAL);
|
||||
sTreePage->Add(m_Treectrl, 1, wxEXPAND | wxALL, 5);
|
||||
sTreePage->AddSpacer(space5);
|
||||
sTreePage->Add(m_Treectrl, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sTreePage->AddSpacer(space5);
|
||||
filesystem_panel->SetSizer(sTreePage);
|
||||
}
|
||||
|
||||
wxSizer* sButtons = CreateButtonSizer(wxNO_DEFAULT);
|
||||
wxStdDialogButtonSizer* sButtons = CreateStdDialogButtonSizer(wxOK | wxNO_DEFAULT);
|
||||
sButtons->Prepend(EditConfigDefault);
|
||||
sButtons->Prepend(EditConfig);
|
||||
sButtons->Add(new wxButton(this, wxID_OK, _("Close")));
|
||||
sButtons->GetAffirmativeButton()->SetLabel(_("Close"));
|
||||
|
||||
// If there is no default gameini, disable the button.
|
||||
bool game_ini_exists = false;
|
||||
@ -803,10 +831,15 @@ void CISOProperties::CreateGUIControls()
|
||||
|
||||
// Add notebook and buttons to the dialog
|
||||
wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND | wxALL, 5);
|
||||
sMain->Add(sButtons, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
sMain->SetMinSize(wxSize(500, -1));
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(m_Notebook, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(sButtons, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->SetMinSize(FromDIP(wxSize(500, -1)));
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(sMain);
|
||||
Center();
|
||||
SetFocus();
|
||||
@ -842,7 +875,7 @@ void CISOProperties::OnBannerImageSave(wxCommandEvent& WXUNUSED(event))
|
||||
wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
|
||||
if (dialog.ShowModal() == wxID_OK)
|
||||
{
|
||||
m_Banner->GetBitmap().ConvertToImage().SaveFile(dialog.GetPath());
|
||||
OpenGameListItem.GetBannerImage().SaveFile(dialog.GetPath());
|
||||
}
|
||||
Raise();
|
||||
}
|
||||
|
@ -19,11 +19,11 @@
|
||||
#include "DolphinWX/ISOFile.h"
|
||||
#include "DolphinWX/PatchAddEdit.h"
|
||||
|
||||
class DolphinSlider;
|
||||
class wxButton;
|
||||
class wxCheckBox;
|
||||
class wxCheckListBox;
|
||||
class wxChoice;
|
||||
class wxSlider;
|
||||
class wxSpinCtrl;
|
||||
class wxStaticBitmap;
|
||||
class wxTextCtrl;
|
||||
@ -90,7 +90,7 @@ private:
|
||||
wxCheckBox* EnableWideScreen;
|
||||
|
||||
// Stereoscopy
|
||||
wxSlider* DepthPercentage;
|
||||
DolphinSlider* DepthPercentage;
|
||||
wxSpinCtrl* Convergence;
|
||||
wxCheckBox* MonoDepth;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cctype>
|
||||
#include <cstddef>
|
||||
#include <memory>
|
||||
@ -16,6 +17,7 @@
|
||||
#include <wx/choice.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/control.h>
|
||||
#include <wx/dcclient.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/event.h>
|
||||
@ -25,9 +27,9 @@
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/statbmp.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
#include <wx/timer.h>
|
||||
@ -41,6 +43,7 @@
|
||||
#include "Core/HW/GCPad.h"
|
||||
#include "Core/HW/Wiimote.h"
|
||||
#include "Core/HotkeyManager.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "DolphinWX/InputConfigDiag.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "InputCommon/ControllerEmu.h"
|
||||
@ -66,8 +69,10 @@ void GamepadPage::ConfigExtension(wxCommandEvent& event)
|
||||
|
||||
ControlGroupsSizer* const szr = new ControlGroupsSizer(
|
||||
ex->attachments[ex->switch_extension].get(), &dlg, this, &control_groups);
|
||||
main_szr->Add(szr, 0, wxLEFT, 5);
|
||||
main_szr->Add(dlg.CreateButtonSizer(wxOK), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
const int space5 = FromDIP(5);
|
||||
main_szr->Add(szr, 0, wxLEFT, space5);
|
||||
main_szr->Add(dlg.CreateButtonSizer(wxOK), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
dlg.SetSizerAndFit(main_szr);
|
||||
dlg.Center();
|
||||
|
||||
@ -122,6 +127,19 @@ void PadSettingCheckBox::UpdateValue()
|
||||
setting->SetValue(((wxCheckBox*)wxcontrol)->GetValue());
|
||||
}
|
||||
|
||||
PadSettingSpin::PadSettingSpin(wxWindow* const parent,
|
||||
ControllerEmu::ControlGroup::NumericSetting* const settings)
|
||||
: PadSetting(new wxSpinCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxSP_ARROW_KEYS, settings->m_low, settings->m_high,
|
||||
(int)(settings->m_value * 100))),
|
||||
setting(settings)
|
||||
{
|
||||
// Compute how wide the control needs to be to fit the maximum value in it.
|
||||
// This accounts for borders, margins and the spinner buttons.
|
||||
wxcontrol->SetMinSize(WxUtils::GetTextWidgetMinSize(static_cast<wxSpinCtrl*>(wxcontrol)));
|
||||
wxcontrol->SetLabelText(setting->m_name);
|
||||
}
|
||||
|
||||
void PadSettingSpin::UpdateGUI()
|
||||
{
|
||||
((wxSpinCtrl*)wxcontrol)->SetValue((int)(setting->GetValue() * 100));
|
||||
@ -139,13 +157,12 @@ ControlDialog::ControlDialog(GamepadPage* const parent, InputConfig& config,
|
||||
control_reference(ref), m_config(config), m_parent(parent)
|
||||
{
|
||||
m_devq = m_parent->controller->default_device;
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// GetStrings() sounds slow :/
|
||||
// device_cbox = new wxComboBox(this, wxID_ANY, StrToWxStr(ref->device_qualifier.ToString()),
|
||||
// wxDefaultPosition, wxSize(256,-1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER);
|
||||
device_cbox =
|
||||
new wxComboBox(this, wxID_ANY, StrToWxStr(m_devq.ToString()), wxDefaultPosition,
|
||||
wxSize(256, -1), parent->device_cbox->GetStrings(), wxTE_PROCESS_ENTER);
|
||||
device_cbox = new wxComboBox(this, wxID_ANY, StrToWxStr(m_devq.ToString()), wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(180, -1)), parent->device_cbox->GetStrings(),
|
||||
wxTE_PROCESS_ENTER);
|
||||
|
||||
device_cbox->Bind(wxEVT_COMBOBOX, &ControlDialog::SetDevice, this);
|
||||
device_cbox->Bind(wxEVT_TEXT_ENTER, &ControlDialog::SetDevice, this);
|
||||
@ -153,12 +170,19 @@ ControlDialog::ControlDialog(GamepadPage* const parent, InputConfig& config,
|
||||
wxStaticBoxSizer* const control_chooser = CreateControlChooser(parent);
|
||||
|
||||
wxStaticBoxSizer* const d_szr = new wxStaticBoxSizer(wxVERTICAL, this, _("Device"));
|
||||
d_szr->Add(device_cbox, 0, wxEXPAND | wxALL, 5);
|
||||
d_szr->AddSpacer(space5);
|
||||
d_szr->Add(device_cbox, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
d_szr->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxVERTICAL);
|
||||
szr->Add(d_szr, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, 5);
|
||||
szr->Add(control_chooser, 1, wxEXPAND | wxALL, 5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(d_szr, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(control_chooser, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr->AddSpacer(space5);
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(szr); // needed
|
||||
|
||||
UpdateGUI();
|
||||
@ -169,15 +193,26 @@ ControlButton::ControlButton(wxWindow* const parent,
|
||||
ControllerInterface::ControlReference* const _ref,
|
||||
const std::string& name, const unsigned int width,
|
||||
const std::string& label)
|
||||
: wxButton(parent, wxID_ANY, "", wxDefaultPosition, wxSize(width, 20)), control_reference(_ref),
|
||||
m_name(name)
|
||||
: wxButton(parent, wxID_ANY), control_reference(_ref), m_name(name),
|
||||
m_configured_width(FromDIP(width))
|
||||
{
|
||||
if (label.empty())
|
||||
SetLabel(StrToWxStr(_ref->expression));
|
||||
SetLabelText(StrToWxStr(_ref->expression));
|
||||
else
|
||||
SetLabel(StrToWxStr(label));
|
||||
}
|
||||
|
||||
wxSize ControlButton::DoGetBestSize() const
|
||||
{
|
||||
if (m_configured_width == wxDefaultCoord)
|
||||
return wxButton::DoGetBestSize();
|
||||
|
||||
static constexpr int PADDING_HEIGHT = 4;
|
||||
wxClientDC dc(const_cast<ControlButton*>(this));
|
||||
wxFontMetrics metrics = dc.GetFontMetrics();
|
||||
return {m_configured_width, metrics.height + FromDIP(PADDING_HEIGHT * 2)};
|
||||
}
|
||||
|
||||
void InputConfigDialog::UpdateProfileComboBox()
|
||||
{
|
||||
std::string pname(File::GetUserPath(D_CONFIG_IDX));
|
||||
@ -222,7 +257,7 @@ void InputConfigDialog::OnCloseButton(wxCommandEvent& event)
|
||||
|
||||
int ControlDialog::GetRangeSliderValue() const
|
||||
{
|
||||
return range_slider->GetValue();
|
||||
return m_range_slider->GetValue();
|
||||
}
|
||||
|
||||
void ControlDialog::UpdateListContents()
|
||||
@ -288,9 +323,7 @@ void GamepadPage::UpdateGUI()
|
||||
{
|
||||
for (ControlButton* button : cgBox->control_buttons)
|
||||
{
|
||||
wxString expr = StrToWxStr(button->control_reference->expression);
|
||||
expr.Replace("&", "&&");
|
||||
button->SetLabel(expr);
|
||||
button->SetLabelText(StrToWxStr(button->control_reference->expression));
|
||||
}
|
||||
|
||||
for (PadSetting* padSetting : cgBox->options)
|
||||
@ -503,6 +536,23 @@ void GamepadPage::EnableControlButton(const std::string& group_name, const std::
|
||||
(*it)->Enable(enabled);
|
||||
}
|
||||
|
||||
void ControlDialog::OnRangeSlide(wxScrollEvent& event)
|
||||
{
|
||||
m_range_spinner->SetValue(event.GetPosition());
|
||||
control_reference->range = static_cast<ControlState>(event.GetPosition()) / SLIDER_TICK_COUNT;
|
||||
}
|
||||
|
||||
void ControlDialog::OnRangeSpin(wxSpinEvent& event)
|
||||
{
|
||||
m_range_slider->SetValue(event.GetValue());
|
||||
control_reference->range = static_cast<ControlState>(event.GetValue()) / SLIDER_TICK_COUNT;
|
||||
}
|
||||
|
||||
void ControlDialog::OnRangeThumbtrack(wxScrollEvent& event)
|
||||
{
|
||||
m_range_spinner->SetValue(event.GetPosition());
|
||||
}
|
||||
|
||||
void GamepadPage::AdjustSetting(wxCommandEvent& event)
|
||||
{
|
||||
const auto* const control = static_cast<wxControl*>(event.GetEventObject());
|
||||
@ -528,12 +578,6 @@ void GamepadPage::AdjustBooleanSetting(wxCommandEvent& event)
|
||||
}
|
||||
}
|
||||
|
||||
void GamepadPage::AdjustControlOption(wxCommandEvent&)
|
||||
{
|
||||
m_control_dialog->control_reference->range =
|
||||
(ControlState)(m_control_dialog->GetRangeSliderValue()) / SLIDER_TICK_COUNT;
|
||||
}
|
||||
|
||||
void GamepadPage::ConfigControl(wxEvent& event)
|
||||
{
|
||||
m_control_dialog = new ControlDialog(this, m_config,
|
||||
@ -647,9 +691,10 @@ wxStaticBoxSizer* ControlDialog::CreateControlChooser(GamepadPage* const parent)
|
||||
{
|
||||
wxStaticBoxSizer* const main_szr = new wxStaticBoxSizer(
|
||||
wxVERTICAL, this, control_reference->is_input ? _("Input") : _("Output"));
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
textctrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(-1, 48),
|
||||
wxTE_MULTILINE | wxTE_RICH2);
|
||||
textctrl = new wxTextCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(-1, 32)), wxTE_MULTILINE | wxTE_RICH2);
|
||||
wxFont font = textctrl->GetFont();
|
||||
font.SetFamily(wxFONTFAMILY_MODERN);
|
||||
textctrl->SetFont(font);
|
||||
@ -665,12 +710,12 @@ wxStaticBoxSizer* ControlDialog::CreateControlChooser(GamepadPage* const parent)
|
||||
wxButton* const or_button = new wxButton(this, wxID_ANY, _("| OR"));
|
||||
or_button->Bind(wxEVT_BUTTON, &ControlDialog::AppendControl, this);
|
||||
|
||||
control_lbox = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 64));
|
||||
control_lbox = new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDLG_UNIT(this, wxSize(-1, 48)));
|
||||
|
||||
wxBoxSizer* const button_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
button_sizer->Add(detect_button, 1, 0, 5);
|
||||
button_sizer->Add(select_button, 1, 0, 5);
|
||||
button_sizer->Add(or_button, 1, 0, 5);
|
||||
button_sizer->Add(detect_button, 1);
|
||||
button_sizer->Add(select_button, 1);
|
||||
button_sizer->Add(or_button, 1);
|
||||
|
||||
if (control_reference->is_input)
|
||||
{
|
||||
@ -683,43 +728,57 @@ wxStaticBoxSizer* ControlDialog::CreateControlChooser(GamepadPage* const parent)
|
||||
not_button->Bind(wxEVT_BUTTON, &ControlDialog::AppendControl, this);
|
||||
add_button->Bind(wxEVT_BUTTON, &ControlDialog::AppendControl, this);
|
||||
|
||||
button_sizer->Add(and_button, 1, 0, 5);
|
||||
button_sizer->Add(not_button, 1, 0, 5);
|
||||
button_sizer->Add(add_button, 1, 0, 5);
|
||||
button_sizer->Add(and_button, 1);
|
||||
button_sizer->Add(not_button, 1);
|
||||
button_sizer->Add(add_button, 1);
|
||||
}
|
||||
|
||||
range_slider =
|
||||
new wxSlider(this, wxID_ANY, SLIDER_TICK_COUNT, -SLIDER_TICK_COUNT * 5, SLIDER_TICK_COUNT * 5,
|
||||
wxDefaultPosition, wxDefaultSize, wxSL_TOP | wxSL_LABELS /*| wxSL_AUTOTICKS*/);
|
||||
|
||||
range_slider->SetValue((int)(control_reference->range * SLIDER_TICK_COUNT));
|
||||
m_range_slider = new DolphinSlider(
|
||||
this, wxID_ANY, static_cast<int>(control_reference->range * SLIDER_TICK_COUNT),
|
||||
-SLIDER_TICK_COUNT * 5, SLIDER_TICK_COUNT * 5, wxDefaultPosition, wxDefaultSize, wxSL_TOP);
|
||||
m_range_spinner = new wxSpinCtrl(this, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(32, -1)),
|
||||
wxSP_ARROW_KEYS | wxALIGN_RIGHT, m_range_slider->GetMin(),
|
||||
m_range_slider->GetMax(), m_range_slider->GetValue());
|
||||
|
||||
detect_button->Bind(wxEVT_BUTTON, &ControlDialog::DetectControl, this);
|
||||
clear_button->Bind(wxEVT_BUTTON, &ControlDialog::ClearControl, this);
|
||||
|
||||
range_slider->Bind(wxEVT_SCROLL_CHANGED, &GamepadPage::AdjustControlOption, parent);
|
||||
wxStaticText* const range_label = new wxStaticText(this, wxID_ANY, _("Range"));
|
||||
m_range_slider->Bind(wxEVT_SCROLL_CHANGED, &ControlDialog::OnRangeSlide, this);
|
||||
m_range_slider->Bind(wxEVT_SCROLL_THUMBTRACK, &ControlDialog::OnRangeThumbtrack, this);
|
||||
m_range_spinner->Bind(wxEVT_SPINCTRL, &ControlDialog::OnRangeSpin, this);
|
||||
|
||||
m_bound_label = new wxStaticText(this, wxID_ANY, "");
|
||||
m_error_label = new wxStaticText(this, wxID_ANY, "");
|
||||
|
||||
wxBoxSizer* const range_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
range_sizer->Add(range_label, 0, wxCENTER | wxLEFT, 5);
|
||||
range_sizer->Add(range_slider, 1, wxEXPAND | wxLEFT, 5);
|
||||
range_sizer->Add(new wxStaticText(this, wxID_ANY, _("Range")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
range_sizer->Add(
|
||||
new wxStaticText(this, wxID_ANY, wxString::Format("%d", m_range_slider->GetMin())), 0,
|
||||
wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
range_sizer->Add(m_range_slider, 1, wxEXPAND);
|
||||
range_sizer->Add(
|
||||
new wxStaticText(this, wxID_ANY, wxString::Format("%d", m_range_slider->GetMax())), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
range_sizer->Add(m_range_spinner, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
|
||||
wxBoxSizer* const ctrls_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
ctrls_sizer->Add(control_lbox, 1, wxEXPAND, 0);
|
||||
ctrls_sizer->Add(button_sizer, 0, wxEXPAND, 0);
|
||||
ctrls_sizer->Add(control_lbox, 1, wxEXPAND);
|
||||
ctrls_sizer->Add(button_sizer, 0, wxEXPAND);
|
||||
|
||||
wxSizer* const bottom_btns_sizer = CreateButtonSizer(wxOK | wxAPPLY);
|
||||
bottom_btns_sizer->Prepend(clear_button, 0, wxLEFT, 5);
|
||||
bottom_btns_sizer->Prepend(clear_button, 0, wxLEFT, space5);
|
||||
|
||||
main_szr->Add(range_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
main_szr->Add(ctrls_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
main_szr->Add(textctrl, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
main_szr->Add(bottom_btns_sizer, 0, wxEXPAND | wxBOTTOM | wxRIGHT, 5);
|
||||
main_szr->Add(m_bound_label, 0, wxCENTER, 0);
|
||||
main_szr->Add(m_error_label, 0, wxCENTER, 0);
|
||||
main_szr->Add(range_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(ctrls_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(textctrl, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(bottom_btns_sizer, 0, wxEXPAND | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(m_bound_label, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
main_szr->Add(m_error_label, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
|
||||
UpdateListContents();
|
||||
|
||||
@ -839,22 +898,25 @@ ControlGroupBox::~ControlGroupBox()
|
||||
|
||||
ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWindow* const parent,
|
||||
GamepadPage* const eventsink)
|
||||
: wxBoxSizer(wxVERTICAL), control_group(group)
|
||||
: wxBoxSizer(wxVERTICAL), control_group(group), static_bitmap(nullptr), m_scale(1)
|
||||
{
|
||||
static_bitmap = nullptr;
|
||||
const std::vector<std::string> exclude_buttons = {"Mic", "Modifier"};
|
||||
const std::vector<std::string> exclude_groups = {"IR", "Swing", "Tilt", "Shake",
|
||||
"UDP Wiimote", "Extension", "Rumble"};
|
||||
static constexpr std::array<const char* const, 2> exclude_buttons{{"Mic", "Modifier"}};
|
||||
static constexpr std::array<const char* const, 7> exclude_groups{
|
||||
{"IR", "Swing", "Tilt", "Shake", "UDP Wiimote", "Extension", "Rumble"}};
|
||||
|
||||
wxFont m_SmallFont(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
for (auto& control : group->controls)
|
||||
wxFont small_font(7, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_NORMAL);
|
||||
const int space3 = parent->FromDIP(3);
|
||||
|
||||
wxFlexGridSizer* control_grid = new wxFlexGridSizer(2, 0, space3);
|
||||
control_grid->AddGrowableCol(0);
|
||||
for (const auto& control : group->controls)
|
||||
{
|
||||
wxStaticText* const label =
|
||||
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(control->name)));
|
||||
|
||||
ControlButton* const control_button =
|
||||
new ControlButton(parent, control->control_ref.get(), control->name, 80);
|
||||
control_button->SetFont(m_SmallFont);
|
||||
control_button->SetFont(small_font);
|
||||
|
||||
control_buttons.push_back(control_button);
|
||||
if (std::find(exclude_groups.begin(), exclude_groups.end(), control_group->name) ==
|
||||
@ -878,15 +940,10 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
control_button->Bind(wxEVT_MIDDLE_DOWN, &GamepadPage::ClearControl, eventsink);
|
||||
control_button->Bind(wxEVT_RIGHT_UP, &GamepadPage::ConfigControl, eventsink);
|
||||
|
||||
wxBoxSizer* const control_sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
control_sizer->AddStretchSpacer(1);
|
||||
control_sizer->Add(label, 0, wxCENTER | wxRIGHT, 3);
|
||||
control_sizer->Add(control_button, 0, 0, 0);
|
||||
|
||||
Add(control_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, 3);
|
||||
control_grid->Add(label, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_RIGHT);
|
||||
control_grid->Add(control_button, 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
wxMemoryDC dc;
|
||||
Add(control_grid, 0, wxEXPAND | wxLEFT | wxRIGHT, space3);
|
||||
|
||||
switch (group->type)
|
||||
{
|
||||
@ -895,9 +952,15 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
case GROUP_TYPE_CURSOR:
|
||||
case GROUP_TYPE_FORCE:
|
||||
{
|
||||
wxBitmap bitmap(64, 64);
|
||||
dc.SelectObject(bitmap);
|
||||
wxSize bitmap_size = parent->FromDIP(wxSize(64, 64));
|
||||
m_scale = bitmap_size.GetWidth() / 64.0;
|
||||
|
||||
wxBitmap bitmap;
|
||||
bitmap.CreateScaled(bitmap_size.GetWidth(), bitmap_size.GetHeight(), wxBITMAP_SCREEN_DEPTH,
|
||||
parent->GetContentScaleFactor());
|
||||
wxMemoryDC dc(bitmap);
|
||||
dc.Clear();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
static_bitmap = new wxStaticBitmap(parent, wxID_ANY, bitmap, wxDefaultPosition, wxDefaultSize,
|
||||
wxBITMAP_TYPE_BMP);
|
||||
|
||||
@ -909,21 +972,23 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
options.push_back(setting);
|
||||
szr->Add(
|
||||
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(groupSetting->m_name))));
|
||||
szr->Add(setting->wxcontrol, 0, wxLEFT, 0);
|
||||
szr->Add(setting->wxcontrol);
|
||||
}
|
||||
for (auto& groupSetting : group->boolean_settings)
|
||||
{
|
||||
auto* checkbox = new PadSettingCheckBox(parent, groupSetting.get());
|
||||
checkbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustBooleanSetting, eventsink);
|
||||
options.push_back(checkbox);
|
||||
Add(checkbox->wxcontrol, 0, wxALL | wxLEFT, 5);
|
||||
Add(checkbox->wxcontrol, 0, wxALL | wxLEFT, space3);
|
||||
}
|
||||
|
||||
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
h_szr->Add(szr, 1, 0, 5);
|
||||
h_szr->Add(static_bitmap, 0, wxALL | wxCENTER, 3);
|
||||
h_szr->Add(szr, 1, wxEXPAND | wxTOP | wxBOTTOM, space3);
|
||||
h_szr->AddSpacer(space3);
|
||||
h_szr->Add(static_bitmap, 0, wxALIGN_CENTER_VERTICAL | wxTOP | wxBOTTOM, space3);
|
||||
|
||||
Add(h_szr, 0, wxEXPAND | wxLEFT | wxCENTER | wxTOP, 3);
|
||||
AddSpacer(space3);
|
||||
Add(h_szr, 0, wxEXPAND | wxLEFT | wxRIGHT, space3);
|
||||
}
|
||||
break;
|
||||
case GROUP_TYPE_BUTTONS:
|
||||
@ -931,10 +996,16 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
// Draw buttons in rows of 8
|
||||
unsigned int button_cols = group->controls.size() > 8 ? 8 : group->controls.size();
|
||||
unsigned int button_rows = ceil((float)group->controls.size() / 8.0f);
|
||||
wxBitmap bitmap(int(12 * button_cols + 1), (11 * button_rows) + 1);
|
||||
wxSize bitmap_size(12 * button_cols + 1, 11 * button_rows + 1);
|
||||
wxSize bitmap_scaled_size = parent->FromDIP(bitmap_size);
|
||||
m_scale = static_cast<double>(bitmap_scaled_size.GetWidth()) / bitmap_size.GetWidth();
|
||||
|
||||
dc.SelectObject(bitmap);
|
||||
wxBitmap bitmap;
|
||||
bitmap.CreateScaled(bitmap_scaled_size.GetWidth(), bitmap_scaled_size.GetHeight(),
|
||||
wxBITMAP_SCREEN_DEPTH, parent->GetContentScaleFactor());
|
||||
wxMemoryDC dc(bitmap);
|
||||
dc.Clear();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
static_bitmap = new wxStaticBitmap(parent, wxID_ANY, bitmap, wxDefaultPosition, wxDefaultSize,
|
||||
wxBITMAP_TYPE_BMP);
|
||||
|
||||
@ -949,11 +1020,13 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
szr->Add(new wxStaticText(parent, wxID_ANY,
|
||||
wxGetTranslation(StrToWxStr(group->numeric_settings[0]->m_name))),
|
||||
0, wxCENTER | wxRIGHT, 3);
|
||||
szr->Add(threshold_cbox->wxcontrol, 0, wxRIGHT, 3);
|
||||
0, wxALIGN_CENTER_VERTICAL | wxRIGHT, space3);
|
||||
szr->Add(threshold_cbox->wxcontrol, 0, wxRIGHT, space3);
|
||||
|
||||
Add(szr, 0, wxALL | wxCENTER, 3);
|
||||
Add(static_bitmap, 0, wxALL | wxCENTER, 3);
|
||||
AddSpacer(space3);
|
||||
Add(szr, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, space3);
|
||||
AddSpacer(space3);
|
||||
Add(static_bitmap, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, space3);
|
||||
}
|
||||
break;
|
||||
case GROUP_TYPE_MIXED_TRIGGERS:
|
||||
@ -968,10 +1041,16 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
|
||||
if (GROUP_TYPE_TRIGGERS != group->type)
|
||||
height /= 2;
|
||||
height += 1;
|
||||
|
||||
wxBitmap bitmap(width, height + 1);
|
||||
dc.SelectObject(bitmap);
|
||||
wxSize bitmap_size = parent->FromDIP(wxSize(width, height));
|
||||
m_scale = static_cast<double>(bitmap_size.GetWidth()) / width;
|
||||
wxBitmap bitmap;
|
||||
bitmap.CreateScaled(bitmap_size.GetWidth(), bitmap_size.GetHeight(), wxBITMAP_SCREEN_DEPTH,
|
||||
parent->GetContentScaleFactor());
|
||||
wxMemoryDC dc(bitmap);
|
||||
dc.Clear();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
static_bitmap = new wxStaticBitmap(parent, wxID_ANY, bitmap, wxDefaultPosition, wxDefaultSize,
|
||||
wxBITMAP_TYPE_BMP);
|
||||
|
||||
@ -983,12 +1062,15 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
szr->Add(
|
||||
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(groupSetting->m_name))), 0,
|
||||
wxCENTER | wxRIGHT, 3);
|
||||
szr->Add(setting->wxcontrol, 0, wxRIGHT, 3);
|
||||
Add(szr, 0, wxALL | wxCENTER, 3);
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
szr->Add(setting->wxcontrol, 0, wxLEFT, space3);
|
||||
|
||||
AddSpacer(space3);
|
||||
Add(szr, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, space3);
|
||||
}
|
||||
|
||||
Add(static_bitmap, 0, wxALL | wxCENTER, 3);
|
||||
AddSpacer(space3);
|
||||
Add(static_bitmap, 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT, space3);
|
||||
}
|
||||
break;
|
||||
case GROUP_TYPE_EXTENSION:
|
||||
@ -1002,8 +1084,10 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
attachments->wxcontrol->Bind(wxEVT_CHOICE, &GamepadPage::AdjustSetting, eventsink);
|
||||
configure_btn->Bind(wxEVT_BUTTON, &GamepadPage::ConfigExtension, eventsink);
|
||||
|
||||
Add(attachments->wxcontrol, 0, wxTOP | wxLEFT | wxRIGHT | wxEXPAND, 3);
|
||||
Add(configure_btn, 0, wxALL | wxEXPAND, 3);
|
||||
AddSpacer(space3);
|
||||
Add(attachments->wxcontrol, 0, wxEXPAND | wxLEFT | wxRIGHT, space3);
|
||||
AddSpacer(space3);
|
||||
Add(configure_btn, 0, wxEXPAND | wxLEFT | wxRIGHT, space3);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@ -1016,7 +1100,8 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
if (groupSetting->m_name == "Iterative Input")
|
||||
groupSetting->SetValue(false);
|
||||
options.push_back(setting_cbox);
|
||||
Add(setting_cbox->wxcontrol, 0, wxALL | wxLEFT, 5);
|
||||
AddSpacer(space3);
|
||||
Add(setting_cbox->wxcontrol, 0, wxLEFT | wxRIGHT, space3);
|
||||
}
|
||||
for (auto& groupSetting : group->numeric_settings)
|
||||
{
|
||||
@ -1026,17 +1111,15 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
szr->Add(
|
||||
new wxStaticText(parent, wxID_ANY, wxGetTranslation(StrToWxStr(groupSetting->m_name))), 0,
|
||||
wxCENTER | wxRIGHT, 3);
|
||||
szr->Add(setting->wxcontrol, 0, wxRIGHT, 3);
|
||||
Add(szr, 0, wxALL | wxCENTER, 3);
|
||||
wxALIGN_CENTER_VERTICAL, space3);
|
||||
szr->Add(setting->wxcontrol, 0, wxLEFT, space3);
|
||||
AddSpacer(space3);
|
||||
Add(szr, 0, wxLEFT | wxRIGHT, space3);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
|
||||
// AddStretchSpacer(0);
|
||||
AddSpacer(space3);
|
||||
}
|
||||
|
||||
ControlGroupsSizer::ControlGroupsSizer(ControllerEmu* const controller, wxWindow* const parent,
|
||||
@ -1044,15 +1127,17 @@ ControlGroupsSizer::ControlGroupsSizer(ControllerEmu* const controller, wxWindow
|
||||
std::vector<ControlGroupBox*>* groups)
|
||||
: wxBoxSizer(wxHORIZONTAL)
|
||||
{
|
||||
const int space5 = parent->FromDIP(5);
|
||||
size_t col_size = 0;
|
||||
|
||||
wxBoxSizer* stacked_groups = nullptr;
|
||||
for (auto& group : controller->groups)
|
||||
{
|
||||
ControlGroupBox* control_group_box = new ControlGroupBox(group.get(), parent, eventsink);
|
||||
wxStaticBoxSizer* control_group =
|
||||
new wxStaticBoxSizer(wxVERTICAL, parent, wxGetTranslation(StrToWxStr(group->ui_name)));
|
||||
control_group->Add(control_group_box);
|
||||
ControlGroupBox* control_group_box =
|
||||
new ControlGroupBox(group.get(), control_group->GetStaticBox(), eventsink);
|
||||
control_group->Add(control_group_box, 0, wxEXPAND);
|
||||
|
||||
const size_t grp_size =
|
||||
group->controls.size() + group->numeric_settings.size() + group->boolean_settings.size();
|
||||
@ -1060,7 +1145,10 @@ ControlGroupsSizer::ControlGroupsSizer(ControllerEmu* const controller, wxWindow
|
||||
if (col_size > 8 || nullptr == stacked_groups)
|
||||
{
|
||||
if (stacked_groups)
|
||||
Add(stacked_groups, 0, /*wxEXPAND|*/ wxBOTTOM | wxRIGHT, 5);
|
||||
{
|
||||
Add(stacked_groups, 0, wxBOTTOM, space5);
|
||||
AddSpacer(space5);
|
||||
}
|
||||
|
||||
stacked_groups = new wxBoxSizer(wxVERTICAL);
|
||||
stacked_groups->Add(control_group, 0, wxEXPAND);
|
||||
@ -1077,7 +1165,7 @@ ControlGroupsSizer::ControlGroupsSizer(ControllerEmu* const controller, wxWindow
|
||||
}
|
||||
|
||||
if (stacked_groups)
|
||||
Add(stacked_groups, 0, /*wxEXPAND|*/ wxBOTTOM | wxRIGHT, 5);
|
||||
Add(stacked_groups, 0, wxBOTTOM, space5);
|
||||
}
|
||||
|
||||
GamepadPage::GamepadPage(wxWindow* parent, InputConfig& config, const int pad_num,
|
||||
@ -1086,65 +1174,81 @@ GamepadPage::GamepadPage(wxWindow* parent, InputConfig& config, const int pad_nu
|
||||
m_config_dialog(config_dialog), m_config(config)
|
||||
{
|
||||
wxBoxSizer* control_group_sizer = new ControlGroupsSizer(controller, this, this, &control_groups);
|
||||
|
||||
wxStaticBoxSizer* profile_sbox = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Profile"));
|
||||
const int space3 = FromDIP(3);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// device chooser
|
||||
wxStaticBoxSizer* const device_sbox = new wxStaticBoxSizer(wxVERTICAL, this, _("Device"));
|
||||
|
||||
wxStaticBoxSizer* const device_sbox = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Device"));
|
||||
|
||||
device_cbox = new wxComboBox(this, wxID_ANY, "", wxDefaultPosition, wxSize(64, -1));
|
||||
device_cbox = new wxComboBox(device_sbox->GetStaticBox(), wxID_ANY, "");
|
||||
device_cbox->ToggleWindowStyle(wxTE_PROCESS_ENTER);
|
||||
|
||||
wxButton* refresh_button =
|
||||
new wxButton(this, wxID_ANY, _("Refresh"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* refresh_button = new wxButton(device_sbox->GetStaticBox(), wxID_ANY, _("Refresh"),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
|
||||
device_cbox->Bind(wxEVT_COMBOBOX, &GamepadPage::SetDevice, this);
|
||||
device_cbox->Bind(wxEVT_TEXT_ENTER, &GamepadPage::SetDevice, this);
|
||||
refresh_button->Bind(wxEVT_BUTTON, &GamepadPage::RefreshDevices, this);
|
||||
|
||||
device_sbox->Add(device_cbox, 1, wxLEFT | wxRIGHT, 3);
|
||||
device_sbox->Add(refresh_button, 0, wxRIGHT | wxBOTTOM, 3);
|
||||
wxBoxSizer* const device_sbox_in = new wxBoxSizer(wxHORIZONTAL);
|
||||
device_sbox_in->Add(WxUtils::GiveMinSizeDIP(device_cbox, wxSize(64, -1)), 1,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
device_sbox_in->Add(refresh_button, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space3);
|
||||
device_sbox->Add(device_sbox_in, 1, wxEXPAND | wxLEFT | wxRIGHT, space3);
|
||||
device_sbox->AddSpacer(space3);
|
||||
|
||||
wxButton* const default_button =
|
||||
new wxButton(this, wxID_ANY, _("Default"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* const clearall_button =
|
||||
new wxButton(this, wxID_ANY, _("Clear"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
// Clear / Reset buttons
|
||||
wxStaticBoxSizer* const clear_sbox = new wxStaticBoxSizer(wxVERTICAL, this, _("Reset"));
|
||||
|
||||
wxStaticBoxSizer* const clear_sbox = new wxStaticBoxSizer(wxHORIZONTAL, this, _("Reset"));
|
||||
clear_sbox->Add(default_button, 1, wxLEFT, 3);
|
||||
clear_sbox->Add(clearall_button, 1, wxRIGHT, 3);
|
||||
wxButton* const default_button = new wxButton(clear_sbox->GetStaticBox(), wxID_ANY, _("Default"),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* const clearall_button = new wxButton(clear_sbox->GetStaticBox(), wxID_ANY, _("Clear"),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
|
||||
wxBoxSizer* clear_sbox_in = new wxBoxSizer(wxHORIZONTAL);
|
||||
clear_sbox_in->Add(default_button, 1, wxALIGN_CENTER_VERTICAL);
|
||||
clear_sbox_in->Add(clearall_button, 1, wxALIGN_CENTER_VERTICAL);
|
||||
clear_sbox->Add(clear_sbox_in, 1, wxEXPAND | wxLEFT | wxRIGHT, space3);
|
||||
clear_sbox->AddSpacer(space3);
|
||||
|
||||
clearall_button->Bind(wxEVT_BUTTON, &GamepadPage::ClearAll, this);
|
||||
default_button->Bind(wxEVT_BUTTON, &GamepadPage::LoadDefaults, this);
|
||||
|
||||
profile_cbox = new wxComboBox(this, wxID_ANY, "", wxDefaultPosition, wxSize(64, -1));
|
||||
// Profile selector
|
||||
wxStaticBoxSizer* profile_sbox = new wxStaticBoxSizer(wxVERTICAL, this, _("Profile"));
|
||||
profile_cbox = new wxComboBox(profile_sbox->GetStaticBox(), wxID_ANY, "");
|
||||
|
||||
wxButton* const pload_btn =
|
||||
new wxButton(this, wxID_ANY, _("Load"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* const psave_btn =
|
||||
new wxButton(this, wxID_ANY, _("Save"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* const pdelete_btn =
|
||||
new wxButton(this, wxID_ANY, _("Delete"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* const pload_btn = new wxButton(profile_sbox->GetStaticBox(), wxID_ANY, _("Load"),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* const psave_btn = new wxButton(profile_sbox->GetStaticBox(), wxID_ANY, _("Save"),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
wxButton* const pdelete_btn = new wxButton(profile_sbox->GetStaticBox(), wxID_ANY, _("Delete"),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
|
||||
pload_btn->Bind(wxEVT_BUTTON, &GamepadPage::LoadProfile, this);
|
||||
psave_btn->Bind(wxEVT_BUTTON, &GamepadPage::SaveProfile, this);
|
||||
pdelete_btn->Bind(wxEVT_BUTTON, &GamepadPage::DeleteProfile, this);
|
||||
|
||||
profile_sbox->Add(profile_cbox, 1, wxLEFT, 3);
|
||||
profile_sbox->Add(pload_btn, 0, wxLEFT, 3);
|
||||
profile_sbox->Add(psave_btn, 0, 0, 3);
|
||||
profile_sbox->Add(pdelete_btn, 0, wxRIGHT | wxBOTTOM, 3);
|
||||
wxBoxSizer* profile_sbox_in = new wxBoxSizer(wxHORIZONTAL);
|
||||
profile_sbox_in->Add(WxUtils::GiveMinSizeDIP(profile_cbox, wxSize(64, -1)), 1,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
profile_sbox_in->AddSpacer(space3);
|
||||
profile_sbox_in->Add(pload_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
profile_sbox_in->Add(psave_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
profile_sbox_in->Add(pdelete_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
profile_sbox->Add(profile_sbox_in, 1, wxEXPAND | wxLEFT | wxRIGHT, space3);
|
||||
profile_sbox->AddSpacer(space3);
|
||||
|
||||
wxBoxSizer* const dio = new wxBoxSizer(wxHORIZONTAL);
|
||||
dio->Add(device_sbox, 1, wxEXPAND | wxRIGHT, 5);
|
||||
dio->Add(clear_sbox, 0, wxEXPAND | wxRIGHT, 5);
|
||||
dio->Add(profile_sbox, 1, wxEXPAND | wxRIGHT, 5);
|
||||
dio->Add(device_sbox, 1, wxEXPAND);
|
||||
dio->Add(clear_sbox, 0, wxEXPAND | wxLEFT, space5);
|
||||
dio->Add(profile_sbox, 1, wxEXPAND | wxLEFT, space5);
|
||||
|
||||
wxBoxSizer* const mapping = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
mapping->Add(dio, 1, wxEXPAND | wxLEFT | wxTOP | wxBOTTOM, 5);
|
||||
mapping->Add(control_group_sizer, 0, wxLEFT | wxEXPAND, 5);
|
||||
mapping->AddSpacer(space5);
|
||||
mapping->Add(dio, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
mapping->AddSpacer(space5);
|
||||
mapping->Add(control_group_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
|
||||
UpdateGUI();
|
||||
|
||||
@ -1154,9 +1258,9 @@ GamepadPage::GamepadPage(wxWindow* parent, InputConfig& config, const int pad_nu
|
||||
|
||||
InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputConfig& config,
|
||||
const wxString& name, const int tab_num)
|
||||
: wxDialog(parent, wxID_ANY, name, wxPoint(128, -1)), m_config(config)
|
||||
: wxDialog(parent, wxID_ANY, name), m_config(config)
|
||||
{
|
||||
m_pad_notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxNB_DEFAULT);
|
||||
m_pad_notebook = new wxNotebook(this, wxID_ANY);
|
||||
GamepadPage* gp = new GamepadPage(m_pad_notebook, m_config, tab_num, this);
|
||||
m_padpages.push_back(gp);
|
||||
m_pad_notebook->AddPage(gp, wxString::Format("%s [%u]",
|
||||
@ -1172,10 +1276,15 @@ InputConfigDialog::InputConfigDialog(wxWindow* const parent, InputConfig& config
|
||||
Bind(wxEVT_BUTTON, &InputConfigDialog::OnCloseButton, this, wxID_CLOSE);
|
||||
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxVERTICAL);
|
||||
szr->Add(m_pad_notebook, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, 5);
|
||||
szr->Add(CreateButtonSizer(wxCLOSE), 0, wxEXPAND | wxALL, 5);
|
||||
const int space5 = FromDIP(5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(m_pad_notebook, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(CreateButtonSizer(wxCLOSE | wxNO_DEFAULT), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr->AddSpacer(space5);
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(szr);
|
||||
Center();
|
||||
|
||||
|
@ -27,11 +27,11 @@
|
||||
#include "InputCommon/ControllerInterface/ControllerInterface.h"
|
||||
#include "InputCommon/ControllerInterface/Device.h"
|
||||
|
||||
class DolphinSlider;
|
||||
class InputConfig;
|
||||
class wxComboBox;
|
||||
class wxListBox;
|
||||
class wxNotebook;
|
||||
class wxSlider;
|
||||
class wxStaticBitmap;
|
||||
class wxStaticText;
|
||||
class wxTextCtrl;
|
||||
@ -62,15 +62,7 @@ class PadSettingSpin : public PadSetting
|
||||
{
|
||||
public:
|
||||
PadSettingSpin(wxWindow* const parent,
|
||||
ControllerEmu::ControlGroup::NumericSetting* const _setting)
|
||||
: PadSetting(new wxSpinCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(54, -1), 0, _setting->m_low, _setting->m_high,
|
||||
(int)(_setting->GetValue() * 100))),
|
||||
setting(_setting)
|
||||
{
|
||||
wxcontrol->SetLabel(setting->m_name);
|
||||
}
|
||||
|
||||
ControllerEmu::ControlGroup::NumericSetting* const setting);
|
||||
void UpdateGUI() override;
|
||||
void UpdateValue() override;
|
||||
|
||||
@ -136,6 +128,9 @@ private:
|
||||
|
||||
void SetSelectedControl(wxCommandEvent& event);
|
||||
void AppendControl(wxCommandEvent& event);
|
||||
void OnRangeSlide(wxScrollEvent&);
|
||||
void OnRangeSpin(wxSpinEvent&);
|
||||
void OnRangeThumbtrack(wxScrollEvent&);
|
||||
|
||||
bool GetExpressionForSelectedControl(wxString& expr);
|
||||
|
||||
@ -143,7 +138,8 @@ private:
|
||||
wxComboBox* device_cbox;
|
||||
wxTextCtrl* textctrl;
|
||||
wxListBox* control_lbox;
|
||||
wxSlider* range_slider;
|
||||
DolphinSlider* m_range_slider;
|
||||
wxSpinCtrl* m_range_spinner;
|
||||
wxStaticText* m_bound_label;
|
||||
wxStaticText* m_error_label;
|
||||
InputEventFilter m_event_filter;
|
||||
@ -165,10 +161,15 @@ class ControlButton : public wxButton
|
||||
{
|
||||
public:
|
||||
ControlButton(wxWindow* const parent, ControllerInterface::ControlReference* const _ref,
|
||||
const std::string& name, const unsigned int width, const std::string& label = "");
|
||||
const std::string& name, const unsigned int width, const std::string& label = {});
|
||||
|
||||
ControllerInterface::ControlReference* const control_reference;
|
||||
const std::string m_name;
|
||||
|
||||
protected:
|
||||
wxSize DoGetBestSize() const override;
|
||||
|
||||
int m_configured_width = wxDefaultCoord;
|
||||
};
|
||||
|
||||
class ControlGroupBox : public wxBoxSizer
|
||||
@ -178,11 +179,18 @@ public:
|
||||
GamepadPage* const eventsink);
|
||||
~ControlGroupBox();
|
||||
|
||||
bool HasBitmapHeading() const
|
||||
{
|
||||
return control_group->type == GROUP_TYPE_STICK || control_group->type == GROUP_TYPE_TILT ||
|
||||
control_group->type == GROUP_TYPE_CURSOR || control_group->type == GROUP_TYPE_FORCE;
|
||||
}
|
||||
|
||||
std::vector<PadSetting*> options;
|
||||
|
||||
ControllerEmu::ControlGroup* const control_group;
|
||||
wxStaticBitmap* static_bitmap;
|
||||
std::vector<ControlButton*> control_buttons;
|
||||
double m_scale;
|
||||
};
|
||||
|
||||
class ControlGroupsSizer : public wxBoxSizer
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <cstring>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@ -11,8 +13,10 @@
|
||||
#include <wx/colour.h>
|
||||
#include <wx/dcmemory.h>
|
||||
#include <wx/font.h>
|
||||
#include <wx/graphics.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/pen.h>
|
||||
#include <wx/settings.h>
|
||||
#include <wx/statbmp.h>
|
||||
|
||||
#include "DolphinWX/InputConfigDiag.h"
|
||||
@ -36,69 +40,64 @@ struct ShapePosition
|
||||
};
|
||||
|
||||
// regular octagon
|
||||
static void DrawOctagon(wxDC* dc, ShapePosition p)
|
||||
static void DrawOctagon(wxGraphicsContext* gc, ShapePosition p)
|
||||
{
|
||||
const int vertices = 8;
|
||||
static constexpr int vertices = 8;
|
||||
double radius = p.max;
|
||||
|
||||
wxPoint point[vertices];
|
||||
wxGraphicsPath path = gc->CreatePath();
|
||||
|
||||
double angle = 2.0 * M_PI / vertices;
|
||||
|
||||
for (int i = 0; i < vertices; i++)
|
||||
{
|
||||
double a = (angle * i);
|
||||
double a = angle * i;
|
||||
double x = radius * cos(a);
|
||||
double y = radius * sin(a);
|
||||
point[i].x = x;
|
||||
point[i].y = y;
|
||||
if (i == 0)
|
||||
path.MoveToPoint(x, y);
|
||||
else
|
||||
path.AddLineToPoint(x, y);
|
||||
}
|
||||
path.CloseSubpath();
|
||||
|
||||
dc->DrawPolygon(vertices, point, p.offset, p.offset);
|
||||
wxGraphicsMatrix matrix = gc->CreateMatrix();
|
||||
matrix.Translate(p.offset, p.offset);
|
||||
path.Transform(matrix);
|
||||
|
||||
gc->DrawPath(path);
|
||||
}
|
||||
|
||||
// irregular dodecagon
|
||||
static void DrawDodecagon(wxDC* dc, ShapePosition p)
|
||||
static void DrawDodecagon(wxGraphicsContext* gc, ShapePosition p)
|
||||
{
|
||||
const int vertices = 12;
|
||||
wxGraphicsPath path = gc->CreatePath();
|
||||
path.MoveToPoint(p.dz, p.max);
|
||||
path.AddLineToPoint(p.diag, p.diag);
|
||||
path.AddLineToPoint(p.max, p.dz);
|
||||
path.AddLineToPoint(p.max, -p.dz);
|
||||
path.AddLineToPoint(p.diag, -p.diag);
|
||||
path.AddLineToPoint(p.dz, -p.max);
|
||||
path.AddLineToPoint(-p.dz, -p.max);
|
||||
path.AddLineToPoint(-p.diag, -p.diag);
|
||||
path.AddLineToPoint(-p.max, -p.dz);
|
||||
path.AddLineToPoint(-p.max, p.dz);
|
||||
path.AddLineToPoint(-p.diag, p.diag);
|
||||
path.AddLineToPoint(-p.dz, p.max);
|
||||
path.CloseSubpath();
|
||||
|
||||
wxPoint point[vertices];
|
||||
point[0].x = p.dz;
|
||||
point[0].y = p.max;
|
||||
point[1].x = p.diag;
|
||||
point[1].y = p.diag;
|
||||
point[2].x = p.max;
|
||||
point[2].y = p.dz;
|
||||
wxGraphicsMatrix matrix = gc->CreateMatrix();
|
||||
matrix.Translate(p.offset, p.offset);
|
||||
path.Transform(matrix);
|
||||
|
||||
point[3].x = p.max;
|
||||
point[3].y = -p.dz;
|
||||
point[4].x = p.diag;
|
||||
point[4].y = -p.diag;
|
||||
point[5].x = p.dz;
|
||||
point[5].y = -p.max;
|
||||
|
||||
point[6].x = -p.dz;
|
||||
point[6].y = -p.max;
|
||||
point[7].x = -p.diag;
|
||||
point[7].y = -p.diag;
|
||||
point[8].x = -p.max;
|
||||
point[8].y = -p.dz;
|
||||
|
||||
point[9].x = -p.max;
|
||||
point[9].y = p.dz;
|
||||
point[10].x = -p.diag;
|
||||
point[10].y = p.diag;
|
||||
point[11].x = -p.dz;
|
||||
point[11].y = p.max;
|
||||
|
||||
dc->DrawPolygon(vertices, point, p.offset, p.offset);
|
||||
gc->DrawPath(path);
|
||||
}
|
||||
|
||||
static void DrawCenteredRectangle(wxDC& dc, int x, int y, int w, int h)
|
||||
static void DrawCenteredRectangle(wxGraphicsContext* gc, double x, double y, double w, double h)
|
||||
{
|
||||
x -= w / 2;
|
||||
y -= h / 2;
|
||||
dc.DrawRectangle(x, y, w, h);
|
||||
gc->DrawRectangle(x, y, w, h);
|
||||
}
|
||||
|
||||
#define VIS_BITMAP_SIZE 64
|
||||
@ -108,37 +107,47 @@ static void DrawCenteredRectangle(wxDC& dc, int x, int y, int w, int h)
|
||||
|
||||
#define COORD_VIS_SIZE 4
|
||||
|
||||
static void DrawCoordinate(wxDC& dc, ControlState x, ControlState y)
|
||||
static void DrawCoordinate(wxGraphicsContext* gc, ControlState x, ControlState y)
|
||||
{
|
||||
int xc = VIS_COORD(x);
|
||||
int yc = VIS_COORD(y);
|
||||
DrawCenteredRectangle(dc, xc, yc, COORD_VIS_SIZE, COORD_VIS_SIZE);
|
||||
double xc = VIS_COORD(x);
|
||||
double yc = VIS_COORD(y);
|
||||
DrawCenteredRectangle(gc, xc, yc, COORD_VIS_SIZE, COORD_VIS_SIZE);
|
||||
}
|
||||
|
||||
static void DrawButton(unsigned int* const bitmasks, unsigned int buttons, unsigned int n, wxDC& dc,
|
||||
ControlGroupBox* g, unsigned int row)
|
||||
static void DrawButton(const std::vector<unsigned int>& bitmasks, unsigned int buttons,
|
||||
unsigned int n, wxGraphicsContext* gc, ControlGroupBox* g, unsigned int row,
|
||||
const wxGraphicsMatrix& null_matrix)
|
||||
{
|
||||
if (buttons & bitmasks[(row * 8) + n])
|
||||
{
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
gc->SetBrush(*wxRED_BRUSH);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto lock = ControllerEmu::GetStateLock();
|
||||
unsigned char amt = 255 - g->control_group->controls[(row * 8) + n]->control_ref->State() * 128;
|
||||
dc.SetBrush(wxBrush(wxColour(amt, amt, amt)));
|
||||
gc->SetBrush(wxBrush(wxColour(amt, amt, amt)));
|
||||
}
|
||||
dc.DrawRectangle(n * 12, (row == 0) ? 0 : (row * 11), 14, 12);
|
||||
gc->DrawRectangle(n * 12, (row == 0) ? 0 : (row * 11), 14, 12);
|
||||
|
||||
// text
|
||||
const std::string name = g->control_group->controls[(row * 8) + n]->name;
|
||||
// Matrix transformation needs to be disabled so we don't draw scaled/zoomed text.
|
||||
wxGraphicsMatrix old_matrix = gc->GetTransform();
|
||||
gc->SetTransform(null_matrix);
|
||||
// bit of hax so ZL, ZR show up as L, R
|
||||
dc.DrawText(StrToWxStr(std::string(1, (name[1] && name[1] < 'a') ? name[1] : name[0])),
|
||||
n * 12 + 2, 1 + ((row == 0) ? 0 : (row * 11)));
|
||||
gc->DrawText(wxUniChar((name[1] && name[1] < 'a') ? name[1] : name[0]), (n * 12 + 2) * g->m_scale,
|
||||
(1 + (row == 0 ? 0 : row * 11)) * g->m_scale);
|
||||
gc->SetTransform(old_matrix);
|
||||
}
|
||||
|
||||
static void DrawControlGroupBox(wxDC& dc, ControlGroupBox* g)
|
||||
static void DrawControlGroupBox(wxGraphicsContext* gc, ControlGroupBox* g)
|
||||
{
|
||||
wxGraphicsMatrix null_matrix = gc->GetTransform();
|
||||
wxGraphicsMatrix scale_matrix = null_matrix;
|
||||
scale_matrix.Scale(g->m_scale, g->m_scale);
|
||||
|
||||
gc->SetTransform(scale_matrix);
|
||||
|
||||
switch (g->control_group->type)
|
||||
{
|
||||
case GROUP_TYPE_TILT:
|
||||
@ -165,29 +174,17 @@ static void DrawControlGroupBox(wxDC& dc, ControlGroupBox* g)
|
||||
// ir cursor forward movement
|
||||
if (GROUP_TYPE_CURSOR == g->control_group->type)
|
||||
{
|
||||
if (z)
|
||||
{
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
dc.SetBrush(*wxGREY_BRUSH);
|
||||
}
|
||||
dc.DrawRectangle(0, 31 - z * 31, 64, 2);
|
||||
gc->SetBrush(z ? *wxRED_BRUSH : *wxGREY_BRUSH);
|
||||
wxGraphicsPath path = gc->CreatePath();
|
||||
path.AddRectangle(0, 31 - z * 31, 64, 2);
|
||||
gc->FillPath(path);
|
||||
}
|
||||
|
||||
// input zone
|
||||
dc.SetPen(*wxLIGHT_GREY_PEN);
|
||||
dc.SetBrush(*wxWHITE_BRUSH);
|
||||
gc->SetPen(*wxLIGHT_GREY_PEN);
|
||||
if (GROUP_TYPE_STICK == g->control_group->type)
|
||||
{
|
||||
// outline and fill colors
|
||||
wxBrush LightGrayBrush("#dddddd");
|
||||
wxPen LightGrayPen("#bfbfbf");
|
||||
dc.SetBrush(LightGrayBrush);
|
||||
dc.SetPen(LightGrayPen);
|
||||
gc->SetBrush(wxColour(0xDDDDDD)); // Light Gray
|
||||
|
||||
ShapePosition p;
|
||||
p.box = 64;
|
||||
@ -215,20 +212,25 @@ static void DrawControlGroupBox(wxDC& dc, ControlGroupBox* g)
|
||||
}
|
||||
|
||||
if (octagon)
|
||||
DrawOctagon(&dc, p);
|
||||
DrawOctagon(gc, p);
|
||||
else
|
||||
DrawDodecagon(&dc, p);
|
||||
DrawDodecagon(gc, p);
|
||||
}
|
||||
else
|
||||
{
|
||||
dc.DrawRectangle(16, 16, 32, 32);
|
||||
gc->SetBrush(*wxWHITE_BRUSH);
|
||||
gc->DrawRectangle(16, 16, 32, 32);
|
||||
}
|
||||
|
||||
if (GROUP_TYPE_CURSOR != g->control_group->type)
|
||||
{
|
||||
// deadzone circle
|
||||
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
dc.DrawCircle(32, 32, g->control_group->numeric_settings[SETTING_DEADZONE]->GetValue() * 32);
|
||||
int deadzone_idx = g->control_group->type == GROUP_TYPE_STICK ? SETTING_DEADZONE : 0;
|
||||
wxGraphicsPath path = gc->CreatePath();
|
||||
path.AddCircle(VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE / 2,
|
||||
g->control_group->numeric_settings[deadzone_idx]->GetValue() *
|
||||
VIS_BITMAP_SIZE / 2);
|
||||
gc->SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
gc->FillPath(path);
|
||||
}
|
||||
|
||||
// raw dot
|
||||
@ -238,21 +240,21 @@ static void DrawControlGroupBox(wxDC& dc, ControlGroupBox* g)
|
||||
yy = g->control_group->controls[1]->control_ref->State();
|
||||
yy -= g->control_group->controls[0]->control_ref->State();
|
||||
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
dc.SetBrush(*wxGREY_BRUSH);
|
||||
DrawCoordinate(dc, xx, yy);
|
||||
gc->SetPen(*wxTRANSPARENT_PEN);
|
||||
gc->SetBrush(*wxGREY_BRUSH);
|
||||
DrawCoordinate(gc, xx, yy);
|
||||
|
||||
// adjusted dot
|
||||
if (x != 0 || y != 0)
|
||||
{
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
gc->SetBrush(*wxRED_BRUSH);
|
||||
// XXX: The adjusted values flip the Y axis to be in the format
|
||||
// the Wii expects. Should this be in WiimoteEmu.cpp instead?
|
||||
DrawCoordinate(dc, x, -y);
|
||||
DrawCoordinate(gc, x, -y);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GROUP_TYPE_FORCE:
|
||||
{
|
||||
ControlState raw_dot[3];
|
||||
@ -270,69 +272,67 @@ static void DrawControlGroupBox(wxDC& dc, ControlGroupBox* g)
|
||||
}
|
||||
|
||||
// deadzone rect for forward/backward visual
|
||||
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
dc.SetPen(*wxLIGHT_GREY_PEN);
|
||||
gc->SetPen(*wxTRANSPARENT_PEN);
|
||||
gc->SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
int deadzone_height = deadzone * VIS_BITMAP_SIZE;
|
||||
DrawCenteredRectangle(dc, 0, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE, deadzone_height);
|
||||
DrawCenteredRectangle(gc, 0, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE, deadzone_height);
|
||||
|
||||
#define LINE_HEIGHT 2
|
||||
int line_y;
|
||||
|
||||
// raw forward/background line
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
dc.SetBrush(*wxGREY_BRUSH);
|
||||
gc->SetBrush(*wxGREY_BRUSH);
|
||||
line_y = VIS_COORD(raw_dot[2]);
|
||||
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, line_y, VIS_BITMAP_SIZE, LINE_HEIGHT);
|
||||
DrawCenteredRectangle(gc, VIS_BITMAP_SIZE / 2, line_y, VIS_BITMAP_SIZE, LINE_HEIGHT);
|
||||
|
||||
// adjusted forward/background line
|
||||
if (adj_dot[2] != 0.0)
|
||||
{
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
gc->SetBrush(*wxRED_BRUSH);
|
||||
line_y = VIS_COORD(adj_dot[2]);
|
||||
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, line_y, VIS_BITMAP_SIZE, LINE_HEIGHT);
|
||||
DrawCenteredRectangle(gc, VIS_BITMAP_SIZE / 2, line_y, VIS_BITMAP_SIZE, LINE_HEIGHT);
|
||||
}
|
||||
|
||||
#define DEADZONE_RECT_SIZE 32
|
||||
|
||||
// empty deadzone square
|
||||
dc.SetBrush(*wxWHITE_BRUSH);
|
||||
dc.SetPen(*wxLIGHT_GREY_PEN);
|
||||
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE / 2, DEADZONE_RECT_SIZE,
|
||||
gc->SetPen(*wxLIGHT_GREY_PEN);
|
||||
gc->SetBrush(*wxWHITE_BRUSH);
|
||||
DrawCenteredRectangle(gc, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE / 2, DEADZONE_RECT_SIZE,
|
||||
DEADZONE_RECT_SIZE);
|
||||
|
||||
// deadzone square
|
||||
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
gc->SetPen(*wxTRANSPARENT_PEN);
|
||||
gc->SetBrush(*wxLIGHT_GREY_BRUSH);
|
||||
int dz_size = (deadzone * DEADZONE_RECT_SIZE);
|
||||
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE / 2, dz_size, dz_size);
|
||||
DrawCenteredRectangle(gc, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE / 2, dz_size, dz_size);
|
||||
|
||||
// raw dot
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
dc.SetBrush(*wxGREY_BRUSH);
|
||||
DrawCoordinate(dc, raw_dot[1], raw_dot[0]);
|
||||
gc->SetBrush(*wxGREY_BRUSH);
|
||||
DrawCoordinate(gc, raw_dot[1], raw_dot[0]);
|
||||
|
||||
// adjusted dot
|
||||
if (adj_dot[1] != 0 && adj_dot[0] != 0)
|
||||
{
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
DrawCoordinate(dc, adj_dot[1], adj_dot[0]);
|
||||
gc->SetBrush(*wxRED_BRUSH);
|
||||
DrawCoordinate(gc, adj_dot[1], adj_dot[0]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GROUP_TYPE_BUTTONS:
|
||||
{
|
||||
unsigned int button_count = ((unsigned int)g->control_group->controls.size());
|
||||
const unsigned int button_count = static_cast<unsigned int>(g->control_group->controls.size());
|
||||
std::vector<unsigned int> bitmasks(button_count);
|
||||
|
||||
// draw the shit
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
gc->SetPen(*wxGREY_PEN);
|
||||
|
||||
unsigned int* const bitmasks = new unsigned int[button_count];
|
||||
for (unsigned int n = 0; n < button_count; ++n)
|
||||
bitmasks[n] = (1 << n);
|
||||
|
||||
unsigned int buttons = 0;
|
||||
((ControllerEmu::Buttons*)g->control_group)->GetState(&buttons, bitmasks);
|
||||
((ControllerEmu::Buttons*)g->control_group)->GetState(&buttons, bitmasks.data());
|
||||
|
||||
// Draw buttons in rows of 8
|
||||
for (unsigned int row = 0; row < ceil((float)button_count / 8.0f); row++)
|
||||
@ -343,155 +343,200 @@ static void DrawControlGroupBox(wxDC& dc, ControlGroupBox* g)
|
||||
|
||||
for (unsigned int n = 0; n < buttons_to_draw; ++n)
|
||||
{
|
||||
DrawButton(bitmasks, buttons, n, dc, g, row);
|
||||
DrawButton(bitmasks, buttons, n, gc, g, row, null_matrix);
|
||||
}
|
||||
}
|
||||
|
||||
delete[] bitmasks;
|
||||
}
|
||||
break;
|
||||
|
||||
case GROUP_TYPE_TRIGGERS:
|
||||
{
|
||||
const unsigned int trigger_count = ((unsigned int)(g->control_group->controls.size()));
|
||||
const unsigned int trigger_count = static_cast<unsigned int>(g->control_group->controls.size());
|
||||
std::vector<ControlState> trigs(trigger_count);
|
||||
|
||||
// draw the shit
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
ControlState deadzone = g->control_group->numeric_settings[0]->GetValue();
|
||||
gc->SetPen(*wxGREY_PEN);
|
||||
|
||||
ControlState* const trigs = new ControlState[trigger_count];
|
||||
((ControllerEmu::Triggers*)g->control_group)->GetState(trigs);
|
||||
ControlState deadzone = g->control_group->numeric_settings[0]->GetValue();
|
||||
((ControllerEmu::Triggers*)g->control_group)->GetState(trigs.data());
|
||||
|
||||
for (unsigned int n = 0; n < trigger_count; ++n)
|
||||
{
|
||||
ControlState trig_r = g->control_group->controls[n]->control_ref->State();
|
||||
|
||||
// outline
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
dc.SetBrush(*wxWHITE_BRUSH);
|
||||
dc.DrawRectangle(0, n * 12, 64, 14);
|
||||
gc->SetBrush(*wxWHITE_BRUSH);
|
||||
gc->DrawRectangle(0, n * 12, 64, 14);
|
||||
|
||||
// raw
|
||||
dc.SetBrush(*wxGREY_BRUSH);
|
||||
dc.DrawRectangle(0, n * 12, trig_r * 64, 14);
|
||||
gc->SetBrush(*wxGREY_BRUSH);
|
||||
gc->DrawRectangle(0, n * 12, trig_r * 64, 14);
|
||||
|
||||
// deadzone affected
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
dc.DrawRectangle(0, n * 12, trigs[n] * 64, 14);
|
||||
gc->SetBrush(*wxRED_BRUSH);
|
||||
gc->DrawRectangle(0, n * 12, trigs[n] * 64, 14);
|
||||
|
||||
// text
|
||||
dc.DrawText(StrToWxStr(g->control_group->controls[n]->name), 3, n * 12 + 1);
|
||||
// We don't want the text to be scaled/zoomed
|
||||
gc->SetTransform(null_matrix);
|
||||
gc->DrawText(StrToWxStr(g->control_group->controls[n]->name), 3 * g->m_scale,
|
||||
(n * 12 + 1) * g->m_scale);
|
||||
gc->SetTransform(scale_matrix);
|
||||
}
|
||||
|
||||
delete[] trigs;
|
||||
|
||||
// deadzone box
|
||||
dc.SetPen(*wxLIGHT_GREY_PEN);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(0, 0, deadzone * 64, trigger_count * 14);
|
||||
gc->SetPen(*wxLIGHT_GREY_PEN);
|
||||
gc->SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
gc->DrawRectangle(0, 0, deadzone * 64, trigger_count * 14);
|
||||
}
|
||||
break;
|
||||
|
||||
case GROUP_TYPE_MIXED_TRIGGERS:
|
||||
{
|
||||
const unsigned int trigger_count = ((unsigned int)(g->control_group->controls.size() / 2));
|
||||
|
||||
// draw the shit
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
gc->SetPen(*wxGREY_PEN);
|
||||
ControlState thresh = g->control_group->numeric_settings[0]->GetValue();
|
||||
|
||||
for (unsigned int n = 0; n < trigger_count; ++n)
|
||||
{
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
gc->SetBrush(*wxRED_BRUSH);
|
||||
|
||||
ControlState trig_d = g->control_group->controls[n]->control_ref->State();
|
||||
|
||||
ControlState trig_a =
|
||||
trig_d > thresh ? 1 : g->control_group->controls[n + trigger_count]->control_ref->State();
|
||||
|
||||
dc.DrawRectangle(0, n * 12, 64 + 20, 14);
|
||||
gc->DrawRectangle(0, n * 12, 64 + 20, 14);
|
||||
if (trig_d <= thresh)
|
||||
dc.SetBrush(*wxWHITE_BRUSH);
|
||||
dc.DrawRectangle(trig_a * 64, n * 12, 64 + 20, 14);
|
||||
dc.DrawRectangle(64, n * 12, 32, 14);
|
||||
gc->SetBrush(*wxWHITE_BRUSH);
|
||||
gc->DrawRectangle(trig_a * 64, n * 12, 64 + 20, 14);
|
||||
gc->DrawRectangle(64, n * 12, 32, 14);
|
||||
|
||||
// text
|
||||
dc.DrawText(StrToWxStr(g->control_group->controls[n + trigger_count]->name), 3, n * 12 + 1);
|
||||
dc.DrawText(StrToWxStr(std::string(1, g->control_group->controls[n]->name[0])), 64 + 3,
|
||||
n * 12 + 1);
|
||||
// We don't want the text to be scaled/zoomed
|
||||
gc->SetTransform(null_matrix);
|
||||
gc->DrawText(StrToWxStr(g->control_group->controls[n + trigger_count]->name), 3 * g->m_scale,
|
||||
(n * 12 + 1) * g->m_scale);
|
||||
gc->DrawText(StrToWxStr(std::string(1, g->control_group->controls[n]->name[0])),
|
||||
(64 + 3) * g->m_scale, (n * 12 + 1) * g->m_scale);
|
||||
gc->SetTransform(scale_matrix);
|
||||
}
|
||||
|
||||
// threshold box
|
||||
dc.SetPen(*wxLIGHT_GREY_PEN);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(thresh * 64, 0, 128, trigger_count * 14);
|
||||
gc->SetPen(*wxLIGHT_GREY_PEN);
|
||||
gc->SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
gc->DrawRectangle(thresh * 64, 0, 128, trigger_count * 14);
|
||||
}
|
||||
break;
|
||||
|
||||
case GROUP_TYPE_SLIDER:
|
||||
{
|
||||
const ControlState deadzone = g->control_group->numeric_settings[0]->GetValue();
|
||||
|
||||
ControlState state = g->control_group->controls[1]->control_ref->State() -
|
||||
g->control_group->controls[0]->control_ref->State();
|
||||
dc.SetPen(*wxGREY_PEN);
|
||||
dc.SetBrush(*wxGREY_BRUSH);
|
||||
dc.DrawRectangle(31 + state * 30, 0, 2, 14);
|
||||
gc->SetPen(*wxTRANSPARENT_PEN);
|
||||
gc->SetBrush(*wxGREY_BRUSH);
|
||||
gc->DrawRectangle(31 + state * 30, 0, 2, 14);
|
||||
|
||||
ControlState adj_state;
|
||||
((ControllerEmu::Slider*)g->control_group)->GetState(&adj_state);
|
||||
if (state)
|
||||
{
|
||||
dc.SetPen(*wxRED_PEN);
|
||||
dc.SetBrush(*wxRED_BRUSH);
|
||||
dc.DrawRectangle(31 + adj_state * 30, 0, 2, 14);
|
||||
gc->SetBrush(*wxRED_BRUSH);
|
||||
gc->DrawRectangle(31 + adj_state * 30, 0, 2, 14);
|
||||
}
|
||||
|
||||
// deadzone box
|
||||
dc.SetPen(*wxLIGHT_GREY_PEN);
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(32 - deadzone * 32, 0, deadzone * 64, 14);
|
||||
gc->SetPen(*wxLIGHT_GREY_PEN);
|
||||
gc->SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
gc->DrawRectangle(32 - deadzone * 32, 0, deadzone * 64, 14);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
gc->SetTransform(null_matrix);
|
||||
}
|
||||
|
||||
static void DrawBorder(wxGraphicsContext* gc, double scale)
|
||||
{
|
||||
double pen_width = std::round(scale); // Pen width = 1px * scale
|
||||
|
||||
// Use the window caption bar color as a safe accent color.
|
||||
wxPen border_pen(wxSystemSettings::GetColour(wxSYS_COLOUR_ACTIVECAPTION),
|
||||
static_cast<int>(pen_width));
|
||||
border_pen.SetCap(wxCAP_PROJECTING);
|
||||
|
||||
double width, height;
|
||||
gc->GetSize(&width, &height);
|
||||
|
||||
wxGraphicsPath path = gc->CreatePath();
|
||||
path.AddRectangle(pen_width / 2, pen_width / 2, width - pen_width, height - pen_width);
|
||||
gc->SetPen(border_pen);
|
||||
gc->StrokePath(path);
|
||||
}
|
||||
|
||||
void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
|
||||
{
|
||||
wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
|
||||
const wxColour font_color{0xB8B8B8};
|
||||
|
||||
g_controller_interface.UpdateInput();
|
||||
|
||||
GamepadPage* const current_page =
|
||||
(GamepadPage*)m_pad_notebook->GetPage(m_pad_notebook->GetSelection());
|
||||
static_cast<GamepadPage*>(m_pad_notebook->GetPage(m_pad_notebook->GetSelection()));
|
||||
|
||||
wxMemoryDC dc;
|
||||
auto lock = ControllerEmu::GetStateLock();
|
||||
for (ControlGroupBox* g : current_page->control_groups)
|
||||
{
|
||||
// if this control group has a bitmap
|
||||
if (g->static_bitmap)
|
||||
// Only if this control group has a bitmap
|
||||
if (!g->static_bitmap)
|
||||
continue;
|
||||
|
||||
wxBitmap bitmap(g->static_bitmap->GetBitmap());
|
||||
// NOTE: Selecting the bitmap inherits the bitmap's ScaleFactor onto the DC as well.
|
||||
dc.SelectObject(bitmap);
|
||||
dc.SetBackground(*wxWHITE_BRUSH);
|
||||
dc.Clear();
|
||||
|
||||
#ifdef __WXGTK20__
|
||||
int dc_height = 0;
|
||||
dc.SetFont(small_font);
|
||||
dc.GetTextExtent(g->control_group->name, nullptr, &dc_height);
|
||||
#endif
|
||||
|
||||
std::unique_ptr<wxGraphicsContext> gc{wxGraphicsContext::Create(dc)};
|
||||
gc->DisableOffset();
|
||||
gc->SetFont(small_font, font_color);
|
||||
|
||||
#ifdef __WXGTK20__
|
||||
double gc_height = 0;
|
||||
gc->GetTextExtent(g->control_group->name, nullptr, &gc_height);
|
||||
// On GTK2, wx creates a new empty Cairo/Pango context for the graphics context instead
|
||||
// of reusing the wxMemoryDC one, this causes it to forget the screen DPI so fonts stop
|
||||
// scaling, we need to scale it manually instead.
|
||||
if (std::ceil(gc_height) < dc_height)
|
||||
{
|
||||
wxMemoryDC dc;
|
||||
wxBitmap bitmap(g->static_bitmap->GetBitmap());
|
||||
dc.SelectObject(bitmap);
|
||||
dc.Clear();
|
||||
|
||||
dc.SetFont(small_font);
|
||||
dc.SetTextForeground(0xC0C0C0);
|
||||
|
||||
DrawControlGroupBox(dc, g);
|
||||
|
||||
// box outline
|
||||
// Windows XP color
|
||||
dc.SetPen(wxPen("#7f9db9"));
|
||||
dc.SetBrush(*wxTRANSPARENT_BRUSH);
|
||||
dc.DrawRectangle(0, 0, bitmap.GetWidth(), bitmap.GetHeight());
|
||||
|
||||
// label for sticks and stuff
|
||||
if (64 == bitmap.GetHeight())
|
||||
dc.DrawText(StrToWxStr(g->control_group->name).Upper(), 4, 2);
|
||||
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
g->static_bitmap->SetBitmap(bitmap);
|
||||
wxFont fixed_font(small_font);
|
||||
fixed_font.SetPointSize(static_cast<int>(fixed_font.GetPointSize() * g->m_scale));
|
||||
gc->SetFont(fixed_font, font_color);
|
||||
}
|
||||
#endif
|
||||
|
||||
DrawControlGroupBox(gc.get(), g);
|
||||
DrawBorder(gc.get(), g->m_scale);
|
||||
|
||||
// label for sticks and stuff
|
||||
if (g->HasBitmapHeading())
|
||||
gc->DrawText(StrToWxStr(g->control_group->name).Upper(), 4 * g->m_scale, 2 * g->m_scale);
|
||||
|
||||
gc.reset();
|
||||
dc.SelectObject(wxNullBitmap);
|
||||
g->static_bitmap->SetBitmap(bitmap);
|
||||
}
|
||||
}
|
||||
|
@ -25,18 +25,11 @@ LogConfigWindow::LogConfigWindow(wxWindow* parent, wxWindowID id)
|
||||
_("Log Configuration")),
|
||||
enableAll(true)
|
||||
{
|
||||
Bind(wxEVT_CLOSE_WINDOW, &LogConfigWindow::OnClose, this);
|
||||
SetMinSize(wxSize(100, 100));
|
||||
m_LogManager = LogManager::GetInstance();
|
||||
CreateGUIControls();
|
||||
LoadSettings();
|
||||
}
|
||||
|
||||
void LogConfigWindow::OnClose(wxCloseEvent& event)
|
||||
{
|
||||
SaveSettings();
|
||||
}
|
||||
|
||||
void LogConfigWindow::CreateGUIControls()
|
||||
{
|
||||
// Verbosity
|
||||
@ -68,23 +61,26 @@ void LogConfigWindow::CreateGUIControls()
|
||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; i++)
|
||||
m_checks->Append(StrToWxStr(m_LogManager->GetFullName((LogTypes::LOG_TYPE)i)));
|
||||
|
||||
const int space1 = FromDIP(1);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// Sizers
|
||||
wxStaticBoxSizer* sbOutputs = new wxStaticBoxSizer(wxVERTICAL, this, _("Logger Outputs"));
|
||||
sbOutputs->Add(m_writeFileCB, 0, wxDOWN, 1);
|
||||
sbOutputs->Add(m_writeConsoleCB, 0, wxDOWN, 1);
|
||||
sbOutputs->Add(m_writeWindowCB, 0);
|
||||
sbOutputs->Add(m_writeFileCB, 0);
|
||||
sbOutputs->Add(m_writeConsoleCB, 0, wxTOP, space1);
|
||||
sbOutputs->Add(m_writeWindowCB, 0, wxTOP, space1);
|
||||
|
||||
wxStaticBoxSizer* sbLogTypes = new wxStaticBoxSizer(wxVERTICAL, this, _("Log Types"));
|
||||
sbLogTypes->Add(m_checks, 1, wxEXPAND);
|
||||
|
||||
wxBoxSizer* sMain = new wxBoxSizer(wxVERTICAL);
|
||||
sMain->Add(m_verbosity, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
sMain->Add(sbOutputs, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
sMain->Add(btn_toggle_all, 0, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
sMain->Add(sbLogTypes, 1, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
sMain->Add(m_verbosity, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->Add(sbOutputs, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->Add(btn_toggle_all, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMain->Add(sbLogTypes, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
|
||||
SetSizer(sMain);
|
||||
Layout();
|
||||
sMain->SetMinSize(FromDIP(wxSize(100, 100)));
|
||||
SetSizerAndFit(sMain);
|
||||
}
|
||||
|
||||
void LogConfigWindow::LoadSettings()
|
||||
|
@ -31,7 +31,6 @@ private:
|
||||
|
||||
void CreateGUIControls();
|
||||
void OnVerbosityChange(wxCommandEvent& event);
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnWriteFileChecked(wxCommandEvent& event);
|
||||
void OnWriteConsoleChecked(wxCommandEvent& event);
|
||||
void OnWriteWindowChecked(wxCommandEvent& event);
|
||||
|
@ -39,7 +39,6 @@ CLogWindow::CLogWindow(CFrame* parent, wxWindowID id, const wxPoint& pos, const
|
||||
: wxPanel(parent, id, pos, size, style, name), x(0), y(0), winpos(0), Parent(parent),
|
||||
m_LogAccess(true), m_Log(nullptr), m_cmdline(nullptr), m_FontChoice(nullptr)
|
||||
{
|
||||
Bind(wxEVT_CLOSE_WINDOW, &CLogWindow::OnClose, this);
|
||||
Bind(wxEVT_TIMER, &CLogWindow::OnLogTimer, this);
|
||||
|
||||
m_LogManager = LogManager::GetInstance();
|
||||
@ -94,6 +93,7 @@ void CLogWindow::CreateGUIControls()
|
||||
|
||||
m_LogManager->SetLogLevel((LogTypes::LOG_TYPE)i, (LogTypes::LOG_LEVELS)(verbosity));
|
||||
}
|
||||
m_has_listeners = true;
|
||||
|
||||
// Font
|
||||
m_FontChoice = new wxChoice(this, wxID_ANY);
|
||||
@ -132,11 +132,13 @@ void CLogWindow::CreateGUIControls()
|
||||
new wxButton(this, wxID_ANY, _("Clear"), wxDefaultPosition, wxDefaultSize, wxBU_EXACTFIT);
|
||||
m_clear_log_btn->Bind(wxEVT_BUTTON, &CLogWindow::OnClear, this);
|
||||
|
||||
const int space3 = FromDIP(3);
|
||||
|
||||
// Sizers
|
||||
wxBoxSizer* sTop = new wxBoxSizer(wxHORIZONTAL);
|
||||
sTop->Add(m_clear_log_btn);
|
||||
sTop->Add(m_FontChoice, 0, wxALIGN_CENTER_VERTICAL | wxLEFT | wxRIGHT, 3);
|
||||
sTop->Add(m_WrapLine, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sTop->Add(m_clear_log_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sTop->Add(m_FontChoice, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space3);
|
||||
sTop->Add(m_WrapLine, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space3);
|
||||
|
||||
sBottom = new wxBoxSizer(wxVERTICAL);
|
||||
PopulateBottom();
|
||||
@ -149,15 +151,17 @@ void CLogWindow::CreateGUIControls()
|
||||
m_cmdline->SetFocus();
|
||||
}
|
||||
|
||||
void CLogWindow::OnClose(wxCloseEvent& event)
|
||||
CLogWindow::~CLogWindow()
|
||||
{
|
||||
SaveSettings();
|
||||
event.Skip();
|
||||
RemoveAllListeners();
|
||||
}
|
||||
|
||||
void CLogWindow::RemoveAllListeners()
|
||||
{
|
||||
if (!m_has_listeners)
|
||||
return;
|
||||
m_has_listeners = false;
|
||||
|
||||
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
|
||||
{
|
||||
m_LogManager->RemoveListener(static_cast<LogTypes::LOG_TYPE>(i),
|
||||
|
@ -28,7 +28,11 @@ public:
|
||||
CLogWindow(CFrame* parent, wxWindowID id = wxID_ANY, const wxPoint& pos = wxDefaultPosition,
|
||||
const wxSize& size = wxDefaultSize, long style = wxTAB_TRAVERSAL,
|
||||
const wxString& name = _("Log"));
|
||||
~CLogWindow() override;
|
||||
|
||||
// Listeners must be removed explicitly before the window is closed to prevent crashes on OS X
|
||||
// when closing via the Dock. (The Core is probably being shutdown before the window)
|
||||
void RemoveAllListeners();
|
||||
void SaveSettings();
|
||||
void Log(LogTypes::LOG_LEVELS, const char* text) override;
|
||||
|
||||
@ -42,6 +46,7 @@ private:
|
||||
LogManager* m_LogManager;
|
||||
std::queue<std::pair<u8, wxString>> msgQueue;
|
||||
bool m_writeFile, m_writeWindow, m_LogAccess;
|
||||
bool m_has_listeners = false;
|
||||
|
||||
// Controls
|
||||
wxBoxSizer* sBottom;
|
||||
@ -57,11 +62,9 @@ private:
|
||||
void CreateGUIControls();
|
||||
void PopulateBottom();
|
||||
void UnPopulateBottom();
|
||||
void OnClose(wxCloseEvent& event);
|
||||
void OnFontChange(wxCommandEvent& event);
|
||||
void OnWrapLineCheck(wxCommandEvent& event);
|
||||
void OnClear(wxCommandEvent& event);
|
||||
void OnLogTimer(wxTimerEvent& WXUNUSED(event));
|
||||
void RemoveAllListeners();
|
||||
void UpdateLog();
|
||||
};
|
||||
|
@ -53,25 +53,6 @@
|
||||
#include <X11/Xlib.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef SM_XVIRTUALSCREEN
|
||||
#define SM_XVIRTUALSCREEN 76
|
||||
#endif
|
||||
#ifndef SM_YVIRTUALSCREEN
|
||||
#define SM_YVIRTUALSCREEN 77
|
||||
#endif
|
||||
#ifndef SM_CXVIRTUALSCREEN
|
||||
#define SM_CXVIRTUALSCREEN 78
|
||||
#endif
|
||||
#ifndef SM_CYVIRTUALSCREEN
|
||||
#define SM_CYVIRTUALSCREEN 79
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
class wxFrame;
|
||||
|
||||
// ------------
|
||||
// Main window
|
||||
|
||||
@ -130,31 +111,14 @@ bool DolphinApp::OnInit()
|
||||
// Enable the PNG image handler for screenshots
|
||||
wxImage::AddHandler(new wxPNGHandler);
|
||||
|
||||
int x = SConfig::GetInstance().iPosX;
|
||||
int y = SConfig::GetInstance().iPosY;
|
||||
int w = SConfig::GetInstance().iWidth;
|
||||
int h = SConfig::GetInstance().iHeight;
|
||||
|
||||
// The following is not needed with X11, where window managers
|
||||
// do not allow windows to be created off the desktop.
|
||||
#ifdef _WIN32
|
||||
// Out of desktop check
|
||||
int leftPos = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
int topPos = GetSystemMetrics(SM_YVIRTUALSCREEN);
|
||||
int width = GetSystemMetrics(SM_CXVIRTUALSCREEN);
|
||||
int height = GetSystemMetrics(SM_CYVIRTUALSCREEN);
|
||||
if ((leftPos + width) < (x + w) || leftPos > x || (topPos + height) < (y + h) || topPos > y)
|
||||
x = y = wxDefaultCoord;
|
||||
#elif defined __APPLE__
|
||||
if (y < 1)
|
||||
y = wxDefaultCoord;
|
||||
#endif
|
||||
|
||||
main_frame = new CFrame(nullptr, wxID_ANY, StrToWxStr(scm_rev_str), wxPoint(x, y), wxSize(w, h),
|
||||
// We have to copy the size and position out of SConfig now because CFrame's OnMove
|
||||
// handler will corrupt them during window creation (various APIs like SetMenuBar cause
|
||||
// event dispatch including WM_MOVE/WM_SIZE)
|
||||
wxRect window_geometry(SConfig::GetInstance().iPosX, SConfig::GetInstance().iPosY,
|
||||
SConfig::GetInstance().iWidth, SConfig::GetInstance().iHeight);
|
||||
main_frame = new CFrame(nullptr, wxID_ANY, StrToWxStr(scm_rev_str), window_geometry,
|
||||
m_use_debugger, m_batch_mode, m_use_logger);
|
||||
|
||||
SetTopWindow(main_frame);
|
||||
main_frame->SetMinSize(wxSize(400, 300));
|
||||
|
||||
AfterInit();
|
||||
|
||||
|
@ -17,7 +17,6 @@
|
||||
#include <wx/listbase.h>
|
||||
#include <wx/menu.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
@ -34,37 +33,24 @@
|
||||
#define FIRSTPAGE 0
|
||||
#define ARROWS slot ? "" : ARROW[slot], slot ? ARROW[slot] : ""
|
||||
|
||||
static wxBitmap wxBitmapFromMemoryRGBA(const unsigned char* data, u32 width, u32 height)
|
||||
static wxImage wxImageFromMemoryRGBA(const u32* data, u32 width, u32 height)
|
||||
{
|
||||
static const std::array<u8, 54> header = {
|
||||
{0x42, 0x4D, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
|
||||
0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // Width
|
||||
0x20, 0x00, 0x00, 0x00, // Height
|
||||
0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, // Data size
|
||||
0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00}};
|
||||
|
||||
u32 stride = (4 * width);
|
||||
|
||||
u32 bytes = (stride * height) + header.size();
|
||||
bytes = (bytes + 3) & ~3;
|
||||
|
||||
u32 data_length = bytes - header.size();
|
||||
|
||||
std::vector<u8> pdata(bytes);
|
||||
std::copy(header.begin(), header.end(), pdata.begin());
|
||||
|
||||
u8* const pixelData = &pdata[header.size()];
|
||||
|
||||
for (u32 y = 0; y < height; y++)
|
||||
std::memcpy(&pixelData[y * stride], &data[(height - y - 1) * stride], stride);
|
||||
|
||||
std::memcpy(&pdata[18], &width, sizeof(u32));
|
||||
std::memcpy(&pdata[22], &height, sizeof(u32));
|
||||
std::memcpy(&pdata[34], &data_length, sizeof(u32));
|
||||
|
||||
wxMemoryInputStream is(pdata.data(), bytes);
|
||||
return wxBitmap(wxImage(is, wxBITMAP_TYPE_BMP));
|
||||
wxImage image(width, height, false);
|
||||
image.InitAlpha();
|
||||
u8* rgb = image.GetData();
|
||||
u8* alpha = image.GetAlpha();
|
||||
for (u32 y = 0; y < height; ++y)
|
||||
{
|
||||
for (u32 x = 0; x < width; ++x)
|
||||
{
|
||||
u32 pixel = data[y * width + x];
|
||||
*rgb++ = (pixel & 0x00FF0000) >> 16; // Red
|
||||
*rgb++ = (pixel & 0x0000FF00) >> 8; // Green
|
||||
*rgb++ = (pixel & 0x000000FF) >> 0; // Blue
|
||||
*alpha++ = (pixel & 0xFF000000) >> 24;
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
BEGIN_EVENT_TABLE(CMemcardManager, wxDialog)
|
||||
@ -94,7 +80,8 @@ END_EVENT_TABLE()
|
||||
CMemcardManager::CMemcardManager(wxWindow* parent)
|
||||
: wxDialog(parent, wxID_ANY, _("Memory Card Manager"), wxDefaultPosition, wxDefaultSize,
|
||||
wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxCLOSE_BOX | wxRESIZE_BORDER |
|
||||
wxMAXIMIZE_BOX)
|
||||
wxMAXIMIZE_BOX),
|
||||
m_image_list_size(FromDIP(wxSize(96, 32)))
|
||||
{
|
||||
memoryCard[SLOT_A] = nullptr;
|
||||
memoryCard[SLOT_B] = nullptr;
|
||||
@ -179,6 +166,7 @@ bool CMemcardManager::SaveSettings()
|
||||
void CMemcardManager::CreateGUIControls()
|
||||
{
|
||||
// Create the controls for both memcards
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
const char* ARROW[2] = {"<-", "->"};
|
||||
|
||||
@ -203,11 +191,11 @@ void CMemcardManager::CreateGUIControls()
|
||||
t_Status[slot] = new wxStaticText(this, 0, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0,
|
||||
wxEmptyString);
|
||||
|
||||
wxBoxSizer* const sPages = new wxBoxSizer(wxHORIZONTAL);
|
||||
sPages->Add(m_PrevPage[slot], 0, wxEXPAND | wxALL, 1);
|
||||
sPages->Add(t_Status[slot], 0, wxEXPAND | wxALL, 5);
|
||||
sPages->Add(0, 0, 1, wxEXPAND | wxALL, 0);
|
||||
sPages->Add(m_NextPage[slot], 0, wxEXPAND | wxALL, 1);
|
||||
wxFlexGridSizer* const paging_sizer = new wxFlexGridSizer(3, wxSize(space5, space5));
|
||||
paging_sizer->AddGrowableCol(1);
|
||||
paging_sizer->Add(m_PrevPage[slot], 0, wxEXPAND);
|
||||
paging_sizer->Add(t_Status[slot], 0, wxALIGN_CENTER);
|
||||
paging_sizer->Add(m_NextPage[slot], 0, wxEXPAND);
|
||||
|
||||
m_MemcardPath[slot] = new wxFilePickerCtrl(
|
||||
this, ID_MEMCARDPATH_A + slot, StrToWxStr(File::GetUserPath(D_GCUSER_IDX)),
|
||||
@ -216,41 +204,51 @@ void CMemcardManager::CreateGUIControls()
|
||||
wxDefaultSize, wxFLP_USE_TEXTCTRL | wxFLP_OPEN);
|
||||
|
||||
m_MemcardList[slot] = new CMemcardListCtrl(
|
||||
this, ID_MEMCARDLIST_A + slot, wxDefaultPosition, wxSize(350, 400),
|
||||
this, ID_MEMCARDLIST_A + slot, wxDefaultPosition, FromDIP(wxSize(350, 400)),
|
||||
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL, mcmSettings);
|
||||
|
||||
m_MemcardList[slot]->AssignImageList(new wxImageList(96, 32), wxIMAGE_LIST_SMALL);
|
||||
m_MemcardList[slot]->AssignImageList(
|
||||
new wxImageList(m_image_list_size.GetWidth(), m_image_list_size.GetHeight()),
|
||||
wxIMAGE_LIST_SMALL);
|
||||
|
||||
sMemcard[slot] = new wxStaticBoxSizer(wxVERTICAL, this,
|
||||
_("Memory Card") + wxString::Format(" %c", 'A' + slot));
|
||||
sMemcard[slot]->Add(m_MemcardPath[slot], 0, wxEXPAND | wxALL, 5);
|
||||
sMemcard[slot]->Add(m_MemcardList[slot], 1, wxEXPAND | wxALL, 5);
|
||||
sMemcard[slot]->Add(sPages, 0, wxEXPAND | wxALL, 1);
|
||||
sMemcard[slot]->AddSpacer(space5);
|
||||
sMemcard[slot]->Add(m_MemcardPath[slot], 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMemcard[slot]->AddSpacer(space5);
|
||||
sMemcard[slot]->Add(m_MemcardList[slot], 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMemcard[slot]->AddSpacer(space5);
|
||||
sMemcard[slot]->Add(paging_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sMemcard[slot]->AddSpacer(space5);
|
||||
}
|
||||
|
||||
wxBoxSizer* const sButtons = new wxBoxSizer(wxVERTICAL);
|
||||
sButtons->AddStretchSpacer(2);
|
||||
sButtons->Add(m_CopyFrom[SLOT_B], 0, wxEXPAND, 5);
|
||||
sButtons->Add(m_CopyFrom[SLOT_A], 0, wxEXPAND, 5);
|
||||
sButtons->AddStretchSpacer(1);
|
||||
sButtons->Add(m_SaveImport[SLOT_A], 0, wxEXPAND, 5);
|
||||
sButtons->Add(m_SaveExport[SLOT_A], 0, wxEXPAND, 5);
|
||||
sButtons->AddStretchSpacer(1);
|
||||
sButtons->Add(m_ConvertToGci, 0, wxEXPAND, 5);
|
||||
sButtons->AddStretchSpacer(1);
|
||||
sButtons->Add(m_SaveImport[SLOT_B], 0, wxEXPAND, 5);
|
||||
sButtons->Add(m_SaveExport[SLOT_B], 0, wxEXPAND, 5);
|
||||
sButtons->AddStretchSpacer(1);
|
||||
sButtons->Add(m_Delete[SLOT_A], 0, wxEXPAND, 5);
|
||||
sButtons->Add(m_Delete[SLOT_B], 0, wxEXPAND, 5);
|
||||
sButtons->Add(m_CopyFrom[SLOT_B], 0, wxEXPAND);
|
||||
sButtons->Add(m_CopyFrom[SLOT_A], 0, wxEXPAND);
|
||||
sButtons->AddStretchSpacer();
|
||||
sButtons->Add(new wxButton(this, wxID_OK, _("Close")), 0, wxEXPAND, 5);
|
||||
sButtons->Add(m_SaveImport[SLOT_A], 0, wxEXPAND);
|
||||
sButtons->Add(m_SaveExport[SLOT_A], 0, wxEXPAND);
|
||||
sButtons->AddStretchSpacer();
|
||||
sButtons->Add(m_ConvertToGci, 0, wxEXPAND);
|
||||
sButtons->AddStretchSpacer();
|
||||
sButtons->Add(m_SaveImport[SLOT_B], 0, wxEXPAND);
|
||||
sButtons->Add(m_SaveExport[SLOT_B], 0, wxEXPAND);
|
||||
sButtons->AddStretchSpacer();
|
||||
sButtons->Add(m_Delete[SLOT_A], 0, wxEXPAND);
|
||||
sButtons->Add(m_Delete[SLOT_B], 0, wxEXPAND);
|
||||
sButtons->AddStretchSpacer();
|
||||
sButtons->Add(new wxButton(this, wxID_OK, _("Close")), 0, wxEXPAND);
|
||||
sButtons->AddStretchSpacer();
|
||||
|
||||
wxBoxSizer* const sMain = new wxBoxSizer(wxHORIZONTAL);
|
||||
sMain->Add(sMemcard[SLOT_A], 1, wxEXPAND | wxALL, 5);
|
||||
sMain->Add(sButtons, 0, wxEXPAND, 0);
|
||||
sMain->Add(sMemcard[SLOT_B], 1, wxEXPAND | wxALL, 5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(sMemcard[SLOT_A], 1, wxEXPAND | wxTOP | wxBOTTOM, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(sButtons, 0, wxEXPAND | wxTOP | wxBOTTOM, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
sMain->Add(sMemcard[SLOT_B], 1, wxEXPAND | wxTOP | wxBOTTOM, space5);
|
||||
sMain->AddSpacer(space5);
|
||||
|
||||
SetSizerAndFit(sMain);
|
||||
Center();
|
||||
@ -653,57 +651,73 @@ bool CMemcardManager::ReloadMemcard(const std::string& fileName, int card)
|
||||
u8 nFiles = memoryCard[card]->GetNumFiles();
|
||||
std::vector<int> images(nFiles * 2);
|
||||
|
||||
static constexpr unsigned int BANNER_WIDTH = 96;
|
||||
static constexpr unsigned int ANIM_FRAME_WIDTH = 32;
|
||||
static constexpr unsigned int IMAGE_HEIGHT = 32;
|
||||
static constexpr unsigned int ANIM_MAX_FRAMES = 8;
|
||||
|
||||
std::vector<u32> pxdata(BANNER_WIDTH * IMAGE_HEIGHT);
|
||||
std::vector<u8> anim_delay(ANIM_MAX_FRAMES);
|
||||
std::vector<u32> anim_data(ANIM_FRAME_WIDTH * IMAGE_HEIGHT * ANIM_MAX_FRAMES);
|
||||
for (u8 i = 0; i < nFiles; i++)
|
||||
{
|
||||
static u32 pxdata[96 * 32];
|
||||
static u8 animDelay[8];
|
||||
static u32 animData[32 * 32 * 8];
|
||||
u8 file_index = memoryCard[card]->GetFileIndex(i);
|
||||
u32 num_frames =
|
||||
memoryCard[card]->ReadAnimRGBA8(file_index, anim_data.data(), anim_delay.data());
|
||||
|
||||
u8 fileIndex = memoryCard[card]->GetFileIndex(i);
|
||||
int numFrames = memoryCard[card]->ReadAnimRGBA8(fileIndex, animData, animDelay);
|
||||
|
||||
if (!memoryCard[card]->ReadBannerRGBA8(fileIndex, pxdata))
|
||||
// Decode Save File Animation
|
||||
wxImage anim_img_strip;
|
||||
if (num_frames > 0)
|
||||
{
|
||||
memset(pxdata, 0, 96 * 32 * 4);
|
||||
unsigned int frames = BANNER_WIDTH / ANIM_FRAME_WIDTH;
|
||||
|
||||
if (numFrames > 0) // Just use the first one
|
||||
if (num_frames < frames)
|
||||
{
|
||||
u32* icdata = animData;
|
||||
frames = num_frames;
|
||||
|
||||
for (int y = 0; y < 32; y++)
|
||||
// Clear unused frame's pixels from the buffer.
|
||||
std::fill(pxdata.begin(), pxdata.end(), 0);
|
||||
}
|
||||
|
||||
for (unsigned int f = 0; f < frames; ++f)
|
||||
{
|
||||
for (unsigned int y = 0; y < IMAGE_HEIGHT; ++y)
|
||||
{
|
||||
for (int x = 0; x < 32; x++)
|
||||
for (unsigned int x = 0; x < ANIM_FRAME_WIDTH; ++x)
|
||||
{
|
||||
pxdata[y * 96 + x + 32] = icdata[y * 32 + x]; // | 0xFF000000
|
||||
// NOTE: pxdata is stacked horizontal, anim_data is stacked vertical
|
||||
pxdata[y * BANNER_WIDTH + f * ANIM_FRAME_WIDTH + x] =
|
||||
anim_data[f * ANIM_FRAME_WIDTH * IMAGE_HEIGHT + y * IMAGE_HEIGHT + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
anim_img_strip = wxImageFromMemoryRGBA(pxdata.data(), BANNER_WIDTH, IMAGE_HEIGHT);
|
||||
}
|
||||
|
||||
wxBitmap map = wxBitmapFromMemoryRGBA((u8*)pxdata, 96, 32);
|
||||
images[i * 2] = list->Add(map);
|
||||
|
||||
if (numFrames > 0)
|
||||
else
|
||||
{
|
||||
memset(pxdata, 0, 96 * 32 * 4);
|
||||
int frames = 3;
|
||||
|
||||
if (numFrames < frames)
|
||||
frames = numFrames;
|
||||
|
||||
for (int f = 0; f < frames; f++)
|
||||
{
|
||||
for (int y = 0; y < 32; y++)
|
||||
{
|
||||
for (int x = 0; x < 32; x++)
|
||||
{
|
||||
pxdata[y * 96 + x + 32 * f] = animData[f * 32 * 32 + y * 32 + x];
|
||||
}
|
||||
}
|
||||
}
|
||||
wxBitmap icon = wxBitmapFromMemoryRGBA((u8*)pxdata, 96, 32);
|
||||
images[i * 2 + 1] = list->Add(icon);
|
||||
// No Animation found, use an empty placeholder instead.
|
||||
anim_img_strip.Create(BANNER_WIDTH, IMAGE_HEIGHT, false);
|
||||
anim_img_strip.Clear(0xFF);
|
||||
anim_img_strip.SetMaskColour(0xFF, 0xFF, 0xFF);
|
||||
}
|
||||
|
||||
// Decode Banner if it exists
|
||||
{
|
||||
wxImage image;
|
||||
if (memoryCard[card]->ReadBannerRGBA8(file_index, pxdata.data()))
|
||||
{
|
||||
image = wxImageFromMemoryRGBA(pxdata.data(), BANNER_WIDTH, IMAGE_HEIGHT);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use first frame of animation instead.
|
||||
image = anim_img_strip.Size(wxSize(ANIM_FRAME_WIDTH, IMAGE_HEIGHT), wxPoint(0, 0));
|
||||
}
|
||||
images[i * 2] = list->Add(WxUtils::ScaleImageToBitmap(image, this, m_image_list_size));
|
||||
}
|
||||
|
||||
images[i * 2 + 1] =
|
||||
list->Add(WxUtils::ScaleImageToBitmap(anim_img_strip, this, m_image_list_size));
|
||||
}
|
||||
|
||||
int pagesMax = (mcmSettings.usePages) ? (page[card] + 1) * itemsPerPage : 128;
|
||||
|
@ -131,5 +131,6 @@ private:
|
||||
void OnRightClick(wxMouseEvent& event);
|
||||
};
|
||||
|
||||
wxSize m_image_list_size;
|
||||
CMemcardListCtrl* m_MemcardList[2];
|
||||
};
|
||||
|
@ -12,6 +12,8 @@
|
||||
ChangeGameDialog::ChangeGameDialog(wxWindow* parent, const CGameListCtrl* const game_list)
|
||||
: wxDialog(parent, wxID_ANY, _("Select Game"))
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
m_game_lbox =
|
||||
new wxListBox(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_SORT);
|
||||
m_game_lbox->Bind(wxEVT_LISTBOX_DCLICK, &ChangeGameDialog::OnPick, this);
|
||||
@ -22,8 +24,11 @@ ChangeGameDialog::ChangeGameDialog(wxWindow* parent, const CGameListCtrl* const
|
||||
ok_btn->Bind(wxEVT_BUTTON, &ChangeGameDialog::OnPick, this);
|
||||
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxVERTICAL);
|
||||
szr->Add(m_game_lbox, 1, wxLEFT | wxRIGHT | wxTOP | wxEXPAND, 5);
|
||||
szr->Add(ok_btn, 0, wxALL | wxALIGN_RIGHT, 5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(m_game_lbox, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(ok_btn, 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, space5);
|
||||
szr->AddSpacer(space5);
|
||||
|
||||
SetSizerAndFit(szr);
|
||||
SetFocus();
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include <wx/gauge.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
#include "Common/StringUtil.h"
|
||||
@ -17,43 +18,54 @@ MD5Dialog::MD5Dialog(wxWindow* parent, NetPlayServer* server, std::vector<const
|
||||
const std::string& game)
|
||||
: wxDialog(parent, wxID_ANY, _("MD5 Checksum")), m_netplay_server(server)
|
||||
{
|
||||
Bind(wxEVT_CLOSE_WINDOW, &MD5Dialog::OnClose, this);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const main_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
main_sizer->Add(new wxStaticText(this, wxID_ANY, _("Computing MD5 Checksum for:") + "\n" + game,
|
||||
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL),
|
||||
0, wxALIGN_CENTER_HORIZONTAL | wxALL, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(new wxStaticText(this, wxID_ANY,
|
||||
wxString::Format(_("Computing MD5 Checksum for:\n%s"), game),
|
||||
wxDefaultPosition, wxDefaultSize,
|
||||
wxALIGN_CENTRE_HORIZONTAL | wxST_NO_AUTORESIZE),
|
||||
0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
|
||||
for (const Player* player : players)
|
||||
{
|
||||
wxStaticBoxSizer* const player_szr = new wxStaticBoxSizer(
|
||||
wxVERTICAL, this, player->name + " (p" + std::to_string(player->pid) + ")");
|
||||
|
||||
wxGauge* gauge = new wxGauge(this, wxID_ANY, 100);
|
||||
wxGauge* gauge = new wxGauge(player_szr->GetStaticBox(), wxID_ANY, 100);
|
||||
m_progress_bars[player->pid] = gauge;
|
||||
player_szr->Add(gauge, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
m_result_labels[player->pid] =
|
||||
new wxStaticText(this, wxID_ANY, _("Computing..."), wxDefaultPosition, wxSize(250, 20),
|
||||
wxALIGN_CENTRE_HORIZONTAL);
|
||||
new wxStaticText(player_szr->GetStaticBox(), wxID_ANY, _("Computing..."));
|
||||
|
||||
m_result_labels[player->pid]->SetSize(250, 15);
|
||||
player_szr->Add(m_result_labels[player->pid], 0, wxALL, 5);
|
||||
player_szr->AddSpacer(space5);
|
||||
player_szr->Add(gauge, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
player_szr->AddSpacer(space5);
|
||||
player_szr->Add(m_result_labels[player->pid], 0, wxALIGN_CENTER_HORIZONTAL | wxLEFT | wxRIGHT,
|
||||
space5);
|
||||
player_szr->AddSpacer(space5);
|
||||
player_szr->SetMinSize(FromDIP(wxSize(250, -1)));
|
||||
|
||||
main_sizer->Add(player_szr, 0, wxEXPAND | wxALL, 5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(player_szr, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
m_final_result_label =
|
||||
new wxStaticText(this, wxID_ANY,
|
||||
" ", // so it takes space
|
||||
wxDefaultPosition, wxDefaultSize, wxALIGN_CENTRE_HORIZONTAL);
|
||||
main_sizer->Add(m_final_result_label, 1, wxALL, 5);
|
||||
|
||||
wxButton* close_btn = new wxButton(this, wxID_ANY, _("Close"));
|
||||
close_btn->Bind(wxEVT_BUTTON, &MD5Dialog::OnCloseBtnPressed, this);
|
||||
main_sizer->Add(close_btn, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(m_final_result_label, 1, wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
main_sizer->Add(CreateStdDialogButtonSizer(wxCLOSE), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_sizer->AddSpacer(space5);
|
||||
SetSizerAndFit(main_sizer);
|
||||
|
||||
Bind(wxEVT_BUTTON, &MD5Dialog::OnCloseBtnPressed, this, wxID_CLOSE);
|
||||
Bind(wxEVT_CLOSE_WINDOW, &MD5Dialog::OnClose, this);
|
||||
SetFocus();
|
||||
Center();
|
||||
}
|
||||
@ -65,6 +77,7 @@ void MD5Dialog::SetProgress(int pid, int progress)
|
||||
|
||||
m_progress_bars[pid]->SetValue(progress);
|
||||
m_result_labels[pid]->SetLabel(_("Computing: ") + std::to_string(progress) + "%");
|
||||
Layout();
|
||||
Update();
|
||||
}
|
||||
|
||||
@ -76,11 +89,12 @@ void MD5Dialog::SetResult(int pid, const std::string& result)
|
||||
m_result_labels[pid]->SetLabel(result);
|
||||
m_hashes.push_back(result);
|
||||
|
||||
if (m_hashes.size() <= 1)
|
||||
return;
|
||||
|
||||
wxString label = AllHashesMatch() ? _("Hashes match!") : _("Hashes do not match.");
|
||||
m_final_result_label->SetLabel(label);
|
||||
if (m_hashes.size() > 1)
|
||||
{
|
||||
wxString label = AllHashesMatch() ? _("Hashes match!") : _("Hashes do not match.");
|
||||
m_final_result_label->SetLabel(label);
|
||||
}
|
||||
Layout();
|
||||
}
|
||||
|
||||
bool MD5Dialog::AllHashesMatch() const
|
||||
@ -89,7 +103,7 @@ bool MD5Dialog::AllHashesMatch() const
|
||||
m_hashes.end();
|
||||
}
|
||||
|
||||
void MD5Dialog::OnClose(wxCloseEvent& event)
|
||||
void MD5Dialog::OnClose(wxCloseEvent&)
|
||||
{
|
||||
m_netplay_server->AbortMD5();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/listbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
@ -41,50 +42,50 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
||||
inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||
|
||||
wxPanel* const panel = new wxPanel(this);
|
||||
panel->Bind(wxEVT_CHAR_HOOK, &NetPlaySetupFrame::OnKeyDown, this);
|
||||
CreateGUI();
|
||||
SetIcons(WxUtils::GetDolphinIconBundle());
|
||||
|
||||
// top row
|
||||
wxBoxSizer* const trav_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* const nick_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
{
|
||||
// Connection Config
|
||||
wxStaticText* const connectiontype_lbl = new wxStaticText(
|
||||
panel, wxID_ANY, _("Connection Type:"), wxDefaultPosition, wxSize(100, -1));
|
||||
std::string temp;
|
||||
netplay_section.Get("Nickname", &temp, "Player");
|
||||
m_nickname_text->SetValue(StrToWxStr(temp));
|
||||
|
||||
m_direct_traversal = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(150, -1));
|
||||
m_direct_traversal->Bind(wxEVT_CHOICE, &NetPlaySetupFrame::OnDirectTraversalChoice, this);
|
||||
m_direct_traversal->Append(_("Direct Connection"));
|
||||
m_direct_traversal->Append(_("Traversal Server"));
|
||||
temp.clear();
|
||||
netplay_section.Get("HostCode", &temp, "00000000");
|
||||
m_connect_hashcode_text->SetValue(StrToWxStr(temp));
|
||||
|
||||
trav_szr->Add(connectiontype_lbl, 0, wxCENTER, 5);
|
||||
trav_szr->AddSpacer(5);
|
||||
trav_szr->Add(m_direct_traversal, 0, wxCENTER, 5);
|
||||
temp.clear();
|
||||
netplay_section.Get("Address", &temp, "127.0.0.1");
|
||||
m_connect_ip_text->SetValue(StrToWxStr(temp));
|
||||
|
||||
m_trav_reset_btn = new wxButton(panel, wxID_ANY, _("Reset Traversal Settings"),
|
||||
wxDefaultPosition, wxSize(-1, 25));
|
||||
m_trav_reset_btn->Bind(wxEVT_BUTTON, &NetPlaySetupFrame::OnResetTraversal, this);
|
||||
temp.clear();
|
||||
netplay_section.Get("ConnectPort", &temp,
|
||||
std::to_string(NetPlayHostConfig::DEFAULT_LISTEN_PORT));
|
||||
m_connect_port_text->SetValue(StrToWxStr(temp));
|
||||
|
||||
trav_szr->AddSpacer(5);
|
||||
temp.clear();
|
||||
netplay_section.Get("HostPort", &temp, std::to_string(NetPlayHostConfig::DEFAULT_LISTEN_PORT));
|
||||
m_host_port_text->SetValue(StrToWxStr(temp));
|
||||
|
||||
trav_szr->Add(m_trav_reset_btn, 0, wxRIGHT);
|
||||
temp.clear();
|
||||
if (netplay_section.Get("SelectedHostGame", &temp, ""))
|
||||
m_game_lbox->SetStringSelection(StrToWxStr(temp));
|
||||
|
||||
// Nickname
|
||||
wxStaticText* const nick_lbl =
|
||||
new wxStaticText(panel, wxID_ANY, _("Nickname:"), wxDefaultPosition, wxSize(100, -1));
|
||||
#ifdef USE_UPNP
|
||||
bool use_upnp = false;
|
||||
netplay_section.Get("UseUPNP", &use_upnp, false);
|
||||
m_upnp_chk->SetValue(use_upnp);
|
||||
#endif
|
||||
|
||||
std::string nickname;
|
||||
netplay_section.Get("Nickname", &nickname, "Player");
|
||||
unsigned int listen_port = 0;
|
||||
netplay_section.Get("ListenPort", &listen_port, 0);
|
||||
m_traversal_listen_port_enabled->SetValue(listen_port != 0);
|
||||
m_traversal_listen_port->Enable(m_traversal_listen_port_enabled->IsChecked());
|
||||
m_traversal_listen_port->SetValue(listen_port);
|
||||
|
||||
m_nickname_text =
|
||||
new wxTextCtrl(panel, wxID_ANY, StrToWxStr(nickname), wxDefaultPosition, wxSize(150, -1));
|
||||
|
||||
nick_szr->Add(nick_lbl, 0, wxCENTER);
|
||||
nick_szr->Add(m_nickname_text, 0, wxALL, 5);
|
||||
|
||||
std::string travChoice;
|
||||
netplay_section.Get("TraversalChoice", &travChoice, "direct");
|
||||
if (travChoice == "traversal")
|
||||
temp.clear();
|
||||
netplay_section.Get("TraversalChoice", &temp, "direct");
|
||||
if (temp == "traversal")
|
||||
{
|
||||
m_direct_traversal->Select(TRAVERSAL_CHOICE);
|
||||
}
|
||||
@ -93,37 +94,96 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
||||
m_direct_traversal->Select(DIRECT_CHOICE);
|
||||
}
|
||||
|
||||
m_traversal_lbl = new wxStaticText(panel, wxID_ANY, GetTraversalLabelText(netplay_section));
|
||||
m_traversal_lbl->SetLabelText(GetTraversalLabelText(netplay_section));
|
||||
}
|
||||
// tabs
|
||||
m_notebook = new wxNotebook(panel, wxID_ANY);
|
||||
wxPanel* const connect_tab = new wxPanel(m_notebook, wxID_ANY);
|
||||
m_notebook->AddPage(connect_tab, _("Connect"));
|
||||
wxPanel* const host_tab = new wxPanel(m_notebook, wxID_ANY);
|
||||
m_notebook->AddPage(host_tab, _("Host"));
|
||||
|
||||
Center();
|
||||
Show();
|
||||
|
||||
// Needs to be done last or it set up the spacing on the page correctly
|
||||
wxCommandEvent ev;
|
||||
OnDirectTraversalChoice(ev);
|
||||
}
|
||||
|
||||
void NetPlaySetupFrame::CreateGUI()
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxPanel* const panel = new wxPanel(this);
|
||||
panel->Bind(wxEVT_CHAR_HOOK, &NetPlaySetupFrame::OnKeyDown, this);
|
||||
|
||||
// Connection Config
|
||||
wxStaticText* const connectiontype_lbl = new wxStaticText(panel, wxID_ANY, _("Connection Type:"));
|
||||
|
||||
m_direct_traversal = new wxChoice(panel, wxID_ANY);
|
||||
m_direct_traversal->Bind(wxEVT_CHOICE, &NetPlaySetupFrame::OnDirectTraversalChoice, this);
|
||||
m_direct_traversal->Append(_("Direct Connection"));
|
||||
m_direct_traversal->Append(_("Traversal Server"));
|
||||
|
||||
m_trav_reset_btn = new wxButton(panel, wxID_ANY, _("Reset Traversal Settings"));
|
||||
m_trav_reset_btn->Bind(wxEVT_BUTTON, &NetPlaySetupFrame::OnResetTraversal, this);
|
||||
|
||||
// Nickname
|
||||
wxStaticText* const nick_lbl = new wxStaticText(panel, wxID_ANY, _("Nickname:"));
|
||||
|
||||
m_nickname_text = new wxTextCtrl(panel, wxID_ANY, "Player");
|
||||
|
||||
m_traversal_lbl = new wxStaticText(panel, wxID_ANY, "Traversal Server");
|
||||
|
||||
wxButton* const quit_btn = new wxButton(panel, wxID_ANY, _("Quit"));
|
||||
quit_btn->Bind(wxEVT_BUTTON, &NetPlaySetupFrame::OnQuit, this);
|
||||
|
||||
wxGridBagSizer* top_sizer = new wxGridBagSizer(space5, space5);
|
||||
top_sizer->Add(connectiontype_lbl, wxGBPosition(0, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
top_sizer->Add(WxUtils::GiveMinSizeDIP(m_direct_traversal, wxSize(100, -1)), wxGBPosition(0, 1),
|
||||
wxDefaultSpan, wxEXPAND);
|
||||
top_sizer->Add(m_trav_reset_btn, wxGBPosition(0, 2), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
top_sizer->Add(nick_lbl, wxGBPosition(1, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
top_sizer->Add(WxUtils::GiveMinSizeDIP(m_nickname_text, wxSize(150, -1)), wxGBPosition(1, 1),
|
||||
wxDefaultSpan, wxEXPAND);
|
||||
|
||||
m_notebook = CreateNotebookGUI(panel);
|
||||
m_notebook->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &NetPlaySetupFrame::OnTabChanged, this);
|
||||
|
||||
// main sizer
|
||||
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(top_sizer, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(m_traversal_lbl, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(m_notebook, 1, wxLEFT | wxRIGHT | wxEXPAND, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(quit_btn, 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
|
||||
panel->SetSizerAndFit(main_szr);
|
||||
main_szr->SetSizeHints(this);
|
||||
}
|
||||
|
||||
wxNotebook* NetPlaySetupFrame::CreateNotebookGUI(wxWindow* parent)
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxNotebook* const notebook = new wxNotebook(parent, wxID_ANY);
|
||||
wxPanel* const connect_tab = new wxPanel(notebook, wxID_ANY);
|
||||
notebook->AddPage(connect_tab, _("Connect"));
|
||||
wxPanel* const host_tab = new wxPanel(notebook, wxID_ANY);
|
||||
notebook->AddPage(host_tab, _("Host"));
|
||||
|
||||
// connect tab
|
||||
{
|
||||
m_ip_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Host Code :"));
|
||||
|
||||
std::string last_hash_code;
|
||||
netplay_section.Get("HostCode", &last_hash_code, "00000000");
|
||||
std::string last_ip_address;
|
||||
netplay_section.Get("Address", &last_ip_address, "127.0.0.1");
|
||||
m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(last_ip_address));
|
||||
m_connect_hashcode_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(last_hash_code));
|
||||
m_connect_ip_text = new wxTextCtrl(connect_tab, wxID_ANY, "127.0.0.1");
|
||||
m_connect_hashcode_text = new wxTextCtrl(connect_tab, wxID_ANY, "00000000");
|
||||
|
||||
// Will be overridden by OnDirectTraversalChoice, but is necessary
|
||||
// so that both inputs do not take up space
|
||||
m_connect_hashcode_text->Hide();
|
||||
|
||||
m_client_port_lbl = new wxStaticText(connect_tab, wxID_ANY, _("Port :"));
|
||||
|
||||
// string? w/e
|
||||
std::string port;
|
||||
netplay_section.Get("ConnectPort", &port,
|
||||
std::to_string(NetPlayHostConfig::DEFAULT_LISTEN_PORT));
|
||||
m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY, StrToWxStr(port));
|
||||
m_connect_port_text = new wxTextCtrl(connect_tab, wxID_ANY,
|
||||
std::to_string(NetPlayHostConfig::DEFAULT_LISTEN_PORT));
|
||||
|
||||
wxButton* const connect_btn = new wxButton(connect_tab, wxID_ANY, _("Connect"));
|
||||
connect_btn->Bind(wxEVT_BUTTON, &NetPlaySetupFrame::OnJoin, this);
|
||||
@ -139,19 +199,22 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
||||
"Wiimote netplay is experimental and should not be expected to work.\n"));
|
||||
|
||||
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
top_szr->Add(m_ip_lbl, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 5);
|
||||
top_szr->Add(m_connect_ip_text, 3);
|
||||
top_szr->Add(m_connect_hashcode_text, 3);
|
||||
top_szr->Add(m_client_port_lbl, 0, wxCENTER | wxRIGHT | wxLEFT, 5);
|
||||
top_szr->Add(m_connect_port_text, 1);
|
||||
top_szr->Add(m_ip_lbl, 0, wxALIGN_CENTER_VERTICAL);
|
||||
top_szr->Add(m_connect_ip_text, 3, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
top_szr->Add(m_connect_hashcode_text, 3, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
top_szr->Add(m_client_port_lbl, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
top_szr->Add(m_connect_port_text, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
|
||||
wxBoxSizer* const con_szr = new wxBoxSizer(wxVERTICAL);
|
||||
con_szr->Add(top_szr, 0, wxALL | wxEXPAND, 5);
|
||||
con_szr->AddSpacer(space5);
|
||||
con_szr->Add(top_szr, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
con_szr->AddStretchSpacer(1);
|
||||
con_szr->Add(alert_lbl, 0, wxLEFT | wxRIGHT | wxEXPAND, 5);
|
||||
con_szr->AddSpacer(space5);
|
||||
con_szr->Add(alert_lbl, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
con_szr->AddStretchSpacer(1);
|
||||
con_szr->Add(connect_btn, 0, wxALL | wxALIGN_RIGHT, 5);
|
||||
con_szr->AddSpacer(space5);
|
||||
con_szr->Add(connect_btn, 0, wxALIGN_RIGHT | wxLEFT | wxRIGHT, space5);
|
||||
con_szr->AddSpacer(space5);
|
||||
|
||||
connect_tab->SetSizerAndFit(con_szr);
|
||||
}
|
||||
@ -159,21 +222,13 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
||||
// host tab
|
||||
{
|
||||
m_host_port_lbl = new wxStaticText(host_tab, wxID_ANY, _("Port :"));
|
||||
|
||||
// string? w/e
|
||||
std::string port;
|
||||
netplay_section.Get("HostPort", &port, std::to_string(NetPlayHostConfig::DEFAULT_LISTEN_PORT));
|
||||
m_host_port_text = new wxTextCtrl(host_tab, wxID_ANY, StrToWxStr(port));
|
||||
m_host_port_text =
|
||||
new wxTextCtrl(host_tab, wxID_ANY, std::to_string(NetPlayHostConfig::DEFAULT_LISTEN_PORT));
|
||||
|
||||
m_traversal_listen_port_enabled = new wxCheckBox(host_tab, wxID_ANY, _("Force Listen Port: "));
|
||||
m_traversal_listen_port = new wxSpinCtrl(host_tab, wxID_ANY, "", wxDefaultPosition,
|
||||
wxSize(80, -1), wxSP_ARROW_KEYS, 1, 65535);
|
||||
|
||||
unsigned int listen_port;
|
||||
netplay_section.Get("ListenPort", &listen_port, 0);
|
||||
m_traversal_listen_port_enabled->SetValue(listen_port != 0);
|
||||
m_traversal_listen_port->Enable(m_traversal_listen_port_enabled->IsChecked());
|
||||
m_traversal_listen_port->SetValue(listen_port);
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 1, 65535);
|
||||
m_traversal_listen_port->SetMinSize(WxUtils::GetTextWidgetMinSize(m_traversal_listen_port));
|
||||
|
||||
m_traversal_listen_port_enabled->Bind(wxEVT_CHECKBOX,
|
||||
&NetPlaySetupFrame::OnTraversalListenPortChanged, this);
|
||||
@ -187,63 +242,35 @@ NetPlaySetupFrame::NetPlaySetupFrame(wxWindow* const parent, const CGameListCtrl
|
||||
new wxListBox(host_tab, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0, nullptr, wxLB_SORT);
|
||||
m_game_lbox->Bind(wxEVT_LISTBOX_DCLICK, &NetPlaySetupFrame::OnHost, this);
|
||||
|
||||
NetPlayDialog::FillWithGameNames(m_game_lbox, *game_list);
|
||||
|
||||
std::string last_hosted_game;
|
||||
if (netplay_section.Get("SelectedHostGame", &last_hosted_game, ""))
|
||||
m_game_lbox->SetStringSelection(last_hosted_game);
|
||||
NetPlayDialog::FillWithGameNames(m_game_lbox, *m_game_list);
|
||||
|
||||
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
top_szr->Add(m_host_port_lbl, 0, wxCENTER | wxRIGHT, 5);
|
||||
top_szr->Add(m_host_port_text, 0);
|
||||
top_szr->Add(m_host_port_lbl, 0, wxALIGN_CENTER_VERTICAL);
|
||||
top_szr->Add(m_host_port_text, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
#ifdef USE_UPNP
|
||||
m_upnp_chk = new wxCheckBox(host_tab, wxID_ANY, _("Forward port (UPnP)"));
|
||||
top_szr->Add(m_upnp_chk, 0, wxALL, 5);
|
||||
top_szr->Add(m_upnp_chk, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
#endif
|
||||
|
||||
wxBoxSizer* const bottom_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
bottom_szr->Add(m_traversal_listen_port_enabled, 0, wxCENTER | wxLEFT, 5);
|
||||
bottom_szr->Add(m_traversal_listen_port, 0, wxCENTER, 0);
|
||||
wxBoxSizer* const host_btn_szr = new wxBoxSizer(wxVERTICAL);
|
||||
host_btn_szr->Add(host_btn, 0, wxCENTER | wxALIGN_RIGHT, 0);
|
||||
bottom_szr->Add(host_btn_szr, 1, wxALL, 5);
|
||||
bottom_szr->Add(m_traversal_listen_port_enabled, 0, wxALIGN_CENTER_VERTICAL);
|
||||
bottom_szr->Add(m_traversal_listen_port, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
bottom_szr->AddStretchSpacer();
|
||||
bottom_szr->Add(host_btn, 0, wxLEFT, space5);
|
||||
|
||||
wxBoxSizer* const host_szr = new wxBoxSizer(wxVERTICAL);
|
||||
host_szr->Add(top_szr, 0, wxALL | wxEXPAND, 5);
|
||||
host_szr->Add(m_game_lbox, 1, wxLEFT | wxRIGHT | wxEXPAND, 5);
|
||||
host_szr->Add(bottom_szr, 0, wxEXPAND, 0);
|
||||
// NOTE: Top row can disappear entirely
|
||||
host_szr->Add(top_szr, 0, wxEXPAND | wxLEFT | wxRIGHT | wxTOP, space5);
|
||||
host_szr->AddSpacer(space5);
|
||||
host_szr->Add(m_game_lbox, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
host_szr->AddSpacer(space5);
|
||||
host_szr->Add(bottom_szr, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
host_szr->AddSpacer(space5);
|
||||
|
||||
host_tab->SetSizerAndFit(host_szr);
|
||||
}
|
||||
|
||||
// bottom row
|
||||
wxButton* const quit_btn = new wxButton(panel, wxID_ANY, _("Quit"));
|
||||
quit_btn->Bind(wxEVT_BUTTON, &NetPlaySetupFrame::OnQuit, this);
|
||||
|
||||
// main sizer
|
||||
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
main_szr->Add(trav_szr, 0, wxALL | wxALIGN_LEFT, 5);
|
||||
main_szr->Add(nick_szr, 0, wxALL | wxALIGN_LEFT, 5);
|
||||
main_szr->Add(m_traversal_lbl, 0, wxALL | wxALIGN_LEFT, 5);
|
||||
main_szr->Add(m_notebook, 1, wxLEFT | wxRIGHT | wxEXPAND, 5);
|
||||
main_szr->Add(quit_btn, 0, wxALL | wxALIGN_RIGHT, 5);
|
||||
|
||||
panel->SetSizerAndFit(main_szr);
|
||||
|
||||
// Handle focus on tab changes
|
||||
panel->Bind(wxEVT_NOTEBOOK_PAGE_CHANGED, &NetPlaySetupFrame::OnTabChanged, this);
|
||||
|
||||
// wxBoxSizer* const diag_szr = new wxBoxSizer(wxVERTICAL);
|
||||
// diag_szr->Add(panel, 1, wxEXPAND);
|
||||
// SetSizerAndFit(diag_szr);
|
||||
|
||||
main_szr->SetSizeHints(this);
|
||||
|
||||
Center();
|
||||
Show();
|
||||
|
||||
// Needs to be done last or it set up the spacing on the page correctly
|
||||
wxCommandEvent ev;
|
||||
OnDirectTraversalChoice(ev);
|
||||
return notebook;
|
||||
}
|
||||
|
||||
NetPlaySetupFrame::~NetPlaySetupFrame()
|
||||
@ -278,6 +305,10 @@ NetPlaySetupFrame::~NetPlaySetupFrame()
|
||||
m_traversal_listen_port->GetValue() :
|
||||
0);
|
||||
|
||||
#ifdef USE_UPNP
|
||||
netplay_section.Set("UseUPNP", m_upnp_chk->GetValue(), false);
|
||||
#endif
|
||||
|
||||
inifile.Save(dolphin_ini);
|
||||
main_frame->g_NetPlaySetupDiag = nullptr;
|
||||
}
|
||||
@ -395,7 +426,7 @@ void NetPlaySetupFrame::OnDirectTraversalChoice(wxCommandEvent& event)
|
||||
|
||||
if (sel == TRAVERSAL_CHOICE)
|
||||
{
|
||||
m_traversal_lbl->Show();
|
||||
m_traversal_lbl->SetLabelText(m_traversal_string);
|
||||
m_trav_reset_btn->Show();
|
||||
m_connect_hashcode_text->Show();
|
||||
m_connect_ip_text->Hide();
|
||||
@ -420,7 +451,7 @@ void NetPlaySetupFrame::OnDirectTraversalChoice(wxCommandEvent& event)
|
||||
}
|
||||
else
|
||||
{
|
||||
m_traversal_lbl->Hide();
|
||||
m_traversal_lbl->SetLabel(wxEmptyString);
|
||||
m_trav_reset_btn->Hide();
|
||||
m_connect_hashcode_text->Hide();
|
||||
m_connect_ip_text->Show();
|
||||
@ -446,7 +477,19 @@ void NetPlaySetupFrame::OnDirectTraversalChoice(wxCommandEvent& event)
|
||||
m_upnp_chk->Show();
|
||||
#endif
|
||||
}
|
||||
m_connect_ip_text->GetParent()->Layout();
|
||||
|
||||
// wxWidgets' layout engine sucks. It only updates when a size event occurs so we
|
||||
// have to manually invoke the layout system.
|
||||
// Caveat: This only works if the new layout is not substantially different from the
|
||||
// old one because otherwise the minimum sizes assigned by SetSizerAndFit won't make
|
||||
// sense and the layout will break (overlapping widgets). You can't just SetSizeHints
|
||||
// because that will change the current sizes as well as the minimum sizes, it's a mess.
|
||||
for (wxWindow* tab : m_notebook->GetChildren())
|
||||
tab->Layout();
|
||||
// Because this is a wxFrame, not a dialog, everything is inside a wxPanel which
|
||||
// is the only direct child of the frame.
|
||||
GetChildren()[0]->Layout();
|
||||
|
||||
DispatchFocus();
|
||||
}
|
||||
|
||||
@ -476,16 +519,8 @@ void NetPlaySetupFrame::OnTabChanged(wxCommandEvent& event)
|
||||
// Propagate event
|
||||
event.Skip();
|
||||
|
||||
// Delaying action so the first tab order element doesn't override the focus
|
||||
m_notebook->Bind(wxEVT_IDLE, &NetPlaySetupFrame::OnAfterTabChange, this);
|
||||
}
|
||||
|
||||
void NetPlaySetupFrame::OnAfterTabChange(wxIdleEvent&)
|
||||
{
|
||||
// Unbinding so we don't hog the idle event
|
||||
m_notebook->Unbind(wxEVT_IDLE, &NetPlaySetupFrame::OnAfterTabChange, this);
|
||||
|
||||
DispatchFocus();
|
||||
// Let the base class fiddle with the focus first then correct it afterwards
|
||||
CallAfter(&NetPlaySetupFrame::DispatchFocus);
|
||||
}
|
||||
|
||||
void NetPlaySetupFrame::DispatchFocus()
|
||||
|
@ -12,6 +12,7 @@ class CGameListCtrl;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
class wxListBox;
|
||||
class wxNotebook;
|
||||
class wxSpinCtrl;
|
||||
class wxStaticText;
|
||||
class wxTextCtrl;
|
||||
@ -29,7 +30,9 @@ private:
|
||||
static constexpr int DIRECT_CHOICE = 0;
|
||||
static constexpr int TRAVERSAL_CHOICE = 1;
|
||||
|
||||
void GetWindowRect(const IniFile::Section& section, wxRect* rect) const;
|
||||
void CreateGUI();
|
||||
wxNotebook* CreateNotebookGUI(wxWindow* parent);
|
||||
|
||||
void OnJoin(wxCommandEvent& event);
|
||||
void OnHost(wxCommandEvent& event);
|
||||
void DoJoin();
|
||||
@ -40,7 +43,6 @@ private:
|
||||
void OnTraversalListenPortChanged(wxCommandEvent& event);
|
||||
void OnKeyDown(wxKeyEvent& event);
|
||||
void OnTabChanged(wxCommandEvent& event);
|
||||
void OnAfterTabChange(wxIdleEvent& event);
|
||||
void DispatchFocus();
|
||||
|
||||
wxStaticText* m_ip_lbl;
|
||||
@ -63,5 +65,6 @@ private:
|
||||
wxCheckBox* m_upnp_chk;
|
||||
#endif
|
||||
|
||||
wxString m_traversal_string;
|
||||
const CGameListCtrl* const m_game_list;
|
||||
};
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <limits>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <tuple>
|
||||
@ -21,6 +22,7 @@
|
||||
#include <wx/panel.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/statbox.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/string.h>
|
||||
#include <wx/textctrl.h>
|
||||
@ -67,12 +69,52 @@ NetPlayDialog::NetPlayDialog(wxWindow* const parent, const CGameListCtrl* const
|
||||
m_host_copy_btn_is_retry(false), m_is_hosting(is_hosting), m_game_list(game_list)
|
||||
{
|
||||
Bind(wxEVT_THREAD, &NetPlayDialog::OnThread, this);
|
||||
CreateGUI();
|
||||
SetIcons(WxUtils::GetDolphinIconBundle());
|
||||
Center();
|
||||
|
||||
// Remember the window size and position for NetWindow
|
||||
{
|
||||
IniFile inifile;
|
||||
inifile.Load(File::GetUserPath(F_DOLPHINCONFIG_IDX));
|
||||
IniFile::Section& netplay_section = *inifile.GetOrCreateSection("NetPlay");
|
||||
|
||||
int winPosX, winPosY, winWidth, winHeight;
|
||||
netplay_section.Get("NetWindowPosX", &winPosX, std::numeric_limits<int>::min());
|
||||
netplay_section.Get("NetWindowPosY", &winPosY, std::numeric_limits<int>::min());
|
||||
netplay_section.Get("NetWindowWidth", &winWidth, -1);
|
||||
netplay_section.Get("NetWindowHeight", &winHeight, -1);
|
||||
|
||||
WxUtils::SetWindowSizeAndFitToScreen(this, wxPoint(winPosX, winPosY),
|
||||
wxSize(winWidth, winHeight), GetSize());
|
||||
}
|
||||
}
|
||||
|
||||
void NetPlayDialog::CreateGUI()
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// NOTE: The design operates top down. Margins / padding are handled by the outermost
|
||||
// sizers, this makes the design easier to change. Inner sizers should only pad between
|
||||
// widgets, they should never have prepended or appended margins/spacers.
|
||||
wxPanel* const panel = new wxPanel(this);
|
||||
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(CreateTopGUI(panel), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(CreateMiddleGUI(panel), 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(CreateBottomGUI(panel), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
|
||||
wxBoxSizer* const top_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
panel->SetSizerAndFit(main_szr);
|
||||
main_szr->SetSizeHints(this);
|
||||
SetSize(FromDIP(wxSize(768, 768 - 128)));
|
||||
}
|
||||
|
||||
m_game_btn = new wxButton(panel, wxID_ANY, StrToWxStr(m_selected_game).Prepend(_(" Game : ")),
|
||||
wxSizer* NetPlayDialog::CreateTopGUI(wxWindow* parent)
|
||||
{
|
||||
m_game_btn = new wxButton(parent, wxID_ANY, _(" Game : ") + StrToWxStr(m_selected_game),
|
||||
wxDefaultPosition, wxDefaultSize, wxBU_LEFT);
|
||||
|
||||
if (m_is_hosting)
|
||||
@ -80,11 +122,12 @@ NetPlayDialog::NetPlayDialog(wxWindow* const parent, const CGameListCtrl* const
|
||||
else
|
||||
m_game_btn->Disable();
|
||||
|
||||
top_szr->Add(m_game_btn, 1, wxALL | wxEXPAND);
|
||||
wxBoxSizer* top_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
top_szr->Add(m_game_btn, 1, wxEXPAND);
|
||||
|
||||
if (m_is_hosting)
|
||||
{
|
||||
m_MD5_choice = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(150, -1));
|
||||
m_MD5_choice = new wxChoice(parent, wxID_ANY, wxDefaultPosition, FromDIP(wxSize(150, -1)));
|
||||
m_MD5_choice->Bind(wxEVT_CHOICE, &NetPlayDialog::OnMD5ComputeRequested, this);
|
||||
m_MD5_choice->Append(_("MD5 check..."));
|
||||
m_MD5_choice->Append(_("Current game"));
|
||||
@ -92,59 +135,89 @@ NetPlayDialog::NetPlayDialog(wxWindow* const parent, const CGameListCtrl* const
|
||||
m_MD5_choice->Append(_("SD card"));
|
||||
m_MD5_choice->SetSelection(0);
|
||||
|
||||
top_szr->Add(m_MD5_choice, 0, wxALL);
|
||||
top_szr->Add(m_MD5_choice, 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
// middle crap
|
||||
return top_szr;
|
||||
}
|
||||
|
||||
// chat
|
||||
m_chat_text = new wxTextCtrl(panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxSizer* NetPlayDialog::CreateMiddleGUI(wxWindow* parent)
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const mid_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
mid_szr->Add(CreateChatGUI(parent), 1, wxEXPAND);
|
||||
mid_szr->Add(CreatePlayerListGUI(parent), 0, wxEXPAND | wxLEFT, space5);
|
||||
return mid_szr;
|
||||
}
|
||||
|
||||
wxSizer* NetPlayDialog::CreateChatGUI(wxWindow* parent)
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxStaticBoxSizer* const chat_szr = new wxStaticBoxSizer(wxVERTICAL, parent, _("Chat"));
|
||||
parent = chat_szr->GetStaticBox();
|
||||
|
||||
m_chat_text = new wxTextCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize,
|
||||
wxTE_READONLY | wxTE_MULTILINE);
|
||||
|
||||
m_chat_msg_text = new wxTextCtrl(panel, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxSize(-1, 25), wxTE_PROCESS_ENTER);
|
||||
m_chat_msg_text = new wxTextCtrl(parent, wxID_ANY, wxEmptyString, wxDefaultPosition,
|
||||
wxDefaultSize, wxTE_PROCESS_ENTER);
|
||||
m_chat_msg_text->Bind(wxEVT_TEXT_ENTER, &NetPlayDialog::OnChat, this);
|
||||
m_chat_msg_text->SetMaxLength(2000);
|
||||
|
||||
wxButton* const chat_msg_btn =
|
||||
new wxButton(panel, wxID_ANY, _("Send"), wxDefaultPosition, wxSize(-1, 26));
|
||||
new wxButton(parent, wxID_ANY, _("Send"), wxDefaultPosition,
|
||||
wxSize(-1, m_chat_msg_text->GetBestSize().GetHeight()));
|
||||
chat_msg_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnChat, this);
|
||||
|
||||
wxBoxSizer* const chat_msg_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
chat_msg_szr->Add(m_chat_msg_text, 1);
|
||||
chat_msg_szr->Add(chat_msg_btn, 0);
|
||||
// NOTE: Remember that fonts are configurable, setting sizes of anything that contains
|
||||
// text in pixels is dangerous because the text may end up being clipped.
|
||||
chat_msg_szr->Add(WxUtils::GiveMinSizeDIP(m_chat_msg_text, wxSize(-1, 25)), 1,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
chat_msg_szr->Add(chat_msg_btn, 0, wxEXPAND);
|
||||
|
||||
wxStaticBoxSizer* const chat_szr = new wxStaticBoxSizer(wxVERTICAL, panel, _("Chat"));
|
||||
chat_szr->Add(m_chat_text, 1, wxEXPAND);
|
||||
chat_szr->Add(chat_msg_szr, 0, wxEXPAND | wxTOP, 5);
|
||||
chat_szr->Add(chat_msg_szr, 0, wxEXPAND | wxTOP, space5);
|
||||
return chat_szr;
|
||||
}
|
||||
|
||||
m_player_lbox = new wxListBox(panel, wxID_ANY, wxDefaultPosition, wxSize(256, -1));
|
||||
wxSizer* NetPlayDialog::CreatePlayerListGUI(wxWindow* parent)
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxStaticBoxSizer* const player_szr = new wxStaticBoxSizer(wxVERTICAL, panel, _("Players"));
|
||||
wxStaticBoxSizer* const player_szr = new wxStaticBoxSizer(wxVERTICAL, parent, _("Players"));
|
||||
// Static box is a widget, new widgets should be children instead of siblings to avoid various
|
||||
// flickering problems.
|
||||
parent = player_szr->GetStaticBox();
|
||||
|
||||
m_player_lbox = new wxListBox(parent, wxID_ANY, wxDefaultPosition, FromDIP(wxSize(256, -1)), 0,
|
||||
nullptr, wxLB_HSCROLL);
|
||||
|
||||
// player list
|
||||
if (m_is_hosting && g_TraversalClient)
|
||||
{
|
||||
wxBoxSizer* const host_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_host_type_choice = new wxChoice(panel, wxID_ANY, wxDefaultPosition, wxSize(76, -1));
|
||||
m_host_type_choice = new wxChoice(parent, wxID_ANY, wxDefaultPosition, FromDIP(wxSize(76, -1)));
|
||||
m_host_type_choice->Bind(wxEVT_CHOICE, &NetPlayDialog::OnChoice, this);
|
||||
m_host_type_choice->Append(_("Room ID:"));
|
||||
host_szr->Add(m_host_type_choice);
|
||||
|
||||
m_host_label = new wxStaticText(panel, wxID_ANY, "555.555.555.555:55555", wxDefaultPosition,
|
||||
wxDefaultSize, wxST_NO_AUTORESIZE | wxALIGN_LEFT);
|
||||
// Update() should fix this immediately.
|
||||
m_host_label->SetLabel("");
|
||||
host_szr->Add(m_host_label, 1, wxLEFT | wxCENTER, 5);
|
||||
|
||||
m_host_copy_btn = new wxButton(panel, wxID_ANY, _("Copy"));
|
||||
m_host_copy_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnCopyIP, this);
|
||||
m_host_copy_btn->Disable();
|
||||
host_szr->Add(m_host_copy_btn, 0, wxLEFT | wxCENTER, 5);
|
||||
player_szr->Add(host_szr, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
m_host_type_choice->Select(0);
|
||||
|
||||
m_host_label = new wxStaticText(parent, wxID_ANY, "555.555.555.555:55555", wxDefaultPosition,
|
||||
wxDefaultSize, wxST_NO_AUTORESIZE);
|
||||
// Update() should fix this immediately.
|
||||
m_host_label->SetLabel("");
|
||||
|
||||
m_host_copy_btn = new wxButton(parent, wxID_ANY, _("Copy"));
|
||||
m_host_copy_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnCopyIP, this);
|
||||
m_host_copy_btn->Disable();
|
||||
|
||||
UpdateHostLabel();
|
||||
|
||||
wxBoxSizer* const host_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
host_szr->Add(m_host_type_choice);
|
||||
host_szr->Add(m_host_label, 1, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
host_szr->Add(m_host_copy_btn, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
player_szr->Add(host_szr, 0, wxEXPAND, space5);
|
||||
}
|
||||
|
||||
player_szr->Add(m_player_lbox, 1, wxEXPAND);
|
||||
@ -152,59 +225,54 @@ NetPlayDialog::NetPlayDialog(wxWindow* const parent, const CGameListCtrl* const
|
||||
if (m_is_hosting)
|
||||
{
|
||||
m_player_lbox->Bind(wxEVT_LISTBOX, &NetPlayDialog::OnPlayerSelect, this);
|
||||
m_kick_btn = new wxButton(panel, wxID_ANY, _("Kick Player"));
|
||||
m_kick_btn = new wxButton(parent, wxID_ANY, _("Kick Player"));
|
||||
m_kick_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnKick, this);
|
||||
player_szr->Add(m_kick_btn, 0, wxEXPAND | wxTOP, 5);
|
||||
m_kick_btn->Disable();
|
||||
|
||||
m_player_config_btn = new wxButton(panel, wxID_ANY, _("Assign Controller Ports"));
|
||||
m_player_config_btn = new wxButton(parent, wxID_ANY, _("Assign Controller Ports"));
|
||||
m_player_config_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnAssignPads, this);
|
||||
player_szr->Add(m_player_config_btn, 0, wxEXPAND | wxTOP, 5);
|
||||
|
||||
player_szr->Add(m_kick_btn, 0, wxEXPAND | wxTOP, space5);
|
||||
player_szr->Add(m_player_config_btn, 0, wxEXPAND | wxTOP, space5);
|
||||
}
|
||||
return player_szr;
|
||||
}
|
||||
|
||||
wxBoxSizer* const mid_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
mid_szr->Add(chat_szr, 1, wxEXPAND | wxRIGHT, 5);
|
||||
mid_szr->Add(player_szr, 0, wxEXPAND);
|
||||
|
||||
// bottom crap
|
||||
wxButton* const quit_btn = new wxButton(panel, wxID_ANY, _("Quit Netplay"));
|
||||
quit_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnQuit, this);
|
||||
wxSizer* NetPlayDialog::CreateBottomGUI(wxWindow* parent)
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxBoxSizer* const bottom_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
if (is_hosting)
|
||||
if (m_is_hosting)
|
||||
{
|
||||
m_start_btn = new wxButton(panel, wxID_ANY, _("Start"));
|
||||
m_start_btn = new wxButton(parent, wxID_ANY, _("Start"));
|
||||
m_start_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnStart, this);
|
||||
bottom_szr->Add(m_start_btn);
|
||||
|
||||
bottom_szr->Add(new wxStaticText(panel, wxID_ANY, _("Buffer:")), 0, wxLEFT | wxCENTER, 5);
|
||||
wxStaticText* buffer_lbl = new wxStaticText(parent, wxID_ANY, _("Buffer:"));
|
||||
wxSpinCtrl* const padbuf_spin =
|
||||
new wxSpinCtrl(panel, wxID_ANY, std::to_string(INITIAL_PAD_BUFFER_SIZE), wxDefaultPosition,
|
||||
wxSize(64, -1), wxSP_ARROW_KEYS, 0, 200, INITIAL_PAD_BUFFER_SIZE);
|
||||
new wxSpinCtrl(parent, wxID_ANY, std::to_string(INITIAL_PAD_BUFFER_SIZE), wxDefaultPosition,
|
||||
wxDefaultSize, wxSP_ARROW_KEYS, 0, 200, INITIAL_PAD_BUFFER_SIZE);
|
||||
padbuf_spin->Bind(wxEVT_SPINCTRL, &NetPlayDialog::OnAdjustBuffer, this);
|
||||
bottom_szr->AddSpacer(3);
|
||||
bottom_szr->Add(padbuf_spin, 0, wxCENTER);
|
||||
bottom_szr->AddSpacer(5);
|
||||
m_memcard_write = new wxCheckBox(panel, wxID_ANY, _("Write to memcards/SD"));
|
||||
bottom_szr->Add(m_memcard_write, 0, wxCENTER);
|
||||
padbuf_spin->SetMinSize(WxUtils::GetTextWidgetMinSize(padbuf_spin));
|
||||
|
||||
m_memcard_write = new wxCheckBox(parent, wxID_ANY, _("Write to memcards/SD"));
|
||||
|
||||
bottom_szr->Add(m_start_btn, 0, wxALIGN_CENTER_VERTICAL);
|
||||
bottom_szr->Add(buffer_lbl, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
bottom_szr->Add(padbuf_spin, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
bottom_szr->Add(m_memcard_write, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
bottom_szr->AddSpacer(space5);
|
||||
}
|
||||
|
||||
bottom_szr->AddSpacer(5);
|
||||
m_record_chkbox = new wxCheckBox(panel, wxID_ANY, _("Record inputs"));
|
||||
bottom_szr->Add(m_record_chkbox, 0, wxCENTER);
|
||||
m_record_chkbox = new wxCheckBox(parent, wxID_ANY, _("Record inputs"));
|
||||
|
||||
bottom_szr->AddStretchSpacer(1);
|
||||
wxButton* quit_btn = new wxButton(parent, wxID_ANY, _("Quit Netplay"));
|
||||
quit_btn->Bind(wxEVT_BUTTON, &NetPlayDialog::OnQuit, this);
|
||||
|
||||
bottom_szr->Add(m_record_chkbox, 0, wxALIGN_CENTER_VERTICAL);
|
||||
bottom_szr->AddStretchSpacer();
|
||||
bottom_szr->Add(quit_btn);
|
||||
|
||||
// main sizer
|
||||
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
main_szr->Add(top_szr, 0, wxEXPAND | wxALL, 5);
|
||||
main_szr->Add(mid_szr, 1, wxEXPAND | wxLEFT | wxRIGHT, 5);
|
||||
main_szr->Add(bottom_szr, 0, wxEXPAND | wxALL, 5);
|
||||
|
||||
panel->SetSizerAndFit(main_szr);
|
||||
|
||||
main_szr->SetSizeHints(this);
|
||||
return bottom_szr;
|
||||
}
|
||||
|
||||
NetPlayDialog::~NetPlayDialog()
|
||||
|
@ -19,6 +19,7 @@ class wxButton;
|
||||
class wxCheckBox;
|
||||
class wxChoice;
|
||||
class wxListBox;
|
||||
class wxSizer;
|
||||
class wxStaticText;
|
||||
class wxString;
|
||||
class wxTextCtrl;
|
||||
@ -101,6 +102,13 @@ public:
|
||||
bool IsRecording() override;
|
||||
|
||||
private:
|
||||
void CreateGUI();
|
||||
wxSizer* CreateTopGUI(wxWindow* parent);
|
||||
wxSizer* CreateMiddleGUI(wxWindow* parent);
|
||||
wxSizer* CreateChatGUI(wxWindow* parent);
|
||||
wxSizer* CreatePlayerListGUI(wxWindow* parent);
|
||||
wxSizer* CreateBottomGUI(wxWindow* parent);
|
||||
|
||||
void OnChat(wxCommandEvent& event);
|
||||
void OnQuit(wxCommandEvent& event);
|
||||
void OnThread(wxThreadEvent& event);
|
||||
@ -133,7 +141,7 @@ private:
|
||||
wxStaticText* m_host_label;
|
||||
wxChoice* m_host_type_choice;
|
||||
wxButton* m_host_copy_btn;
|
||||
wxChoice* m_MD5_choice;
|
||||
wxChoice* m_MD5_choice = nullptr;
|
||||
MD5Dialog* m_MD5_dialog = nullptr;
|
||||
bool m_host_copy_btn_is_retry;
|
||||
bool m_is_hosting;
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <wx/choice.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
@ -10,79 +11,63 @@
|
||||
#include "Core/NetPlayProto.h"
|
||||
#include "Core/NetPlayServer.h"
|
||||
#include "DolphinWX/NetPlay/PadMapDialog.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
PadMapDialog::PadMapDialog(wxWindow* parent, NetPlayServer* server, NetPlayClient* client)
|
||||
: wxDialog(parent, wxID_ANY, _("Controller Ports")), m_pad_mapping(server->GetPadMapping()),
|
||||
m_wii_mapping(server->GetWiimoteMapping()), m_player_list(client->GetPlayers())
|
||||
{
|
||||
wxBoxSizer* const h_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
h_szr->AddSpacer(10);
|
||||
const int space5 = FromDIP(5);
|
||||
const int space10 = FromDIP(10);
|
||||
|
||||
wxGridBagSizer* pad_sizer = new wxGridBagSizer(space5, space10);
|
||||
|
||||
wxArrayString player_names;
|
||||
player_names.Add(_("None"));
|
||||
for (auto& player : m_player_list)
|
||||
player_names.Add(player->name);
|
||||
for (const auto& player : m_player_list)
|
||||
player_names.Add(StrToWxStr(player->name));
|
||||
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL);
|
||||
v_szr->Add(new wxStaticText(this, wxID_ANY, (wxString(_("GC Port ")) + (wxChar)('1' + i))), 1,
|
||||
wxALIGN_CENTER_HORIZONTAL);
|
||||
auto build_choice = [&](unsigned int base_idx, unsigned int idx, const PadMappingArray& mapping,
|
||||
const wxString& port_name) {
|
||||
pad_sizer->Add(new wxStaticText(this, wxID_ANY, wxString::Format("%s %d", port_name, idx + 1)),
|
||||
wxGBPosition(0, base_idx + idx), wxDefaultSpan, wxALIGN_CENTER);
|
||||
|
||||
m_map_cbox[i] = new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, player_names);
|
||||
m_map_cbox[i]->Bind(wxEVT_CHOICE, &PadMapDialog::OnAdjust, this);
|
||||
if (m_pad_mapping[i] == -1)
|
||||
{
|
||||
m_map_cbox[i]->Select(0);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int j = 0; j < m_player_list.size(); j++)
|
||||
{
|
||||
if (m_pad_mapping[i] == m_player_list[j]->pid)
|
||||
m_map_cbox[i]->Select(j + 1);
|
||||
}
|
||||
}
|
||||
|
||||
v_szr->Add(m_map_cbox[i], 1);
|
||||
|
||||
h_szr->Add(v_szr, 1, wxTOP | wxEXPAND, 20);
|
||||
h_szr->AddSpacer(10);
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
wxBoxSizer* const v_szr = new wxBoxSizer(wxVERTICAL);
|
||||
v_szr->Add(new wxStaticText(this, wxID_ANY, (wxString(_("Wiimote ")) + (wxChar)('1' + i))), 1,
|
||||
wxALIGN_CENTER_HORIZONTAL);
|
||||
|
||||
m_map_cbox[i + 4] =
|
||||
m_map_cbox[base_idx + idx] =
|
||||
new wxChoice(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, player_names);
|
||||
m_map_cbox[i + 4]->Bind(wxEVT_CHOICE, &PadMapDialog::OnAdjust, this);
|
||||
if (m_wii_mapping[i] == -1)
|
||||
{
|
||||
m_map_cbox[i + 4]->Select(0);
|
||||
}
|
||||
else
|
||||
m_map_cbox[base_idx + idx]->Select(0);
|
||||
m_map_cbox[base_idx + idx]->Bind(wxEVT_CHOICE, &PadMapDialog::OnAdjust, this);
|
||||
if (mapping[idx] != -1)
|
||||
{
|
||||
for (unsigned int j = 0; j < m_player_list.size(); j++)
|
||||
{
|
||||
if (m_wii_mapping[i] == m_player_list[j]->pid)
|
||||
m_map_cbox[i + 4]->Select(j + 1);
|
||||
if (m_pad_mapping[idx] == m_player_list[j]->pid)
|
||||
{
|
||||
m_map_cbox[base_idx + idx]->Select(j + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Combo boxes break on Windows when wxEXPAND-ed vertically but you can't control the
|
||||
// direction of expansion in a grid sizer. Solution is to wrap in a box sizer.
|
||||
wxBoxSizer* wrapper = new wxBoxSizer(wxHORIZONTAL);
|
||||
wrapper->Add(m_map_cbox[base_idx + idx], 1, wxALIGN_CENTER_VERTICAL);
|
||||
pad_sizer->Add(wrapper, wxGBPosition(1, base_idx + idx), wxDefaultSpan, wxEXPAND);
|
||||
};
|
||||
|
||||
v_szr->Add(m_map_cbox[i + 4], 1);
|
||||
|
||||
h_szr->Add(v_szr, 1, wxTOP | wxEXPAND, 20);
|
||||
h_szr->AddSpacer(10);
|
||||
for (unsigned int i = 0; i < 4; ++i)
|
||||
{
|
||||
// This looks a little weird but it's fine because we're using a grid bag sizer;
|
||||
// we can add columns in any order.
|
||||
build_choice(0, i, m_pad_mapping, _("GC Port"));
|
||||
build_choice(4, i, m_wii_mapping, _("Wiimote"));
|
||||
}
|
||||
|
||||
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
main_szr->Add(h_szr);
|
||||
main_szr->AddSpacer(5);
|
||||
main_szr->Add(CreateButtonSizer(wxOK), 0, wxEXPAND | wxLEFT | wxRIGHT, 20);
|
||||
main_szr->AddSpacer(5);
|
||||
main_szr->AddSpacer(space10);
|
||||
main_szr->Add(pad_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space10);
|
||||
main_szr->AddSpacer(space10);
|
||||
main_szr->Add(CreateButtonSizer(wxOK), 0, wxEXPAND | wxLEFT | wxRIGHT, space10);
|
||||
main_szr->AddSpacer(space5);
|
||||
SetSizerAndFit(main_szr);
|
||||
SetFocus();
|
||||
}
|
||||
|
@ -12,7 +12,9 @@
|
||||
class NetPlayClient;
|
||||
class NetPlayServer;
|
||||
class Player;
|
||||
class wxArrayString;
|
||||
class wxChoice;
|
||||
class wxSizer;
|
||||
|
||||
class PadMapDialog final : public wxDialog
|
||||
{
|
||||
|
@ -52,7 +52,8 @@ void CPatchAddEdit::CreateGUIControls(int _selection)
|
||||
|
||||
itCurEntry = tempEntries.begin();
|
||||
|
||||
wxBoxSizer* sEditPatch = new wxBoxSizer(wxVERTICAL);
|
||||
const int space5 = FromDIP(5);
|
||||
const int space10 = FromDIP(10);
|
||||
|
||||
wxStaticText* EditPatchNameText = new wxStaticText(this, wxID_ANY, _("Name:"));
|
||||
EditPatchName = new wxTextCtrl(this, wxID_ANY);
|
||||
@ -89,32 +90,38 @@ void CPatchAddEdit::CreateGUIControls(int _selection)
|
||||
EntryRemove->Disable();
|
||||
|
||||
wxBoxSizer* sEditPatchName = new wxBoxSizer(wxHORIZONTAL);
|
||||
sEditPatchName->Add(EditPatchNameText, 0, wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sEditPatchName->Add(EditPatchName, 1, wxEXPAND | wxALL, 5);
|
||||
sEditPatch->Add(sEditPatchName, 0, wxEXPAND);
|
||||
sEditPatchName->Add(EditPatchNameText, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sEditPatchName->Add(EditPatchName, 1, wxEXPAND | wxLEFT, space5);
|
||||
sbEntry = new wxStaticBoxSizer(wxVERTICAL, this,
|
||||
wxString::Format(_("Entry 1/%d"), (int)tempEntries.size()));
|
||||
currentItem = 1;
|
||||
|
||||
wxGridBagSizer* sgEntry = new wxGridBagSizer(0, 0);
|
||||
sgEntry->Add(EditPatchType, wxGBPosition(0, 0), wxGBSpan(1, 2), wxEXPAND | wxALL, 5);
|
||||
sgEntry->Add(EditPatchOffsetText, wxGBPosition(1, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sgEntry->Add(EditPatchOffset, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
sgEntry->Add(EditPatchValueText, wxGBPosition(2, 0), wxGBSpan(1, 1),
|
||||
wxALIGN_CENTER_VERTICAL | wxALL, 5);
|
||||
sgEntry->Add(EditPatchValue, wxGBPosition(2, 1), wxGBSpan(1, 1), wxEXPAND | wxALL, 5);
|
||||
sgEntry->Add(EntrySelection, wxGBPosition(0, 2), wxGBSpan(3, 1), wxEXPAND | wxALL, 5);
|
||||
wxGridBagSizer* sgEntry = new wxGridBagSizer(space10, space10);
|
||||
sgEntry->Add(EditPatchType, wxGBPosition(0, 0), wxGBSpan(1, 2), wxEXPAND);
|
||||
sgEntry->Add(EditPatchOffsetText, wxGBPosition(1, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sgEntry->Add(EditPatchOffset, wxGBPosition(1, 1), wxGBSpan(1, 1), wxEXPAND);
|
||||
sgEntry->Add(EditPatchValueText, wxGBPosition(2, 0), wxGBSpan(1, 1), wxALIGN_CENTER_VERTICAL);
|
||||
sgEntry->Add(EditPatchValue, wxGBPosition(2, 1), wxGBSpan(1, 1), wxEXPAND);
|
||||
sgEntry->Add(EntrySelection, wxGBPosition(0, 2), wxGBSpan(3, 1), wxEXPAND);
|
||||
sgEntry->AddGrowableCol(1);
|
||||
|
||||
wxBoxSizer* sEntryAddRemove = new wxBoxSizer(wxHORIZONTAL);
|
||||
sEntryAddRemove->Add(EntryAdd, 0, wxALL, 5);
|
||||
sEntryAddRemove->Add(EntryRemove, 0, wxALL, 5);
|
||||
sbEntry->Add(sgEntry, 0, wxEXPAND);
|
||||
sbEntry->Add(sEntryAddRemove, 0, wxEXPAND);
|
||||
sEntryAddRemove->Add(EntryAdd, 0, wxALIGN_CENTER_VERTICAL);
|
||||
sEntryAddRemove->Add(EntryRemove, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
sbEntry->AddSpacer(space5);
|
||||
sbEntry->Add(sgEntry, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbEntry->AddSpacer(space5);
|
||||
sbEntry->Add(sEntryAddRemove, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sbEntry->AddSpacer(space5);
|
||||
|
||||
sEditPatch->Add(sbEntry, 0, wxEXPAND | wxALL, 5);
|
||||
sEditPatch->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxBoxSizer* sEditPatch = new wxBoxSizer(wxVERTICAL);
|
||||
sEditPatch->AddSpacer(space5);
|
||||
sEditPatch->Add(sEditPatchName, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sEditPatch->AddSpacer(space5);
|
||||
sEditPatch->Add(sbEntry, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sEditPatch->AddSpacer(space5);
|
||||
sEditPatch->Add(CreateButtonSizer(wxOK | wxCANCEL), 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sEditPatch->AddSpacer(space5);
|
||||
SetSizerAndFit(sEditPatch);
|
||||
SetFocus();
|
||||
}
|
||||
|
@ -2,15 +2,13 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <math.h>
|
||||
#include <unordered_map>
|
||||
#include <cmath>
|
||||
|
||||
#include <wx/button.h>
|
||||
#include <wx/checkbox.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/stattext.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
@ -37,45 +35,54 @@ PostProcessingConfigDiag::PostProcessingConfigDiag(wxWindow* parent, const std::
|
||||
|
||||
// Create our UI classes
|
||||
const PostProcessingShaderConfiguration::ConfigMap& config_map = m_post_processor->GetOptions();
|
||||
std::vector<std::unique_ptr<ConfigGrouping>> config_groups;
|
||||
config_groups.reserve(config_map.size());
|
||||
m_config_map.reserve(config_map.size());
|
||||
for (const auto& it : config_map)
|
||||
{
|
||||
std::unique_ptr<ConfigGrouping> group;
|
||||
if (it.second.m_type ==
|
||||
PostProcessingShaderConfiguration::ConfigurationOption::OptionType::OPTION_BOOL)
|
||||
{
|
||||
ConfigGrouping* group =
|
||||
new ConfigGrouping(ConfigGrouping::WidgetType::TYPE_TOGGLE, it.second.m_gui_name,
|
||||
it.first, it.second.m_dependent_option, &it.second);
|
||||
m_config_map[it.first] = group;
|
||||
group = std::make_unique<ConfigGrouping>(ConfigGrouping::WidgetType::TYPE_TOGGLE,
|
||||
it.second.m_gui_name, it.first,
|
||||
it.second.m_dependent_option, &it.second);
|
||||
}
|
||||
else
|
||||
{
|
||||
ConfigGrouping* group =
|
||||
new ConfigGrouping(ConfigGrouping::WidgetType::TYPE_SLIDER, it.second.m_gui_name,
|
||||
it.first, it.second.m_dependent_option, &it.second);
|
||||
m_config_map[it.first] = group;
|
||||
group = std::make_unique<ConfigGrouping>(ConfigGrouping::WidgetType::TYPE_SLIDER,
|
||||
it.second.m_gui_name, it.first,
|
||||
it.second.m_dependent_option, &it.second);
|
||||
}
|
||||
m_config_map[it.first] = group.get();
|
||||
config_groups.emplace_back(std::move(group));
|
||||
}
|
||||
|
||||
// Arrange our vectors based on dependency
|
||||
for (const auto& it : m_config_map)
|
||||
for (auto& group : config_groups)
|
||||
{
|
||||
const std::string parent_name = it.second->GetParent();
|
||||
if (parent_name.size())
|
||||
const std::string& parent_name = group->GetParent();
|
||||
if (parent_name.empty())
|
||||
{
|
||||
// Since it depends on a different object, push it to a parent's object
|
||||
m_config_map[parent_name]->AddChild(m_config_map[it.first]);
|
||||
// It doesn't have a parent, just push it to the vector
|
||||
m_config_groups.emplace_back(std::move(group));
|
||||
}
|
||||
else
|
||||
{
|
||||
// It doesn't have a child, just push it to the vector
|
||||
m_config_groups.push_back(m_config_map[it.first]);
|
||||
// Since it depends on a different object, push it to a parent's object
|
||||
m_config_map[parent_name]->AddChild(std::move(group));
|
||||
}
|
||||
}
|
||||
config_groups.clear(); // Full of null unique_ptrs now
|
||||
config_groups.shrink_to_fit();
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
const int space10 = FromDIP(10);
|
||||
|
||||
// Generate our UI
|
||||
wxNotebook* const notebook = new wxNotebook(this, wxID_ANY);
|
||||
wxPanel* const page_general = new wxPanel(notebook);
|
||||
wxFlexGridSizer* const szr_general = new wxFlexGridSizer(2, 5, 5);
|
||||
wxFlexGridSizer* const szr_general = new wxFlexGridSizer(2, space5, space5);
|
||||
|
||||
// Now let's actually populate our window with our information
|
||||
bool add_general_page = false;
|
||||
@ -85,7 +92,8 @@ PostProcessingConfigDiag::PostProcessingConfigDiag(wxWindow* parent, const std::
|
||||
{
|
||||
// Options with children get their own tab
|
||||
wxPanel* const page_option = new wxPanel(notebook);
|
||||
wxFlexGridSizer* const szr_option = new wxFlexGridSizer(2, 10, 5);
|
||||
wxBoxSizer* const wrap_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
wxFlexGridSizer* const szr_option = new wxFlexGridSizer(2, space10, space5);
|
||||
it->GenerateUI(this, page_option, szr_option);
|
||||
|
||||
// Add all the children
|
||||
@ -93,8 +101,11 @@ PostProcessingConfigDiag::PostProcessingConfigDiag(wxWindow* parent, const std::
|
||||
{
|
||||
child->GenerateUI(this, page_option, szr_option);
|
||||
}
|
||||
page_option->SetSizerAndFit(szr_option);
|
||||
notebook->AddPage(page_option, _(it->GetGUIName()));
|
||||
wrap_sizer->AddSpacer(space5);
|
||||
wrap_sizer->Add(szr_option, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
wrap_sizer->AddSpacer(space5);
|
||||
page_option->SetSizerAndFit(wrap_sizer);
|
||||
notebook->AddPage(page_option, it->GetGUIName());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -110,20 +121,30 @@ PostProcessingConfigDiag::PostProcessingConfigDiag(wxWindow* parent, const std::
|
||||
|
||||
if (add_general_page)
|
||||
{
|
||||
page_general->SetSizerAndFit(szr_general);
|
||||
wxBoxSizer* const wrap_sizer = new wxBoxSizer(wxVERTICAL);
|
||||
wrap_sizer->AddSpacer(space5);
|
||||
wrap_sizer->Add(szr_general, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
wrap_sizer->AddSpacer(space5);
|
||||
|
||||
page_general->SetSizerAndFit(wrap_sizer);
|
||||
notebook->InsertPage(0, page_general, _("General"));
|
||||
}
|
||||
|
||||
// Close Button
|
||||
wxButton* const btn_close = new wxButton(this, wxID_OK, _("Close"));
|
||||
btn_close->Bind(wxEVT_BUTTON, &PostProcessingConfigDiag::Event_ClickClose, this);
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, &PostProcessingConfigDiag::Event_Close, this);
|
||||
wxStdDialogButtonSizer* const btn_strip = CreateStdDialogButtonSizer(wxOK | wxNO_DEFAULT);
|
||||
btn_strip->GetAffirmativeButton()->SetLabel(_("Close"));
|
||||
SetEscapeId(wxID_OK); // Treat closing the window by 'X' or hitting escape as 'OK'
|
||||
|
||||
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5);
|
||||
szr_main->Add(btn_close, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_main->AddSpacer(space5);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_main->AddSpacer(space5);
|
||||
szr_main->Add(btn_strip, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_main->AddSpacer(space5);
|
||||
szr_main->SetMinSize(FromDIP(wxSize(400, -1)));
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(szr_main);
|
||||
Center();
|
||||
SetFocus();
|
||||
@ -145,7 +166,7 @@ void PostProcessingConfigDiag::ConfigGrouping::GenerateUI(PostProcessingConfigDi
|
||||
{
|
||||
if (m_type == WidgetType::TYPE_TOGGLE)
|
||||
{
|
||||
m_option_checkbox = new wxCheckBox(parent, wxID_ANY, _(m_gui_name));
|
||||
m_option_checkbox = new wxCheckBox(parent, wxID_ANY, m_gui_name);
|
||||
m_option_checkbox->SetValue(m_config_option->m_bool_value);
|
||||
m_option_checkbox->Bind(wxEVT_CHECKBOX, &PostProcessingConfigDiag::Event_CheckBox, dialog,
|
||||
wxID_ANY, wxID_ANY, new UserEventData(m_option));
|
||||
@ -162,8 +183,8 @@ void PostProcessingConfigDiag::ConfigGrouping::GenerateUI(PostProcessingConfigDi
|
||||
else
|
||||
vector_size = m_config_option->m_float_values.size();
|
||||
|
||||
wxFlexGridSizer* const szr_values = new wxFlexGridSizer(vector_size + 1, 0, 0);
|
||||
wxStaticText* const option_static_text = new wxStaticText(parent, wxID_ANY, _(m_gui_name));
|
||||
wxFlexGridSizer* const szr_values = new wxFlexGridSizer(vector_size + 1);
|
||||
wxStaticText* const option_static_text = new wxStaticText(parent, wxID_ANY, m_gui_name);
|
||||
sizer->Add(option_static_text);
|
||||
|
||||
for (size_t i = 0; i < vector_size; ++i)
|
||||
@ -185,7 +206,7 @@ void PostProcessingConfigDiag::ConfigGrouping::GenerateUI(PostProcessingConfigDi
|
||||
// This may not be 100% spot on accurate since developers can have odd stepping intervals
|
||||
// set.
|
||||
// Round up so if it is outside our range, then set it to the minimum or maximum
|
||||
steps = ceil(range / (double)m_config_option->m_integer_step_values[i]);
|
||||
steps = std::ceil(range / (double)m_config_option->m_integer_step_values[i]);
|
||||
|
||||
// Default value is just the currently set value here
|
||||
current_value = m_config_option->m_integer_values[i];
|
||||
@ -196,7 +217,7 @@ void PostProcessingConfigDiag::ConfigGrouping::GenerateUI(PostProcessingConfigDi
|
||||
// Same as above but with floats
|
||||
float range =
|
||||
m_config_option->m_float_max_values[i] - m_config_option->m_float_min_values[i];
|
||||
steps = ceil(range / m_config_option->m_float_step_values[i]);
|
||||
steps = std::ceil(range / m_config_option->m_float_step_values[i]);
|
||||
|
||||
// We need to convert our default float value from a float to the nearest step value range
|
||||
current_value =
|
||||
@ -204,8 +225,9 @@ void PostProcessingConfigDiag::ConfigGrouping::GenerateUI(PostProcessingConfigDi
|
||||
string_value = std::to_string(m_config_option->m_float_values[i]);
|
||||
}
|
||||
|
||||
wxSlider* slider = new wxSlider(parent, wxID_ANY, current_value, 0, steps, wxDefaultPosition,
|
||||
wxSize(200, -1), wxSL_HORIZONTAL | wxSL_BOTTOM);
|
||||
DolphinSlider* slider =
|
||||
new DolphinSlider(parent, wxID_ANY, current_value, 0, steps, wxDefaultPosition,
|
||||
parent->FromDIP(wxSize(200, -1)), wxSL_HORIZONTAL | wxSL_BOTTOM);
|
||||
wxTextCtrl* text_ctrl = new wxTextCtrl(parent, wxID_ANY, string_value);
|
||||
|
||||
// Disable the textctrl, it's only there to show the absolute value from the slider
|
||||
@ -222,18 +244,18 @@ void PostProcessingConfigDiag::ConfigGrouping::GenerateUI(PostProcessingConfigDi
|
||||
|
||||
if (vector_size == 1)
|
||||
{
|
||||
szr_values->Add(m_option_sliders[0], wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
|
||||
szr_values->Add(m_option_text_ctrls[0]);
|
||||
szr_values->Add(m_option_sliders[0], 0, wxALIGN_CENTER_VERTICAL);
|
||||
szr_values->Add(m_option_text_ctrls[0], 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
sizer->Add(szr_values);
|
||||
}
|
||||
else
|
||||
{
|
||||
wxFlexGridSizer* const szr_inside = new wxFlexGridSizer(2, 0, 0);
|
||||
wxFlexGridSizer* const szr_inside = new wxFlexGridSizer(2);
|
||||
for (size_t i = 0; i < vector_size; ++i)
|
||||
{
|
||||
szr_inside->Add(m_option_sliders[i], wxSizerFlags().Align(wxALIGN_CENTER_VERTICAL));
|
||||
szr_inside->Add(m_option_text_ctrls[i]);
|
||||
szr_inside->Add(m_option_sliders[i], 0, wxALIGN_CENTER_VERTICAL);
|
||||
szr_inside->Add(m_option_text_ctrls[i], 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
szr_values->Add(szr_inside);
|
||||
@ -313,13 +335,3 @@ void PostProcessingConfigDiag::Event_Slider(wxCommandEvent& ev)
|
||||
}
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void PostProcessingConfigDiag::Event_ClickClose(wxCommandEvent&)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void PostProcessingConfigDiag::Event_Close(wxCloseEvent& ev)
|
||||
{
|
||||
EndModal(wxID_OK);
|
||||
}
|
||||
|
@ -4,14 +4,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/textctrl.h>
|
||||
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
|
||||
class wxButton;
|
||||
@ -54,9 +56,12 @@ private:
|
||||
{
|
||||
}
|
||||
|
||||
void AddChild(ConfigGrouping* child) { m_children.push_back(child); }
|
||||
void AddChild(std::unique_ptr<ConfigGrouping>&& child)
|
||||
{
|
||||
m_children.emplace_back(std::move(child));
|
||||
}
|
||||
bool HasChildren() { return m_children.size() != 0; }
|
||||
std::vector<ConfigGrouping*>& GetChildren() { return m_children; }
|
||||
const std::vector<std::unique_ptr<ConfigGrouping>>& GetChildren() { return m_children; }
|
||||
// Gets the string that is shown in the UI for the option
|
||||
const std::string& GetGUIName() { return m_gui_name; }
|
||||
// Gets the option name for use in the shader
|
||||
@ -86,21 +91,19 @@ private:
|
||||
|
||||
// For TYPE_SLIDER
|
||||
// Can have up to 4
|
||||
std::vector<wxSlider*> m_option_sliders;
|
||||
std::vector<DolphinSlider*> m_option_sliders;
|
||||
std::vector<wxTextCtrl*> m_option_text_ctrls;
|
||||
|
||||
std::vector<ConfigGrouping*> m_children;
|
||||
std::vector<std::unique_ptr<ConfigGrouping>> m_children;
|
||||
};
|
||||
|
||||
// WX UI things
|
||||
void Event_Close(wxCloseEvent&);
|
||||
void Event_ClickClose(wxCommandEvent&);
|
||||
void Event_Slider(wxCommandEvent& ev);
|
||||
void Event_CheckBox(wxCommandEvent& ev);
|
||||
|
||||
const std::string& m_shader;
|
||||
PostProcessingShaderConfiguration* m_post_processor;
|
||||
|
||||
std::map<std::string, ConfigGrouping*> m_config_map;
|
||||
std::vector<ConfigGrouping*> m_config_groups;
|
||||
std::unordered_map<std::string, ConfigGrouping*> m_config_map;
|
||||
std::vector<std::unique_ptr<ConfigGrouping>> m_config_groups;
|
||||
};
|
||||
|
@ -36,11 +36,12 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std
|
||||
wxString(wxString::Format(_("Dolphin %s Graphics Configuration"), title)))
|
||||
{
|
||||
VideoConfig& vconfig = g_Config;
|
||||
|
||||
vconfig.Load(File::GetUserPath(D_CONFIG_IDX) + "GFX.ini");
|
||||
|
||||
wxNotebook* const notebook = new wxNotebook(this, wxID_ANY);
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// -- GENERAL --
|
||||
{
|
||||
wxPanel* const page_general = new wxPanel(notebook);
|
||||
@ -51,9 +52,11 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std
|
||||
{
|
||||
wxStaticBoxSizer* const group_rendering =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Rendering"));
|
||||
szr_general->Add(group_rendering, 0, wxEXPAND | wxALL, 5);
|
||||
wxGridSizer* const szr_rendering = new wxGridSizer(2, 5, 5);
|
||||
group_rendering->Add(szr_rendering, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->Add(group_rendering, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
wxGridSizer* const szr_rendering = new wxGridSizer(2, space5, space5);
|
||||
group_rendering->Add(szr_rendering, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_rendering->AddSpacer(space5);
|
||||
|
||||
// backend
|
||||
wxStaticText* const label_backend = new wxStaticText(page_general, wxID_ANY, _("Backend:"));
|
||||
@ -68,8 +71,8 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std
|
||||
choice_backend->SetStringSelection(StrToWxStr(g_video_backend->GetName()));
|
||||
choice_backend->Bind(wxEVT_CHOICE, &SoftwareVideoConfigDialog::Event_Backend, this);
|
||||
|
||||
szr_rendering->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
szr_rendering->Add(choice_backend, 1, 0, 0);
|
||||
szr_rendering->Add(label_backend, 0, wxALIGN_CENTER_VERTICAL);
|
||||
szr_rendering->Add(choice_backend, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
if (Core::GetState() != Core::CORE_UNINITIALIZED)
|
||||
{
|
||||
@ -86,9 +89,11 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std
|
||||
{
|
||||
wxStaticBoxSizer* const group_info =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Overlay Information"));
|
||||
szr_general->Add(group_info, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxGridSizer* const szr_info = new wxGridSizer(2, 5, 5);
|
||||
group_info->Add(szr_info, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->Add(group_info, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
wxGridSizer* const szr_info = new wxGridSizer(2, space5, space5);
|
||||
group_info->Add(szr_info, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_info->AddSpacer(space5);
|
||||
|
||||
szr_info->Add(
|
||||
new SettingCheckBox(page_general, _("Various Statistics"), "", vconfig.bOverlayStats));
|
||||
@ -98,9 +103,11 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std
|
||||
{
|
||||
wxStaticBoxSizer* const group_utility =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Utility"));
|
||||
szr_general->Add(group_utility, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxGridSizer* const szr_utility = new wxGridSizer(2, 5, 5);
|
||||
group_utility->Add(szr_utility, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->Add(group_utility, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
wxGridSizer* const szr_utility = new wxGridSizer(2, space5, space5);
|
||||
group_utility->Add(szr_utility, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_utility->AddSpacer(space5);
|
||||
|
||||
szr_utility->Add(
|
||||
new SettingCheckBox(page_general, _("Dump Textures"), "", vconfig.bDumpTextures));
|
||||
@ -110,10 +117,12 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std
|
||||
// - debug only
|
||||
wxStaticBoxSizer* const group_debug_only_utility =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, page_general, _("Debug Only"));
|
||||
group_utility->Add(group_debug_only_utility, 0, wxEXPAND | wxBOTTOM, 5);
|
||||
wxGridSizer* const szr_debug_only_utility = new wxGridSizer(2, 5, 5);
|
||||
group_debug_only_utility->Add(szr_debug_only_utility, 1,
|
||||
wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_utility->Add(group_debug_only_utility, 0, wxEXPAND);
|
||||
group_utility->AddSpacer(space5);
|
||||
wxGridSizer* const szr_debug_only_utility = new wxGridSizer(2, space5, space5);
|
||||
group_debug_only_utility->AddSpacer(space5);
|
||||
group_debug_only_utility->Add(szr_debug_only_utility, 0, wxEXPAND | wxBOTTOM, space5);
|
||||
group_debug_only_utility->AddSpacer(space5);
|
||||
|
||||
szr_debug_only_utility->Add(
|
||||
new SettingCheckBox(page_general, _("Dump TEV Stages"), "", vconfig.bDumpTevStages));
|
||||
@ -125,23 +134,33 @@ SoftwareVideoConfigDialog::SoftwareVideoConfigDialog(wxWindow* parent, const std
|
||||
{
|
||||
wxStaticBoxSizer* const group_misc =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Drawn Object Range"));
|
||||
szr_general->Add(group_misc, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxFlexGridSizer* const szr_misc = new wxFlexGridSizer(2, 5, 5);
|
||||
group_misc->Add(szr_misc, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->Add(group_misc, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
wxFlexGridSizer* const szr_misc = new wxFlexGridSizer(2, space5, space5);
|
||||
group_misc->Add(szr_misc, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_misc->AddSpacer(space5);
|
||||
|
||||
szr_misc->Add(
|
||||
new IntegerSetting<int>(page_general, _("Start"), vconfig.drawStart, 0, 100000));
|
||||
szr_misc->Add(new IntegerSetting<int>(page_general, _("End"), vconfig.drawEnd, 0, 100000));
|
||||
}
|
||||
|
||||
szr_general->AddSpacer(space5);
|
||||
page_general->SetSizerAndFit(szr_general);
|
||||
}
|
||||
|
||||
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5);
|
||||
szr_main->Add(new wxButton(this, wxID_OK, _("Close"), wxDefaultPosition), 0,
|
||||
wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
|
||||
wxStdDialogButtonSizer* const btn_sizer = CreateStdDialogButtonSizer(wxOK | wxNO_DEFAULT);
|
||||
btn_sizer->GetAffirmativeButton()->SetLabel(_("Close"));
|
||||
|
||||
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
|
||||
szr_main->AddSpacer(space5);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_main->AddSpacer(space5);
|
||||
szr_main->Add(btn_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_main->AddSpacer(space5);
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(szr_main);
|
||||
Center();
|
||||
SetFocus();
|
||||
|
@ -2,6 +2,8 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cstddef>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/checkbox.h>
|
||||
@ -23,7 +25,9 @@
|
||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||
#include "Core/HW/WiimoteReal/WiimoteReal.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "DolphinWX/TASInputDlg.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "InputCommon/GCPadStatus.h"
|
||||
#include "InputCommon/InputConfig.h"
|
||||
|
||||
@ -63,37 +67,38 @@ void TASInputDlg::CreateBaseLayout()
|
||||
m_controls[0] = &m_main_stick.x_cont;
|
||||
m_controls[1] = &m_main_stick.y_cont;
|
||||
|
||||
m_a = CreateButton("A");
|
||||
m_a = CreateButton(_("A"));
|
||||
m_a.checkbox->SetClientData(&m_a);
|
||||
m_b = CreateButton("B");
|
||||
m_b = CreateButton(_("B"));
|
||||
m_b.checkbox->SetClientData(&m_b);
|
||||
m_dpad_up = CreateButton("Up");
|
||||
m_dpad_up = CreateButton(_("Up"));
|
||||
m_dpad_up.checkbox->SetClientData(&m_dpad_up);
|
||||
m_dpad_right = CreateButton("Right");
|
||||
m_dpad_right = CreateButton(_("Right"));
|
||||
m_dpad_right.checkbox->SetClientData(&m_dpad_right);
|
||||
m_dpad_down = CreateButton("Down");
|
||||
m_dpad_down = CreateButton(_("Down"));
|
||||
m_dpad_down.checkbox->SetClientData(&m_dpad_down);
|
||||
m_dpad_left = CreateButton("Left");
|
||||
m_dpad_left = CreateButton(_("Left"));
|
||||
m_dpad_left.checkbox->SetClientData(&m_dpad_left);
|
||||
|
||||
m_buttons_dpad = new wxGridSizer(3);
|
||||
m_buttons_dpad->AddSpacer(20);
|
||||
const int space20 = FromDIP(20);
|
||||
m_buttons_dpad->Add(space20, space20);
|
||||
m_buttons_dpad->Add(m_dpad_up.checkbox);
|
||||
m_buttons_dpad->AddSpacer(20);
|
||||
m_buttons_dpad->Add(space20, space20);
|
||||
m_buttons_dpad->Add(m_dpad_left.checkbox);
|
||||
m_buttons_dpad->AddSpacer(20);
|
||||
m_buttons_dpad->Add(space20, space20);
|
||||
m_buttons_dpad->Add(m_dpad_right.checkbox);
|
||||
m_buttons_dpad->AddSpacer(20);
|
||||
m_buttons_dpad->Add(space20, space20);
|
||||
m_buttons_dpad->Add(m_dpad_down.checkbox);
|
||||
m_buttons_dpad->AddSpacer(20);
|
||||
m_buttons_dpad->Add(space20, space20);
|
||||
}
|
||||
|
||||
const int TASInputDlg::m_gc_pad_buttons_bitmask[12] = {
|
||||
static constexpr int s_gc_pad_buttons_bitmask[12] = {
|
||||
PAD_BUTTON_DOWN, PAD_BUTTON_UP, PAD_BUTTON_LEFT, PAD_BUTTON_RIGHT,
|
||||
PAD_BUTTON_A, PAD_BUTTON_B, PAD_BUTTON_X, PAD_BUTTON_Y,
|
||||
PAD_TRIGGER_Z, PAD_TRIGGER_L, PAD_TRIGGER_R, PAD_BUTTON_START};
|
||||
|
||||
const int TASInputDlg::m_wii_buttons_bitmask[11] = {
|
||||
static constexpr int s_wii_buttons_bitmask[11] = {
|
||||
WiimoteEmu::Wiimote::PAD_DOWN, WiimoteEmu::Wiimote::PAD_UP,
|
||||
WiimoteEmu::Wiimote::PAD_LEFT, WiimoteEmu::Wiimote::PAD_RIGHT,
|
||||
WiimoteEmu::Wiimote::BUTTON_A, WiimoteEmu::Wiimote::BUTTON_B,
|
||||
@ -102,7 +107,7 @@ const int TASInputDlg::m_wii_buttons_bitmask[11] = {
|
||||
WiimoteEmu::Wiimote::BUTTON_HOME,
|
||||
};
|
||||
|
||||
const int TASInputDlg::m_cc_buttons_bitmask[15] = {
|
||||
static constexpr int s_cc_buttons_bitmask[15] = {
|
||||
WiimoteEmu::Classic::PAD_DOWN, WiimoteEmu::Classic::PAD_UP,
|
||||
WiimoteEmu::Classic::PAD_LEFT, WiimoteEmu::Classic::PAD_RIGHT,
|
||||
WiimoteEmu::Classic::BUTTON_A, WiimoteEmu::Classic::BUTTON_B,
|
||||
@ -113,13 +118,11 @@ const int TASInputDlg::m_cc_buttons_bitmask[15] = {
|
||||
WiimoteEmu::Classic::BUTTON_HOME,
|
||||
};
|
||||
|
||||
const std::string TASInputDlg::m_cc_button_names[] = {
|
||||
"Down", "Up", "Left", "Right", "A", "B", "X", "Y", "+", "-", "L", "R", "ZR", "ZL", "Home"};
|
||||
|
||||
void TASInputDlg::CreateWiiLayout(int num)
|
||||
{
|
||||
if (m_has_layout)
|
||||
return;
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
CreateBaseLayout();
|
||||
|
||||
@ -142,23 +145,17 @@ void TASInputDlg::CreateWiiLayout(int num)
|
||||
wxStaticBoxSizer* const axisBox =
|
||||
CreateAccelLayout(&m_x_cont, &m_y_cont, &m_z_cont, _("Orientation"));
|
||||
|
||||
wxStaticBoxSizer* const m_buttons_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Buttons"));
|
||||
wxGridSizer* const m_buttons_grid = new wxGridSizer(4);
|
||||
|
||||
m_plus = CreateButton("+");
|
||||
m_plus = CreateButton(_("+"));
|
||||
m_plus.checkbox->SetClientData(&m_plus);
|
||||
m_minus = CreateButton("-");
|
||||
m_minus = CreateButton(_("-"));
|
||||
m_minus.checkbox->SetClientData(&m_minus);
|
||||
m_one = CreateButton("1");
|
||||
m_one = CreateButton(_("1"));
|
||||
m_one.checkbox->SetClientData(&m_one);
|
||||
m_two = CreateButton("2");
|
||||
m_two = CreateButton(_("2"));
|
||||
m_two.checkbox->SetClientData(&m_two);
|
||||
m_home = CreateButton("Home");
|
||||
m_home = CreateButton(_("Home"));
|
||||
m_home.checkbox->SetClientData(&m_home);
|
||||
|
||||
m_main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
m_wiimote_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_ext_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_cc_szr = CreateCCLayout();
|
||||
|
||||
if (Core::IsRunning())
|
||||
@ -196,12 +193,10 @@ void TASInputDlg::CreateWiiLayout(int num)
|
||||
wxStaticBoxSizer* const nunchukaxisBox =
|
||||
CreateAccelLayout(&m_nx_cont, &m_ny_cont, &m_nz_cont, _("Nunchuk orientation"));
|
||||
|
||||
m_c = CreateButton("C");
|
||||
m_c = CreateButton(_("C"));
|
||||
m_c.checkbox->SetClientData(&m_c);
|
||||
m_z = CreateButton("Z");
|
||||
m_z = CreateButton(_("Z"));
|
||||
m_z.checkbox->SetClientData(&m_z);
|
||||
m_ext_szr->Add(m_c_stick_szr, 0, wxLEFT | wxBOTTOM | wxRIGHT, 5);
|
||||
m_ext_szr->Add(nunchukaxisBox);
|
||||
|
||||
for (Control* const control : m_controls)
|
||||
{
|
||||
@ -209,21 +204,35 @@ void TASInputDlg::CreateWiiLayout(int num)
|
||||
control->slider->Bind(wxEVT_RIGHT_UP, &TASInputDlg::OnRightClickSlider, this);
|
||||
}
|
||||
|
||||
m_ext_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_ext_szr->Add(m_c_stick_szr, 0, wxBOTTOM, space5);
|
||||
m_ext_szr->AddSpacer(space5);
|
||||
m_ext_szr->Add(nunchukaxisBox, 0, wxBOTTOM, space5);
|
||||
|
||||
wxGridSizer* const buttons_grid = new wxGridSizer(4);
|
||||
for (unsigned int i = 4; i < ArraySize(m_buttons); ++i)
|
||||
if (m_buttons[i] != nullptr)
|
||||
m_buttons_grid->Add(m_buttons[i]->checkbox);
|
||||
m_buttons_grid->AddSpacer(5);
|
||||
buttons_grid->Add(m_buttons[i]->checkbox);
|
||||
buttons_grid->Add(space5, space5);
|
||||
|
||||
m_buttons_box->Add(m_buttons_grid);
|
||||
m_buttons_box->Add(m_buttons_dpad);
|
||||
wxStaticBoxSizer* const buttons_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Buttons"));
|
||||
buttons_box->Add(buttons_grid);
|
||||
buttons_box->Add(m_buttons_dpad, 0, wxTOP, space5);
|
||||
|
||||
m_wiimote_szr->Add(m_main_stick_szr, 0, wxALL, 5);
|
||||
m_wiimote_szr->Add(axisBox, 0, wxTOP | wxRIGHT, 5);
|
||||
m_wiimote_szr->Add(m_buttons_box, 0, wxTOP | wxRIGHT, 5);
|
||||
m_main_szr->Add(m_wiimote_szr);
|
||||
m_main_szr->Add(m_ext_szr);
|
||||
m_main_szr->Add(m_cc_szr);
|
||||
m_wiimote_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_wiimote_szr->AddSpacer(space5);
|
||||
m_wiimote_szr->Add(m_main_stick_szr);
|
||||
m_wiimote_szr->Add(axisBox, 0, wxLEFT, space5);
|
||||
m_wiimote_szr->Add(buttons_box, 0, wxLEFT, space5);
|
||||
m_wiimote_szr->AddSpacer(space5);
|
||||
|
||||
// NOTE: Not all of these are visible at the same time.
|
||||
m_main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
m_main_szr->Add(m_wiimote_szr, 0, wxTOP | wxBOTTOM, space5);
|
||||
m_main_szr->Add(m_ext_szr, 0, wxLEFT | wxRIGHT, space5);
|
||||
m_main_szr->Add(m_cc_szr, 0, wxLEFT | wxRIGHT, space5);
|
||||
|
||||
SetSizer(m_main_szr);
|
||||
HandleExtensionChange();
|
||||
FinishLayout();
|
||||
}
|
||||
@ -239,11 +248,12 @@ void TASInputDlg::FinishLayout()
|
||||
|
||||
wxBoxSizer* TASInputDlg::CreateCCLayout()
|
||||
{
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
|
||||
for (size_t i = 0; i < ArraySize(m_cc_buttons); ++i)
|
||||
const std::array<wxString, 15> button_names{{_("Down"), _("Up"), _("Left"), _("Right"), _("A"),
|
||||
_("B"), _("X"), _("Y"), _("+"), _("-"), _("L"),
|
||||
_("R"), _("ZR"), _("ZL"), _("Home")}};
|
||||
for (size_t i = 0; i < button_names.size(); ++i)
|
||||
{
|
||||
m_cc_buttons[i] = CreateButton(m_cc_button_names[i]);
|
||||
m_cc_buttons[i] = CreateButton(button_names[i]);
|
||||
m_cc_buttons[i].checkbox->SetClientData(&m_cc_buttons[i]);
|
||||
}
|
||||
|
||||
@ -265,6 +275,9 @@ wxBoxSizer* TASInputDlg::CreateCCLayout()
|
||||
m_cc_l = CreateControl(wxSL_VERTICAL, -1, 100, false, 31, 0);
|
||||
m_cc_r = CreateControl(wxSL_VERTICAL, -1, 100, false, 31, 0);
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
const int space20 = FromDIP(20);
|
||||
|
||||
wxStaticBoxSizer* const shoulder_box =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, this, _("Shoulder Buttons"));
|
||||
shoulder_box->Add(m_cc_l.slider, 0, wxALIGN_CENTER_VERTICAL);
|
||||
@ -272,32 +285,37 @@ wxBoxSizer* TASInputDlg::CreateCCLayout()
|
||||
shoulder_box->Add(m_cc_r.slider, 0, wxALIGN_CENTER_VERTICAL);
|
||||
shoulder_box->Add(m_cc_r.text, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxStaticBoxSizer* const cc_buttons_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Buttons"));
|
||||
wxGridSizer* const cc_buttons_grid = new wxGridSizer(4);
|
||||
wxGridSizer* const cc_buttons_dpad = new wxGridSizer(3);
|
||||
|
||||
cc_buttons_dpad->AddSpacer(20);
|
||||
cc_buttons_dpad->Add(space20, space20);
|
||||
cc_buttons_dpad->Add(m_cc_buttons[1].checkbox);
|
||||
cc_buttons_dpad->AddSpacer(20);
|
||||
cc_buttons_dpad->Add(space20, space20);
|
||||
cc_buttons_dpad->Add(m_cc_buttons[2].checkbox);
|
||||
cc_buttons_dpad->AddSpacer(20);
|
||||
cc_buttons_dpad->Add(space20, space20);
|
||||
cc_buttons_dpad->Add(m_cc_buttons[3].checkbox);
|
||||
cc_buttons_dpad->AddSpacer(20);
|
||||
cc_buttons_dpad->Add(space20, space20);
|
||||
cc_buttons_dpad->Add(m_cc_buttons[0].checkbox);
|
||||
cc_buttons_dpad->AddSpacer(20);
|
||||
cc_buttons_dpad->Add(space20, space20);
|
||||
|
||||
for (auto button : m_cc_buttons)
|
||||
wxGridSizer* const cc_buttons_grid = new wxGridSizer(4);
|
||||
for (auto& button : m_cc_buttons)
|
||||
if (!button.checkbox->GetContainingSizer())
|
||||
cc_buttons_grid->Add(button.checkbox);
|
||||
cc_buttons_grid->AddSpacer(5);
|
||||
cc_buttons_grid->Add(space5, space5);
|
||||
|
||||
wxStaticBoxSizer* const cc_buttons_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Buttons"));
|
||||
cc_buttons_box->Add(cc_buttons_grid);
|
||||
cc_buttons_box->Add(cc_buttons_dpad);
|
||||
cc_buttons_box->Add(cc_buttons_dpad, 0, wxTOP, space5);
|
||||
|
||||
szr->Add(m_cc_l_stick_szr, 0, wxALL, 5);
|
||||
szr->Add(m_cc_r_stick_szr, 0, wxALL, 5);
|
||||
szr->Add(shoulder_box, 0, wxLEFT | wxRIGHT, 5);
|
||||
szr->Add(cc_buttons_box, 0, wxTOP | wxRIGHT, 5);
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(m_cc_l_stick_szr, 0, wxTOP | wxBOTTOM, space5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(m_cc_r_stick_szr, 0, wxTOP | wxBOTTOM, space5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(shoulder_box, 0, wxTOP | wxBOTTOM, space5);
|
||||
szr->AddSpacer(space5);
|
||||
szr->Add(cc_buttons_box, 0, wxTOP | wxBOTTOM, space5);
|
||||
szr->AddSpacer(space5);
|
||||
|
||||
for (Control* const control : m_cc_controls)
|
||||
{
|
||||
@ -327,8 +345,9 @@ void TASInputDlg::HandleExtensionChange()
|
||||
m_main_szr->Hide(m_cc_szr);
|
||||
m_main_szr->Show(m_wiimote_szr);
|
||||
}
|
||||
SetSizerAndFit(m_main_szr, true);
|
||||
ResetValues();
|
||||
m_main_szr->SetSizeHints(this);
|
||||
Layout();
|
||||
}
|
||||
|
||||
void TASInputDlg::CreateGCLayout()
|
||||
@ -350,8 +369,6 @@ void TASInputDlg::CreateGCLayout()
|
||||
m_controls[4] = &m_l_cont;
|
||||
m_controls[5] = &m_r_cont;
|
||||
|
||||
wxBoxSizer* const top_box = new wxBoxSizer(wxHORIZONTAL);
|
||||
wxBoxSizer* const bottom_box = new wxBoxSizer(wxHORIZONTAL);
|
||||
m_main_stick = CreateStick(ID_MAIN_STICK, 255, 255, 128, 128, false, true);
|
||||
wxStaticBoxSizer* const main_box = CreateStickLayout(&m_main_stick, _("Main Stick"));
|
||||
|
||||
@ -373,38 +390,45 @@ void TASInputDlg::CreateGCLayout()
|
||||
control->slider->Bind(wxEVT_RIGHT_UP, &TASInputDlg::OnRightClickSlider, this);
|
||||
}
|
||||
|
||||
wxStaticBoxSizer* const m_buttons_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Buttons"));
|
||||
wxGridSizer* const m_buttons_grid = new wxGridSizer(4);
|
||||
|
||||
m_x = CreateButton("X");
|
||||
m_x = CreateButton(_("X"));
|
||||
m_x.checkbox->SetClientData(&m_x);
|
||||
m_y = CreateButton("Y");
|
||||
m_y = CreateButton(_("Y"));
|
||||
m_y.checkbox->SetClientData(&m_y);
|
||||
m_l = CreateButton("L");
|
||||
m_l = CreateButton(_("L"));
|
||||
m_l.checkbox->SetClientData(&m_l);
|
||||
m_r = CreateButton("R");
|
||||
m_r = CreateButton(_("R"));
|
||||
m_r.checkbox->SetClientData(&m_r);
|
||||
m_z = CreateButton("Z");
|
||||
m_z = CreateButton(_("Z"));
|
||||
m_z.checkbox->SetClientData(&m_z);
|
||||
m_start = CreateButton("Start");
|
||||
m_start = CreateButton(_("Start"));
|
||||
m_start.checkbox->SetClientData(&m_start);
|
||||
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
wxGridSizer* const buttons_grid = new wxGridSizer(4);
|
||||
for (unsigned int i = 4; i < ArraySize(m_buttons); ++i)
|
||||
if (m_buttons[i] != nullptr)
|
||||
m_buttons_grid->Add(m_buttons[i]->checkbox, false);
|
||||
m_buttons_grid->AddSpacer(5);
|
||||
buttons_grid->Add(m_buttons[i]->checkbox, false);
|
||||
buttons_grid->Add(space5, space5);
|
||||
|
||||
m_buttons_box->Add(m_buttons_grid);
|
||||
m_buttons_box->Add(m_buttons_dpad);
|
||||
wxStaticBoxSizer* const buttons_box = new wxStaticBoxSizer(wxVERTICAL, this, _("Buttons"));
|
||||
buttons_box->Add(buttons_grid);
|
||||
buttons_box->Add(m_buttons_dpad);
|
||||
|
||||
wxBoxSizer* const top_box = new wxBoxSizer(wxHORIZONTAL);
|
||||
top_box->Add(main_box);
|
||||
top_box->Add(c_box, 0, wxLEFT, space5);
|
||||
|
||||
wxBoxSizer* const bottom_box = new wxBoxSizer(wxHORIZONTAL);
|
||||
bottom_box->Add(shoulder_box);
|
||||
bottom_box->Add(buttons_box, 0, wxLEFT, space5);
|
||||
|
||||
wxBoxSizer* const main_szr = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
top_box->Add(main_box, 0, wxALL, 5);
|
||||
top_box->Add(c_box, 0, wxTOP | wxRIGHT, 5);
|
||||
bottom_box->Add(shoulder_box, 0, wxLEFT | wxRIGHT, 5);
|
||||
bottom_box->Add(m_buttons_box, 0, wxBOTTOM, 5);
|
||||
main_szr->Add(top_box);
|
||||
main_szr->Add(bottom_box);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(top_box, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
main_szr->Add(bottom_box, 0, wxLEFT | wxRIGHT, space5);
|
||||
main_szr->AddSpacer(space5);
|
||||
SetSizerAndFit(main_szr);
|
||||
|
||||
ResetValues();
|
||||
@ -414,21 +438,20 @@ void TASInputDlg::CreateGCLayout()
|
||||
TASInputDlg::Control TASInputDlg::CreateControl(long style, int width, int height, bool reverse,
|
||||
u32 range, u32 default_value)
|
||||
{
|
||||
Control tempCont;
|
||||
tempCont.range = range;
|
||||
tempCont.default_value = default_value;
|
||||
tempCont.slider = new wxSlider(this, m_eleID++, default_value, 0, range, wxDefaultPosition,
|
||||
wxDefaultSize, style);
|
||||
tempCont.slider->SetMinSize(wxSize(width, height));
|
||||
tempCont.slider->Bind(wxEVT_SLIDER, &TASInputDlg::UpdateFromSliders, this);
|
||||
tempCont.text = new wxTextCtrl(this, m_eleID++, std::to_string(default_value), wxDefaultPosition,
|
||||
wxSize(40, 20));
|
||||
tempCont.text->SetMaxLength(range > 999 ? 4 : 3);
|
||||
tempCont.text_id = m_eleID - 1;
|
||||
tempCont.text->Bind(wxEVT_TEXT, &TASInputDlg::UpdateFromText, this);
|
||||
tempCont.slider_id = m_eleID - 2;
|
||||
tempCont.reverse = reverse;
|
||||
return tempCont;
|
||||
Control control;
|
||||
control.range = range;
|
||||
control.default_value = default_value;
|
||||
control.slider_id = m_eleID++;
|
||||
control.slider = new DolphinSlider(this, control.slider_id, default_value, 0, range,
|
||||
wxDefaultPosition, FromDIP(wxSize(width, height)), style);
|
||||
control.slider->Bind(wxEVT_SLIDER, &TASInputDlg::UpdateFromSliders, this);
|
||||
control.text_id = m_eleID++;
|
||||
control.text = new wxTextCtrl(this, control.text_id, std::to_string(default_value));
|
||||
control.text->SetMaxLength(range > 999 ? 4 : 3);
|
||||
control.text->SetMinSize(WxUtils::GetTextWidgetMinSize(control.text, range));
|
||||
control.text->Bind(wxEVT_TEXT, &TASInputDlg::UpdateFromText, this);
|
||||
control.reverse = reverse;
|
||||
return control;
|
||||
}
|
||||
|
||||
TASInputDlg::Stick TASInputDlg::CreateStick(int id_stick, int xRange, int yRange, u32 defaultX,
|
||||
@ -446,18 +469,23 @@ TASInputDlg::Stick TASInputDlg::CreateStick(int id_stick, int xRange, int yRange
|
||||
return tempStick;
|
||||
}
|
||||
|
||||
wxStaticBoxSizer* TASInputDlg::CreateStickLayout(Stick* tempStick, const wxString& title)
|
||||
wxStaticBoxSizer* TASInputDlg::CreateStickLayout(Stick* stick, const wxString& title)
|
||||
{
|
||||
wxStaticBoxSizer* const temp_box = new wxStaticBoxSizer(wxHORIZONTAL, this, title);
|
||||
wxFlexGridSizer* grid = new wxFlexGridSizer(2, 3, 3);
|
||||
const int space3 = FromDIP(3);
|
||||
|
||||
grid->Add(tempStick->x_cont.slider, 0, wxALIGN_CENTER_HORIZONTAL | wxALIGN_BOTTOM);
|
||||
grid->Add(tempStick->x_cont.text, 0, wxEXPAND);
|
||||
grid->Add(tempStick->bitmap, 0, wxALL | wxALIGN_CENTER, 3);
|
||||
grid->Add(tempStick->y_cont.slider, 0, wxALIGN_CENTER_VERTICAL | wxALIGN_LEFT);
|
||||
grid->Add(1, 1);
|
||||
grid->Add(tempStick->y_cont.text, 0, wxEXPAND);
|
||||
temp_box->Add(grid, 1, wxEXPAND | wxALL, 3);
|
||||
wxStaticBoxSizer* const temp_box = new wxStaticBoxSizer(wxVERTICAL, this, title);
|
||||
wxFlexGridSizer* const layout = new wxFlexGridSizer(2, space3, space3);
|
||||
|
||||
layout->Add(stick->x_cont.slider, 0, wxEXPAND);
|
||||
layout->Add(stick->x_cont.text, 0, wxALIGN_CENTER);
|
||||
layout->Add(stick->bitmap, 0, wxALIGN_RIGHT);
|
||||
layout->Add(stick->y_cont.slider, 0, wxEXPAND);
|
||||
layout->AddSpacer(1); // Placeholder for unused cell
|
||||
layout->Add(stick->y_cont.text, 0, wxALIGN_CENTER);
|
||||
|
||||
temp_box->AddSpacer(space3);
|
||||
temp_box->Add(layout, 0, wxLEFT | wxRIGHT, space3);
|
||||
temp_box->AddSpacer(space3);
|
||||
return temp_box;
|
||||
}
|
||||
|
||||
@ -468,6 +496,7 @@ wxStaticBoxSizer* TASInputDlg::CreateAccelLayout(Control* x, Control* y, Control
|
||||
wxStaticBoxSizer* const xBox = new wxStaticBoxSizer(wxVERTICAL, this, _("X"));
|
||||
wxStaticBoxSizer* const yBox = new wxStaticBoxSizer(wxVERTICAL, this, _("Y"));
|
||||
wxStaticBoxSizer* const zBox = new wxStaticBoxSizer(wxVERTICAL, this, _("Z"));
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
xBox->Add(x->slider, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
xBox->Add(x->text, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
@ -475,21 +504,25 @@ wxStaticBoxSizer* TASInputDlg::CreateAccelLayout(Control* x, Control* y, Control
|
||||
yBox->Add(y->text, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
zBox->Add(z->slider, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
zBox->Add(z->text, 0, wxALIGN_CENTER_HORIZONTAL);
|
||||
temp_box->Add(xBox, 0, wxLEFT | wxBOTTOM | wxRIGHT, 5);
|
||||
temp_box->Add(yBox, 0, wxRIGHT, 5);
|
||||
temp_box->Add(zBox, 0, wxRIGHT, 5);
|
||||
temp_box->AddSpacer(space5);
|
||||
temp_box->Add(xBox, 0, wxBOTTOM, space5);
|
||||
temp_box->AddSpacer(space5);
|
||||
temp_box->Add(yBox, 0, wxBOTTOM, space5);
|
||||
temp_box->AddSpacer(space5);
|
||||
temp_box->Add(zBox, 0, wxBOTTOM, space5);
|
||||
temp_box->AddSpacer(space5);
|
||||
return temp_box;
|
||||
}
|
||||
|
||||
TASInputDlg::Button TASInputDlg::CreateButton(const std::string& name)
|
||||
TASInputDlg::Button TASInputDlg::CreateButton(const wxString& name)
|
||||
{
|
||||
Button temp;
|
||||
wxCheckBox* checkbox = new wxCheckBox(this, m_eleID++, name);
|
||||
temp.id = m_eleID++;
|
||||
wxCheckBox* checkbox = new wxCheckBox(this, temp.id, name);
|
||||
checkbox->Bind(wxEVT_RIGHT_DOWN, &TASInputDlg::SetTurbo, this);
|
||||
checkbox->Bind(wxEVT_LEFT_DOWN, &TASInputDlg::SetTurbo, this);
|
||||
checkbox->Bind(wxEVT_CHECKBOX, &TASInputDlg::OnCheckboxToggle, this);
|
||||
temp.checkbox = checkbox;
|
||||
temp.id = m_eleID - 1;
|
||||
return temp;
|
||||
}
|
||||
|
||||
@ -606,7 +639,7 @@ void TASInputDlg::SetWiiButtons(u16* butt)
|
||||
for (unsigned int i = 0; i < 11; ++i)
|
||||
{
|
||||
if (m_buttons[i] != nullptr)
|
||||
*butt |= (m_buttons[i]->is_checked) ? m_wii_buttons_bitmask[i] : 0;
|
||||
*butt |= (m_buttons[i]->is_checked) ? s_wii_buttons_bitmask[i] : 0;
|
||||
}
|
||||
ButtonTurbo();
|
||||
}
|
||||
@ -625,7 +658,7 @@ void TASInputDlg::GetKeyBoardInput(GCPadStatus* PadStatus)
|
||||
for (unsigned int i = 0; i < ArraySize(m_buttons); ++i)
|
||||
{
|
||||
if (m_buttons[i] != nullptr)
|
||||
SetButtonValue(m_buttons[i], ((PadStatus->button & m_gc_pad_buttons_bitmask[i]) != 0));
|
||||
SetButtonValue(m_buttons[i], ((PadStatus->button & s_gc_pad_buttons_bitmask[i]) != 0));
|
||||
}
|
||||
SetButtonValue(&m_l,
|
||||
((PadStatus->triggerLeft) == 255) || ((PadStatus->button & PAD_TRIGGER_L) != 0));
|
||||
@ -648,7 +681,7 @@ void TASInputDlg::GetKeyBoardInput(u8* data, WiimoteEmu::ReportFeatures rptf, in
|
||||
{
|
||||
if (m_buttons[i] != nullptr)
|
||||
SetButtonValue(m_buttons[i],
|
||||
(((wm_buttons*)coreData)->hex & m_wii_buttons_bitmask[i]) != 0);
|
||||
(((wm_buttons*)coreData)->hex & s_wii_buttons_bitmask[i]) != 0);
|
||||
}
|
||||
}
|
||||
if (accelData)
|
||||
@ -688,7 +721,7 @@ void TASInputDlg::GetKeyBoardInput(u8* data, WiimoteEmu::ReportFeatures rptf, in
|
||||
cc.bt.hex = cc.bt.hex ^ 0xFFFF;
|
||||
for (unsigned int i = 0; i < 15; ++i)
|
||||
{
|
||||
SetButtonValue(&m_cc_buttons[i], ((cc.bt.hex & m_cc_buttons_bitmask[i]) != 0));
|
||||
SetButtonValue(&m_cc_buttons[i], ((cc.bt.hex & s_cc_buttons_bitmask[i]) != 0));
|
||||
}
|
||||
|
||||
if (m_cc_l.value == 31)
|
||||
@ -835,7 +868,7 @@ void TASInputDlg::GetValues(u8* data, WiimoteEmu::ReportFeatures rptf, int ext,
|
||||
|
||||
for (unsigned int i = 0; i < ArraySize(m_cc_buttons); ++i)
|
||||
{
|
||||
cc.bt.hex |= (m_cc_buttons[i].is_checked) ? m_cc_buttons_bitmask[i] : 0;
|
||||
cc.bt.hex |= (m_cc_buttons[i].is_checked) ? s_cc_buttons_bitmask[i] : 0;
|
||||
}
|
||||
cc.bt.hex ^= 0xFFFF;
|
||||
|
||||
@ -877,9 +910,9 @@ void TASInputDlg::GetValues(GCPadStatus* PadStatus)
|
||||
if (m_buttons[i] != nullptr)
|
||||
{
|
||||
if (m_buttons[i]->is_checked)
|
||||
PadStatus->button |= m_gc_pad_buttons_bitmask[i];
|
||||
PadStatus->button |= s_gc_pad_buttons_bitmask[i];
|
||||
else
|
||||
PadStatus->button &= ~m_gc_pad_buttons_bitmask[i];
|
||||
PadStatus->button &= ~s_gc_pad_buttons_bitmask[i];
|
||||
}
|
||||
}
|
||||
|
||||
@ -1042,8 +1075,9 @@ void TASInputDlg::OnMouseDownL(wxMouseEvent& event)
|
||||
return;
|
||||
|
||||
wxPoint ptM(event.GetPosition());
|
||||
stick->x_cont.value = ptM.x * stick->x_cont.range / 127;
|
||||
stick->y_cont.value = ptM.y * stick->y_cont.range / 127;
|
||||
wxSize bitmap_size = FromDIP(wxSize(127, 127));
|
||||
stick->x_cont.value = ptM.x * stick->x_cont.range / bitmap_size.GetWidth();
|
||||
stick->y_cont.value = ptM.y * stick->y_cont.range / bitmap_size.GetHeight();
|
||||
|
||||
if ((unsigned)stick->y_cont.value > stick->y_cont.range)
|
||||
stick->y_cont.value = stick->y_cont.range;
|
||||
@ -1055,12 +1089,8 @@ void TASInputDlg::OnMouseDownL(wxMouseEvent& event)
|
||||
if (stick->x_cont.reverse)
|
||||
stick->x_cont.value = stick->x_cont.range - (u16)stick->x_cont.value;
|
||||
|
||||
stick->x_cont.value = (unsigned int)stick->x_cont.value > stick->x_cont.range ?
|
||||
stick->x_cont.range :
|
||||
stick->x_cont.value;
|
||||
stick->y_cont.value = (unsigned int)stick->y_cont.value > stick->y_cont.range ?
|
||||
stick->y_cont.range :
|
||||
stick->y_cont.value;
|
||||
stick->x_cont.value = std::min<u32>(stick->x_cont.value, stick->x_cont.range);
|
||||
stick->y_cont.value = std::min<u32>(stick->y_cont.value, stick->y_cont.range);
|
||||
|
||||
// This updates sliders and the bitmap too.
|
||||
stick->x_cont.text->SetValue(std::to_string(stick->x_cont.value));
|
||||
@ -1188,9 +1218,19 @@ wxBitmap TASInputDlg::CreateStickBitmap(int x, int y)
|
||||
x = x / 2;
|
||||
y = y / 2;
|
||||
|
||||
// Scale for screen DPI
|
||||
static constexpr int WIDTH = 129;
|
||||
static constexpr int HEIGHT = 129;
|
||||
wxSize bitmap_size = FromDIP(wxSize(WIDTH, HEIGHT));
|
||||
double scale_x = bitmap_size.GetWidth() / static_cast<double>(WIDTH);
|
||||
double scale_y = bitmap_size.GetHeight() / static_cast<double>(HEIGHT);
|
||||
|
||||
wxMemoryDC memDC;
|
||||
wxBitmap bitmap(129, 129);
|
||||
wxBitmap bitmap;
|
||||
bitmap.CreateScaled(bitmap_size.GetWidth(), bitmap_size.GetHeight(), wxBITMAP_SCREEN_DEPTH,
|
||||
GetContentScaleFactor());
|
||||
memDC.SelectObject(bitmap);
|
||||
memDC.SetUserScale(scale_x, scale_y);
|
||||
memDC.SetBackground(*wxLIGHT_GREY_BRUSH);
|
||||
memDC.Clear();
|
||||
memDC.SetBrush(*wxWHITE_BRUSH);
|
||||
@ -1198,7 +1238,8 @@ wxBitmap TASInputDlg::CreateStickBitmap(int x, int y)
|
||||
memDC.SetPen(wxPen(*wxBLACK, 3, wxPENSTYLE_SOLID));
|
||||
memDC.DrawLine(64, 64, x, y);
|
||||
memDC.SetPen(*wxBLACK_PEN);
|
||||
memDC.CrossHair(64, 64);
|
||||
memDC.DrawLine(64, 0, 64, HEIGHT); // CrossHair doesn't work @96DPI on Windows for some reason
|
||||
memDC.DrawLine(0, 64, WIDTH, 64);
|
||||
memDC.SetBrush(*wxBLUE_BRUSH);
|
||||
memDC.DrawCircle(x, y, 5);
|
||||
memDC.SelectObject(wxNullBitmap);
|
||||
|
@ -13,8 +13,8 @@
|
||||
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
|
||||
#include "InputCommon/GCPadStatus.h"
|
||||
|
||||
class DolphinSlider;
|
||||
class wxCheckBox;
|
||||
class wxSlider;
|
||||
class wxStaticBitmap;
|
||||
class wxTextCtrl;
|
||||
|
||||
@ -25,36 +25,24 @@ public:
|
||||
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize,
|
||||
long style = wxDEFAULT_DIALOG_STYLE | wxSTAY_ON_TOP);
|
||||
|
||||
void OnCloseWindow(wxCloseEvent& event);
|
||||
void UpdateFromSliders(wxCommandEvent& event);
|
||||
void UpdateFromText(wxCommandEvent& event);
|
||||
void OnMouseDownL(wxMouseEvent& event);
|
||||
void OnMouseUpR(wxMouseEvent& event);
|
||||
void OnRightClickSlider(wxMouseEvent& event);
|
||||
void ResetValues();
|
||||
void GetValues(GCPadStatus* PadStatus);
|
||||
void GetValues(u8* data, WiimoteEmu::ReportFeatures rptf, int ext, const wiimote_key key);
|
||||
void SetTurbo(wxMouseEvent& event);
|
||||
void ButtonTurbo();
|
||||
void GetKeyBoardInput(GCPadStatus* PadStatus);
|
||||
void GetKeyBoardInput(u8* data, WiimoteEmu::ReportFeatures rptf, int ext, const wiimote_key key);
|
||||
void CreateGCLayout();
|
||||
void CreateWiiLayout(int num);
|
||||
wxBitmap CreateStickBitmap(int x, int y);
|
||||
void SetWiiButtons(u16* butt);
|
||||
void HandleExtensionChange();
|
||||
|
||||
private:
|
||||
const int ID_C_STICK = 1001;
|
||||
const int ID_MAIN_STICK = 1002;
|
||||
const int ID_CC_L_STICK = 1003;
|
||||
const int ID_CC_R_STICK = 1004;
|
||||
static constexpr int ID_C_STICK = 1001;
|
||||
static constexpr int ID_MAIN_STICK = 1002;
|
||||
static constexpr int ID_CC_L_STICK = 1003;
|
||||
static constexpr int ID_CC_R_STICK = 1004;
|
||||
int m_eleID = 1005;
|
||||
|
||||
struct Control
|
||||
{
|
||||
wxTextCtrl* text;
|
||||
wxSlider* slider;
|
||||
DolphinSlider* slider;
|
||||
int value = -1;
|
||||
int text_id;
|
||||
int slider_id;
|
||||
@ -100,9 +88,22 @@ private:
|
||||
bool reverseY);
|
||||
wxStaticBoxSizer* CreateStickLayout(Stick* tempStick, const wxString& title);
|
||||
wxStaticBoxSizer* CreateAccelLayout(Control* x, Control* y, Control* z, const wxString& title);
|
||||
Button CreateButton(const std::string& name);
|
||||
Button CreateButton(const wxString& name);
|
||||
Control CreateControl(long style, int width, int height, bool reverse = false, u32 range = 255,
|
||||
u32 default_value = 128);
|
||||
wxBitmap CreateStickBitmap(int x, int y);
|
||||
|
||||
void OnCloseWindow(wxCloseEvent& event);
|
||||
void UpdateFromSliders(wxCommandEvent& event);
|
||||
void UpdateFromText(wxCommandEvent& event);
|
||||
void OnMouseDownL(wxMouseEvent& event);
|
||||
void OnMouseUpR(wxMouseEvent& event);
|
||||
void OnRightClickSlider(wxMouseEvent& event);
|
||||
void SetTurbo(wxMouseEvent& event);
|
||||
void ButtonTurbo();
|
||||
void HandleExtensionChange();
|
||||
void ResetValues();
|
||||
void SetWiiButtons(u16* butt);
|
||||
|
||||
enum
|
||||
{
|
||||
@ -127,10 +128,6 @@ private:
|
||||
Button m_cc_buttons[15];
|
||||
Control* m_controls[10];
|
||||
Control* m_cc_controls[6];
|
||||
static const int m_gc_pad_buttons_bitmask[12];
|
||||
static const int m_wii_buttons_bitmask[11];
|
||||
static const int m_cc_buttons_bitmask[15];
|
||||
static const std::string m_cc_button_names[15];
|
||||
u8 m_ext = 0;
|
||||
wxBoxSizer* m_main_szr;
|
||||
wxBoxSizer* m_wiimote_szr;
|
||||
|
@ -3,6 +3,7 @@
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
@ -12,11 +13,11 @@
|
||||
#include <wx/choice.h>
|
||||
#include <wx/control.h>
|
||||
#include <wx/dialog.h>
|
||||
#include <wx/gbsizer.h>
|
||||
#include <wx/notebook.h>
|
||||
#include <wx/panel.h>
|
||||
#include <wx/radiobut.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/slider.h>
|
||||
#include <wx/stattext.h>
|
||||
|
||||
#include "Common/Assert.h"
|
||||
@ -76,18 +77,14 @@ void SettingChoice::UpdateValue(wxCommandEvent& ev)
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void VideoConfigDiag::Event_ClickClose(wxCommandEvent&)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
void VideoConfigDiag::Event_Close(wxCloseEvent& ev)
|
||||
void VideoConfigDiag::Event_Close(wxCommandEvent& ev)
|
||||
{
|
||||
g_Config.Save(File::GetUserPath(D_CONFIG_IDX) + "GFX.ini");
|
||||
|
||||
EndModal(wxID_OK);
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
static wxString default_desc =
|
||||
wxTRANSLATE("Move the mouse pointer over an option to display a detailed description.");
|
||||
#if defined(_WIN32)
|
||||
static wxString backend_desc =
|
||||
wxTRANSLATE("Selects what graphics API to use internally.\nThe software renderer is extremely "
|
||||
@ -352,6 +349,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
Bind(wxEVT_UPDATE_UI, &VideoConfigDiag::OnUpdateUI, this);
|
||||
|
||||
wxNotebook* const notebook = new wxNotebook(this, wxID_ANY);
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// -- GENERAL --
|
||||
{
|
||||
@ -361,7 +359,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
// - basic
|
||||
{
|
||||
wxFlexGridSizer* const szr_basic = new wxFlexGridSizer(2, 5, 5);
|
||||
wxFlexGridSizer* const szr_basic = new wxFlexGridSizer(2, space5, space5);
|
||||
|
||||
// backend
|
||||
{
|
||||
@ -378,8 +376,8 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
wxGetTranslation(StrToWxStr(g_video_backend->GetDisplayName())));
|
||||
choice_backend->Bind(wxEVT_CHOICE, &VideoConfigDiag::Event_Backend, this);
|
||||
|
||||
szr_basic->Add(label_backend, 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
szr_basic->Add(choice_backend, 1, 0, 0);
|
||||
szr_basic->Add(label_backend, 0, wxALIGN_CENTER_VERTICAL);
|
||||
szr_basic->Add(choice_backend, 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
// adapter (D3D only)
|
||||
@ -396,12 +394,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
choice_adapter->Select(vconfig.iAdapter);
|
||||
|
||||
label_adapter = new wxStaticText(page_general, wxID_ANY, _("Adapter:"));
|
||||
szr_basic->Add(label_adapter, 1, wxALIGN_CENTER_VERTICAL, 5);
|
||||
szr_basic->Add(choice_adapter, 1, 0, 0);
|
||||
szr_basic->Add(label_adapter, 0, wxALIGN_CENTER_VERTICAL);
|
||||
szr_basic->Add(choice_adapter, 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
// - display
|
||||
wxFlexGridSizer* const szr_display = new wxFlexGridSizer(2, 5, 5);
|
||||
wxFlexGridSizer* const szr_display = new wxFlexGridSizer(2, space5, space5);
|
||||
|
||||
{
|
||||
#if !defined(__APPLE__)
|
||||
@ -420,9 +418,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
choice_display_resolution->SetStringSelection(
|
||||
StrToWxStr(SConfig::GetInstance().strFullscreenResolution));
|
||||
// "Auto" is used as a keyword, convert to translated string
|
||||
if (SConfig::GetInstance().strFullscreenResolution == "Auto")
|
||||
choice_display_resolution->SetSelection(0);
|
||||
|
||||
szr_display->Add(label_display_resolution, 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_display->Add(choice_display_resolution);
|
||||
szr_display->Add(label_display_resolution, 0, wxALIGN_CENTER_VERTICAL);
|
||||
szr_display->Add(choice_display_resolution, 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -431,12 +432,12 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
const wxString ar_choices[] = {_("Auto"), _("Force 16:9"), _("Force 4:3"),
|
||||
_("Stretch to Window")};
|
||||
|
||||
szr_display->Add(new wxStaticText(page_general, wxID_ANY, _("Aspect Ratio:")), 1,
|
||||
wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_display->Add(new wxStaticText(page_general, wxID_ANY, _("Aspect Ratio:")), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
wxChoice* const choice_aspect =
|
||||
CreateChoice(page_general, vconfig.iAspectRatio, wxGetTranslation(ar_desc),
|
||||
sizeof(ar_choices) / sizeof(*ar_choices), ar_choices);
|
||||
szr_display->Add(choice_aspect, 1, 0, 0);
|
||||
szr_display->Add(choice_aspect, 0, wxALIGN_CENTER_VERTICAL);
|
||||
}
|
||||
|
||||
// various other display options
|
||||
@ -450,7 +451,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
}
|
||||
|
||||
// - other
|
||||
wxFlexGridSizer* const szr_other = new wxFlexGridSizer(2, 5, 5);
|
||||
wxFlexGridSizer* const szr_other = new wxFlexGridSizer(2, space5, space5);
|
||||
|
||||
{
|
||||
szr_other->Add(CreateCheckBox(page_general, _("Show FPS"), wxGetTranslation(show_fps_desc),
|
||||
@ -488,20 +489,28 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
wxStaticBoxSizer* const group_basic =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Basic"));
|
||||
group_basic->Add(szr_basic, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_general->Add(group_basic, 0, wxEXPAND | wxALL, 5);
|
||||
group_basic->Add(szr_basic, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_basic->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const group_display =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Display"));
|
||||
group_display->Add(szr_display, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_general->Add(group_display, 0, wxEXPAND | wxALL, 5);
|
||||
group_display->Add(szr_display, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_display->AddSpacer(space5);
|
||||
|
||||
wxStaticBoxSizer* const group_other =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_general, _("Other"));
|
||||
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_general->Add(group_other, 0, wxEXPAND | wxALL, 5);
|
||||
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_other->AddSpacer(space5);
|
||||
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->Add(group_basic, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->Add(group_display, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->Add(group_other, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
szr_general->AddSpacer(space5);
|
||||
szr_general->AddStretchSpacer();
|
||||
CreateDescriptionArea(page_general, szr_general);
|
||||
page_general->SetSizerAndFit(szr_general);
|
||||
@ -514,7 +523,9 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
wxBoxSizer* const szr_enh_main = new wxBoxSizer(wxVERTICAL);
|
||||
|
||||
// - enhancements
|
||||
wxFlexGridSizer* const szr_enh = new wxFlexGridSizer(2, 5, 5);
|
||||
wxGridBagSizer* const szr_enh = new wxGridBagSizer(space5, space5);
|
||||
const wxGBSpan span2(1, 2);
|
||||
int row = 0;
|
||||
|
||||
// Internal resolution
|
||||
{
|
||||
@ -540,9 +551,10 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
if (vconfig.iEFBScale > 11)
|
||||
choice_efbscale->SetSelection(12);
|
||||
|
||||
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Internal Resolution:")), 1,
|
||||
wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_enh->Add(choice_efbscale);
|
||||
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Internal Resolution:")),
|
||||
wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
szr_enh->Add(choice_efbscale, wxGBPosition(row, 1), span2, wxALIGN_CENTER_VERTICAL);
|
||||
row += 1;
|
||||
}
|
||||
|
||||
// AA
|
||||
@ -553,23 +565,25 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
PopulateAAList();
|
||||
choice_aamode->Bind(wxEVT_CHOICE, &VideoConfigDiag::OnAAChanged, this);
|
||||
|
||||
szr_enh->Add(text_aamode, 1, wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_enh->Add(choice_aamode);
|
||||
szr_enh->Add(text_aamode, wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
szr_enh->Add(choice_aamode, wxGBPosition(row, 1), span2, wxALIGN_CENTER_VERTICAL);
|
||||
row += 1;
|
||||
}
|
||||
|
||||
// AF
|
||||
{
|
||||
const wxString af_choices[] = {"1x", "2x", "4x", "8x", "16x"};
|
||||
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Anisotropic Filtering:")), 1,
|
||||
wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_enh->Add(
|
||||
CreateChoice(page_enh, vconfig.iMaxAnisotropy, wxGetTranslation(af_desc), 5, af_choices));
|
||||
const std::array<wxString, 5> af_choices{{"1x", "2x", "4x", "8x", "16x"}};
|
||||
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Anisotropic Filtering:")),
|
||||
wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
szr_enh->Add(CreateChoice(page_enh, vconfig.iMaxAnisotropy, wxGetTranslation(af_desc),
|
||||
af_choices.size(), af_choices.data()),
|
||||
wxGBPosition(row, 1), span2, wxALIGN_CENTER_VERTICAL);
|
||||
row += 1;
|
||||
}
|
||||
|
||||
// postproc shader
|
||||
if (vconfig.backend_info.bSupportsPostProcessing)
|
||||
{
|
||||
wxFlexGridSizer* const szr_pp = new wxFlexGridSizer(3, 5, 5);
|
||||
choice_ppshader = new wxChoice(page_enh, wxID_ANY);
|
||||
RegisterControl(choice_ppshader, wxGetTranslation(ppshader_desc));
|
||||
button_config_pp = new wxButton(page_enh, wxID_ANY, _("Config"));
|
||||
@ -579,11 +593,11 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
choice_ppshader->Bind(wxEVT_CHOICE, &VideoConfigDiag::Event_PPShader, this);
|
||||
button_config_pp->Bind(wxEVT_BUTTON, &VideoConfigDiag::Event_ConfigurePPShader, this);
|
||||
|
||||
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Post-Processing Effect:")), 1,
|
||||
wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_pp->Add(choice_ppshader);
|
||||
szr_pp->Add(button_config_pp);
|
||||
szr_enh->Add(szr_pp);
|
||||
szr_enh->Add(new wxStaticText(page_enh, wxID_ANY, _("Post-Processing Effect:")),
|
||||
wxGBPosition(row, 0), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
szr_enh->Add(choice_ppshader, wxGBPosition(row, 1), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
szr_enh->Add(button_config_pp, wxGBPosition(row, 2), wxDefaultSpan, wxALIGN_CENTER_VERTICAL);
|
||||
row += 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -592,31 +606,38 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
}
|
||||
|
||||
// Scaled copy, PL, Bilinear filter
|
||||
szr_enh->Add(CreateCheckBox(page_enh, _("Scaled EFB Copy"),
|
||||
wxGetTranslation(scaled_efb_copy_desc), vconfig.bCopyEFBScaled));
|
||||
szr_enh->Add(CreateCheckBox(page_enh, _("Per-Pixel Lighting"),
|
||||
wxGetTranslation(pixel_lighting_desc),
|
||||
vconfig.bEnablePixelLighting));
|
||||
szr_enh->Add(CreateCheckBox(page_enh, _("Force Texture Filtering"),
|
||||
wxGetTranslation(force_filtering_desc), vconfig.bForceFiltering));
|
||||
szr_enh->Add(CreateCheckBox(page_enh, _("Widescreen Hack"), wxGetTranslation(ws_hack_desc),
|
||||
vconfig.bWidescreenHack));
|
||||
szr_enh->Add(CreateCheckBox(page_enh, _("Disable Fog"), wxGetTranslation(disable_fog_desc),
|
||||
vconfig.bDisableFog));
|
||||
wxGridSizer* const cb_szr = new wxGridSizer(2, space5, space5);
|
||||
cb_szr->Add(CreateCheckBox(page_enh, _("Scaled EFB Copy"),
|
||||
wxGetTranslation(scaled_efb_copy_desc), vconfig.bCopyEFBScaled));
|
||||
cb_szr->Add(CreateCheckBox(page_enh, _("Per-Pixel Lighting"),
|
||||
wxGetTranslation(pixel_lighting_desc),
|
||||
vconfig.bEnablePixelLighting));
|
||||
cb_szr->Add(CreateCheckBox(page_enh, _("Force Texture Filtering"),
|
||||
wxGetTranslation(force_filtering_desc), vconfig.bForceFiltering));
|
||||
cb_szr->Add(CreateCheckBox(page_enh, _("Widescreen Hack"), wxGetTranslation(ws_hack_desc),
|
||||
vconfig.bWidescreenHack));
|
||||
cb_szr->Add(CreateCheckBox(page_enh, _("Disable Fog"), wxGetTranslation(disable_fog_desc),
|
||||
vconfig.bDisableFog));
|
||||
szr_enh->Add(cb_szr, wxGBPosition(row, 0), wxGBSpan(1, 3));
|
||||
row += 1;
|
||||
|
||||
wxStaticBoxSizer* const group_enh =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_enh, _("Enhancements"));
|
||||
group_enh->Add(szr_enh, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_enh_main->Add(group_enh, 0, wxEXPAND | wxALL, 5);
|
||||
group_enh->Add(szr_enh, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_enh->AddSpacer(space5);
|
||||
|
||||
szr_enh_main->AddSpacer(space5);
|
||||
szr_enh_main->Add(group_enh, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
|
||||
// - stereoscopy
|
||||
|
||||
if (vconfig.backend_info.bSupportsGeometryShaders)
|
||||
{
|
||||
wxFlexGridSizer* const szr_stereo = new wxFlexGridSizer(2, 5, 5);
|
||||
wxFlexGridSizer* const szr_stereo = new wxFlexGridSizer(2, space5, space5);
|
||||
szr_stereo->AddGrowableCol(1);
|
||||
|
||||
szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Stereoscopic 3D Mode:")), 1,
|
||||
wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Stereoscopic 3D Mode:")), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
const wxString stereo_choices[] = {_("Off"), _("Side-by-Side"), _("Top-and-Bottom"),
|
||||
_("Anaglyph"), _("Nvidia 3D Vision")};
|
||||
@ -626,37 +647,41 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
ArraySize(stereo_choices) - 1,
|
||||
stereo_choices);
|
||||
stereo_choice->Bind(wxEVT_CHOICE, &VideoConfigDiag::Event_StereoMode, this);
|
||||
szr_stereo->Add(stereo_choice);
|
||||
szr_stereo->Add(stereo_choice, 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
wxSlider* const sep_slider = new wxSlider(page_enh, wxID_ANY, vconfig.iStereoDepth, 0, 100,
|
||||
wxDefaultPosition, wxDefaultSize);
|
||||
DolphinSlider* const sep_slider =
|
||||
new DolphinSlider(page_enh, wxID_ANY, vconfig.iStereoDepth, 0, 100, wxDefaultPosition,
|
||||
FromDIP(wxSize(200, -1)));
|
||||
sep_slider->Bind(wxEVT_SLIDER, &VideoConfigDiag::Event_StereoDepth, this);
|
||||
RegisterControl(sep_slider, wxGetTranslation(stereo_depth_desc));
|
||||
|
||||
szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Depth:")), 1, wxALIGN_CENTER_VERTICAL,
|
||||
0);
|
||||
szr_stereo->Add(sep_slider, 0, wxEXPAND | wxRIGHT);
|
||||
szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Depth:")));
|
||||
szr_stereo->Add(sep_slider);
|
||||
|
||||
conv_slider = new wxSlider(page_enh, wxID_ANY, vconfig.iStereoConvergencePercentage, 0, 200,
|
||||
wxDefaultPosition, wxDefaultSize, wxSL_AUTOTICKS);
|
||||
conv_slider =
|
||||
new DolphinSlider(page_enh, wxID_ANY, vconfig.iStereoConvergencePercentage, 0, 200,
|
||||
wxDefaultPosition, FromDIP(wxSize(200, -1)), wxSL_AUTOTICKS);
|
||||
conv_slider->ClearTicks();
|
||||
conv_slider->SetTick(100);
|
||||
conv_slider->Bind(wxEVT_SLIDER, &VideoConfigDiag::Event_StereoConvergence, this);
|
||||
RegisterControl(conv_slider, wxGetTranslation(stereo_convergence_desc));
|
||||
|
||||
szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Convergence:")), 1,
|
||||
wxALIGN_CENTER_VERTICAL, 0);
|
||||
szr_stereo->Add(conv_slider, 0, wxEXPAND | wxRIGHT);
|
||||
szr_stereo->Add(new wxStaticText(page_enh, wxID_ANY, _("Convergence:")));
|
||||
szr_stereo->Add(conv_slider);
|
||||
|
||||
szr_stereo->Add(CreateCheckBox(page_enh, _("Swap Eyes"), wxGetTranslation(stereo_swap_desc),
|
||||
vconfig.bStereoSwapEyes));
|
||||
|
||||
wxStaticBoxSizer* const group_stereo =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_enh, _("Stereoscopy"));
|
||||
group_stereo->Add(szr_stereo, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_enh_main->Add(group_stereo, 0, wxEXPAND | wxALL, 5);
|
||||
group_stereo->Add(szr_stereo, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_stereo->AddSpacer(space5);
|
||||
|
||||
szr_enh_main->AddSpacer(space5);
|
||||
szr_enh_main->Add(group_stereo, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
szr_enh_main->AddSpacer(space5);
|
||||
szr_enh_main->AddStretchSpacer();
|
||||
CreateDescriptionArea(page_enh, szr_enh_main);
|
||||
page_enh->SetSizerAndFit(szr_enh_main);
|
||||
@ -674,53 +699,71 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
szr_efb->Add(CreateCheckBox(page_hacks, _("Skip EFB Access from CPU"),
|
||||
wxGetTranslation(efb_access_desc), vconfig.bEFBAccessEnable, true),
|
||||
0, wxBOTTOM | wxLEFT, 5);
|
||||
0, wxLEFT | wxRIGHT, space5);
|
||||
szr_efb->AddSpacer(space5);
|
||||
szr_efb->Add(CreateCheckBox(page_hacks, _("Ignore Format Changes"),
|
||||
wxGetTranslation(efb_emulate_format_changes_desc),
|
||||
vconfig.bEFBEmulateFormatChanges, true),
|
||||
0, wxBOTTOM | wxLEFT, 5);
|
||||
0, wxLEFT | wxRIGHT, space5);
|
||||
szr_efb->AddSpacer(space5);
|
||||
szr_efb->Add(CreateCheckBox(page_hacks, _("Store EFB Copies to Texture Only"),
|
||||
wxGetTranslation(skip_efb_copy_to_ram_desc),
|
||||
vconfig.bSkipEFBCopyToRam),
|
||||
0, wxBOTTOM | wxLEFT, 5);
|
||||
0, wxLEFT | wxRIGHT, space5);
|
||||
szr_efb->AddSpacer(space5);
|
||||
|
||||
szr_hacks->Add(szr_efb, 0, wxEXPAND | wxALL, 5);
|
||||
szr_hacks->AddSpacer(space5);
|
||||
szr_hacks->Add(szr_efb, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
|
||||
// Texture cache
|
||||
{
|
||||
wxStaticBoxSizer* const szr_safetex =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, page_hacks, _("Texture Cache"));
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("Texture Cache"));
|
||||
|
||||
// TODO: Use wxSL_MIN_MAX_LABELS or wxSL_VALUE_LABEL with wx 2.9.1
|
||||
wxSlider* const stc_slider = new wxSlider(page_hacks, wxID_ANY, 0, 0, 2, wxDefaultPosition,
|
||||
wxDefaultSize, wxSL_HORIZONTAL | wxSL_BOTTOM);
|
||||
int slider_pos = -1;
|
||||
if (vconfig.iSafeTextureCache_ColorSamples == 0)
|
||||
slider_pos = 0;
|
||||
else if (vconfig.iSafeTextureCache_ColorSamples == 512)
|
||||
slider_pos = 1;
|
||||
else if (vconfig.iSafeTextureCache_ColorSamples == 128)
|
||||
slider_pos = 2;
|
||||
|
||||
DolphinSlider* const stc_slider =
|
||||
new DolphinSlider(page_hacks, wxID_ANY, std::max(slider_pos, 0), 0, 2, wxDefaultPosition,
|
||||
wxDefaultSize, wxSL_HORIZONTAL | wxSL_BOTTOM);
|
||||
stc_slider->Bind(wxEVT_SLIDER, &VideoConfigDiag::Event_Stc, this);
|
||||
RegisterControl(stc_slider, wxGetTranslation(stc_desc));
|
||||
|
||||
if (vconfig.iSafeTextureCache_ColorSamples == 0)
|
||||
stc_slider->SetValue(0);
|
||||
else if (vconfig.iSafeTextureCache_ColorSamples == 512)
|
||||
stc_slider->SetValue(1);
|
||||
else if (vconfig.iSafeTextureCache_ColorSamples == 128)
|
||||
stc_slider->SetValue(2);
|
||||
else
|
||||
stc_slider->Disable(); // Using custom number of samples; TODO: Inform the user why this is
|
||||
// disabled..
|
||||
wxBoxSizer* const slide_szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
slide_szr->Add(new wxStaticText(page_hacks, wxID_ANY, _("Accuracy:")), 0,
|
||||
wxALIGN_CENTER_VERTICAL);
|
||||
slide_szr->AddStretchSpacer(1);
|
||||
slide_szr->Add(new wxStaticText(page_hacks, wxID_ANY, _("Safe")), 0,
|
||||
wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
slide_szr->Add(stc_slider, 2, wxALIGN_CENTER_VERTICAL);
|
||||
slide_szr->Add(new wxStaticText(page_hacks, wxID_ANY, _("Fast")), 0, wxALIGN_CENTER_VERTICAL);
|
||||
|
||||
szr_safetex->Add(new wxStaticText(page_hacks, wxID_ANY, _("Accuracy:")), 0, wxALL, 5);
|
||||
szr_safetex->AddStretchSpacer(1);
|
||||
szr_safetex->Add(new wxStaticText(page_hacks, wxID_ANY, _("Safe")), 0,
|
||||
wxLEFT | wxTOP | wxBOTTOM, 5);
|
||||
szr_safetex->Add(stc_slider, 2, wxRIGHT, 0);
|
||||
szr_safetex->Add(new wxStaticText(page_hacks, wxID_ANY, _("Fast")), 0,
|
||||
wxRIGHT | wxTOP | wxBOTTOM, 5);
|
||||
szr_hacks->Add(szr_safetex, 0, wxEXPAND | wxALL, 5);
|
||||
szr_safetex->Add(slide_szr, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
if (slider_pos == -1)
|
||||
{
|
||||
stc_slider->Disable();
|
||||
wxString msg = wxString::Format(_("Hash tap count is set to %d which is non-standard.\n"
|
||||
"You will need to edit the INI manually."),
|
||||
vconfig.iSafeTextureCache_ColorSamples);
|
||||
szr_safetex->AddSpacer(space5);
|
||||
szr_safetex->Add(new wxStaticText(page_hacks, wxID_ANY, msg), 0,
|
||||
wxALIGN_RIGHT | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
szr_safetex->AddSpacer(space5);
|
||||
|
||||
szr_hacks->AddSpacer(space5);
|
||||
szr_hacks->Add(szr_safetex, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
// - XFB
|
||||
{
|
||||
wxStaticBoxSizer* const group_xfb =
|
||||
new wxStaticBoxSizer(wxHORIZONTAL, page_hacks, _("External Frame Buffer (XFB)"));
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("External Frame Buffer (XFB)"));
|
||||
|
||||
SettingCheckBox* disable_xfb = CreateCheckBox(
|
||||
page_hacks, _("Disable"), wxGetTranslation(xfb_desc), vconfig.bUseXFB, true);
|
||||
@ -729,16 +772,22 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
real_xfb = CreateRadioButton(page_hacks, _("Real"), wxGetTranslation(xfb_real_desc),
|
||||
vconfig.bUseRealXFB);
|
||||
|
||||
group_xfb->Add(disable_xfb, 0, wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_xfb->AddStretchSpacer(1);
|
||||
group_xfb->Add(virtual_xfb, 0, wxRIGHT, 5);
|
||||
group_xfb->Add(real_xfb, 0, wxRIGHT, 5);
|
||||
szr_hacks->Add(group_xfb, 0, wxEXPAND | wxALL, 5);
|
||||
wxBoxSizer* const szr = new wxBoxSizer(wxHORIZONTAL);
|
||||
szr->Add(disable_xfb, 0, wxALIGN_CENTER_VERTICAL);
|
||||
szr->AddStretchSpacer(1);
|
||||
szr->Add(virtual_xfb, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
szr->Add(real_xfb, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, space5);
|
||||
|
||||
group_xfb->Add(szr, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_xfb->AddSpacer(space5);
|
||||
|
||||
szr_hacks->AddSpacer(space5);
|
||||
szr_hacks->Add(group_xfb, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
} // xfb
|
||||
|
||||
// - other hacks
|
||||
{
|
||||
wxGridSizer* const szr_other = new wxGridSizer(2, 5, 5);
|
||||
wxGridSizer* const szr_other = new wxGridSizer(2, space5, space5);
|
||||
szr_other->Add(CreateCheckBox(page_hacks, _("Fast Depth Calculation"),
|
||||
wxGetTranslation(fast_depth_calc_desc),
|
||||
vconfig.bFastDepthCalc));
|
||||
@ -748,10 +797,14 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
wxStaticBoxSizer* const group_other =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_hacks, _("Other"));
|
||||
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_hacks->Add(group_other, 0, wxEXPAND | wxALL, 5);
|
||||
group_other->Add(szr_other, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_other->AddSpacer(space5);
|
||||
|
||||
szr_hacks->AddSpacer(space5);
|
||||
szr_hacks->Add(group_other, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
szr_hacks->AddSpacer(space5);
|
||||
szr_hacks->AddStretchSpacer();
|
||||
CreateDescriptionArea(page_hacks, szr_hacks);
|
||||
page_hacks->SetSizerAndFit(szr_hacks);
|
||||
@ -765,7 +818,7 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
// - debug
|
||||
{
|
||||
wxGridSizer* const szr_debug = new wxGridSizer(2, 5, 5);
|
||||
wxGridSizer* const szr_debug = new wxGridSizer(2, space5, space5);
|
||||
|
||||
szr_debug->Add(CreateCheckBox(page_advanced, _("Enable Wireframe"),
|
||||
wxGetTranslation(wireframe_desc), vconfig.bWireFrame));
|
||||
@ -779,13 +832,16 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
wxStaticBoxSizer* const group_debug =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_advanced, _("Debugging"));
|
||||
szr_advanced->Add(group_debug, 0, wxEXPAND | wxALL, 5);
|
||||
group_debug->Add(szr_debug, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_debug->Add(szr_debug, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_debug->AddSpacer(space5);
|
||||
|
||||
szr_advanced->AddSpacer(space5);
|
||||
szr_advanced->Add(group_debug, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
// - utility
|
||||
{
|
||||
wxGridSizer* const szr_utility = new wxGridSizer(2, 5, 5);
|
||||
wxGridSizer* const szr_utility = new wxGridSizer(2, space5, space5);
|
||||
|
||||
szr_utility->Add(CreateCheckBox(page_advanced, _("Dump Textures"),
|
||||
wxGetTranslation(dump_textures_desc), vconfig.bDumpTextures));
|
||||
@ -807,13 +863,16 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
wxStaticBoxSizer* const group_utility =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_advanced, _("Utility"));
|
||||
szr_advanced->Add(group_utility, 0, wxEXPAND | wxALL, 5);
|
||||
group_utility->Add(szr_utility, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_utility->Add(szr_utility, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_utility->AddSpacer(space5);
|
||||
|
||||
szr_advanced->AddSpacer(space5);
|
||||
szr_advanced->Add(group_utility, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
// - misc
|
||||
{
|
||||
wxGridSizer* const szr_misc = new wxGridSizer(2, 5, 5);
|
||||
wxGridSizer* const szr_misc = new wxGridSizer(2, space5, space5);
|
||||
|
||||
szr_misc->Add(
|
||||
CreateCheckBox(page_advanced, _("Crop"), wxGetTranslation(crop_desc), vconfig.bCrop));
|
||||
@ -844,24 +903,34 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
wxStaticBoxSizer* const group_misc =
|
||||
new wxStaticBoxSizer(wxVERTICAL, page_advanced, _("Misc"));
|
||||
szr_advanced->Add(group_misc, 0, wxEXPAND | wxALL, 5);
|
||||
group_misc->Add(szr_misc, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
group_misc->Add(szr_misc, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
group_misc->AddSpacer(space5);
|
||||
|
||||
szr_advanced->AddSpacer(space5);
|
||||
szr_advanced->Add(group_misc, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
}
|
||||
|
||||
szr_advanced->AddSpacer(space5);
|
||||
szr_advanced->AddStretchSpacer();
|
||||
CreateDescriptionArea(page_advanced, szr_advanced);
|
||||
page_advanced->SetSizerAndFit(szr_advanced);
|
||||
}
|
||||
|
||||
wxButton* const btn_close = new wxButton(this, wxID_OK, _("Close"));
|
||||
btn_close->Bind(wxEVT_BUTTON, &VideoConfigDiag::Event_ClickClose, this);
|
||||
wxStdDialogButtonSizer* btn_sizer = CreateStdDialogButtonSizer(wxOK | wxNO_DEFAULT);
|
||||
btn_sizer->GetAffirmativeButton()->SetLabel(_("Close"));
|
||||
SetEscapeId(wxID_OK); // Escape key or window manager 'X'
|
||||
|
||||
Bind(wxEVT_CLOSE_WINDOW, &VideoConfigDiag::Event_Close, this);
|
||||
Bind(wxEVT_BUTTON, &VideoConfigDiag::Event_Close, this, wxID_OK);
|
||||
|
||||
wxBoxSizer* const szr_main = new wxBoxSizer(wxVERTICAL);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxALL, 5);
|
||||
szr_main->Add(btn_close, 0, wxALIGN_RIGHT | wxRIGHT | wxBOTTOM, 5);
|
||||
szr_main->AddSpacer(space5);
|
||||
szr_main->Add(notebook, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_main->AddSpacer(space5);
|
||||
szr_main->Add(btn_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
szr_main->AddSpacer(space5);
|
||||
|
||||
SetLayoutAdaptationMode(wxDIALOG_ADAPTATION_MODE_ENABLED);
|
||||
SetLayoutAdaptationLevel(wxDIALOG_ADAPTATION_STANDARD_SIZER);
|
||||
SetSizerAndFit(szr_main);
|
||||
Center();
|
||||
SetFocus();
|
||||
@ -871,8 +940,18 @@ VideoConfigDiag::VideoConfigDiag(wxWindow* parent, const std::string& title)
|
||||
|
||||
void VideoConfigDiag::Event_DisplayResolution(wxCommandEvent& ev)
|
||||
{
|
||||
SConfig::GetInstance().strFullscreenResolution =
|
||||
WxStrToStr(choice_display_resolution->GetStringSelection());
|
||||
// "Auto" has been translated, it needs to be the English string "Auto" to work
|
||||
switch (choice_display_resolution->GetSelection())
|
||||
{
|
||||
case 0:
|
||||
SConfig::GetInstance().strFullscreenResolution = "Auto";
|
||||
break;
|
||||
case wxNOT_FOUND:
|
||||
break; // Nothing is selected.
|
||||
default:
|
||||
SConfig::GetInstance().strFullscreenResolution =
|
||||
WxStrToStr(choice_display_resolution->GetStringSelection());
|
||||
}
|
||||
#if defined(HAVE_XRANDR) && HAVE_XRANDR
|
||||
main_frame->m_XRRConfig->Update();
|
||||
#endif
|
||||
@ -936,43 +1015,43 @@ void VideoConfigDiag::Evt_EnterControl(wxMouseEvent& ev)
|
||||
// look up the description of the selected control and assign it to the current description text
|
||||
// object's label
|
||||
descr_text->SetLabel(ctrl_descs[ctrl]);
|
||||
descr_text->Wrap(descr_text->GetContainingSizer()->GetSize().x - 20);
|
||||
descr_text->Wrap(descr_text->GetSize().GetWidth());
|
||||
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
// TODO: Don't hardcode the size of the description area via line breaks
|
||||
#define DEFAULT_DESC_TEXT \
|
||||
_("Move the mouse pointer over an option to display a detailed description.\n\n\n\n\n\n\n")
|
||||
void VideoConfigDiag::Evt_LeaveControl(wxMouseEvent& ev)
|
||||
{
|
||||
// look up description text control and reset its label
|
||||
wxWindow* ctrl = (wxWindow*)ev.GetEventObject();
|
||||
wxWindow* ctrl = static_cast<wxWindow*>(ev.GetEventObject());
|
||||
if (!ctrl)
|
||||
return;
|
||||
wxStaticText* descr_text = desc_texts[ctrl->GetParent()];
|
||||
if (!descr_text)
|
||||
return;
|
||||
|
||||
descr_text->SetLabel(DEFAULT_DESC_TEXT);
|
||||
descr_text->Wrap(descr_text->GetContainingSizer()->GetSize().x - 20);
|
||||
descr_text->SetLabel(wxGetTranslation(default_desc));
|
||||
descr_text->Wrap(descr_text->GetSize().GetWidth());
|
||||
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void VideoConfigDiag::CreateDescriptionArea(wxPanel* const page, wxBoxSizer* const sizer)
|
||||
{
|
||||
const int space5 = FromDIP(5);
|
||||
|
||||
// Create description frame
|
||||
wxStaticBoxSizer* const desc_sizer = new wxStaticBoxSizer(wxVERTICAL, page, _("Description"));
|
||||
sizer->Add(desc_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
sizer->Add(desc_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
sizer->AddSpacer(space5);
|
||||
|
||||
// Need to call SetSizerAndFit here, since we don't want the description texts to change the
|
||||
// dialog width
|
||||
page->SetSizerAndFit(sizer);
|
||||
|
||||
// Create description text
|
||||
wxStaticText* const desc_text = new wxStaticText(page, wxID_ANY, DEFAULT_DESC_TEXT);
|
||||
desc_text->Wrap(desc_sizer->GetSize().x - 20);
|
||||
desc_sizer->Add(desc_text, 1, wxEXPAND | wxLEFT | wxRIGHT | wxBOTTOM, 5);
|
||||
// Create description text (220 = 75*4 (75 chars), 80 = 10*8 (10 lines))
|
||||
wxStaticText* const desc_text =
|
||||
new wxStaticText(page, wxID_ANY, wxGetTranslation(default_desc), wxDefaultPosition,
|
||||
wxDLG_UNIT(this, wxSize(220, 80)), wxST_NO_AUTORESIZE);
|
||||
desc_text->Wrap(desc_text->GetMinWidth());
|
||||
desc_sizer->Add(desc_text, 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
|
||||
desc_sizer->AddSpacer(space5);
|
||||
|
||||
// Store description text object for later lookup
|
||||
desc_texts.emplace(page, desc_text);
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "Common/SysConf.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "DolphinWX/DolphinSlider.h"
|
||||
#include "DolphinWX/PostProcessingConfigDiag.h"
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
#include "VideoCommon/PostProcessing.h"
|
||||
@ -100,8 +101,7 @@ protected:
|
||||
wxMessageBox(_("Software rendering is an order of magnitude slower than using the "
|
||||
"other backends.\nIt's only useful for debugging purposes.\nDo you "
|
||||
"really want to enable software rendering? If unsure, select 'No'."),
|
||||
_("Warning"), wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION,
|
||||
wxWindow::FindFocus()));
|
||||
_("Warning"), wxYES_NO | wxNO_DEFAULT | wxICON_EXCLAMATION, this));
|
||||
}
|
||||
|
||||
if (do_switch)
|
||||
@ -198,8 +198,7 @@ protected:
|
||||
ev.Skip();
|
||||
}
|
||||
|
||||
void Event_ClickClose(wxCommandEvent&);
|
||||
void Event_Close(wxCloseEvent&);
|
||||
void Event_Close(wxCommandEvent&);
|
||||
|
||||
// Enables/disables UI elements depending on current config
|
||||
void OnUpdateUI(wxUpdateUIEvent& ev)
|
||||
@ -274,7 +273,7 @@ protected:
|
||||
|
||||
wxStaticText* text_aamode;
|
||||
wxChoice* choice_aamode;
|
||||
wxSlider* conv_slider;
|
||||
DolphinSlider* conv_slider;
|
||||
|
||||
wxStaticText* label_display_resolution;
|
||||
|
||||
|
@ -2,21 +2,36 @@
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <wx/app.h>
|
||||
#include <wx/bitmap.h>
|
||||
#include <wx/choice.h>
|
||||
#include <wx/combo.h>
|
||||
#include <wx/combobox.h>
|
||||
#include <wx/display.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/image.h>
|
||||
#include <wx/msgdlg.h>
|
||||
#include <wx/mstream.h>
|
||||
#include <wx/sizer.h>
|
||||
#include <wx/spinctrl.h>
|
||||
#include <wx/toolbar.h>
|
||||
#include <wx/toplevel.h>
|
||||
#include <wx/utils.h>
|
||||
|
||||
#include "Common/CommonPaths.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
|
||||
#include "DolphinWX/WxUtils.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <Windows.h>
|
||||
#endif
|
||||
|
||||
namespace WxUtils
|
||||
{
|
||||
// Launch a file according to its mime type
|
||||
@ -55,45 +70,10 @@ void ShowErrorDialog(const wxString& error_msg)
|
||||
wxMessageBox(error_msg, _("Error"), wxOK | wxICON_ERROR);
|
||||
}
|
||||
|
||||
wxBitmap LoadResourceBitmap(const std::string& name, const wxSize& padded_size)
|
||||
{
|
||||
const std::string path_base = File::GetSysDirectory() + RESOURCES_DIR + DIR_SEP + name;
|
||||
std::string path = path_base + ".png";
|
||||
double scale_factor = 1.0;
|
||||
#ifdef __APPLE__
|
||||
if (wxTheApp->GetTopWindow()->GetContentScaleFactor() >= 2)
|
||||
{
|
||||
const std::string path_2x = path_base + "@2x.png";
|
||||
if (File::Exists(path_2x))
|
||||
{
|
||||
path = path_2x;
|
||||
scale_factor = 2.0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
wxImage image(StrToWxStr(path), wxBITMAP_TYPE_PNG);
|
||||
|
||||
if (padded_size != wxSize())
|
||||
{
|
||||
// Add padding if necessary (or crop, but images aren't supposed to be large enough to require
|
||||
// that).
|
||||
// The image will be left-aligned and vertically centered.
|
||||
const wxSize scaled_padded_size = padded_size * scale_factor;
|
||||
image.Resize(scaled_padded_size,
|
||||
wxPoint(0, (scaled_padded_size.GetHeight() - image.GetHeight()) / 2));
|
||||
}
|
||||
|
||||
#ifdef __APPLE__
|
||||
return wxBitmap(image, -1, scale_factor);
|
||||
#else
|
||||
return wxBitmap(image);
|
||||
#endif
|
||||
}
|
||||
|
||||
wxBitmap CreateDisabledButtonBitmap(const wxBitmap& original)
|
||||
{
|
||||
wxImage image = original.ConvertToImage();
|
||||
return wxBitmap(image.ConvertToDisabled(240));
|
||||
return wxBitmap(image.ConvertToDisabled(240), wxBITMAP_SCREEN_DEPTH, original.GetScaleFactor());
|
||||
}
|
||||
|
||||
void AddToolbarButton(wxToolBar* toolbar, int toolID, const wxString& label, const wxBitmap& bitmap,
|
||||
@ -105,6 +85,440 @@ void AddToolbarButton(wxToolBar* toolbar, int toolID, const wxString& label, con
|
||||
wxITEM_NORMAL, shortHelp);
|
||||
}
|
||||
|
||||
wxIconBundle GetDolphinIconBundle()
|
||||
{
|
||||
static wxIconBundle s_bundle;
|
||||
if (!s_bundle.IsEmpty())
|
||||
return s_bundle;
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
// Convert the Windows ICO file into a wxIconBundle by tearing it apart into each individual
|
||||
// sub-icon using the Win32 API. This is necessary because WX uses its own wxIcons internally
|
||||
// which (unlike QIcon in Qt) only contain 1 image per icon, hence why wxIconBundle exists.
|
||||
HINSTANCE dolphin = GetModuleHandleW(nullptr);
|
||||
for (int size : {16, 32, 48, 256})
|
||||
{
|
||||
// Extract resource from embedded DolphinWX.rc
|
||||
HANDLE win32_icon =
|
||||
LoadImageW(dolphin, L"\"DOLPHIN\"", IMAGE_ICON, size, size, LR_CREATEDIBSECTION);
|
||||
if (win32_icon && win32_icon != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
wxIcon icon;
|
||||
icon.CreateFromHICON(reinterpret_cast<HICON>(win32_icon));
|
||||
s_bundle.AddIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
for (const char* fname : {"Dolphin.png", "dolphin_logo.png", "dolphin_logo@2x.png"})
|
||||
{
|
||||
wxImage image{StrToWxStr(File::GetSysDirectory() + RESOURCES_DIR DIR_SEP + fname),
|
||||
wxBITMAP_TYPE_PNG};
|
||||
if (image.IsOk())
|
||||
{
|
||||
wxIcon icon;
|
||||
icon.CopyFromBitmap(image);
|
||||
s_bundle.AddIcon(icon);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return s_bundle;
|
||||
}
|
||||
|
||||
wxRect GetVirtualScreenGeometry()
|
||||
{
|
||||
wxRect geometry;
|
||||
for (unsigned int i = 0, end = wxDisplay::GetCount(); i < end; ++i)
|
||||
geometry.Union(wxDisplay(i).GetGeometry());
|
||||
return geometry;
|
||||
}
|
||||
|
||||
void SetWindowSizeAndFitToScreen(wxTopLevelWindow* tlw, wxPoint pos, wxSize size,
|
||||
wxSize default_size)
|
||||
{
|
||||
if (tlw->IsMaximized())
|
||||
return;
|
||||
|
||||
// NOTE: Positions can be negative and still be valid. Coordinates are relative to the
|
||||
// primary monitor so if the primary monitor is in the middle then (-1000, 10) is a
|
||||
// valid position on the monitor to the left of the primary. (This does not apply to
|
||||
// sizes obviously)
|
||||
wxRect screen_geometry;
|
||||
wxRect window_geometry{pos, size};
|
||||
|
||||
if (wxDisplay::GetCount() > 1)
|
||||
screen_geometry = GetVirtualScreenGeometry();
|
||||
else
|
||||
screen_geometry = wxDisplay(0).GetClientArea();
|
||||
|
||||
// Initialize the default size if it is wxDefaultSize or otherwise negative.
|
||||
default_size.DecTo(screen_geometry.GetSize());
|
||||
default_size.IncTo(tlw->GetMinSize());
|
||||
if (!default_size.IsFullySpecified())
|
||||
default_size.SetDefaults(wxDisplay(0).GetClientArea().GetSize() / 2);
|
||||
|
||||
// If the position we're given doesn't make sense then go with the current position.
|
||||
// (Assuming the window was created with wxDefaultPosition then this should be reasonable)
|
||||
if (pos.x - screen_geometry.GetLeft() < -1000 || pos.y - screen_geometry.GetTop() < -1000 ||
|
||||
pos.x - screen_geometry.GetRight() > 1000 || pos.y - screen_geometry.GetBottom() > 1000)
|
||||
{
|
||||
window_geometry.SetPosition(tlw->GetPosition());
|
||||
}
|
||||
|
||||
// If the window is bigger than all monitors combined, or negative (uninitialized) then reset it.
|
||||
if (window_geometry.IsEmpty() || window_geometry.GetWidth() > screen_geometry.GetWidth() ||
|
||||
window_geometry.GetHeight() > screen_geometry.GetHeight())
|
||||
{
|
||||
window_geometry.SetSize(default_size);
|
||||
}
|
||||
|
||||
// Check if the window entirely lives on a single monitor without spanning.
|
||||
// If the window does not span multiple screens then we should constrain it within that
|
||||
// single monitor instead of the entire virtual desktop space.
|
||||
// The benefit to doing this is that we can account for the OS X menu bar and Windows task
|
||||
// bar which are treated as invisible when only looking at the virtual desktop instead of
|
||||
// an individual screen.
|
||||
if (wxDisplay::GetCount() > 1)
|
||||
{
|
||||
// SPECIAL CASE: If the window is entirely outside the visible area of the desktop then we
|
||||
// put it back on the primary (zero) monitor.
|
||||
wxRect monitor_intersection{window_geometry};
|
||||
int the_monitor = 0;
|
||||
if (!monitor_intersection.Intersect(screen_geometry).IsEmpty())
|
||||
{
|
||||
std::array<int, 4> monitors{{wxDisplay::GetFromPoint(monitor_intersection.GetTopLeft()),
|
||||
wxDisplay::GetFromPoint(monitor_intersection.GetTopRight()),
|
||||
wxDisplay::GetFromPoint(monitor_intersection.GetBottomLeft()),
|
||||
wxDisplay::GetFromPoint(monitor_intersection.GetBottomRight())}};
|
||||
the_monitor = wxNOT_FOUND;
|
||||
bool intersected = false;
|
||||
for (int one_monitor : monitors)
|
||||
{
|
||||
if (one_monitor == the_monitor || one_monitor == wxNOT_FOUND)
|
||||
continue;
|
||||
if (the_monitor != wxNOT_FOUND)
|
||||
{
|
||||
// The window is spanning multiple screens.
|
||||
the_monitor = wxNOT_FOUND;
|
||||
break;
|
||||
}
|
||||
the_monitor = one_monitor;
|
||||
intersected = true;
|
||||
}
|
||||
// If we get wxNOT_FOUND for all corners then there are holes in the virtual desktop and the
|
||||
// entire window is lost in one. (e.g. 3 monitors in an 'L', window in top-right)
|
||||
if (!intersected)
|
||||
the_monitor = 0;
|
||||
}
|
||||
if (the_monitor != wxNOT_FOUND)
|
||||
{
|
||||
// We'll only use the client area of this monitor if the window will actually fit.
|
||||
// (It may not fit if the window is spilling off the edge so it isn't entirely visible)
|
||||
wxRect client_area{wxDisplay(the_monitor).GetClientArea()};
|
||||
if (client_area.GetWidth() >= window_geometry.GetWidth() &&
|
||||
client_area.GetHeight() >= window_geometry.GetHeight())
|
||||
{
|
||||
screen_geometry = client_area;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The window SHOULD be small enough to fit on the screen, but it might be spilling off an edge
|
||||
// so we'll snap it to the nearest edge as necessary.
|
||||
if (!screen_geometry.Contains(window_geometry))
|
||||
{
|
||||
// NOTE: The order is important here, if the window *is* too big to fit then it will snap to
|
||||
// the top-left corner.
|
||||
int spill_x = std::max(0, window_geometry.GetRight() - screen_geometry.GetRight());
|
||||
int spill_y = std::max(0, window_geometry.GetBottom() - screen_geometry.GetBottom());
|
||||
window_geometry.Offset(-spill_x, -spill_y);
|
||||
if (window_geometry.GetTop() < screen_geometry.GetTop())
|
||||
window_geometry.SetTop(screen_geometry.GetTop());
|
||||
if (window_geometry.GetLeft() < screen_geometry.GetLeft())
|
||||
window_geometry.SetLeft(screen_geometry.GetLeft());
|
||||
}
|
||||
|
||||
tlw->SetSize(window_geometry, wxSIZE_ALLOW_MINUS_ONE);
|
||||
}
|
||||
|
||||
wxSizer* GiveMinSize(wxWindow* window, const wxSize& min_size)
|
||||
{
|
||||
wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);
|
||||
int flags = wxEXPAND;
|
||||
// On Windows comboboxes will misrender when stretched vertically.
|
||||
if (wxDynamicCast(window, wxChoice) || wxDynamicCast(window, wxComboBox) ||
|
||||
wxDynamicCast(window, wxComboCtrl))
|
||||
flags = wxALIGN_CENTER_VERTICAL;
|
||||
sizer->Add(window, 1, flags);
|
||||
sizer->SetMinSize(min_size);
|
||||
return sizer;
|
||||
}
|
||||
|
||||
wxSizer* GiveMinSizeDIP(wxWindow* window, const wxSize& min_size)
|
||||
{
|
||||
return GiveMinSize(window, window->FromDIP(min_size));
|
||||
}
|
||||
|
||||
wxSize GetTextWidgetMinSize(const wxControl* control, const wxString& value)
|
||||
{
|
||||
return control->GetSizeFromTextSize(control->GetTextExtent(value));
|
||||
}
|
||||
|
||||
wxSize GetTextWidgetMinSize(const wxControl* control, unsigned int value)
|
||||
{
|
||||
return GetTextWidgetMinSize(control, wxString::Format("%u", value));
|
||||
}
|
||||
|
||||
wxSize GetTextWidgetMinSize(const wxControl* control, int value)
|
||||
{
|
||||
return GetTextWidgetMinSize(control, wxString::Format("%d", value));
|
||||
}
|
||||
|
||||
wxSize GetTextWidgetMinSize(const wxSpinCtrl* spinner)
|
||||
{
|
||||
wxSize size = GetTextWidgetMinSize(spinner, spinner->GetMin());
|
||||
size.IncTo(GetTextWidgetMinSize(spinner, spinner->GetMax()));
|
||||
return size;
|
||||
}
|
||||
|
||||
static wxImage LoadScaledImage(const std::string& file_path, const wxWindow* context,
|
||||
const wxSize& output_size, const wxRect& usable_rect, LSIFlags flags,
|
||||
const wxColour& fill_color)
|
||||
{
|
||||
std::string fpath, fname, fext;
|
||||
SplitPath(file_path, &fpath, &fname, &fext);
|
||||
|
||||
const double window_scale_factor = context->GetContentScaleFactor();
|
||||
// Compute the total scale factor from the ratio of DIPs to window pixels (FromDIP) and
|
||||
// window pixels to framebuffer pixels (GetContentScaleFactor).
|
||||
// NOTE: Usually only one of these is meaningful:
|
||||
// - On Windows/GTK2: content_scale = 1.0, FromDIP = 96DPI -> Screen DPI
|
||||
// - On Mac OS X: content_scale = screen_dpi / 96, FromDIP = 96DPI -> 96DPI (no-op)
|
||||
// [The 1024 is arbitrarily large to minimise rounding error, it has no significance]
|
||||
const double scale_factor = (context->FromDIP(1024) / 1024.0) * window_scale_factor;
|
||||
|
||||
// We search for files on quarter ratios of DIPs to framebuffer pixels.
|
||||
// By default, the algorithm prefers to find an exact or bigger size then downscale if
|
||||
// needed but will resort to upscaling if a bigger image cannot be found.
|
||||
// E.g. A basic retina screen on Mac OS X has a scale_factor of 2.0, so we would look for
|
||||
// @2x, @2.25x, @2.5x, @2.75x, @3x, @1.75x, @1.5x, @1.25x, @1x, then give up.
|
||||
// (At 125% on Windows the search is @1.25, @1.5, @1.75, @2, @2.25, @1)
|
||||
// If flags does not include LSI_SCALE_DOWN (i.e. we would be forced to crop big
|
||||
// images instead of scaling them) then we will only accept smaller sizes, i.e.
|
||||
// @2x, @1.75, @1.5, @1.25, @1, then give up.
|
||||
// NOTE: We do a lot of exact comparisons against floating point here but it's fine
|
||||
// because the numbers involved are all powers of 2 so can be represented exactly.
|
||||
wxImage image;
|
||||
double selected_image_scale = 1;
|
||||
{
|
||||
auto image_check = [&](double scale) -> bool {
|
||||
std::string path = fpath + fname + StringFromFormat("@%gx", scale) + fext;
|
||||
if (!File::Exists(path))
|
||||
{
|
||||
// Special Case: @1x may not have a suffix at all.
|
||||
if (scale != 1.0 || !File::Exists(file_path))
|
||||
return false;
|
||||
path = file_path;
|
||||
}
|
||||
if (!image.LoadFile(StrToWxStr(path), wxBITMAP_TYPE_ANY))
|
||||
return false;
|
||||
selected_image_scale = scale;
|
||||
return true;
|
||||
};
|
||||
const bool prefer_smaller = !(flags & LSI_SCALE_DOWN);
|
||||
const double scale_factor_quarter =
|
||||
prefer_smaller ? std::floor(scale_factor * 4) / 4 : std::ceil(scale_factor * 4) / 4;
|
||||
// Search for bigger sizes first (preferred)
|
||||
if (!prefer_smaller)
|
||||
{
|
||||
// We search within a 'circle' of the exact match limited by scale=1.0.
|
||||
// i.e. scale_factor = 1.5, radius = 0.5; scale = 2.5, radius = 1.5.
|
||||
// The minimum radius is 1.0.
|
||||
double limit = std::max(scale_factor_quarter * 2 - 1, scale_factor_quarter + 1);
|
||||
for (double quarter = scale_factor_quarter; quarter <= limit; quarter += 0.25)
|
||||
{
|
||||
if (image_check(quarter))
|
||||
break;
|
||||
}
|
||||
}
|
||||
// If we didn't hit a bigger size then we'll fallback to looking for smaller ones
|
||||
if (!image.IsOk())
|
||||
{
|
||||
double quarter = scale_factor_quarter;
|
||||
if (!prefer_smaller) // So we don't recheck the exact match
|
||||
quarter -= 0.25;
|
||||
for (; quarter >= 1.0; quarter -= 0.25)
|
||||
{
|
||||
if (image_check(quarter))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The file apparently does not exist so we give up. Create a white square placeholder instead.
|
||||
if (!image.IsOk())
|
||||
{
|
||||
wxLogError("Could not find resource: %s", StrToWxStr(file_path));
|
||||
image.Create(1, 1, false);
|
||||
image.Clear(0xFF);
|
||||
}
|
||||
|
||||
return ScaleImage(image, selected_image_scale, window_scale_factor, output_size, usable_rect,
|
||||
flags, fill_color);
|
||||
}
|
||||
|
||||
wxBitmap LoadScaledBitmap(const std::string& file_path, const wxWindow* context,
|
||||
const wxSize& output_size, const wxRect& usable_rect, LSIFlags flags,
|
||||
const wxColour& fill_color)
|
||||
{
|
||||
return wxBitmap(LoadScaledImage(file_path, context, output_size, usable_rect, flags, fill_color),
|
||||
wxBITMAP_SCREEN_DEPTH, context->GetContentScaleFactor());
|
||||
}
|
||||
|
||||
wxBitmap LoadScaledResourceBitmap(const std::string& name, const wxWindow* context,
|
||||
const wxSize& output_size, const wxRect& usable_rect,
|
||||
LSIFlags flags, const wxColour& fill_color)
|
||||
{
|
||||
std::string path = File::GetSysDirectory() + RESOURCES_DIR DIR_SEP + name + ".png";
|
||||
return LoadScaledBitmap(path, context, output_size, usable_rect, flags, fill_color);
|
||||
}
|
||||
|
||||
wxBitmap LoadScaledThemeBitmap(const std::string& name, const wxWindow* context,
|
||||
const wxSize& output_size, const wxRect& usable_rect, LSIFlags flags,
|
||||
const wxColour& fill_color)
|
||||
{
|
||||
std::string path = File::GetThemeDir(SConfig::GetInstance().theme_name) + name + ".png";
|
||||
return LoadScaledBitmap(path, context, output_size, usable_rect, flags, fill_color);
|
||||
}
|
||||
|
||||
wxBitmap ScaleImageToBitmap(const wxImage& image, const wxWindow* context,
|
||||
const wxSize& output_size, const wxRect& usable_rect, LSIFlags flags,
|
||||
const wxColour& fill_color)
|
||||
{
|
||||
double scale_factor = context->GetContentScaleFactor();
|
||||
return wxBitmap(ScaleImage(image, 1.0, scale_factor, output_size, usable_rect, flags, fill_color),
|
||||
wxBITMAP_SCREEN_DEPTH, scale_factor);
|
||||
}
|
||||
|
||||
wxBitmap ScaleImageToBitmap(const wxImage& image, const wxWindow* context, double source_scale,
|
||||
LSIFlags flags, const wxColour& fill_color)
|
||||
{
|
||||
double scale_factor = context->GetContentScaleFactor();
|
||||
return wxBitmap(ScaleImage(image, source_scale, scale_factor, wxDefaultSize, wxDefaultSize, flags,
|
||||
fill_color),
|
||||
wxBITMAP_SCREEN_DEPTH, scale_factor);
|
||||
}
|
||||
|
||||
wxImage ScaleImage(wxImage image, double source_scale_factor, double content_scale_factor,
|
||||
wxSize output_size, wxRect usable_rect, LSIFlags flags,
|
||||
const wxColour& fill_color)
|
||||
{
|
||||
if (!image.IsOk())
|
||||
{
|
||||
wxFAIL_MSG("WxUtils::ScaleImage expects a valid image.");
|
||||
return image;
|
||||
}
|
||||
|
||||
if (content_scale_factor != 1.0)
|
||||
{
|
||||
output_size *= content_scale_factor;
|
||||
usable_rect.SetPosition(usable_rect.GetPosition() * content_scale_factor);
|
||||
usable_rect.SetSize(usable_rect.GetSize() * content_scale_factor);
|
||||
}
|
||||
|
||||
// Fix the output size if it's unset.
|
||||
wxSize img_size = image.GetSize();
|
||||
if (output_size.GetWidth() < 1)
|
||||
output_size.SetWidth(
|
||||
static_cast<int>(img_size.GetWidth() * (content_scale_factor / source_scale_factor)));
|
||||
if (output_size.GetHeight() < 1)
|
||||
output_size.SetHeight(
|
||||
static_cast<int>(img_size.GetHeight() * (content_scale_factor / source_scale_factor)));
|
||||
|
||||
// Fix the usable rect. If it's empty then the whole canvas is usable.
|
||||
if (usable_rect.IsEmpty())
|
||||
{
|
||||
// Constructs a temp wxRect 0,0->output_size then move assigns it.
|
||||
usable_rect = output_size;
|
||||
}
|
||||
else if (!usable_rect.Intersects(output_size))
|
||||
{
|
||||
wxFAIL_MSG("Usable Zone Rectangle is not inside the canvas. Check the output size is correct.");
|
||||
image.Create(1, 1, false);
|
||||
image.SetRGB(0, 0, fill_color.Red(), fill_color.Green(), fill_color.Blue());
|
||||
if (fill_color.Alpha() == wxALPHA_TRANSPARENT)
|
||||
image.SetMaskColour(fill_color.Red(), fill_color.Green(), fill_color.Blue());
|
||||
usable_rect = output_size;
|
||||
}
|
||||
|
||||
// Step 1: Scale the image
|
||||
if ((flags & LSI_SCALE) != LSI_SCALE_NONE)
|
||||
{
|
||||
if (flags & LSI_SCALE_NO_ASPECT)
|
||||
{
|
||||
// Stretch scale without preserving the aspect ratio.
|
||||
bool scale_width = (img_size.GetWidth() > usable_rect.GetWidth() && flags & LSI_SCALE_DOWN) ||
|
||||
(img_size.GetWidth() < usable_rect.GetWidth() && flags & LSI_SCALE_UP);
|
||||
bool scale_height =
|
||||
(img_size.GetHeight() > usable_rect.GetHeight() && flags & LSI_SCALE_DOWN) ||
|
||||
(img_size.GetHeight() < usable_rect.GetHeight() && flags & LSI_SCALE_UP);
|
||||
if (scale_width || scale_height)
|
||||
{
|
||||
// NOTE: Using BICUBIC instead of HIGH because it's the same internally
|
||||
// except that downscaling uses a box filter with awful obvious aliasing
|
||||
// for non-integral scale factors.
|
||||
image.Rescale(scale_width ? usable_rect.GetWidth() : img_size.GetWidth(),
|
||||
scale_height ? usable_rect.GetHeight() : img_size.GetHeight(),
|
||||
wxIMAGE_QUALITY_BICUBIC);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scale while preserving the aspect ratio.
|
||||
double scale = std::min(static_cast<double>(usable_rect.GetWidth()) / img_size.GetWidth(),
|
||||
static_cast<double>(usable_rect.GetHeight()) / img_size.GetHeight());
|
||||
int target_width = static_cast<int>(img_size.GetWidth() * scale);
|
||||
int target_height = static_cast<int>(img_size.GetHeight() * scale);
|
||||
// Bilinear produces sharper images when upscaling, bicubic tends to smear/blur sharp edges.
|
||||
if (scale > 1.0 && flags & LSI_SCALE_UP)
|
||||
image.Rescale(target_width, target_height, wxIMAGE_QUALITY_BILINEAR);
|
||||
else if (scale < 1.0 && flags & LSI_SCALE_DOWN)
|
||||
image.Rescale(target_width, target_height, wxIMAGE_QUALITY_BICUBIC);
|
||||
}
|
||||
img_size = image.GetSize();
|
||||
}
|
||||
|
||||
// Step 2: Resize the canvas to match the output size.
|
||||
// NOTE: If NOT using LSI_SCALE_DOWN then this will implicitly crop the image
|
||||
if (img_size != output_size || usable_rect.GetPosition() != wxPoint())
|
||||
{
|
||||
wxPoint base = usable_rect.GetPosition();
|
||||
if (flags & LSI_ALIGN_HCENTER)
|
||||
base.x += (usable_rect.GetWidth() - img_size.GetWidth()) / 2;
|
||||
else if (flags & LSI_ALIGN_RIGHT)
|
||||
base.x += usable_rect.GetWidth() - img_size.GetWidth();
|
||||
if (flags & LSI_ALIGN_VCENTER)
|
||||
base.y += (usable_rect.GetHeight() - img_size.GetHeight()) / 2;
|
||||
else if (flags & LSI_ALIGN_BOTTOM)
|
||||
base.y += usable_rect.GetHeight() - img_size.GetHeight();
|
||||
|
||||
int r = -1, g = -1, b = -1;
|
||||
if (fill_color.Alpha() != wxALPHA_TRANSPARENT)
|
||||
{
|
||||
r = fill_color.Red();
|
||||
g = fill_color.Green();
|
||||
b = fill_color.Blue();
|
||||
}
|
||||
image.Resize(output_size, base, r, g, b);
|
||||
}
|
||||
|
||||
return image;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string WxStrToStr(const wxString& str)
|
||||
|
@ -5,11 +5,18 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <wx/colour.h>
|
||||
#include <wx/gdicmn.h>
|
||||
#include <wx/string.h>
|
||||
|
||||
class wxControl;
|
||||
class wxBitmap;
|
||||
class wxImage;
|
||||
class wxSizer;
|
||||
class wxSpinCtrl;
|
||||
class wxToolBar;
|
||||
class wxTopLevelWindow;
|
||||
class wxWindow;
|
||||
|
||||
namespace WxUtils
|
||||
{
|
||||
@ -22,9 +29,6 @@ void Explore(const std::string& path);
|
||||
// Displays a wxMessageBox geared for errors
|
||||
void ShowErrorDialog(const wxString& error_msg);
|
||||
|
||||
// Reads a PNG from the Resources folder
|
||||
wxBitmap LoadResourceBitmap(const std::string& name, const wxSize& padded_size = wxSize());
|
||||
|
||||
// From a wxBitmap, creates the corresponding disabled version for toolbar buttons
|
||||
wxBitmap CreateDisabledButtonBitmap(const wxBitmap& original);
|
||||
|
||||
@ -32,6 +36,111 @@ wxBitmap CreateDisabledButtonBitmap(const wxBitmap& original);
|
||||
void AddToolbarButton(wxToolBar* toolbar, int toolID, const wxString& label, const wxBitmap& bitmap,
|
||||
const wxString& shortHelp);
|
||||
|
||||
// Gets a complete set of window icons at all relevant sizes, use with wxTopLevelWindow::SetIcons
|
||||
wxIconBundle GetDolphinIconBundle();
|
||||
|
||||
// Get the dimensions of the virtual desktop that spans all monitors.
|
||||
// Matches GetSystemMetrics(SM_XVIRTUALSCREEN), etc on Windows.
|
||||
wxRect GetVirtualScreenGeometry();
|
||||
|
||||
// Takes a top-level window and resizes / repositions it so it fits on the screen.
|
||||
// Supports spanning multiple monitors if there are multiple monitors.
|
||||
// Will snap to edge if the window is small enough to fit but spills over the boundary.
|
||||
void SetWindowSizeAndFitToScreen(wxTopLevelWindow* tlw, wxPoint pos, wxSize size,
|
||||
wxSize default_size = wxDefaultSize);
|
||||
|
||||
// wxSizers use the minimum size of a widget when computing layout instead of the best size.
|
||||
// The best size is only taken when the minsize is -1,-1 (i.e. undefined).
|
||||
// This means that elements with a MinSize specified will always have that exact size unless
|
||||
// wxEXPAND-ed.
|
||||
// This problem can be resolved by wrapping the widget in a sizer and setting the minimum size on
|
||||
// the sizer instead. Sizers will always use the best size of the widget, treating their own MinSize
|
||||
// as a floor which is usually what you want.
|
||||
wxSizer* GiveMinSize(wxWindow* window, const wxSize& min_size);
|
||||
wxSizer* GiveMinSizeDIP(wxWindow* window, const wxSize& min_size);
|
||||
|
||||
// Compute the proper size for a text widget (wxTextCtrl, wxChoice, wxSpinCtrl, etc)
|
||||
// Based on the text it will be required to hold. This gives the element the minimum
|
||||
// width to hold the largest text value instead of being arbitrarily wide.
|
||||
wxSize GetTextWidgetMinSize(const wxControl* control, const wxString& value);
|
||||
wxSize GetTextWidgetMinSize(const wxControl* control, unsigned int value);
|
||||
wxSize GetTextWidgetMinSize(const wxControl* control, int value);
|
||||
wxSize GetTextWidgetMinSize(const wxSpinCtrl* spinner);
|
||||
|
||||
enum LSIFlags : unsigned int
|
||||
{
|
||||
LSI_SCALE_NONE = 0, // Disable scaling, only resize canvas
|
||||
LSI_SCALE_UP = 1, // Scale up if needed, but crop instead of scaling down
|
||||
LSI_SCALE_DOWN = 2, // Scale down if needed, only expand canvas instead of scaling up
|
||||
LSI_SCALE = LSI_SCALE_UP | LSI_SCALE_DOWN, // Scale either way as needed.
|
||||
LSI_SCALE_NO_ASPECT = 8, // Disable preserving the aspect ratio of the image.
|
||||
|
||||
LSI_ALIGN_LEFT = 0, // Place image at the left edge of canvas
|
||||
LSI_ALIGN_RIGHT = 0x10, // Place image at the right edge of canvas
|
||||
LSI_ALIGN_HCENTER = 0x20, // Place image in the horizontal center of canvas
|
||||
LSI_ALIGN_TOP = 0, // Place image at the top of the canvas
|
||||
LSI_ALIGN_BOTTOM = 0x40, // Place image at the bottom of the canvas
|
||||
LSI_ALIGN_VCENTER = 0x80, // Place image in the vertical center of canvas
|
||||
|
||||
LSI_ALIGN_CENTER = LSI_ALIGN_HCENTER | LSI_ALIGN_VCENTER,
|
||||
|
||||
LSI_DEFAULT = LSI_SCALE | LSI_ALIGN_CENTER
|
||||
};
|
||||
constexpr LSIFlags operator|(LSIFlags left, LSIFlags right)
|
||||
{
|
||||
return static_cast<LSIFlags>(static_cast<unsigned int>(left) | right);
|
||||
}
|
||||
constexpr LSIFlags operator&(LSIFlags left, LSIFlags right)
|
||||
{
|
||||
return static_cast<LSIFlags>(static_cast<unsigned int>(left) & right);
|
||||
}
|
||||
|
||||
// Swiss army knife loader function for preparing a scaled resource image file.
|
||||
// Only the path and context are mandatory, other parameters can be ignored.
|
||||
// NOTE: All size parameters are in window pixels, not DIPs or framebuffer pixels.
|
||||
// output_size = size of image canvas if different from native image size. E.g. 96x32
|
||||
// usable_rect = part of image canvas that is considered usable. E.g. 0,0 -> 32,32
|
||||
// Usable zone is helpful if the canvas is bigger than the area which will be drawn on screen.
|
||||
// flags = See LSIFlags
|
||||
// fill_color = Color to fill the unused canvas area (due to aspect ratio or usable_rect).
|
||||
wxBitmap LoadScaledBitmap(const std::string& file_path, const wxWindow* context,
|
||||
const wxSize& output_size = wxDefaultSize,
|
||||
const wxRect& usable_rect = wxDefaultSize, LSIFlags flags = LSI_DEFAULT,
|
||||
const wxColour& fill_color = wxTransparentColour);
|
||||
wxBitmap LoadScaledResourceBitmap(const std::string& name, const wxWindow* context,
|
||||
const wxSize& output_size = wxDefaultSize,
|
||||
const wxRect& usable_rect = wxDefaultSize,
|
||||
LSIFlags flags = LSI_DEFAULT,
|
||||
const wxColour& fill_color = wxTransparentColour);
|
||||
wxBitmap LoadScaledThemeBitmap(const std::string& name, const wxWindow* context,
|
||||
const wxSize& output_size = wxDefaultSize,
|
||||
const wxRect& usable_rect = wxDefaultSize,
|
||||
LSIFlags flags = LSI_DEFAULT,
|
||||
const wxColour& fill_color = wxTransparentColour);
|
||||
|
||||
// Variant of LoadScaledBitmap to scale an image that didn't come from a file.
|
||||
wxBitmap ScaleImageToBitmap(const wxImage& image, const wxWindow* context,
|
||||
const wxSize& output_size = wxDefaultSize,
|
||||
const wxRect& usable_rect = wxDefaultSize, LSIFlags flags = LSI_DEFAULT,
|
||||
const wxColour& fill_color = wxTransparentColour);
|
||||
|
||||
// Rescales image to screen DPI.
|
||||
// "Source scale" is essentially the image's DPI as a ratio to 96DPI, e.g. 144DPI image has a
|
||||
// scale of 1.5.
|
||||
wxBitmap ScaleImageToBitmap(const wxImage& image, const wxWindow* context, double source_scale,
|
||||
LSIFlags flags = LSI_DEFAULT,
|
||||
const wxColour& fill_color = wxTransparentColour);
|
||||
|
||||
// Internal scaling engine behind all the Scaling functions.
|
||||
// Exposes all control parameters instead of infering them from other sources.
|
||||
// "Content scale" is a factor applied to output_size and usable_rect internally to convert them
|
||||
// to framebuffer pixel sizes.
|
||||
// NOTE: Source scale factor only matters if you don't explicitly specify the output size.
|
||||
wxImage ScaleImage(wxImage image, double source_scale_factor = 1.0,
|
||||
double content_scale_factor = 1.0, wxSize output_size = wxDefaultSize,
|
||||
wxRect usable_rect = wxDefaultSize, LSIFlags flags = LSI_DEFAULT,
|
||||
const wxColour& fill_color = wxTransparentColour);
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string WxStrToStr(const wxString& str);
|
||||
|
Loading…
x
Reference in New Issue
Block a user