diff --git a/.gitattributes b/.gitattributes index ff8d85d60e..19602a1f35 100644 --- a/.gitattributes +++ b/.gitattributes @@ -6,6 +6,3 @@ *.props text eol=crlf *.vcxproj text eol=crlf *.vcxproj.filters text eol=crlf - -# Hide generated files for easier pull-request reviewing -pcsx2/Recording/VirtualPad/img/*.h linguist-generated \ No newline at end of file diff --git a/.github/workflows/linux-workflow.yml b/.github/workflows/linux-workflow.yml index 102124c85e..d49e9bb13c 100644 --- a/.github/workflows/linux-workflow.yml +++ b/.github/workflows/linux-workflow.yml @@ -78,13 +78,13 @@ jobs: string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC) message("::set-output name=timestamp::${current_date}") - # - name: ccache cache files - # uses: actions/cache@v2 - # with: - # path: .ccache - # key: ${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }} - # restore-keys: | - # ${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache- + - name: ccache cache files + uses: actions/cache@v2 + with: + path: .ccache + key: ${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }} + restore-keys: | + ${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache- - name: Install Packages env: @@ -102,4 +102,3 @@ jobs: chmod +x .github/workflows/scripts/build-linux.sh ./.github/workflows/scripts/build-linux.sh generate_cmake ./.github/workflows/scripts/build-linux.sh compile - ls ./pcsx2/Recording/VirtualPad/img diff --git a/pcsx2/CMakeLists.txt b/pcsx2/CMakeLists.txt index 7f6139337d..bca3c21b7f 100644 --- a/pcsx2/CMakeLists.txt +++ b/pcsx2/CMakeLists.txt @@ -507,7 +507,9 @@ set(pcsx2RecordingHeaders set(res_rec_vp_src "${CMAKE_SOURCE_DIR}/pcsx2/Recording/VirtualPad/img") set(pcsx2RecordingVirtualPadResources ${res_rec_vp_src}/circlePressed.h - ${res_rec_vp_src}/controller.h + ${res_rec_vp_src}/controllerFull.h + ${res_rec_vp_src}/controllerHalf.h + ${res_rec_vp_src}/controllerThreeQuarters.h ${res_rec_vp_src}/crossPressed.h ${res_rec_vp_src}/downPressed.h ${res_rec_vp_src}/l1Pressed.h @@ -760,7 +762,7 @@ endforeach() ### Generate Recording resource files ### Drop them into the folder alongside the png files foreach(res_file IN ITEMS - circlePressed controller crossPressed downPressed l1Pressed l2Pressed l3Pressed leftPressed + circlePressed controllerFull controllerHalf controllerThreeQuarters crossPressed downPressed l1Pressed l2Pressed l3Pressed leftPressed r1Pressed r2Pressed r3Pressed rightPressed selectPressed squarePressed startPressed trianglePressed upPressed) add_custom_command(OUTPUT "${res_rec_vp_src}/${res_file}.h" COMMAND perl ${CMAKE_SOURCE_DIR}/linux_various/hex2h.pl "${res_rec_vp_src}/${res_file}.png" "${res_rec_vp_src}/${res_file}" ) endforeach() diff --git a/pcsx2/Recording/InputRecording.cpp b/pcsx2/Recording/InputRecording.cpp index d580afa7b9..59d66a7899 100644 --- a/pcsx2/Recording/InputRecording.cpp +++ b/pcsx2/Recording/InputRecording.cpp @@ -60,11 +60,11 @@ InputRecording g_InputRecording; InputRecording::InputRecording() { // NOTE - No multi-tap support, only two controllers - padData[CONTROLLER_PORT_ONE] = new PadData(); - padData[CONTROLLER_PORT_TWO] = new PadData(); + padData[CONTROLLER_PORT_ONE] = new PadData(); + padData[CONTROLLER_PORT_TWO] = new PadData(); } -void InputRecording::setVirtualPadPtr(VirtualPad *ptr, int const port) +void InputRecording::setVirtualPadPtr(VirtualPad* ptr, int const port) { virtualPads[port] = ptr; } @@ -85,62 +85,53 @@ void InputRecording::RecordingReset() g_InputRecordingControls.Resume(); } -void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 &bufCount, u8 buf[]) +void InputRecording::ControllerInterrupt(u8& data, u8& port, u16& bufCount, u8 buf[]) { // TODO - Multi-Tap Support if (bufCount == 1) fInterruptFrame = data == READ_DATA_AND_VIBRATE_FIRST_BYTE; - else if (bufCount == 2) - { - if (buf[bufCount] != READ_DATA_AND_VIBRATE_SECOND_BYTE) - fInterruptFrame = false; - } + else if (bufCount == 2 && buf[bufCount] != READ_DATA_AND_VIBRATE_SECOND_BYTE) + fInterruptFrame = false; + // We do not want to record or save the first two bytes in the data returned from the PAD plugin else if (fInterruptFrame && bufCount >= 3 && frameCounter >= 0 && frameCounter < INT_MAX) { - u8 &bufVal = buf[bufCount]; - const u16 bufIndex = bufCount - 3; + u8& bufVal = buf[bufCount]; + const u16 bufIndex = bufCount - 3; if (state == InputRecordingMode::Replaying) { u8 tmp = 0; if (inputRecordingData.ReadKeyBuffer(tmp, frameCounter, port, bufIndex)) - { - // Overwrite value originally provided by the PAD plugin - bufVal = tmp; - // Update controller data state for future VirtualPad / logging usage. - padData[port]->UpdateControllerData(bufIndex, bufVal); - if (virtualPads[port] && virtualPads[port]->IsShown()) - { - virtualPads[port]->UpdateControllerData(bufIndex, padData[port]); - } - } + { + // Overwrite value originally provided by the PAD plugin + bufVal = tmp; + } } // Update controller data state for future VirtualPad / logging usage. padData[port]->UpdateControllerData(bufIndex, bufVal); - if (virtualPads[port] && virtualPads[port]->IsShown()) + if (virtualPads[port] && + virtualPads[port]->IsShown() && + virtualPads[port]->UpdateControllerData(bufIndex, padData[port]) && + state != InputRecordingMode::Replaying) { // If the VirtualPad updated the PadData, we have to update the buffer // before committing it to the recording / sending it to the game // - Do not do this if we are in replay mode! - if (virtualPads[port]->UpdateControllerData(bufIndex, padData[port]) && state != InputRecordingMode::Replaying) - { - bufVal = padData[port]->PollControllerData(bufIndex); - } + bufVal = padData[port]->PollControllerData(bufIndex); } // If we have reached the end of the pad data, log it out - if (bufIndex == PadData::END_INDEX_CONTROLLER_BUFFER) { + if (bufIndex == PadData::END_INDEX_CONTROLLER_BUFFER) + { padData[port]->LogPadData(port); // As well as re-render the virtual pad UI, if applicable // - Don't render if it's minimized if (virtualPads[port] && virtualPads[port]->IsShown() && !virtualPads[port]->IsIconized()) - { virtualPads[port]->Redraw(); - } } // Finally, commit the byte to the movie file if we are recording @@ -161,7 +152,7 @@ s32 InputRecording::GetFrameCounter() return frameCounter; } -InputRecordingFile &InputRecording::GetInputRecordingData() +InputRecordingFile& InputRecording::GetInputRecordingData() { return inputRecordingData; } @@ -223,17 +214,21 @@ wxString InputRecording::RecordingModeTitleSegment() void InputRecording::SetToRecordMode() { state = InputRecordingMode::Recording; + virtualPads[CONTROLLER_PORT_ONE]->SetReadOnlyMode(false); + virtualPads[CONTROLLER_PORT_TWO]->SetReadOnlyMode(false); recordingConLog("[REC]: Record mode ON.\n"); } void InputRecording::SetToReplayMode() { state = InputRecordingMode::Replaying; + virtualPads[CONTROLLER_PORT_ONE]->SetReadOnlyMode(true); + virtualPads[CONTROLLER_PORT_TWO]->SetReadOnlyMode(true); recordingConLog("[REC]: Replay mode ON.\n"); } void InputRecording::SetFrameCounter(u32 newGFrameCount) -{ +{ if (newGFrameCount > startingFrame + (u32)g_InputRecording.GetInputRecordingData().GetTotalFrames()) { recordingConLog(L"[REC]: Warning, you've loaded PCSX2 emulation to a point after the end of the original recording. This should be avoided.\n"); @@ -272,6 +267,8 @@ void InputRecording::SetStartingFrame(u32 newStartingFrame) void InputRecording::Stop() { state = InputRecordingMode::NotActive; + virtualPads[CONTROLLER_PORT_ONE]->SetReadOnlyMode(false); + virtualPads[CONTROLLER_PORT_TWO]->SetReadOnlyMode(false); incrementUndo = false; if (inputRecordingData.Close()) recordingConLog(L"[REC]: InputRecording Recording Stopped.\n"); @@ -303,7 +300,7 @@ bool InputRecording::Create(wxString FileName, bool fromSaveState, wxString auth inputRecordingData.GetHeader().SetGameName(resolveGameName()); // Write header contents inputRecordingData.WriteHeader(); - state = InputRecordingMode::Recording; + SetToRecordMode(); g_InputRecordingControls.DisableFrameAdvance(); recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName)); return true; @@ -328,8 +325,8 @@ bool InputRecording::Play(wxString fileName) } if (!wxFileExists(inputRecordingData.GetFilename() + "_SaveState.p2s")) { - recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s_SaveState.p2s\n", - inputRecordingData.GetFilename())); + recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s_SaveState.p2s\n", + inputRecordingData.GetFilename())); inputRecordingData.Close(); return false; } @@ -348,7 +345,7 @@ bool InputRecording::Play(wxString fileName) recordingConLog(L"[REC]: Recording was possibly constructed for a different game.\n"); incrementUndo = true; - state = InputRecordingMode::Replaying; + SetToReplayMode(); g_InputRecordingControls.DisableFrameAdvance(); recordingConLog(wxString::Format(L"[REC]: Replaying input recording - [%s]\n", inputRecordingData.GetFilename())); recordingConLog(wxString::Format(L"[REC]: PCSX2 Version Used: %s\n", inputRecordingData.GetHeader().emu)); @@ -380,4 +377,4 @@ wxString InputRecording::resolveGameName() return !gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso); } -#endif \ No newline at end of file +#endif diff --git a/pcsx2/Recording/InputRecording.h b/pcsx2/Recording/InputRecording.h index fa19fa4429..fea6cfe383 100644 --- a/pcsx2/Recording/InputRecording.h +++ b/pcsx2/Recording/InputRecording.h @@ -24,7 +24,7 @@ class InputRecording { public: InputRecording(); - + // Save or load PCSX2's global frame counter (g_FrameCount) along with each full/fast boot // // This is to prevent any inaccuracy issues caused by having a different @@ -34,26 +34,26 @@ public: // Main handler for ingesting input data and either saving it to the recording file (recording) // or mutating it to the contents of the recording file (replaying) - void ControllerInterrupt(u8 &data, u8 &port, u16 &BufCount, u8 buf[]); + void ControllerInterrupt(u8& data, u8& port, u16& BufCount, u8 buf[]); // The running frame counter for the input recording s32 GetFrameCounter(); - InputRecordingFile &GetInputRecordingData(); + InputRecordingFile& GetInputRecordingData(); // The internal PCSX2 g_FrameCount value on the first frame of the recording u32 GetStartingFrame(); void IncrementFrameCounter(); - // DEPRECATED: Slated for removal + // DEPRECATED: Slated for removal // If the current frame contains controller / input data bool IsInterruptFrame(); // If there is currently an input recording being played back or actively being recorded bool IsActive(); - // Whether or not the recording's initial state has yet to be loaded or saved and + // Whether or not the recording's initial state has yet to be loaded or saved and // the rest of the recording can be initialized // This is not applicable to recordings from a "power-on" state bool IsInitialLoad(); @@ -78,7 +78,7 @@ public: // Store the starting internal PCSX2 g_FrameCount value void SetStartingFrame(u32 newStartingFrame); - + /// Functions called from GUI // Create a new input recording file @@ -87,8 +87,8 @@ public: bool Play(wxString filename); // Stop the active input recording void Stop(); - - void setVirtualPadPtr(VirtualPad *ptr, int const port); + // Initialze VirtualPad window + void setVirtualPadPtr(VirtualPad* ptr, int const port); private: enum class InputRecordingMode @@ -99,16 +99,16 @@ private: }; static const int CONTROLLER_PORT_ONE = 0; - static const int CONTROLLER_PORT_TWO = 1; + static const int CONTROLLER_PORT_TWO = 1; // 0x42 is the magic number to indicate the default controller read query // See - Lilypad.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/v1.5.0-dev/plugins/LilyPad/LilyPad.cpp#L1193 static const u8 READ_DATA_AND_VIBRATE_FIRST_BYTE = 0x42; // 0x5A is always the second byte in the buffer when the normal READ_DATA_AND_VIBRATE (0x42) query is executed. // See - LilyPad.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/v1.5.0-dev/plugins/LilyPad/LilyPad.cpp#L1194 - static const u8 READ_DATA_AND_VIBRATE_SECOND_BYTE = 0x5A; + static const u8 READ_DATA_AND_VIBRATE_SECOND_BYTE = 0x5A; - // DEPRECATED: Slated for removal + // DEPRECATED: Slated for removal bool fInterruptFrame = false; InputRecordingFile inputRecordingData; bool initialLoad = false; @@ -116,13 +116,13 @@ private: s32 frameCounter = 0; bool incrementUndo = false; InputRecordingMode state = InputRecording::InputRecordingMode::NotActive; - + // Controller Data - PadData *padData[2]; + PadData* padData[2]; // VirtualPads - VirtualPad *virtualPads[2]; - + VirtualPad* virtualPads[2]; + // Resolve the name and region of the game currently loaded using the GameDB // If the game cannot be found in the DB, the fallback is the ISO filename wxString resolveGameName(); @@ -130,4 +130,4 @@ private: extern InputRecording g_InputRecording; -#endif \ No newline at end of file +#endif diff --git a/pcsx2/Recording/NewRecordingFrame.cpp b/pcsx2/Recording/NewRecordingFrame.cpp index b44ca33223..a34117d1f3 100644 --- a/pcsx2/Recording/NewRecordingFrame.cpp +++ b/pcsx2/Recording/NewRecordingFrame.cpp @@ -19,13 +19,13 @@ #ifndef DISABLE_RECORDING -NewRecordingFrame::NewRecordingFrame(wxWindow *parent) +NewRecordingFrame::NewRecordingFrame(wxWindow* parent) : wxDialog(parent, wxID_ANY, "New Input Recording", wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP | wxCAPTION) { - wxPanel *panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("panel")); + wxPanel* panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTAB_TRAVERSAL, _("panel")); - wxFlexGridSizer *fgs = new wxFlexGridSizer(4, 2, 20, 20); - wxBoxSizer *container = new wxBoxSizer(wxVERTICAL); + wxFlexGridSizer* fgs = new wxFlexGridSizer(4, 2, 20, 20); + wxBoxSizer* container = new wxBoxSizer(wxVERTICAL); m_fileLabel = new wxStaticText(panel, wxID_ANY, _("File Path"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); m_authorLabel = new wxStaticText(panel, wxID_ANY, _("Author"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER); @@ -65,7 +65,8 @@ wxString NewRecordingFrame::GetFile() const wxString path = m_filePicker->GetPath(); // wxWidget's removes the extension if it contains wildcards // on wxGTK https://trac.wxwidgets.org/ticket/15285 - if (!path.EndsWith(".p2m2")) { + if (!path.EndsWith(".p2m2")) + { return wxString::Format("%s.p2m2", path); } return path; diff --git a/pcsx2/Recording/NewRecordingFrame.h b/pcsx2/Recording/NewRecordingFrame.h index 6df841ab97..e4268245c0 100644 --- a/pcsx2/Recording/NewRecordingFrame.h +++ b/pcsx2/Recording/NewRecordingFrame.h @@ -31,20 +31,20 @@ enum MenuIds_New_Recording_Frame class NewRecordingFrame : public wxDialog { public: - NewRecordingFrame(wxWindow *parent); + NewRecordingFrame(wxWindow* parent); wxString GetFile() const; wxString GetAuthor() const; int GetFrom() const; private: - wxStaticText *m_fileLabel; - wxFilePickerCtrl *m_filePicker; - wxStaticText *m_authorLabel; - wxTextCtrl *m_authorInput; - wxStaticText *m_fromLabel; - wxChoice *m_fromChoice; - wxButton *m_startRecording; - wxButton *m_cancelRecording; + wxStaticText* m_fileLabel; + wxFilePickerCtrl* m_filePicker; + wxStaticText* m_authorLabel; + wxTextCtrl* m_authorInput; + wxStaticText* m_fromLabel; + wxChoice* m_fromChoice; + wxButton* m_startRecording; + wxButton* m_cancelRecording; }; #endif diff --git a/pcsx2/Recording/PadData.cpp b/pcsx2/Recording/PadData.cpp index 1deab67bbe..65e8097b52 100644 --- a/pcsx2/Recording/PadData.cpp +++ b/pcsx2/Recording/PadData.cpp @@ -184,9 +184,7 @@ wxString PadData::RawPadBytesToString(int start, int end) { str += wxString::Format("%d", PollControllerData(i)); if (i != end - 1) - { str += ", "; - } } return str; } diff --git a/pcsx2/Recording/VirtualPad/VirtualPad.cpp b/pcsx2/Recording/VirtualPad/VirtualPad.cpp index b3ad162347..7fbfc2192d 100644 --- a/pcsx2/Recording/VirtualPad/VirtualPad.cpp +++ b/pcsx2/Recording/VirtualPad/VirtualPad.cpp @@ -20,6 +20,7 @@ #include #include "App.h" +#include "MSWstuff.h" #include "Utilities/EmbeddedImage.h" #include "wx/dcbuffer.h" #include "wx/display.h" @@ -29,7 +30,9 @@ #include "Recording/VirtualPad/VirtualPadResources.h" #include "Recording/VirtualPad/img/circlePressed.h" -#include "Recording/VirtualPad/img/controller.h" +#include "Recording/VirtualPad/img/controllerFull.h" +#include "Recording/VirtualPad/img/controllerThreeQuarters.h" +#include "Recording/VirtualPad/img/controllerHalf.h" #include "Recording/VirtualPad/img/crossPressed.h" #include "Recording/VirtualPad/img/downPressed.h" #include "Recording/VirtualPad/img/l1Pressed.h" @@ -46,57 +49,72 @@ #include "Recording/VirtualPad/img/trianglePressed.h" #include "Recording/VirtualPad/img/upPressed.h" + VirtualPad::VirtualPad(wxWindow* parent, int controllerPort, AppConfig::InputRecordingOptions& options) : wxFrame(parent, wxID_ANY, wxEmptyString) , options(options) { // Images at 1.00 scale are designed to work well on HiDPI (4k) at 150% scaling (default recommended setting on windows) // Therefore, on a 1080p monitor we halve the scaling, on 1440p we reduce it by 25%, which from some quick tests looks comparable - // Side-note - It would be possible to factor in monitor scaling, but considering that is platform specific (with some platforms only supporting - // integer scaling) this is likely not reliable. + // Side-note - Getting the DPI scaling amount is platform specific (with some platforms only supporting + // integer scaling as well) this is likely not reliable. // Slight multi-monitor support, will use whatever window pcsx2 is opened with, but won't currently re-init if // windows are dragged between differing monitors! wxDisplay display(wxDisplay::GetFromWindow(this)); const wxRect screen = display.GetClientArea(); + float dpiScale = MSW_GetDPIScale(); // linux returns 1.0 if (screen.height > 1080 && screen.height <= 1440) // 1440p display - { - scalingFactor = 0.75; - } + scalingFactor = 0.75 * dpiScale; else if (screen.height <= 1080) // 1080p display { - scalingFactor = 0.5; - } // otherwise use default 1.0 scaling + scalingFactor = 0.5 * dpiScale; + } + // otherwise use default 1.0 scaling virtualPadData = VirtualPadData(); - virtualPadData.background = NewBitmap(EmbeddedImage().Get(), wxPoint(0, 0)); + // Based on the scaling factor, select the appropriate background image + // Don't scale these images as they've already been pre-scaled + if (floatCompare(scalingFactor, 0.5)) + virtualPadData.background = NewBitmap(EmbeddedImage().Get(), wxPoint(0, 0), true); + else if (floatCompare(scalingFactor, 0.75)) + virtualPadData.background = NewBitmap(EmbeddedImage().Get(), wxPoint(0, 0), true); + else + // Otherwise, scale down/up (or don't in the case of 1.0) the largst image + virtualPadData.background = NewBitmap(EmbeddedImage().Get(), wxPoint(0, 0)); + // Use the background image's size to define the window size SetClientSize(virtualPadData.background.width, virtualPadData.background.height); - InitPressureButtonGuiElements(virtualPadData.cross, NewBitmap(EmbeddedImage().Get(), wxPoint(938, 369)), this, wxPoint(1055, 525)); - InitPressureButtonGuiElements(virtualPadData.circle, NewBitmap(EmbeddedImage().Get(), wxPoint(1024, 286)), this, wxPoint(1055, 565)); - InitPressureButtonGuiElements(virtualPadData.triangle, NewBitmap(EmbeddedImage().Get(), wxPoint(938, 201)), this, wxPoint(1055, 605)); - InitPressureButtonGuiElements(virtualPadData.square, NewBitmap(EmbeddedImage().Get(), wxPoint(852, 287)), this, wxPoint(1055, 645)); + // These hard-coded pixels correspond to where the background image's components are (ie. the buttons) + // Everything is automatically scaled and adjusted based on the `scalingFactor` variable + InitPressureButtonGuiElements(virtualPadData.square, NewBitmap(EmbeddedImage().Get(), wxPoint(852, 287)), this, wxPoint(1055, 525)); + InitPressureButtonGuiElements(virtualPadData.triangle, NewBitmap(EmbeddedImage().Get(), wxPoint(938, 201)), this, wxPoint(1055, 565)); + InitPressureButtonGuiElements(virtualPadData.circle, NewBitmap(EmbeddedImage().Get(), wxPoint(1024, 286)), this, wxPoint(1055, 605)); + InitPressureButtonGuiElements(virtualPadData.cross, NewBitmap(EmbeddedImage().Get(), wxPoint(938, 369)), this, wxPoint(1055, 645)); - InitPressureButtonGuiElements(virtualPadData.down, NewBitmap(EmbeddedImage().Get(), wxPoint(186, 359)), this, wxPoint(175, 525), true); - InitPressureButtonGuiElements(virtualPadData.right, NewBitmap(EmbeddedImage().Get(), wxPoint(248, 302)), this, wxPoint(175, 565), true); - InitPressureButtonGuiElements(virtualPadData.up, NewBitmap(EmbeddedImage().Get(), wxPoint(186, 227)), this, wxPoint(175, 605), true); - InitPressureButtonGuiElements(virtualPadData.left, NewBitmap(EmbeddedImage().Get(), wxPoint(110, 302)), this, wxPoint(175, 645), true); + InitPressureButtonGuiElements(virtualPadData.left, NewBitmap(EmbeddedImage().Get(), wxPoint(110, 303)), this, wxPoint(175, 525), true); + InitPressureButtonGuiElements(virtualPadData.up, NewBitmap(EmbeddedImage().Get(), wxPoint(186, 227)), this, wxPoint(175, 565), true); + InitPressureButtonGuiElements(virtualPadData.right, NewBitmap(EmbeddedImage().Get(), wxPoint(248, 302)), this, wxPoint(175, 605), true); + InitPressureButtonGuiElements(virtualPadData.down, NewBitmap(EmbeddedImage().Get(), wxPoint(186, 359)), this, wxPoint(175, 645), true); InitPressureButtonGuiElements(virtualPadData.l1, NewBitmap(EmbeddedImage().Get(), wxPoint(156, 98)), this, wxPoint(170, 135)); - InitPressureButtonGuiElements(virtualPadData.l2, NewBitmap(EmbeddedImage().Get(), wxPoint(156, 57)), this, wxPoint(170, 18)); + InitPressureButtonGuiElements(virtualPadData.l2, NewBitmap(EmbeddedImage().Get(), wxPoint(156, 57)), this, wxPoint(170, 52), false, true); InitPressureButtonGuiElements(virtualPadData.r1, NewBitmap(EmbeddedImage().Get(), wxPoint(921, 98)), this, wxPoint(1035, 135), true); - InitPressureButtonGuiElements(virtualPadData.r2, NewBitmap(EmbeddedImage().Get(), wxPoint(921, 57)), this, wxPoint(1035, 18), true); + InitPressureButtonGuiElements(virtualPadData.r2, NewBitmap(EmbeddedImage().Get(), wxPoint(921, 57)), this, wxPoint(1035, 52), true, true); - InitNormalButtonGuiElements(virtualPadData.select, NewBitmap(EmbeddedImage().Get(), wxPoint(457, 313)), this, wxPoint(530, 320)); - InitNormalButtonGuiElements(virtualPadData.start, NewBitmap(EmbeddedImage().Get(), wxPoint(688, 311)), this, wxPoint(650, 320)); - InitNormalButtonGuiElements(virtualPadData.l3, NewBitmap(EmbeddedImage().Get(), wxPoint(726, 453)), this, wxPoint(440, 835)); // TODO - text for L3 / R3 - InitNormalButtonGuiElements(virtualPadData.r3, NewBitmap(EmbeddedImage().Get(), wxPoint(336, 453)), this, wxPoint(844, 835)); // TODO - text for L3 / R3 + InitNormalButtonGuiElements(virtualPadData.select, NewBitmap(EmbeddedImage().Get(), wxPoint(458, 313)), this, wxPoint(530, 315)); + InitNormalButtonGuiElements(virtualPadData.start, NewBitmap(EmbeddedImage().Get(), wxPoint(688, 311)), this, wxPoint(646, 315)); + InitNormalButtonGuiElements(virtualPadData.l3, NewBitmap(EmbeddedImage().Get(), wxPoint(336, 453)), this, wxPoint(560, 638)); + InitNormalButtonGuiElements(virtualPadData.r3, NewBitmap(EmbeddedImage().Get(), wxPoint(726, 453)), this, wxPoint(615, 638)); - InitAnalogStickGuiElements(virtualPadData.leftAnalog, this, wxPoint(405, 522), 101, wxPoint(312, 642), wxPoint(525, 431), false, wxPoint(507, 662), wxPoint(507, 622)); - InitAnalogStickGuiElements(virtualPadData.rightAnalog, this, wxPoint(795, 522), 101, wxPoint(703, 642), wxPoint(648, 431), true, wxPoint(695, 662), wxPoint(695, 622), true); + InitAnalogStickGuiElements(virtualPadData.leftAnalog, this, wxPoint(404, 522), 100, wxPoint(314, 642), wxPoint(526, 432), false, wxPoint(504, 685), wxPoint(570, 425), true); + InitAnalogStickGuiElements(virtualPadData.rightAnalog, this, wxPoint(794, 522), 100, wxPoint(706, 642), wxPoint(648, 432), true, wxPoint(700, 685), wxPoint(635, 425)); + + ignoreRealControllerBox = new wxCheckBox(this, wxID_ANY, wxEmptyString, ScaledPoint(wxPoint(586, 135)), wxDefaultSize); + resetButton = new wxButton(this, wxID_ANY, _("Reset"), ScaledPoint(wxPoint(1195, 5), wxSize(100, 50), true), ScaledSize(wxSize(100, 50))); - ignoreRealControllerBox = new wxCheckBox(this, wxID_ANY, wxEmptyString, ScaledPoint(575, 135), wxDefaultSize); Bind(wxEVT_CHECKBOX, &VirtualPad::OnIgnoreRealController, this, ignoreRealControllerBox->GetId()); + Bind(wxEVT_BUTTON, &VirtualPad::OnResetButton, this, resetButton->GetId()); // Bind Window Events Bind(wxEVT_MOVE, &VirtualPad::OnMoveAround, this); @@ -116,8 +134,10 @@ VirtualPad::VirtualPad(wxWindow* parent, int controllerPort, AppConfig::InputRec SetBackgroundColour(*wxWHITE); SetBackgroundStyle(wxBG_STYLE_PAINT); // This window does not allow for resizing for sake of simplicity: all images are scaled initially and stored, ready to be rendered - SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER); - SetDoubleBuffered(true); + SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER & ~wxMAXIMIZE_BOX); + + // Causes flickering, despite it supposed to be preventing it! + // SetDoubleBuffered(true); } void VirtualPad::OnMoveAround(wxMoveEvent& event) @@ -158,30 +178,28 @@ void VirtualPad::OnEraseBackground(wxEraseEvent& event) void VirtualPad::OnPaint(wxPaintEvent& event) { // DevCon.WriteLn("Paint Event Called"); - wxPaintDC dc(this); + wxBufferedPaintDC dc(this, wxBUFFER_VIRTUAL_AREA); Render(dc); } void VirtualPad::Redraw() { - wxClientDC dc(this); + wxClientDC cdc(this); + wxBufferedDC dc(&cdc); Render(dc); } -void VirtualPad::Render(wxDC& dc) +void VirtualPad::Render(wxDC& bdc) { // Update GUI Elements and figure out what needs to be rendered for (VirtualPadElement* virtualPadElement : virtualPadElements) - { virtualPadElement->UpdateGuiElement(renderQueue, clearScreenRequired); - } // Update Graphic Elements off render stack // Before we start rendering (if we have to) clear and re-draw the background if (!manualRedrawMode || clearScreenRequired || !renderQueue.empty()) { - wxBufferedDC bdc(&dc, dc.GetSize()); - bdc.SetBrush(*wxRED); + bdc.SetBrush(*wxWHITE); bdc.DrawRectangle(wxPoint(0, 0), bdc.GetSize()); bdc.SetBrush(wxNullBrush); bdc.DrawBitmap(virtualPadData.background.image, virtualPadData.background.coords, true); @@ -206,9 +224,7 @@ void VirtualPad::Render(wxDC& dc) { VirtualPadElement* element = renderQueue.front(); if (element) - { element->Render(bdc); - } renderQueue.pop(); } } @@ -219,33 +235,34 @@ bool VirtualPad::UpdateControllerData(u16 const bufIndex, PadData* padData) return virtualPadData.UpdateVirtualPadData(bufIndex, padData, ignoreRealController && !readOnlyMode, readOnlyMode); } -void VirtualPad::enablePadElements(bool enable) +void VirtualPad::enableUiElements(bool enable) { + ignoreRealControllerBox->Enable(enable); + resetButton->Enable(enable); for (VirtualPadElement* virtualPadElement : virtualPadElements) - { virtualPadElement->EnableWidgets(enable); - } } -void VirtualPad::SetReadOnlyMode() +void VirtualPad::SetReadOnlyMode(bool readOnly) { - enablePadElements(false); - readOnlyMode = true; + enableUiElements(!readOnly); + readOnlyMode = readOnly; } -void VirtualPad::ClearReadOnlyMode() -{ - enablePadElements(true); - readOnlyMode = false; -} - -void VirtualPad::OnIgnoreRealController(wxCommandEvent const& event) +void VirtualPad::OnIgnoreRealController(wxCommandEvent& event) { const wxCheckBox* ignoreButton = (wxCheckBox*)event.GetEventObject(); if (ignoreButton) - { ignoreRealController = ignoreButton->GetValue(); - } +} + +void VirtualPad::OnResetButton(wxCommandEvent& event) +{ + if (readOnlyMode) + return; + + for (VirtualPadElement* virtualPadElement : virtualPadElements) + virtualPadElement->Reset(this); } void VirtualPad::OnNormalButtonPress(wxCommandEvent& event) @@ -254,14 +271,10 @@ void VirtualPad::OnNormalButtonPress(wxCommandEvent& event) ControllerNormalButton* eventBtn = buttonElements[pressedButton->GetId()]; if (pressedButton) - { eventBtn->pressed = pressedButton->GetValue(); - } if (!eventBtn->isControllerPressBypassed) - { eventBtn->isControllerPressBypassed = true; - } } void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent& event) @@ -270,9 +283,8 @@ void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent& event) ControllerPressureButton* eventBtn = pressureElements[pressureSpinner->GetId()]; if (pressureSpinner) - { eventBtn->pressure = pressureSpinner->GetValue(); - } + eventBtn->pressed = eventBtn->pressure > 0; if (!eventBtn->isControllerPressureBypassed || !eventBtn->isControllerPressBypassed) @@ -288,15 +300,12 @@ void VirtualPad::OnAnalogSpinnerChange(wxCommandEvent& event) AnalogVector* eventVector = analogElements[analogSpinner->GetId()]; if (analogSpinner) - { eventVector->val = analogSpinner->GetValue(); - } + eventVector->slider->SetValue(eventVector->val); if (!eventVector->isControllerBypassed) - { eventVector->isControllerBypassed = true; - } } void VirtualPad::OnAnalogSliderChange(wxCommandEvent& event) @@ -305,46 +314,57 @@ void VirtualPad::OnAnalogSliderChange(wxCommandEvent& event) AnalogVector* eventVector = analogElements[analogSlider->GetId()]; if (analogSlider) - { eventVector->val = analogSlider->GetValue(); - } + eventVector->spinner->SetValue(eventVector->val); if (!eventVector->isControllerBypassed) - { eventVector->isControllerBypassed = true; - } } /// GUI Element Utility Functions -wxPoint VirtualPad::ScaledPoint(wxPoint point, int widgetWidth, bool rightAligned) +bool VirtualPad::floatCompare(float a, float b, float epsilon) { - return ScaledPoint(point.x, point.y, widgetWidth, rightAligned); + return (fabs(a - b) < epsilon); } -wxPoint VirtualPad::ScaledPoint(int x, int y, int widgetWidth, bool rightAligned) +wxPoint VirtualPad::ScaledPoint(wxPoint point, wxSize widgetWidth, bool rightAlignedCoord, bool bottomAlignedCoord) +{ + return ScaledPoint(point.x, point.y, widgetWidth.x, widgetWidth.y, rightAlignedCoord, bottomAlignedCoord); +} + +wxPoint VirtualPad::ScaledPoint(int x, int y, int widgetWidth, int widgetHeight, bool rightAlignedCoord, bool bottomAlignedCoord) { wxPoint scaledPoint = wxPoint(x * scalingFactor, y * scalingFactor); - if (rightAligned) + if (rightAlignedCoord) { scaledPoint.x -= widgetWidth * scalingFactor; if (scaledPoint.x < 0) - { scaledPoint.x = 0; - } + } + if (bottomAlignedCoord) + { + scaledPoint.y -= widgetHeight * scalingFactor; + if (scaledPoint.y < 0) + scaledPoint.y = 0; } return scaledPoint; } +wxSize VirtualPad::ScaledSize(wxSize size) +{ + return ScaledSize(size.x, size.y); +} + wxSize VirtualPad::ScaledSize(int x, int y) { return wxSize(x * scalingFactor, y * scalingFactor); } -ImageFile VirtualPad::NewBitmap(wxImage resource, wxPoint imgCoord) +ImageFile VirtualPad::NewBitmap(wxImage resource, wxPoint imgCoord, bool dontScale) { - return NewBitmap(scalingFactor, resource, imgCoord); + return NewBitmap(dontScale ? 1 : scalingFactor, resource, imgCoord); } ImageFile VirtualPad::NewBitmap(float scalingFactor, wxImage resource, wxPoint imgCoord) @@ -368,11 +388,10 @@ void VirtualPad::InitNormalButtonGuiElements(ControllerNormalButton& button, Ima virtualPadElements.push_back(&button); } -void VirtualPad::InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord) +void VirtualPad::InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord, bool bottomAlignedCoord) { - const int spinnerWidth = 100; - const wxPoint scaledPoint = ScaledPoint(pressureSpinnerCoord.x, pressureSpinnerCoord.y, spinnerWidth, rightAlignedCoord); - wxSpinCtrl* spinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, scaledPoint, ScaledSize(spinnerWidth, wxDefaultSize.GetHeight()), wxSP_ARROW_KEYS, 0, 255, 0); + const wxPoint scaledPoint = ScaledPoint(pressureSpinnerCoord, SPINNER_SIZE, rightAlignedCoord, bottomAlignedCoord); + wxSpinCtrl* spinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, scaledPoint, ScaledSize(SPINNER_SIZE), wxSP_ARROW_KEYS, 0, 255, 0); button.icon = image; button.pressureSpinner = spinner; @@ -381,7 +400,8 @@ void VirtualPad::InitPressureButtonGuiElements(ControllerPressureButton& button, virtualPadElements.push_back(&button); } -void VirtualPad::InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* parentWindow, wxPoint centerPoint, int radius, wxPoint xSliderPoint, wxPoint ySliderPoint, bool flipYSlider, wxPoint xSpinnerPoint, wxPoint ySpinnerPoint, bool rightAlignedSpinners) +void VirtualPad::InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* parentWindow, wxPoint centerPoint, int radius, + wxPoint xSliderPoint, wxPoint ySliderPoint, bool flipYSlider, wxPoint xSpinnerPoint, wxPoint ySpinnerPoint, bool rightAlignedSpinners) { AnalogPosition analogPos = AnalogPosition(); analogPos.centerCoords = ScaledPoint(centerPoint); @@ -389,14 +409,15 @@ void VirtualPad::InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* paren analogPos.radius = radius * scalingFactor; analogPos.lineThickness = 6 * scalingFactor; - const int spinnerWidth = 90; - const wxPoint xSpinnerScaledPoint = ScaledPoint(xSpinnerPoint, spinnerWidth, rightAlignedSpinners); - const wxPoint ySpinnerScaledPoint = ScaledPoint(ySpinnerPoint, spinnerWidth, rightAlignedSpinners); + const wxPoint xSpinnerScaledPoint = ScaledPoint(xSpinnerPoint, SPINNER_SIZE, rightAlignedSpinners); + const wxPoint ySpinnerScaledPoint = ScaledPoint(ySpinnerPoint, SPINNER_SIZE, rightAlignedSpinners, true); - wxSlider* xSlider = new wxSlider(parentWindow, wxID_ANY, 127, 0, 255, ScaledPoint(xSliderPoint), ScaledSize(185, 30)); - wxSlider* ySlider = new wxSlider(parentWindow, wxID_ANY, 127, 0, 255, ScaledPoint(ySliderPoint), ScaledSize(30, 185), flipYSlider ? wxSL_LEFT : wxSL_RIGHT); - wxSpinCtrl* xSpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, xSpinnerScaledPoint, ScaledSize(90, wxDefaultSize.GetHeight()), wxSP_ARROW_KEYS, 0, 255, 127); - wxSpinCtrl* ySpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, ySpinnerScaledPoint, ScaledSize(90, wxDefaultSize.GetHeight()), wxSP_ARROW_KEYS, 0, 255, 127); + wxSlider* xSlider = new wxSlider(parentWindow, wxID_ANY, ANALOG_NEUTRAL, 0, ANALOG_MAX, + ScaledPoint(xSliderPoint), ScaledSize(ANALOG_SLIDER_WIDTH, ANALOG_SLIDER_HEIGHT)); + wxSlider* ySlider = new wxSlider(parentWindow, wxID_ANY, ANALOG_NEUTRAL, 0, ANALOG_MAX, + ScaledPoint(ySliderPoint), ScaledSize(ANALOG_SLIDER_HEIGHT, ANALOG_SLIDER_WIDTH), flipYSlider ? wxSL_LEFT : wxSL_RIGHT); + wxSpinCtrl* xSpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, xSpinnerScaledPoint, ScaledSize(SPINNER_SIZE), wxSP_ARROW_KEYS, 0, 255, 127); + wxSpinCtrl* ySpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, ySpinnerScaledPoint, ScaledSize(SPINNER_SIZE), wxSP_ARROW_KEYS, 0, 255, 127); analog.xVector.slider = xSlider; analog.yVector.slider = ySlider; diff --git a/pcsx2/Recording/VirtualPad/VirtualPad.h b/pcsx2/Recording/VirtualPad/VirtualPad.h index e154bc675a..94cf7ad4c8 100644 --- a/pcsx2/Recording/VirtualPad/VirtualPad.h +++ b/pcsx2/Recording/VirtualPad/VirtualPad.h @@ -43,14 +43,21 @@ public: // - PadData will not be updated if ReadOnly mode is set // - returns a bool to indicate if the PadData has been updated bool UpdateControllerData(u16 const bufIndex, PadData* padData); - // Enables ReadOnly mode and disables GUI widgets - void SetReadOnlyMode(); - // Disables ReadOnly mode and re-enables GUI widgets - void ClearReadOnlyMode(); + // Enables/Disables read only mode and enables/disables GUI widgets + void SetReadOnlyMode(bool readOnly); // To be called at maximum, once per frame to update widget's value and re-render the VirtualPad's graphics void Redraw(); private: + /// Constants + const wxSize SPINNER_SIZE = wxSize(100, 40); + static const int ANALOG_SLIDER_WIDTH = 185; + static const int ANALOG_SLIDER_HEIGHT = 30; + + static const int PRESSURE_MAX = 255; + static const int ANALOG_NEUTRAL = 127; + static const int ANALOG_MAX = 255; + AppConfig::InputRecordingOptions& options; bool clearScreenRequired = false; @@ -65,10 +72,11 @@ private: std::vector virtualPadElements; std::queue renderQueue; - void enablePadElements(bool enable); + void enableUiElements(bool enable); /// GUI Elements wxCheckBox* ignoreRealControllerBox; + wxButton* resetButton; std::map buttonElements; std::map pressureElements; @@ -84,21 +92,24 @@ private: void OnAnalogSliderChange(wxCommandEvent& event); void OnAnalogSpinnerChange(wxCommandEvent& event); - void OnIgnoreRealController(wxCommandEvent const& event); + void OnIgnoreRealController(wxCommandEvent& event); void OnNormalButtonPress(wxCommandEvent& event); void OnPressureButtonPressureChange(wxCommandEvent& event); + void OnResetButton(wxCommandEvent& event); /// GUI Creation Utility Functions float scalingFactor = 1.0; + bool floatCompare(float A, float B, float epsilon = 0.005f); + wxSize ScaledSize(wxSize size); wxSize ScaledSize(int x, int y); - wxPoint ScaledPoint(wxPoint point, int widgetWidth = 0, bool rightAligned = false); - wxPoint ScaledPoint(int x, int y, int widgetWidth = 0, bool rightAligned = false); + wxPoint ScaledPoint(wxPoint point, wxSize widgetSize = wxDefaultSize, bool rightAlignedCoord = false, bool bottomAlignedCoord = false); + wxPoint ScaledPoint(int x, int y, int widgetWidth, int widgetHeight, bool rightAlignedCoord = false, bool bottomAlignedCoord = false); - ImageFile NewBitmap(wxImage resource, wxPoint imgCoord); + ImageFile NewBitmap(wxImage resource, wxPoint imgCoord, bool dontScale = false); ImageFile NewBitmap(float scalingFactor, wxImage resource, wxPoint imgCoord); - void InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord = false); + void InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord = false, bool bottomAlignedCoord = false); void InitNormalButtonGuiElements(ControllerNormalButton& btn, ImageFile image, wxWindow* parentWindow, wxPoint checkboxCoord); void InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* parentWindow, wxPoint centerPoint, int radius, wxPoint xSliderPoint, wxPoint ySliderPoint, bool flipYSlider, wxPoint xSpinnerPoint, wxPoint ySpinnerPoint, bool rightAlignedSpinners = false); diff --git a/pcsx2/Recording/VirtualPad/VirtualPadResources.cpp b/pcsx2/Recording/VirtualPad/VirtualPadResources.cpp index b9f3ffbf3e..289fb0bd65 100644 --- a/pcsx2/Recording/VirtualPad/VirtualPadResources.cpp +++ b/pcsx2/Recording/VirtualPad/VirtualPadResources.cpp @@ -22,21 +22,31 @@ #include "Recording/VirtualPad/VirtualPadResources.h" #include "Recording/PadData.h" +wxCommandEvent VirtualPadElement::ConstructEvent(wxEventTypeTag eventType, wxWindow* obj) +{ + wxCommandEvent event(eventType, obj->GetId()); + event.SetEventObject(obj); + return event; +} + +wxCommandEvent VirtualPadElement::ConstructEvent(wxEventTypeTag eventType, wxWindow* obj) +{ + wxCommandEvent event(eventType, obj->GetId()); + event.SetEventObject(obj); + return event; +} + void ControllerNormalButton::UpdateGuiElement(std::queue& renderQueue, bool& clearScreenRequired) { ControllerNormalButton& button = *this; // This boolean is set when we parse the PadData in VirtualPadData::UpdateVirtualPadData // Updating wxWidget elements can be expensive, we only want to do this if required if (button.widgetUpdateRequired) - { button.pressedBox->SetValue(button.pressed); - } // We only render the button if it is pressed if (button.pressed) - { renderQueue.push(this); - } // However, if the button has been drawn to the screen in the past // we need to ensure the screen is cleared. // This is needed in the scenario where only a single button is being pressed/released @@ -52,14 +62,10 @@ void ControllerPressureButton::UpdateGuiElement(std::queue& { ControllerPressureButton& button = *this; if (button.widgetUpdateRequired) - { button.pressureSpinner->SetValue(button.pressure); - } if (button.pressed) - { renderQueue.push(this); - } else if (button.currentlyRendered) { button.currentlyRendered = false; @@ -83,9 +89,7 @@ void AnalogStick::UpdateGuiElement(std::queue& renderQueue, // We render the analog sticks as long as they are not in the neutral position if (!(analogStick.xVector.val == PadData::ANALOG_VECTOR_NEUTRAL && analogStick.yVector.val == PadData::ANALOG_VECTOR_NEUTRAL)) - { renderQueue.push(this); - } else if (analogStick.currentlyRendered) { analogStick.currentlyRendered = false; @@ -95,47 +99,20 @@ void AnalogStick::UpdateGuiElement(std::queue& renderQueue, void ControllerNormalButton::EnableWidgets(bool enable) { - ControllerNormalButton& button = *this; - if (enable) - { - button.pressedBox->Enable(); - } - else - { - button.pressedBox->Disable(); - } + this->pressedBox->Enable(enable); } void ControllerPressureButton::EnableWidgets(bool enable) { - ControllerPressureButton& button = *this; - if (enable) - { - button.pressureSpinner->Enable(); - } - else - { - button.pressureSpinner->Disable(); - } + this->pressureSpinner->Enable(enable); } void AnalogStick::EnableWidgets(bool enable) { - AnalogStick& analog = *this; - if (enable) - { - analog.xVector.slider->Enable(); - analog.yVector.slider->Enable(); - analog.xVector.spinner->Enable(); - analog.yVector.spinner->Enable(); - } - else - { - analog.xVector.slider->Disable(); - analog.yVector.slider->Disable(); - analog.xVector.spinner->Disable(); - analog.yVector.spinner->Disable(); - } + this->xVector.slider->Enable(enable); + this->yVector.slider->Enable(enable); + this->xVector.spinner->Enable(enable); + this->yVector.spinner->Enable(enable); } void ControllerNormalButton::Render(wxDC& dc) @@ -181,6 +158,30 @@ void AnalogStick::Render(wxDC& dc) analogStick.currentlyRendered = true; } +void ControllerNormalButton::Reset(wxEvtHandler* destWindow) +{ + this->pressedBox->SetValue(false); + wxPostEvent(destWindow, ConstructEvent(wxEVT_CHECKBOX, this->pressedBox)); +} + +void ControllerPressureButton::Reset(wxEvtHandler* destWindow) +{ + this->pressureSpinner->SetValue(0); + wxPostEvent(destWindow, ConstructEvent(wxEVT_SPINCTRL, this->pressureSpinner)); +} + +void AnalogStick::Reset(wxEvtHandler* destWindow) +{ + this->xVector.slider->SetValue(127); + this->yVector.slider->SetValue(127); + wxPostEvent(destWindow, ConstructEvent(wxEVT_SLIDER, this->xVector.slider)); + wxPostEvent(destWindow, ConstructEvent(wxEVT_SLIDER, this->yVector.slider)); + this->xVector.spinner->SetValue(127); + this->xVector.spinner->SetValue(127); + wxPostEvent(destWindow, ConstructEvent(wxEVT_SPINCTRL, this->xVector.spinner)); + wxPostEvent(destWindow, ConstructEvent(wxEVT_SPINCTRL, this->yVector.spinner)); +} + bool ControllerNormalButton::UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly) { return this->UpdateButtonData(padDataVal, ignoreRealController, readOnly); diff --git a/pcsx2/Recording/VirtualPad/VirtualPadResources.h b/pcsx2/Recording/VirtualPad/VirtualPadResources.h index b3faeec192..7aba06a141 100644 --- a/pcsx2/Recording/VirtualPad/VirtualPadResources.h +++ b/pcsx2/Recording/VirtualPad/VirtualPadResources.h @@ -25,6 +25,7 @@ #include "wx/gdicmn.h" #include "wx/slider.h" #include "wx/spinctrl.h" +#include "wx/dcbuffer.h" struct ImageFile { @@ -63,8 +64,12 @@ class VirtualPadElement public: bool currentlyRendered = false; + wxCommandEvent ConstructEvent(wxEventTypeTag eventType, wxWindow *obj); + wxCommandEvent ConstructEvent(wxEventTypeTag eventType, wxWindow *obj); + virtual void EnableWidgets(bool enable) = 0; virtual void Render(wxDC& dc) = 0; + virtual void Reset(wxEvtHandler* destWindow) = 0; virtual void UpdateGuiElement(std::queue& renderQueue, bool& clearScreenRequired) = 0; }; @@ -88,6 +93,7 @@ public: bool UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly); void EnableWidgets(bool enable) override; void Render(wxDC& dc) override; + void Reset(wxEvtHandler* destWindow) override; void UpdateGuiElement(std::queue& renderQueue, bool& clearScreenRequired) override; }; @@ -106,6 +112,7 @@ public: bool UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly); void EnableWidgets(bool enable) override; void Render(wxDC& dc) override; + void Reset(wxEvtHandler* destWindow) override; void UpdateGuiElement(std::queue& renderQueue, bool& clearScreenRequired) override; }; @@ -119,6 +126,7 @@ public: void EnableWidgets(bool enable) override; void Render(wxDC& dc) override; + void Reset(wxEvtHandler* destWindow) override; void UpdateGuiElement(std::queue& renderQueue, bool& clearScreenRequired) override; }; diff --git a/pcsx2/Recording/VirtualPad/img/controller.png b/pcsx2/Recording/VirtualPad/img/controller.png deleted file mode 100644 index 9ccbdf2415..0000000000 Binary files a/pcsx2/Recording/VirtualPad/img/controller.png and /dev/null differ diff --git a/pcsx2/Recording/VirtualPad/img/controllerFull.png b/pcsx2/Recording/VirtualPad/img/controllerFull.png new file mode 100644 index 0000000000..a584c56ffc Binary files /dev/null and b/pcsx2/Recording/VirtualPad/img/controllerFull.png differ diff --git a/pcsx2/Recording/VirtualPad/img/controllerHalf.png b/pcsx2/Recording/VirtualPad/img/controllerHalf.png new file mode 100644 index 0000000000..35a89a441b Binary files /dev/null and b/pcsx2/Recording/VirtualPad/img/controllerHalf.png differ diff --git a/pcsx2/Recording/VirtualPad/img/controllerThreeQuarters.png b/pcsx2/Recording/VirtualPad/img/controllerThreeQuarters.png new file mode 100644 index 0000000000..50b97ada99 Binary files /dev/null and b/pcsx2/Recording/VirtualPad/img/controllerThreeQuarters.png differ diff --git a/pcsx2/gui/MainFrame.cpp b/pcsx2/gui/MainFrame.cpp index 73c54b25e3..39062a67f6 100644 --- a/pcsx2/gui/MainFrame.cpp +++ b/pcsx2/gui/MainFrame.cpp @@ -466,12 +466,14 @@ void MainEmuFrame::CreateCaptureMenu() void MainEmuFrame::CreateRecordMenu() { +#ifndef DISABLE_RECORDING m_menuRecording.Append(MenuId_Recording_New, _("New")); m_menuRecording.Append(MenuId_Recording_Stop, _("Stop"))->Enable(false); m_menuRecording.Append(MenuId_Recording_Play, _("Play")); m_menuRecording.AppendSeparator(); m_menuRecording.Append(MenuId_Recording_VirtualPad_Port0, _("Virtual Pad (Port 1)")); m_menuRecording.Append(MenuId_Recording_VirtualPad_Port1, _("Virtual Pad (Port 2)")); +#endif } void MainEmuFrame::CreateHelpMenu() diff --git a/pcsx2/windows/VCprojects/pcsx2.vcxproj b/pcsx2/windows/VCprojects/pcsx2.vcxproj index 36191acdbf..946f187445 100644 --- a/pcsx2/windows/VCprojects/pcsx2.vcxproj +++ b/pcsx2/windows/VCprojects/pcsx2.vcxproj @@ -145,7 +145,15 @@ %(RelativeDir)%(Filename).h - + + cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension) + %(RelativeDir)%(Filename).h + + + cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension) + %(RelativeDir)%(Filename).h + + cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension) %(RelativeDir)%(Filename).h