mirror of https://github.com/PCSX2/pcsx2.git
recording: Many adjustments on VirtualPad from review feedback
recording: Factor in DPIScaling when scaling VirtualPad window recording: Add a reset button, hopefully better quality backgrounds for lower resolutions recording: Improved VPad analog alignment Co-authored-by: sonicfind recording: Some final VirtualPad coordinate adjustments
This commit is contained in:
parent
28a4d0390f
commit
400ed82715
|
@ -6,6 +6,3 @@
|
||||||
*.props text eol=crlf
|
*.props text eol=crlf
|
||||||
*.vcxproj text eol=crlf
|
*.vcxproj text eol=crlf
|
||||||
*.vcxproj.filters text eol=crlf
|
*.vcxproj.filters text eol=crlf
|
||||||
|
|
||||||
# Hide generated files for easier pull-request reviewing
|
|
||||||
pcsx2/Recording/VirtualPad/img/*.h linguist-generated
|
|
|
@ -78,13 +78,13 @@ jobs:
|
||||||
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
|
string(TIMESTAMP current_date "%Y-%m-%d-%H;%M;%S" UTC)
|
||||||
message("::set-output name=timestamp::${current_date}")
|
message("::set-output name=timestamp::${current_date}")
|
||||||
|
|
||||||
# - name: ccache cache files
|
- name: ccache cache files
|
||||||
# uses: actions/cache@v2
|
uses: actions/cache@v2
|
||||||
# with:
|
with:
|
||||||
# path: .ccache
|
path: .ccache
|
||||||
# key: ${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
key: ${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache-${{ steps.ccache_cache_timestamp.outputs.timestamp }}
|
||||||
# restore-keys: |
|
restore-keys: |
|
||||||
# ${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache-
|
${{ matrix.os }}-${{ matrix.platform }}-${{ matrix.compiler }}-${{ matrix.compiler-version }}-ccache-
|
||||||
|
|
||||||
- name: Install Packages
|
- name: Install Packages
|
||||||
env:
|
env:
|
||||||
|
@ -102,4 +102,3 @@ jobs:
|
||||||
chmod +x .github/workflows/scripts/build-linux.sh
|
chmod +x .github/workflows/scripts/build-linux.sh
|
||||||
./.github/workflows/scripts/build-linux.sh generate_cmake
|
./.github/workflows/scripts/build-linux.sh generate_cmake
|
||||||
./.github/workflows/scripts/build-linux.sh compile
|
./.github/workflows/scripts/build-linux.sh compile
|
||||||
ls ./pcsx2/Recording/VirtualPad/img
|
|
||||||
|
|
|
@ -507,7 +507,9 @@ set(pcsx2RecordingHeaders
|
||||||
set(res_rec_vp_src "${CMAKE_SOURCE_DIR}/pcsx2/Recording/VirtualPad/img")
|
set(res_rec_vp_src "${CMAKE_SOURCE_DIR}/pcsx2/Recording/VirtualPad/img")
|
||||||
set(pcsx2RecordingVirtualPadResources
|
set(pcsx2RecordingVirtualPadResources
|
||||||
${res_rec_vp_src}/circlePressed.h
|
${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}/crossPressed.h
|
||||||
${res_rec_vp_src}/downPressed.h
|
${res_rec_vp_src}/downPressed.h
|
||||||
${res_rec_vp_src}/l1Pressed.h
|
${res_rec_vp_src}/l1Pressed.h
|
||||||
|
@ -760,7 +762,7 @@ endforeach()
|
||||||
### Generate Recording resource files
|
### Generate Recording resource files
|
||||||
### Drop them into the folder alongside the png files
|
### Drop them into the folder alongside the png files
|
||||||
foreach(res_file IN ITEMS
|
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)
|
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}" )
|
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()
|
endforeach()
|
||||||
|
|
|
@ -60,11 +60,11 @@ InputRecording g_InputRecording;
|
||||||
InputRecording::InputRecording()
|
InputRecording::InputRecording()
|
||||||
{
|
{
|
||||||
// NOTE - No multi-tap support, only two controllers
|
// NOTE - No multi-tap support, only two controllers
|
||||||
padData[CONTROLLER_PORT_ONE] = new PadData();
|
padData[CONTROLLER_PORT_ONE] = new PadData();
|
||||||
padData[CONTROLLER_PORT_TWO] = 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;
|
virtualPads[port] = ptr;
|
||||||
}
|
}
|
||||||
|
@ -85,62 +85,53 @@ void InputRecording::RecordingReset()
|
||||||
g_InputRecordingControls.Resume();
|
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
|
// TODO - Multi-Tap Support
|
||||||
|
|
||||||
if (bufCount == 1)
|
if (bufCount == 1)
|
||||||
fInterruptFrame = data == READ_DATA_AND_VIBRATE_FIRST_BYTE;
|
fInterruptFrame = data == READ_DATA_AND_VIBRATE_FIRST_BYTE;
|
||||||
else if (bufCount == 2)
|
else if (bufCount == 2 && buf[bufCount] != READ_DATA_AND_VIBRATE_SECOND_BYTE)
|
||||||
{
|
fInterruptFrame = false;
|
||||||
if (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
|
// 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)
|
else if (fInterruptFrame && bufCount >= 3 && frameCounter >= 0 && frameCounter < INT_MAX)
|
||||||
{
|
{
|
||||||
u8 &bufVal = buf[bufCount];
|
u8& bufVal = buf[bufCount];
|
||||||
const u16 bufIndex = bufCount - 3;
|
const u16 bufIndex = bufCount - 3;
|
||||||
|
|
||||||
if (state == InputRecordingMode::Replaying)
|
if (state == InputRecordingMode::Replaying)
|
||||||
{
|
{
|
||||||
u8 tmp = 0;
|
u8 tmp = 0;
|
||||||
if (inputRecordingData.ReadKeyBuffer(tmp, frameCounter, port, bufIndex))
|
if (inputRecordingData.ReadKeyBuffer(tmp, frameCounter, port, bufIndex))
|
||||||
{
|
{
|
||||||
// Overwrite value originally provided by the PAD plugin
|
// Overwrite value originally provided by the PAD plugin
|
||||||
bufVal = tmp;
|
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]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update controller data state for future VirtualPad / logging usage.
|
// Update controller data state for future VirtualPad / logging usage.
|
||||||
padData[port]->UpdateControllerData(bufIndex, bufVal);
|
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
|
// If the VirtualPad updated the PadData, we have to update the buffer
|
||||||
// before committing it to the recording / sending it to the game
|
// before committing it to the recording / sending it to the game
|
||||||
// - Do not do this if we are in replay mode!
|
// - 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 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);
|
padData[port]->LogPadData(port);
|
||||||
// As well as re-render the virtual pad UI, if applicable
|
// As well as re-render the virtual pad UI, if applicable
|
||||||
// - Don't render if it's minimized
|
// - Don't render if it's minimized
|
||||||
if (virtualPads[port] && virtualPads[port]->IsShown() && !virtualPads[port]->IsIconized())
|
if (virtualPads[port] && virtualPads[port]->IsShown() && !virtualPads[port]->IsIconized())
|
||||||
{
|
|
||||||
virtualPads[port]->Redraw();
|
virtualPads[port]->Redraw();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, commit the byte to the movie file if we are recording
|
// Finally, commit the byte to the movie file if we are recording
|
||||||
|
@ -161,7 +152,7 @@ s32 InputRecording::GetFrameCounter()
|
||||||
return frameCounter;
|
return frameCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
InputRecordingFile &InputRecording::GetInputRecordingData()
|
InputRecordingFile& InputRecording::GetInputRecordingData()
|
||||||
{
|
{
|
||||||
return inputRecordingData;
|
return inputRecordingData;
|
||||||
}
|
}
|
||||||
|
@ -223,17 +214,21 @@ wxString InputRecording::RecordingModeTitleSegment()
|
||||||
void InputRecording::SetToRecordMode()
|
void InputRecording::SetToRecordMode()
|
||||||
{
|
{
|
||||||
state = InputRecordingMode::Recording;
|
state = InputRecordingMode::Recording;
|
||||||
|
virtualPads[CONTROLLER_PORT_ONE]->SetReadOnlyMode(false);
|
||||||
|
virtualPads[CONTROLLER_PORT_TWO]->SetReadOnlyMode(false);
|
||||||
recordingConLog("[REC]: Record mode ON.\n");
|
recordingConLog("[REC]: Record mode ON.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecording::SetToReplayMode()
|
void InputRecording::SetToReplayMode()
|
||||||
{
|
{
|
||||||
state = InputRecordingMode::Replaying;
|
state = InputRecordingMode::Replaying;
|
||||||
|
virtualPads[CONTROLLER_PORT_ONE]->SetReadOnlyMode(true);
|
||||||
|
virtualPads[CONTROLLER_PORT_TWO]->SetReadOnlyMode(true);
|
||||||
recordingConLog("[REC]: Replay mode ON.\n");
|
recordingConLog("[REC]: Replay mode ON.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
void InputRecording::SetFrameCounter(u32 newGFrameCount)
|
void InputRecording::SetFrameCounter(u32 newGFrameCount)
|
||||||
{
|
{
|
||||||
if (newGFrameCount > startingFrame + (u32)g_InputRecording.GetInputRecordingData().GetTotalFrames())
|
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");
|
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()
|
void InputRecording::Stop()
|
||||||
{
|
{
|
||||||
state = InputRecordingMode::NotActive;
|
state = InputRecordingMode::NotActive;
|
||||||
|
virtualPads[CONTROLLER_PORT_ONE]->SetReadOnlyMode(false);
|
||||||
|
virtualPads[CONTROLLER_PORT_TWO]->SetReadOnlyMode(false);
|
||||||
incrementUndo = false;
|
incrementUndo = false;
|
||||||
if (inputRecordingData.Close())
|
if (inputRecordingData.Close())
|
||||||
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
|
recordingConLog(L"[REC]: InputRecording Recording Stopped.\n");
|
||||||
|
@ -303,7 +300,7 @@ bool InputRecording::Create(wxString FileName, bool fromSaveState, wxString auth
|
||||||
inputRecordingData.GetHeader().SetGameName(resolveGameName());
|
inputRecordingData.GetHeader().SetGameName(resolveGameName());
|
||||||
// Write header contents
|
// Write header contents
|
||||||
inputRecordingData.WriteHeader();
|
inputRecordingData.WriteHeader();
|
||||||
state = InputRecordingMode::Recording;
|
SetToRecordMode();
|
||||||
g_InputRecordingControls.DisableFrameAdvance();
|
g_InputRecordingControls.DisableFrameAdvance();
|
||||||
recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName));
|
recordingConLog(wxString::Format(L"[REC]: Started new recording - [%s]\n", FileName));
|
||||||
return true;
|
return true;
|
||||||
|
@ -328,8 +325,8 @@ bool InputRecording::Play(wxString fileName)
|
||||||
}
|
}
|
||||||
if (!wxFileExists(inputRecordingData.GetFilename() + "_SaveState.p2s"))
|
if (!wxFileExists(inputRecordingData.GetFilename() + "_SaveState.p2s"))
|
||||||
{
|
{
|
||||||
recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s_SaveState.p2s\n",
|
recordingConLog(wxString::Format("[REC]: Could not locate savestate file at location - %s_SaveState.p2s\n",
|
||||||
inputRecordingData.GetFilename()));
|
inputRecordingData.GetFilename()));
|
||||||
inputRecordingData.Close();
|
inputRecordingData.Close();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -348,7 +345,7 @@ bool InputRecording::Play(wxString fileName)
|
||||||
recordingConLog(L"[REC]: Recording was possibly constructed for a different game.\n");
|
recordingConLog(L"[REC]: Recording was possibly constructed for a different game.\n");
|
||||||
|
|
||||||
incrementUndo = true;
|
incrementUndo = true;
|
||||||
state = InputRecordingMode::Replaying;
|
SetToReplayMode();
|
||||||
g_InputRecordingControls.DisableFrameAdvance();
|
g_InputRecordingControls.DisableFrameAdvance();
|
||||||
recordingConLog(wxString::Format(L"[REC]: Replaying input recording - [%s]\n", inputRecordingData.GetFilename()));
|
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));
|
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);
|
return !gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -24,7 +24,7 @@ class InputRecording
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InputRecording();
|
InputRecording();
|
||||||
|
|
||||||
// Save or load PCSX2's global frame counter (g_FrameCount) along with each full/fast boot
|
// 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
|
// 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)
|
// 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)
|
// 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
|
// The running frame counter for the input recording
|
||||||
s32 GetFrameCounter();
|
s32 GetFrameCounter();
|
||||||
|
|
||||||
InputRecordingFile &GetInputRecordingData();
|
InputRecordingFile& GetInputRecordingData();
|
||||||
|
|
||||||
// The internal PCSX2 g_FrameCount value on the first frame of the recording
|
// The internal PCSX2 g_FrameCount value on the first frame of the recording
|
||||||
u32 GetStartingFrame();
|
u32 GetStartingFrame();
|
||||||
|
|
||||||
void IncrementFrameCounter();
|
void IncrementFrameCounter();
|
||||||
|
|
||||||
// DEPRECATED: Slated for removal
|
// DEPRECATED: Slated for removal
|
||||||
// If the current frame contains controller / input data
|
// If the current frame contains controller / input data
|
||||||
bool IsInterruptFrame();
|
bool IsInterruptFrame();
|
||||||
|
|
||||||
// If there is currently an input recording being played back or actively being recorded
|
// If there is currently an input recording being played back or actively being recorded
|
||||||
bool IsActive();
|
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
|
// the rest of the recording can be initialized
|
||||||
// This is not applicable to recordings from a "power-on" state
|
// This is not applicable to recordings from a "power-on" state
|
||||||
bool IsInitialLoad();
|
bool IsInitialLoad();
|
||||||
|
@ -78,7 +78,7 @@ public:
|
||||||
|
|
||||||
// Store the starting internal PCSX2 g_FrameCount value
|
// Store the starting internal PCSX2 g_FrameCount value
|
||||||
void SetStartingFrame(u32 newStartingFrame);
|
void SetStartingFrame(u32 newStartingFrame);
|
||||||
|
|
||||||
/// Functions called from GUI
|
/// Functions called from GUI
|
||||||
|
|
||||||
// Create a new input recording file
|
// Create a new input recording file
|
||||||
|
@ -87,8 +87,8 @@ public:
|
||||||
bool Play(wxString filename);
|
bool Play(wxString filename);
|
||||||
// Stop the active input recording
|
// Stop the active input recording
|
||||||
void Stop();
|
void Stop();
|
||||||
|
// Initialze VirtualPad window
|
||||||
void setVirtualPadPtr(VirtualPad *ptr, int const port);
|
void setVirtualPadPtr(VirtualPad* ptr, int const port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class InputRecordingMode
|
enum class InputRecordingMode
|
||||||
|
@ -99,16 +99,16 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
static const int CONTROLLER_PORT_ONE = 0;
|
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
|
// 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
|
// 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;
|
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.
|
// 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
|
// 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;
|
bool fInterruptFrame = false;
|
||||||
InputRecordingFile inputRecordingData;
|
InputRecordingFile inputRecordingData;
|
||||||
bool initialLoad = false;
|
bool initialLoad = false;
|
||||||
|
@ -116,13 +116,13 @@ private:
|
||||||
s32 frameCounter = 0;
|
s32 frameCounter = 0;
|
||||||
bool incrementUndo = false;
|
bool incrementUndo = false;
|
||||||
InputRecordingMode state = InputRecording::InputRecordingMode::NotActive;
|
InputRecordingMode state = InputRecording::InputRecordingMode::NotActive;
|
||||||
|
|
||||||
// Controller Data
|
// Controller Data
|
||||||
PadData *padData[2];
|
PadData* padData[2];
|
||||||
|
|
||||||
// VirtualPads
|
// VirtualPads
|
||||||
VirtualPad *virtualPads[2];
|
VirtualPad* virtualPads[2];
|
||||||
|
|
||||||
// Resolve the name and region of the game currently loaded using the GameDB
|
// 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
|
// If the game cannot be found in the DB, the fallback is the ISO filename
|
||||||
wxString resolveGameName();
|
wxString resolveGameName();
|
||||||
|
@ -130,4 +130,4 @@ private:
|
||||||
|
|
||||||
extern InputRecording g_InputRecording;
|
extern InputRecording g_InputRecording;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
NewRecordingFrame::NewRecordingFrame(wxWindow *parent)
|
NewRecordingFrame::NewRecordingFrame(wxWindow* parent)
|
||||||
: wxDialog(parent, wxID_ANY, "New Input Recording", wxDefaultPosition, wxDefaultSize, wxSTAY_ON_TOP | wxCAPTION)
|
: 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);
|
wxFlexGridSizer* fgs = new wxFlexGridSizer(4, 2, 20, 20);
|
||||||
wxBoxSizer *container = new wxBoxSizer(wxVERTICAL);
|
wxBoxSizer* container = new wxBoxSizer(wxVERTICAL);
|
||||||
|
|
||||||
m_fileLabel = new wxStaticText(panel, wxID_ANY, _("File Path"), wxDefaultPosition, wxDefaultSize, wxALIGN_CENTER);
|
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);
|
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();
|
wxString path = m_filePicker->GetPath();
|
||||||
// wxWidget's removes the extension if it contains wildcards
|
// wxWidget's removes the extension if it contains wildcards
|
||||||
// on wxGTK https://trac.wxwidgets.org/ticket/15285
|
// on wxGTK https://trac.wxwidgets.org/ticket/15285
|
||||||
if (!path.EndsWith(".p2m2")) {
|
if (!path.EndsWith(".p2m2"))
|
||||||
|
{
|
||||||
return wxString::Format("%s.p2m2", path);
|
return wxString::Format("%s.p2m2", path);
|
||||||
}
|
}
|
||||||
return path;
|
return path;
|
||||||
|
|
|
@ -31,20 +31,20 @@ enum MenuIds_New_Recording_Frame
|
||||||
class NewRecordingFrame : public wxDialog
|
class NewRecordingFrame : public wxDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NewRecordingFrame(wxWindow *parent);
|
NewRecordingFrame(wxWindow* parent);
|
||||||
|
|
||||||
wxString GetFile() const;
|
wxString GetFile() const;
|
||||||
wxString GetAuthor() const;
|
wxString GetAuthor() const;
|
||||||
int GetFrom() const;
|
int GetFrom() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
wxStaticText *m_fileLabel;
|
wxStaticText* m_fileLabel;
|
||||||
wxFilePickerCtrl *m_filePicker;
|
wxFilePickerCtrl* m_filePicker;
|
||||||
wxStaticText *m_authorLabel;
|
wxStaticText* m_authorLabel;
|
||||||
wxTextCtrl *m_authorInput;
|
wxTextCtrl* m_authorInput;
|
||||||
wxStaticText *m_fromLabel;
|
wxStaticText* m_fromLabel;
|
||||||
wxChoice *m_fromChoice;
|
wxChoice* m_fromChoice;
|
||||||
wxButton *m_startRecording;
|
wxButton* m_startRecording;
|
||||||
wxButton *m_cancelRecording;
|
wxButton* m_cancelRecording;
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -184,9 +184,7 @@ wxString PadData::RawPadBytesToString(int start, int end)
|
||||||
{
|
{
|
||||||
str += wxString::Format("%d", PollControllerData(i));
|
str += wxString::Format("%d", PollControllerData(i));
|
||||||
if (i != end - 1)
|
if (i != end - 1)
|
||||||
{
|
|
||||||
str += ", ";
|
str += ", ";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
|
#include "MSWstuff.h"
|
||||||
#include "Utilities/EmbeddedImage.h"
|
#include "Utilities/EmbeddedImage.h"
|
||||||
#include "wx/dcbuffer.h"
|
#include "wx/dcbuffer.h"
|
||||||
#include "wx/display.h"
|
#include "wx/display.h"
|
||||||
|
@ -29,7 +30,9 @@
|
||||||
#include "Recording/VirtualPad/VirtualPadResources.h"
|
#include "Recording/VirtualPad/VirtualPadResources.h"
|
||||||
|
|
||||||
#include "Recording/VirtualPad/img/circlePressed.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/crossPressed.h"
|
||||||
#include "Recording/VirtualPad/img/downPressed.h"
|
#include "Recording/VirtualPad/img/downPressed.h"
|
||||||
#include "Recording/VirtualPad/img/l1Pressed.h"
|
#include "Recording/VirtualPad/img/l1Pressed.h"
|
||||||
|
@ -46,57 +49,72 @@
|
||||||
#include "Recording/VirtualPad/img/trianglePressed.h"
|
#include "Recording/VirtualPad/img/trianglePressed.h"
|
||||||
#include "Recording/VirtualPad/img/upPressed.h"
|
#include "Recording/VirtualPad/img/upPressed.h"
|
||||||
|
|
||||||
|
|
||||||
VirtualPad::VirtualPad(wxWindow* parent, int controllerPort, AppConfig::InputRecordingOptions& options)
|
VirtualPad::VirtualPad(wxWindow* parent, int controllerPort, AppConfig::InputRecordingOptions& options)
|
||||||
: wxFrame(parent, wxID_ANY, wxEmptyString)
|
: wxFrame(parent, wxID_ANY, wxEmptyString)
|
||||||
, options(options)
|
, options(options)
|
||||||
{
|
{
|
||||||
// Images at 1.00 scale are designed to work well on HiDPI (4k) at 150% scaling (default recommended setting on windows)
|
// 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
|
// 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
|
// Side-note - Getting the DPI scaling amount is platform specific (with some platforms only supporting
|
||||||
// integer scaling) this is likely not reliable.
|
// 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
|
// 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!
|
// windows are dragged between differing monitors!
|
||||||
wxDisplay display(wxDisplay::GetFromWindow(this));
|
wxDisplay display(wxDisplay::GetFromWindow(this));
|
||||||
const wxRect screen = display.GetClientArea();
|
const wxRect screen = display.GetClientArea();
|
||||||
|
float dpiScale = MSW_GetDPIScale(); // linux returns 1.0
|
||||||
if (screen.height > 1080 && screen.height <= 1440) // 1440p display
|
if (screen.height > 1080 && screen.height <= 1440) // 1440p display
|
||||||
{
|
scalingFactor = 0.75 * dpiScale;
|
||||||
scalingFactor = 0.75;
|
|
||||||
}
|
|
||||||
else if (screen.height <= 1080) // 1080p display
|
else if (screen.height <= 1080) // 1080p display
|
||||||
{
|
{
|
||||||
scalingFactor = 0.5;
|
scalingFactor = 0.5 * dpiScale;
|
||||||
} // otherwise use default 1.0 scaling
|
}
|
||||||
|
// otherwise use default 1.0 scaling
|
||||||
|
|
||||||
virtualPadData = VirtualPadData();
|
virtualPadData = VirtualPadData();
|
||||||
virtualPadData.background = NewBitmap(EmbeddedImage<res_controller>().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<res_controllerHalf>().Get(), wxPoint(0, 0), true);
|
||||||
|
else if (floatCompare(scalingFactor, 0.75))
|
||||||
|
virtualPadData.background = NewBitmap(EmbeddedImage<res_controllerThreeQuarters>().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<res_controllerFull>().Get(), wxPoint(0, 0));
|
||||||
|
|
||||||
// Use the background image's size to define the window size
|
// Use the background image's size to define the window size
|
||||||
SetClientSize(virtualPadData.background.width, virtualPadData.background.height);
|
SetClientSize(virtualPadData.background.width, virtualPadData.background.height);
|
||||||
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.cross, NewBitmap(EmbeddedImage<res_crossPressed>().Get(), wxPoint(938, 369)), this, wxPoint(1055, 525));
|
// These hard-coded pixels correspond to where the background image's components are (ie. the buttons)
|
||||||
InitPressureButtonGuiElements(virtualPadData.circle, NewBitmap(EmbeddedImage<res_circlePressed>().Get(), wxPoint(1024, 286)), this, wxPoint(1055, 565));
|
// Everything is automatically scaled and adjusted based on the `scalingFactor` variable
|
||||||
InitPressureButtonGuiElements(virtualPadData.triangle, NewBitmap(EmbeddedImage<res_trianglePressed>().Get(), wxPoint(938, 201)), this, wxPoint(1055, 605));
|
InitPressureButtonGuiElements(virtualPadData.square, NewBitmap(EmbeddedImage<res_squarePressed>().Get(), wxPoint(852, 287)), this, wxPoint(1055, 525));
|
||||||
InitPressureButtonGuiElements(virtualPadData.square, NewBitmap(EmbeddedImage<res_squarePressed>().Get(), wxPoint(852, 287)), this, wxPoint(1055, 645));
|
InitPressureButtonGuiElements(virtualPadData.triangle, NewBitmap(EmbeddedImage<res_trianglePressed>().Get(), wxPoint(938, 201)), this, wxPoint(1055, 565));
|
||||||
|
InitPressureButtonGuiElements(virtualPadData.circle, NewBitmap(EmbeddedImage<res_circlePressed>().Get(), wxPoint(1024, 286)), this, wxPoint(1055, 605));
|
||||||
|
InitPressureButtonGuiElements(virtualPadData.cross, NewBitmap(EmbeddedImage<res_crossPressed>().Get(), wxPoint(938, 369)), this, wxPoint(1055, 645));
|
||||||
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.down, NewBitmap(EmbeddedImage<res_downPressed>().Get(), wxPoint(186, 359)), this, wxPoint(175, 525), true);
|
InitPressureButtonGuiElements(virtualPadData.left, NewBitmap(EmbeddedImage<res_leftPressed>().Get(), wxPoint(110, 303)), this, wxPoint(175, 525), true);
|
||||||
InitPressureButtonGuiElements(virtualPadData.right, NewBitmap(EmbeddedImage<res_rightPressed>().Get(), wxPoint(248, 302)), this, wxPoint(175, 565), true);
|
InitPressureButtonGuiElements(virtualPadData.up, NewBitmap(EmbeddedImage<res_upPressed>().Get(), wxPoint(186, 227)), this, wxPoint(175, 565), true);
|
||||||
InitPressureButtonGuiElements(virtualPadData.up, NewBitmap(EmbeddedImage<res_upPressed>().Get(), wxPoint(186, 227)), this, wxPoint(175, 605), true);
|
InitPressureButtonGuiElements(virtualPadData.right, NewBitmap(EmbeddedImage<res_rightPressed>().Get(), wxPoint(248, 302)), this, wxPoint(175, 605), true);
|
||||||
InitPressureButtonGuiElements(virtualPadData.left, NewBitmap(EmbeddedImage<res_leftPressed>().Get(), wxPoint(110, 302)), this, wxPoint(175, 645), true);
|
InitPressureButtonGuiElements(virtualPadData.down, NewBitmap(EmbeddedImage<res_downPressed>().Get(), wxPoint(186, 359)), this, wxPoint(175, 645), true);
|
||||||
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.l1, NewBitmap(EmbeddedImage<res_l1Pressed>().Get(), wxPoint(156, 98)), this, wxPoint(170, 135));
|
InitPressureButtonGuiElements(virtualPadData.l1, NewBitmap(EmbeddedImage<res_l1Pressed>().Get(), wxPoint(156, 98)), this, wxPoint(170, 135));
|
||||||
InitPressureButtonGuiElements(virtualPadData.l2, NewBitmap(EmbeddedImage<res_l2Pressed>().Get(), wxPoint(156, 57)), this, wxPoint(170, 18));
|
InitPressureButtonGuiElements(virtualPadData.l2, NewBitmap(EmbeddedImage<res_l2Pressed>().Get(), wxPoint(156, 57)), this, wxPoint(170, 52), false, true);
|
||||||
InitPressureButtonGuiElements(virtualPadData.r1, NewBitmap(EmbeddedImage<res_r1Pressed>().Get(), wxPoint(921, 98)), this, wxPoint(1035, 135), true);
|
InitPressureButtonGuiElements(virtualPadData.r1, NewBitmap(EmbeddedImage<res_r1Pressed>().Get(), wxPoint(921, 98)), this, wxPoint(1035, 135), true);
|
||||||
InitPressureButtonGuiElements(virtualPadData.r2, NewBitmap(EmbeddedImage<res_r2Pressed>().Get(), wxPoint(921, 57)), this, wxPoint(1035, 18), true);
|
InitPressureButtonGuiElements(virtualPadData.r2, NewBitmap(EmbeddedImage<res_r2Pressed>().Get(), wxPoint(921, 57)), this, wxPoint(1035, 52), true, true);
|
||||||
|
|
||||||
InitNormalButtonGuiElements(virtualPadData.select, NewBitmap(EmbeddedImage<res_selectPressed>().Get(), wxPoint(457, 313)), this, wxPoint(530, 320));
|
InitNormalButtonGuiElements(virtualPadData.select, NewBitmap(EmbeddedImage<res_selectPressed>().Get(), wxPoint(458, 313)), this, wxPoint(530, 315));
|
||||||
InitNormalButtonGuiElements(virtualPadData.start, NewBitmap(EmbeddedImage<res_startPressed>().Get(), wxPoint(688, 311)), this, wxPoint(650, 320));
|
InitNormalButtonGuiElements(virtualPadData.start, NewBitmap(EmbeddedImage<res_startPressed>().Get(), wxPoint(688, 311)), this, wxPoint(646, 315));
|
||||||
InitNormalButtonGuiElements(virtualPadData.l3, NewBitmap(EmbeddedImage<res_r3Pressed>().Get(), wxPoint(726, 453)), this, wxPoint(440, 835)); // TODO - text for L3 / R3
|
InitNormalButtonGuiElements(virtualPadData.l3, NewBitmap(EmbeddedImage<res_l3Pressed>().Get(), wxPoint(336, 453)), this, wxPoint(560, 638));
|
||||||
InitNormalButtonGuiElements(virtualPadData.r3, NewBitmap(EmbeddedImage<res_l3Pressed>().Get(), wxPoint(336, 453)), this, wxPoint(844, 835)); // TODO - text for L3 / R3
|
InitNormalButtonGuiElements(virtualPadData.r3, NewBitmap(EmbeddedImage<res_r3Pressed>().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.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(795, 522), 101, wxPoint(703, 642), wxPoint(648, 431), true, wxPoint(695, 662), wxPoint(695, 622), 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_CHECKBOX, &VirtualPad::OnIgnoreRealController, this, ignoreRealControllerBox->GetId());
|
||||||
|
Bind(wxEVT_BUTTON, &VirtualPad::OnResetButton, this, resetButton->GetId());
|
||||||
|
|
||||||
// Bind Window Events
|
// Bind Window Events
|
||||||
Bind(wxEVT_MOVE, &VirtualPad::OnMoveAround, this);
|
Bind(wxEVT_MOVE, &VirtualPad::OnMoveAround, this);
|
||||||
|
@ -116,8 +134,10 @@ VirtualPad::VirtualPad(wxWindow* parent, int controllerPort, AppConfig::InputRec
|
||||||
SetBackgroundColour(*wxWHITE);
|
SetBackgroundColour(*wxWHITE);
|
||||||
SetBackgroundStyle(wxBG_STYLE_PAINT);
|
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
|
// 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);
|
SetWindowStyle(wxDEFAULT_FRAME_STYLE & ~wxRESIZE_BORDER & ~wxMAXIMIZE_BOX);
|
||||||
SetDoubleBuffered(true);
|
|
||||||
|
// Causes flickering, despite it supposed to be preventing it!
|
||||||
|
// SetDoubleBuffered(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnMoveAround(wxMoveEvent& event)
|
void VirtualPad::OnMoveAround(wxMoveEvent& event)
|
||||||
|
@ -158,30 +178,28 @@ void VirtualPad::OnEraseBackground(wxEraseEvent& event)
|
||||||
void VirtualPad::OnPaint(wxPaintEvent& event)
|
void VirtualPad::OnPaint(wxPaintEvent& event)
|
||||||
{
|
{
|
||||||
// DevCon.WriteLn("Paint Event Called");
|
// DevCon.WriteLn("Paint Event Called");
|
||||||
wxPaintDC dc(this);
|
wxBufferedPaintDC dc(this, wxBUFFER_VIRTUAL_AREA);
|
||||||
Render(dc);
|
Render(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::Redraw()
|
void VirtualPad::Redraw()
|
||||||
{
|
{
|
||||||
wxClientDC dc(this);
|
wxClientDC cdc(this);
|
||||||
|
wxBufferedDC dc(&cdc);
|
||||||
Render(dc);
|
Render(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::Render(wxDC& dc)
|
void VirtualPad::Render(wxDC& bdc)
|
||||||
{
|
{
|
||||||
// Update GUI Elements and figure out what needs to be rendered
|
// Update GUI Elements and figure out what needs to be rendered
|
||||||
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
||||||
{
|
|
||||||
virtualPadElement->UpdateGuiElement(renderQueue, clearScreenRequired);
|
virtualPadElement->UpdateGuiElement(renderQueue, clearScreenRequired);
|
||||||
}
|
|
||||||
|
|
||||||
// Update Graphic Elements off render stack
|
// Update Graphic Elements off render stack
|
||||||
// Before we start rendering (if we have to) clear and re-draw the background
|
// Before we start rendering (if we have to) clear and re-draw the background
|
||||||
if (!manualRedrawMode || clearScreenRequired || !renderQueue.empty())
|
if (!manualRedrawMode || clearScreenRequired || !renderQueue.empty())
|
||||||
{
|
{
|
||||||
wxBufferedDC bdc(&dc, dc.GetSize());
|
bdc.SetBrush(*wxWHITE);
|
||||||
bdc.SetBrush(*wxRED);
|
|
||||||
bdc.DrawRectangle(wxPoint(0, 0), bdc.GetSize());
|
bdc.DrawRectangle(wxPoint(0, 0), bdc.GetSize());
|
||||||
bdc.SetBrush(wxNullBrush);
|
bdc.SetBrush(wxNullBrush);
|
||||||
bdc.DrawBitmap(virtualPadData.background.image, virtualPadData.background.coords, true);
|
bdc.DrawBitmap(virtualPadData.background.image, virtualPadData.background.coords, true);
|
||||||
|
@ -206,9 +224,7 @@ void VirtualPad::Render(wxDC& dc)
|
||||||
{
|
{
|
||||||
VirtualPadElement* element = renderQueue.front();
|
VirtualPadElement* element = renderQueue.front();
|
||||||
if (element)
|
if (element)
|
||||||
{
|
|
||||||
element->Render(bdc);
|
element->Render(bdc);
|
||||||
}
|
|
||||||
renderQueue.pop();
|
renderQueue.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,33 +235,34 @@ bool VirtualPad::UpdateControllerData(u16 const bufIndex, PadData* padData)
|
||||||
return virtualPadData.UpdateVirtualPadData(bufIndex, padData, ignoreRealController && !readOnlyMode, readOnlyMode);
|
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)
|
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
||||||
{
|
|
||||||
virtualPadElement->EnableWidgets(enable);
|
virtualPadElement->EnableWidgets(enable);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::SetReadOnlyMode()
|
void VirtualPad::SetReadOnlyMode(bool readOnly)
|
||||||
{
|
{
|
||||||
enablePadElements(false);
|
enableUiElements(!readOnly);
|
||||||
readOnlyMode = true;
|
readOnlyMode = readOnly;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::ClearReadOnlyMode()
|
void VirtualPad::OnIgnoreRealController(wxCommandEvent& event)
|
||||||
{
|
|
||||||
enablePadElements(true);
|
|
||||||
readOnlyMode = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void VirtualPad::OnIgnoreRealController(wxCommandEvent const& event)
|
|
||||||
{
|
{
|
||||||
const wxCheckBox* ignoreButton = (wxCheckBox*)event.GetEventObject();
|
const wxCheckBox* ignoreButton = (wxCheckBox*)event.GetEventObject();
|
||||||
if (ignoreButton)
|
if (ignoreButton)
|
||||||
{
|
|
||||||
ignoreRealController = ignoreButton->GetValue();
|
ignoreRealController = ignoreButton->GetValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VirtualPad::OnResetButton(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
if (readOnlyMode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
||||||
|
virtualPadElement->Reset(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnNormalButtonPress(wxCommandEvent& event)
|
void VirtualPad::OnNormalButtonPress(wxCommandEvent& event)
|
||||||
|
@ -254,14 +271,10 @@ void VirtualPad::OnNormalButtonPress(wxCommandEvent& event)
|
||||||
ControllerNormalButton* eventBtn = buttonElements[pressedButton->GetId()];
|
ControllerNormalButton* eventBtn = buttonElements[pressedButton->GetId()];
|
||||||
|
|
||||||
if (pressedButton)
|
if (pressedButton)
|
||||||
{
|
|
||||||
eventBtn->pressed = pressedButton->GetValue();
|
eventBtn->pressed = pressedButton->GetValue();
|
||||||
}
|
|
||||||
|
|
||||||
if (!eventBtn->isControllerPressBypassed)
|
if (!eventBtn->isControllerPressBypassed)
|
||||||
{
|
|
||||||
eventBtn->isControllerPressBypassed = true;
|
eventBtn->isControllerPressBypassed = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent& event)
|
void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent& event)
|
||||||
|
@ -270,9 +283,8 @@ void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent& event)
|
||||||
ControllerPressureButton* eventBtn = pressureElements[pressureSpinner->GetId()];
|
ControllerPressureButton* eventBtn = pressureElements[pressureSpinner->GetId()];
|
||||||
|
|
||||||
if (pressureSpinner)
|
if (pressureSpinner)
|
||||||
{
|
|
||||||
eventBtn->pressure = pressureSpinner->GetValue();
|
eventBtn->pressure = pressureSpinner->GetValue();
|
||||||
}
|
|
||||||
eventBtn->pressed = eventBtn->pressure > 0;
|
eventBtn->pressed = eventBtn->pressure > 0;
|
||||||
|
|
||||||
if (!eventBtn->isControllerPressureBypassed || !eventBtn->isControllerPressBypassed)
|
if (!eventBtn->isControllerPressureBypassed || !eventBtn->isControllerPressBypassed)
|
||||||
|
@ -288,15 +300,12 @@ void VirtualPad::OnAnalogSpinnerChange(wxCommandEvent& event)
|
||||||
AnalogVector* eventVector = analogElements[analogSpinner->GetId()];
|
AnalogVector* eventVector = analogElements[analogSpinner->GetId()];
|
||||||
|
|
||||||
if (analogSpinner)
|
if (analogSpinner)
|
||||||
{
|
|
||||||
eventVector->val = analogSpinner->GetValue();
|
eventVector->val = analogSpinner->GetValue();
|
||||||
}
|
|
||||||
eventVector->slider->SetValue(eventVector->val);
|
eventVector->slider->SetValue(eventVector->val);
|
||||||
|
|
||||||
if (!eventVector->isControllerBypassed)
|
if (!eventVector->isControllerBypassed)
|
||||||
{
|
|
||||||
eventVector->isControllerBypassed = true;
|
eventVector->isControllerBypassed = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnAnalogSliderChange(wxCommandEvent& event)
|
void VirtualPad::OnAnalogSliderChange(wxCommandEvent& event)
|
||||||
|
@ -305,46 +314,57 @@ void VirtualPad::OnAnalogSliderChange(wxCommandEvent& event)
|
||||||
AnalogVector* eventVector = analogElements[analogSlider->GetId()];
|
AnalogVector* eventVector = analogElements[analogSlider->GetId()];
|
||||||
|
|
||||||
if (analogSlider)
|
if (analogSlider)
|
||||||
{
|
|
||||||
eventVector->val = analogSlider->GetValue();
|
eventVector->val = analogSlider->GetValue();
|
||||||
}
|
|
||||||
eventVector->spinner->SetValue(eventVector->val);
|
eventVector->spinner->SetValue(eventVector->val);
|
||||||
|
|
||||||
if (!eventVector->isControllerBypassed)
|
if (!eventVector->isControllerBypassed)
|
||||||
{
|
|
||||||
eventVector->isControllerBypassed = true;
|
eventVector->isControllerBypassed = true;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// GUI Element Utility Functions
|
/// 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);
|
wxPoint scaledPoint = wxPoint(x * scalingFactor, y * scalingFactor);
|
||||||
if (rightAligned)
|
if (rightAlignedCoord)
|
||||||
{
|
{
|
||||||
scaledPoint.x -= widgetWidth * scalingFactor;
|
scaledPoint.x -= widgetWidth * scalingFactor;
|
||||||
if (scaledPoint.x < 0)
|
if (scaledPoint.x < 0)
|
||||||
{
|
|
||||||
scaledPoint.x = 0;
|
scaledPoint.x = 0;
|
||||||
}
|
}
|
||||||
|
if (bottomAlignedCoord)
|
||||||
|
{
|
||||||
|
scaledPoint.y -= widgetHeight * scalingFactor;
|
||||||
|
if (scaledPoint.y < 0)
|
||||||
|
scaledPoint.y = 0;
|
||||||
}
|
}
|
||||||
return scaledPoint;
|
return scaledPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wxSize VirtualPad::ScaledSize(wxSize size)
|
||||||
|
{
|
||||||
|
return ScaledSize(size.x, size.y);
|
||||||
|
}
|
||||||
|
|
||||||
wxSize VirtualPad::ScaledSize(int x, int y)
|
wxSize VirtualPad::ScaledSize(int x, int y)
|
||||||
{
|
{
|
||||||
return wxSize(x * scalingFactor, y * scalingFactor);
|
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)
|
ImageFile VirtualPad::NewBitmap(float scalingFactor, wxImage resource, wxPoint imgCoord)
|
||||||
|
@ -368,11 +388,10 @@ void VirtualPad::InitNormalButtonGuiElements(ControllerNormalButton& button, Ima
|
||||||
virtualPadElements.push_back(&button);
|
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, SPINNER_SIZE, rightAlignedCoord, bottomAlignedCoord);
|
||||||
const wxPoint scaledPoint = ScaledPoint(pressureSpinnerCoord.x, pressureSpinnerCoord.y, spinnerWidth, rightAlignedCoord);
|
wxSpinCtrl* spinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, scaledPoint, ScaledSize(SPINNER_SIZE), wxSP_ARROW_KEYS, 0, 255, 0);
|
||||||
wxSpinCtrl* spinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, scaledPoint, ScaledSize(spinnerWidth, wxDefaultSize.GetHeight()), wxSP_ARROW_KEYS, 0, 255, 0);
|
|
||||||
|
|
||||||
button.icon = image;
|
button.icon = image;
|
||||||
button.pressureSpinner = spinner;
|
button.pressureSpinner = spinner;
|
||||||
|
@ -381,7 +400,8 @@ void VirtualPad::InitPressureButtonGuiElements(ControllerPressureButton& button,
|
||||||
virtualPadElements.push_back(&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();
|
AnalogPosition analogPos = AnalogPosition();
|
||||||
analogPos.centerCoords = ScaledPoint(centerPoint);
|
analogPos.centerCoords = ScaledPoint(centerPoint);
|
||||||
|
@ -389,14 +409,15 @@ void VirtualPad::InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* paren
|
||||||
analogPos.radius = radius * scalingFactor;
|
analogPos.radius = radius * scalingFactor;
|
||||||
analogPos.lineThickness = 6 * scalingFactor;
|
analogPos.lineThickness = 6 * scalingFactor;
|
||||||
|
|
||||||
const int spinnerWidth = 90;
|
const wxPoint xSpinnerScaledPoint = ScaledPoint(xSpinnerPoint, SPINNER_SIZE, rightAlignedSpinners);
|
||||||
const wxPoint xSpinnerScaledPoint = ScaledPoint(xSpinnerPoint, spinnerWidth, rightAlignedSpinners);
|
const wxPoint ySpinnerScaledPoint = ScaledPoint(ySpinnerPoint, SPINNER_SIZE, rightAlignedSpinners, true);
|
||||||
const wxPoint ySpinnerScaledPoint = ScaledPoint(ySpinnerPoint, spinnerWidth, rightAlignedSpinners);
|
|
||||||
|
|
||||||
wxSlider* xSlider = new wxSlider(parentWindow, wxID_ANY, 127, 0, 255, ScaledPoint(xSliderPoint), ScaledSize(185, 30));
|
wxSlider* xSlider = new wxSlider(parentWindow, wxID_ANY, ANALOG_NEUTRAL, 0, ANALOG_MAX,
|
||||||
wxSlider* ySlider = new wxSlider(parentWindow, wxID_ANY, 127, 0, 255, ScaledPoint(ySliderPoint), ScaledSize(30, 185), flipYSlider ? wxSL_LEFT : wxSL_RIGHT);
|
ScaledPoint(xSliderPoint), ScaledSize(ANALOG_SLIDER_WIDTH, ANALOG_SLIDER_HEIGHT));
|
||||||
wxSpinCtrl* xSpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, xSpinnerScaledPoint, ScaledSize(90, wxDefaultSize.GetHeight()), wxSP_ARROW_KEYS, 0, 255, 127);
|
wxSlider* ySlider = new wxSlider(parentWindow, wxID_ANY, ANALOG_NEUTRAL, 0, ANALOG_MAX,
|
||||||
wxSpinCtrl* ySpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, ySpinnerScaledPoint, ScaledSize(90, wxDefaultSize.GetHeight()), wxSP_ARROW_KEYS, 0, 255, 127);
|
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.xVector.slider = xSlider;
|
||||||
analog.yVector.slider = ySlider;
|
analog.yVector.slider = ySlider;
|
||||||
|
|
|
@ -43,14 +43,21 @@ public:
|
||||||
// - PadData will not be updated if ReadOnly mode is set
|
// - PadData will not be updated if ReadOnly mode is set
|
||||||
// - returns a bool to indicate if the PadData has been updated
|
// - returns a bool to indicate if the PadData has been updated
|
||||||
bool UpdateControllerData(u16 const bufIndex, PadData* padData);
|
bool UpdateControllerData(u16 const bufIndex, PadData* padData);
|
||||||
// Enables ReadOnly mode and disables GUI widgets
|
// Enables/Disables read only mode and enables/disables GUI widgets
|
||||||
void SetReadOnlyMode();
|
void SetReadOnlyMode(bool readOnly);
|
||||||
// Disables ReadOnly mode and re-enables GUI widgets
|
|
||||||
void ClearReadOnlyMode();
|
|
||||||
// To be called at maximum, once per frame to update widget's value and re-render the VirtualPad's graphics
|
// To be called at maximum, once per frame to update widget's value and re-render the VirtualPad's graphics
|
||||||
void Redraw();
|
void Redraw();
|
||||||
|
|
||||||
private:
|
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;
|
AppConfig::InputRecordingOptions& options;
|
||||||
|
|
||||||
bool clearScreenRequired = false;
|
bool clearScreenRequired = false;
|
||||||
|
@ -65,10 +72,11 @@ private:
|
||||||
std::vector<VirtualPadElement*> virtualPadElements;
|
std::vector<VirtualPadElement*> virtualPadElements;
|
||||||
std::queue<VirtualPadElement*> renderQueue;
|
std::queue<VirtualPadElement*> renderQueue;
|
||||||
|
|
||||||
void enablePadElements(bool enable);
|
void enableUiElements(bool enable);
|
||||||
|
|
||||||
/// GUI Elements
|
/// GUI Elements
|
||||||
wxCheckBox* ignoreRealControllerBox;
|
wxCheckBox* ignoreRealControllerBox;
|
||||||
|
wxButton* resetButton;
|
||||||
|
|
||||||
std::map<wxWindowID, ControllerNormalButton*> buttonElements;
|
std::map<wxWindowID, ControllerNormalButton*> buttonElements;
|
||||||
std::map<wxWindowID, ControllerPressureButton*> pressureElements;
|
std::map<wxWindowID, ControllerPressureButton*> pressureElements;
|
||||||
|
@ -84,21 +92,24 @@ private:
|
||||||
|
|
||||||
void OnAnalogSliderChange(wxCommandEvent& event);
|
void OnAnalogSliderChange(wxCommandEvent& event);
|
||||||
void OnAnalogSpinnerChange(wxCommandEvent& event);
|
void OnAnalogSpinnerChange(wxCommandEvent& event);
|
||||||
void OnIgnoreRealController(wxCommandEvent const& event);
|
void OnIgnoreRealController(wxCommandEvent& event);
|
||||||
void OnNormalButtonPress(wxCommandEvent& event);
|
void OnNormalButtonPress(wxCommandEvent& event);
|
||||||
void OnPressureButtonPressureChange(wxCommandEvent& event);
|
void OnPressureButtonPressureChange(wxCommandEvent& event);
|
||||||
|
void OnResetButton(wxCommandEvent& event);
|
||||||
|
|
||||||
/// GUI Creation Utility Functions
|
/// GUI Creation Utility Functions
|
||||||
float scalingFactor = 1.0;
|
float scalingFactor = 1.0;
|
||||||
|
bool floatCompare(float A, float B, float epsilon = 0.005f);
|
||||||
|
|
||||||
|
wxSize ScaledSize(wxSize size);
|
||||||
wxSize ScaledSize(int x, int y);
|
wxSize ScaledSize(int x, int y);
|
||||||
wxPoint ScaledPoint(wxPoint point, 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 = 0, bool rightAligned = 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);
|
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 InitNormalButtonGuiElements(ControllerNormalButton& btn, ImageFile image, wxWindow* parentWindow, wxPoint checkboxCoord);
|
||||||
void InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* parentWindow, wxPoint centerPoint, int radius, wxPoint xSliderPoint,
|
void InitAnalogStickGuiElements(AnalogStick& analog, wxWindow* parentWindow, wxPoint centerPoint, int radius, wxPoint xSliderPoint,
|
||||||
wxPoint ySliderPoint, bool flipYSlider, wxPoint xSpinnerPoint, wxPoint ySpinnerPoint, bool rightAlignedSpinners = false);
|
wxPoint ySliderPoint, bool flipYSlider, wxPoint xSpinnerPoint, wxPoint ySpinnerPoint, bool rightAlignedSpinners = false);
|
||||||
|
|
|
@ -22,21 +22,31 @@
|
||||||
#include "Recording/VirtualPad/VirtualPadResources.h"
|
#include "Recording/VirtualPad/VirtualPadResources.h"
|
||||||
#include "Recording/PadData.h"
|
#include "Recording/PadData.h"
|
||||||
|
|
||||||
|
wxCommandEvent VirtualPadElement::ConstructEvent(wxEventTypeTag<wxCommandEvent> eventType, wxWindow* obj)
|
||||||
|
{
|
||||||
|
wxCommandEvent event(eventType, obj->GetId());
|
||||||
|
event.SetEventObject(obj);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
|
wxCommandEvent VirtualPadElement::ConstructEvent(wxEventTypeTag<wxSpinEvent> eventType, wxWindow* obj)
|
||||||
|
{
|
||||||
|
wxCommandEvent event(eventType, obj->GetId());
|
||||||
|
event.SetEventObject(obj);
|
||||||
|
return event;
|
||||||
|
}
|
||||||
|
|
||||||
void ControllerNormalButton::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired)
|
void ControllerNormalButton::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired)
|
||||||
{
|
{
|
||||||
ControllerNormalButton& button = *this;
|
ControllerNormalButton& button = *this;
|
||||||
// This boolean is set when we parse the PadData in VirtualPadData::UpdateVirtualPadData
|
// 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
|
// Updating wxWidget elements can be expensive, we only want to do this if required
|
||||||
if (button.widgetUpdateRequired)
|
if (button.widgetUpdateRequired)
|
||||||
{
|
|
||||||
button.pressedBox->SetValue(button.pressed);
|
button.pressedBox->SetValue(button.pressed);
|
||||||
}
|
|
||||||
|
|
||||||
// We only render the button if it is pressed
|
// We only render the button if it is pressed
|
||||||
if (button.pressed)
|
if (button.pressed)
|
||||||
{
|
|
||||||
renderQueue.push(this);
|
renderQueue.push(this);
|
||||||
}
|
|
||||||
// However, if the button has been drawn to the screen in the past
|
// However, if the button has been drawn to the screen in the past
|
||||||
// we need to ensure the screen is cleared.
|
// we need to ensure the screen is cleared.
|
||||||
// This is needed in the scenario where only a single button is being pressed/released
|
// This is needed in the scenario where only a single button is being pressed/released
|
||||||
|
@ -52,14 +62,10 @@ void ControllerPressureButton::UpdateGuiElement(std::queue<VirtualPadElement*>&
|
||||||
{
|
{
|
||||||
ControllerPressureButton& button = *this;
|
ControllerPressureButton& button = *this;
|
||||||
if (button.widgetUpdateRequired)
|
if (button.widgetUpdateRequired)
|
||||||
{
|
|
||||||
button.pressureSpinner->SetValue(button.pressure);
|
button.pressureSpinner->SetValue(button.pressure);
|
||||||
}
|
|
||||||
|
|
||||||
if (button.pressed)
|
if (button.pressed)
|
||||||
{
|
|
||||||
renderQueue.push(this);
|
renderQueue.push(this);
|
||||||
}
|
|
||||||
else if (button.currentlyRendered)
|
else if (button.currentlyRendered)
|
||||||
{
|
{
|
||||||
button.currentlyRendered = false;
|
button.currentlyRendered = false;
|
||||||
|
@ -83,9 +89,7 @@ void AnalogStick::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue,
|
||||||
|
|
||||||
// We render the analog sticks as long as they are not in the neutral position
|
// 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))
|
if (!(analogStick.xVector.val == PadData::ANALOG_VECTOR_NEUTRAL && analogStick.yVector.val == PadData::ANALOG_VECTOR_NEUTRAL))
|
||||||
{
|
|
||||||
renderQueue.push(this);
|
renderQueue.push(this);
|
||||||
}
|
|
||||||
else if (analogStick.currentlyRendered)
|
else if (analogStick.currentlyRendered)
|
||||||
{
|
{
|
||||||
analogStick.currentlyRendered = false;
|
analogStick.currentlyRendered = false;
|
||||||
|
@ -95,47 +99,20 @@ void AnalogStick::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue,
|
||||||
|
|
||||||
void ControllerNormalButton::EnableWidgets(bool enable)
|
void ControllerNormalButton::EnableWidgets(bool enable)
|
||||||
{
|
{
|
||||||
ControllerNormalButton& button = *this;
|
this->pressedBox->Enable(enable);
|
||||||
if (enable)
|
|
||||||
{
|
|
||||||
button.pressedBox->Enable();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
button.pressedBox->Disable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerPressureButton::EnableWidgets(bool enable)
|
void ControllerPressureButton::EnableWidgets(bool enable)
|
||||||
{
|
{
|
||||||
ControllerPressureButton& button = *this;
|
this->pressureSpinner->Enable(enable);
|
||||||
if (enable)
|
|
||||||
{
|
|
||||||
button.pressureSpinner->Enable();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
button.pressureSpinner->Disable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogStick::EnableWidgets(bool enable)
|
void AnalogStick::EnableWidgets(bool enable)
|
||||||
{
|
{
|
||||||
AnalogStick& analog = *this;
|
this->xVector.slider->Enable(enable);
|
||||||
if (enable)
|
this->yVector.slider->Enable(enable);
|
||||||
{
|
this->xVector.spinner->Enable(enable);
|
||||||
analog.xVector.slider->Enable();
|
this->yVector.spinner->Enable(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();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerNormalButton::Render(wxDC& dc)
|
void ControllerNormalButton::Render(wxDC& dc)
|
||||||
|
@ -181,6 +158,30 @@ void AnalogStick::Render(wxDC& dc)
|
||||||
analogStick.currentlyRendered = true;
|
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)
|
bool ControllerNormalButton::UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly)
|
||||||
{
|
{
|
||||||
return this->UpdateButtonData(padDataVal, ignoreRealController, readOnly);
|
return this->UpdateButtonData(padDataVal, ignoreRealController, readOnly);
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "wx/gdicmn.h"
|
#include "wx/gdicmn.h"
|
||||||
#include "wx/slider.h"
|
#include "wx/slider.h"
|
||||||
#include "wx/spinctrl.h"
|
#include "wx/spinctrl.h"
|
||||||
|
#include "wx/dcbuffer.h"
|
||||||
|
|
||||||
struct ImageFile
|
struct ImageFile
|
||||||
{
|
{
|
||||||
|
@ -63,8 +64,12 @@ class VirtualPadElement
|
||||||
public:
|
public:
|
||||||
bool currentlyRendered = false;
|
bool currentlyRendered = false;
|
||||||
|
|
||||||
|
wxCommandEvent ConstructEvent(wxEventTypeTag<wxCommandEvent> eventType, wxWindow *obj);
|
||||||
|
wxCommandEvent ConstructEvent(wxEventTypeTag<wxSpinEvent> eventType, wxWindow *obj);
|
||||||
|
|
||||||
virtual void EnableWidgets(bool enable) = 0;
|
virtual void EnableWidgets(bool enable) = 0;
|
||||||
virtual void Render(wxDC& dc) = 0;
|
virtual void Render(wxDC& dc) = 0;
|
||||||
|
virtual void Reset(wxEvtHandler* destWindow) = 0;
|
||||||
virtual void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) = 0;
|
virtual void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,6 +93,7 @@ public:
|
||||||
bool UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly);
|
bool UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly);
|
||||||
void EnableWidgets(bool enable) override;
|
void EnableWidgets(bool enable) override;
|
||||||
void Render(wxDC& dc) override;
|
void Render(wxDC& dc) override;
|
||||||
|
void Reset(wxEvtHandler* destWindow) override;
|
||||||
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -106,6 +112,7 @@ public:
|
||||||
bool UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly);
|
bool UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly);
|
||||||
void EnableWidgets(bool enable) override;
|
void EnableWidgets(bool enable) override;
|
||||||
void Render(wxDC& dc) override;
|
void Render(wxDC& dc) override;
|
||||||
|
void Reset(wxEvtHandler* destWindow) override;
|
||||||
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,6 +126,7 @@ public:
|
||||||
|
|
||||||
void EnableWidgets(bool enable) override;
|
void EnableWidgets(bool enable) override;
|
||||||
void Render(wxDC& dc) override;
|
void Render(wxDC& dc) override;
|
||||||
|
void Reset(wxEvtHandler* destWindow) override;
|
||||||
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 121 KiB |
Binary file not shown.
After Width: | Height: | Size: 121 KiB |
Binary file not shown.
After Width: | Height: | Size: 55 KiB |
Binary file not shown.
After Width: | Height: | Size: 87 KiB |
|
@ -466,12 +466,14 @@ void MainEmuFrame::CreateCaptureMenu()
|
||||||
|
|
||||||
void MainEmuFrame::CreateRecordMenu()
|
void MainEmuFrame::CreateRecordMenu()
|
||||||
{
|
{
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
m_menuRecording.Append(MenuId_Recording_New, _("New"));
|
m_menuRecording.Append(MenuId_Recording_New, _("New"));
|
||||||
m_menuRecording.Append(MenuId_Recording_Stop, _("Stop"))->Enable(false);
|
m_menuRecording.Append(MenuId_Recording_Stop, _("Stop"))->Enable(false);
|
||||||
m_menuRecording.Append(MenuId_Recording_Play, _("Play"));
|
m_menuRecording.Append(MenuId_Recording_Play, _("Play"));
|
||||||
m_menuRecording.AppendSeparator();
|
m_menuRecording.AppendSeparator();
|
||||||
m_menuRecording.Append(MenuId_Recording_VirtualPad_Port0, _("Virtual Pad (Port 1)"));
|
m_menuRecording.Append(MenuId_Recording_VirtualPad_Port0, _("Virtual Pad (Port 1)"));
|
||||||
m_menuRecording.Append(MenuId_Recording_VirtualPad_Port1, _("Virtual Pad (Port 2)"));
|
m_menuRecording.Append(MenuId_Recording_VirtualPad_Port1, _("Virtual Pad (Port 2)"));
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainEmuFrame::CreateHelpMenu()
|
void MainEmuFrame::CreateHelpMenu()
|
||||||
|
|
|
@ -145,7 +145,15 @@
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
<!-- Generate Recording GUI Image Headers -->
|
<!-- Generate Recording GUI Image Headers -->
|
||||||
<CustomBuild Include="..\..\Recording\VirtualPad\img\controller.png">
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\controllerFull.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\controllerThreeQuarters.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\controllerHalf.png">
|
||||||
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
|
Loading…
Reference in New Issue