vs/recording: Remove the committed header files, generate them at build-time
recording: General cleanup, remove obvious code duplication recording: Improved function arg names in VirtualPad format: Clang-format all new files
|
@ -364,7 +364,7 @@ set(pcsx2GuiHeaders
|
||||||
)
|
)
|
||||||
|
|
||||||
# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
|
# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
|
||||||
# from the bin2cpp tools at the good moment (ie .h must be created before the pcsx2 compilation)
|
# from the bin2cpp tools at right good moment (ie .h must be created before the pcsx2 compilation)
|
||||||
# Gui resources headers
|
# Gui resources headers
|
||||||
set(res_bin "${CMAKE_BINARY_DIR}/pcsx2/gui/Resources")
|
set(res_bin "${CMAKE_BINARY_DIR}/pcsx2/gui/Resources")
|
||||||
set(res_src "${CMAKE_SOURCE_DIR}/pcsx2/gui/Resources")
|
set(res_src "${CMAKE_SOURCE_DIR}/pcsx2/gui/Resources")
|
||||||
|
@ -502,7 +502,7 @@ set(pcsx2RecordingHeaders
|
||||||
)
|
)
|
||||||
|
|
||||||
# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
|
# Warning: the declaration of the .h are mandatory in case of resources files. It will ensure the creation
|
||||||
# from the bin2cpp tools at the good moment (ie .h must be created before the pcsx2 compilation)
|
# from the bin2cpp tools at the right moment (ie .h must be created before the pcsx2 compilation)
|
||||||
# Recording - VirtualPad resources headers
|
# Recording - VirtualPad resources headers
|
||||||
set(res_rec_vp_bin "${CMAKE_BINARY_DIR}/pcsx2/Recording/VirtualPad/img")
|
set(res_rec_vp_bin "${CMAKE_BINARY_DIR}/pcsx2/Recording/VirtualPad/img")
|
||||||
set(res_rec_vp_src "${CMAKE_SOURCE_DIR}/pcsx2/Recording/VirtualPad/img")
|
set(res_rec_vp_src "${CMAKE_SOURCE_DIR}/pcsx2/Recording/VirtualPad/img")
|
||||||
|
|
|
@ -51,6 +51,8 @@ void SaveStateBase::InputRecordingFreeze()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
InputRecording g_InputRecording;
|
InputRecording g_InputRecording;
|
||||||
|
|
||||||
InputRecording::InputRecording()
|
InputRecording::InputRecording()
|
||||||
|
@ -60,7 +62,7 @@ InputRecording::InputRecording()
|
||||||
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,25 +87,11 @@ void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 &bufCount, u8 b
|
||||||
{
|
{
|
||||||
// TODO - Multi-Tap Support
|
// TODO - Multi-Tap Support
|
||||||
|
|
||||||
/*
|
|
||||||
This appears to try to ensure that we are only paying attention
|
|
||||||
to the frames that matter, the ones that are reading from
|
|
||||||
the controller.
|
|
||||||
|
|
||||||
See - Lilypad.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/v1.5.0-dev/plugins/LilyPad/LilyPad.cpp#L1193
|
|
||||||
0x42 is the magic number for the default read query
|
|
||||||
*/
|
|
||||||
if (bufCount == 1)
|
if (bufCount == 1)
|
||||||
fInterruptFrame = data == 0x42;
|
fInterruptFrame = data == READ_DATA_AND_VIBRATE_FIRST_BYTE;
|
||||||
else if (bufCount == 2)
|
else if (bufCount == 2)
|
||||||
{
|
{
|
||||||
/*
|
if (buf[bufCount] != READ_DATA_AND_VIBRATE_SECOND_BYTE)
|
||||||
See - LilyPad.cpp::PADpoll - https://github.com/PCSX2/pcsx2/blob/v1.5.0-dev/plugins/LilyPad/LilyPad.cpp#L1194
|
|
||||||
0x5A is always the second byte in the buffer
|
|
||||||
when the normal READ_DATA_AND_VIBRRATE (0x42)
|
|
||||||
query is executed, this looks like a sanity check
|
|
||||||
*/
|
|
||||||
if (buf[bufCount] != 0x5A)
|
|
||||||
fInterruptFrame = false;
|
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
|
||||||
|
@ -112,17 +100,7 @@ void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 &bufCount, u8 b
|
||||||
u8 &bufVal = buf[bufCount];
|
u8 &bufVal = buf[bufCount];
|
||||||
const u16 bufIndex = bufCount - 3;
|
const u16 bufIndex = bufCount - 3;
|
||||||
|
|
||||||
// Read or Write
|
if (state == InputRecordingMode::Replaying)
|
||||||
if (state == InputRecordingMode::Recording)
|
|
||||||
{
|
|
||||||
if (incrementUndo)
|
|
||||||
{
|
|
||||||
inputRecordingData.IncrementUndoCount();
|
|
||||||
incrementUndo = false;
|
|
||||||
}
|
|
||||||
inputRecordingData.WriteKeyBuffer(frameCounter, port, bufIndex, buf[bufCount]);
|
|
||||||
}
|
|
||||||
else if (state == InputRecordingMode::Replaying)
|
|
||||||
{
|
{
|
||||||
u8 tmp = 0;
|
u8 tmp = 0;
|
||||||
if (inputRecordingData.ReadKeyBuffer(tmp, frameCounter, port, bufIndex))
|
if (inputRecordingData.ReadKeyBuffer(tmp, frameCounter, port, bufIndex))
|
||||||
|
@ -137,40 +115,43 @@ void InputRecording::ControllerInterrupt(u8 &data, u8 &port, u16 &bufCount, u8 b
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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())
|
||||||
{
|
|
||||||
// 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 != INPUT_RECORDING_MODE_REPLAY)
|
|
||||||
{
|
{
|
||||||
bufVal = padData[port]->PollControllerData(bufIndex);
|
// 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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, commit the byte to the movie file if we are recording
|
||||||
|
if (state == InputRecordingMode::Recording)
|
||||||
{
|
{
|
||||||
virtualPads[port]->Redraw();
|
if (incrementUndo)
|
||||||
|
{
|
||||||
|
inputRecordingData.IncrementUndoCount();
|
||||||
|
incrementUndo = false;
|
||||||
|
}
|
||||||
|
inputRecordingData.WriteKeyBuffer(frameCounter, port, bufIndex, bufVal);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, commit the byte to the movie file if we are recording
|
|
||||||
if (state == INPUT_RECORDING_MODE_RECORD)
|
|
||||||
{
|
|
||||||
InputRecordingData.UpdateFrameMax(g_FrameCount);
|
|
||||||
InputRecordingData.WriteKeyBuf(g_FrameCount, port, bufIndex, bufVal);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s32 InputRecording::GetFrameCounter()
|
s32 InputRecording::GetFrameCounter()
|
||||||
|
@ -396,3 +377,5 @@ wxString InputRecording::resolveGameName()
|
||||||
}
|
}
|
||||||
return !gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso);
|
return !gameName.IsEmpty() ? gameName : Path::GetFilename(g_Conf->CurrentIso);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
#include "Recording/InputRecordingFile.h"
|
#include "Recording/InputRecordingFile.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -86,7 +88,7 @@ public:
|
||||||
// Stop the active input recording
|
// Stop the active input recording
|
||||||
void Stop();
|
void Stop();
|
||||||
|
|
||||||
void SetVirtualPadPtr(VirtualPad *ptr, int const port);
|
void setVirtualPadPtr(VirtualPad *ptr, int const port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class InputRecordingMode
|
enum class InputRecordingMode
|
||||||
|
@ -96,6 +98,16 @@ private:
|
||||||
Replaying,
|
Replaying,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const int CONTROLLER_PORT_ONE = 0;
|
||||||
|
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;
|
||||||
|
|
||||||
// DEPRECATED: Slated for removal
|
// DEPRECATED: Slated for removal
|
||||||
bool fInterruptFrame = false;
|
bool fInterruptFrame = false;
|
||||||
InputRecordingFile inputRecordingData;
|
InputRecordingFile inputRecordingData;
|
||||||
|
@ -117,3 +129,5 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern InputRecording g_InputRecording;
|
extern InputRecording g_InputRecording;
|
||||||
|
|
||||||
|
#endif
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
#include "App.h"
|
#include "App.h"
|
||||||
#include "Counters.h"
|
#include "Counters.h"
|
||||||
#include "DebugTools/Debug.h"
|
#include "DebugTools/Debug.h"
|
||||||
|
@ -25,11 +27,8 @@
|
||||||
#include "InputRecordingControls.h"
|
#include "InputRecordingControls.h"
|
||||||
|
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
|
||||||
|
|
||||||
InputRecordingControls g_InputRecordingControls;
|
InputRecordingControls g_InputRecordingControls;
|
||||||
|
|
||||||
|
|
||||||
void InputRecordingControls::HandleFrameAdvanceAndPausing()
|
void InputRecordingControls::HandleFrameAdvanceAndPausing()
|
||||||
{
|
{
|
||||||
// This function can be called multiple times per frame via Counters::rcntUpdate_vSync,
|
// This function can be called multiple times per frame via Counters::rcntUpdate_vSync,
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
class InputRecordingControls
|
class InputRecordingControls
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -82,4 +83,5 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
extern InputRecordingControls g_InputRecordingControls;
|
extern InputRecordingControls g_InputRecordingControls;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -15,14 +15,14 @@
|
||||||
|
|
||||||
#include "PrecompiledHeader.h"
|
#include "PrecompiledHeader.h"
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
#include "DebugTools/Debug.h"
|
#include "DebugTools/Debug.h"
|
||||||
#include "MainFrame.h"
|
#include "MainFrame.h"
|
||||||
#include "MemoryTypes.h"
|
#include "MemoryTypes.h"
|
||||||
|
|
||||||
#include "Recording/InputRecordingFile.h"
|
#include "Recording/InputRecordingFile.h"
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
|
||||||
|
|
||||||
void InputRecordingFileHeader::Init()
|
void InputRecordingFileHeader::Init()
|
||||||
{
|
{
|
||||||
memset(author, 0, ArraySize(author));
|
memset(author, 0, ArraySize(author));
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
#include "System.h"
|
#include "System.h"
|
||||||
|
|
||||||
#include "PadData.h"
|
#include "PadData.h"
|
||||||
|
@ -22,7 +24,6 @@
|
||||||
// NOTE / TODOs for Version 2
|
// NOTE / TODOs for Version 2
|
||||||
// - Move fromSavestate, undoCount, and total frames into the header
|
// - Move fromSavestate, undoCount, and total frames into the header
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
|
||||||
struct InputRecordingFileHeader
|
struct InputRecordingFileHeader
|
||||||
{
|
{
|
||||||
u8 version = 1;
|
u8 version = 1;
|
||||||
|
@ -109,4 +110,5 @@ private:
|
||||||
bool open(const wxString path, bool newRecording);
|
bool open(const wxString path, bool newRecording);
|
||||||
bool verifyRecordingFileHeader();
|
bool verifyRecordingFileHeader();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -21,79 +21,79 @@
|
||||||
|
|
||||||
#include "Recording/PadData.h"
|
#include "Recording/PadData.h"
|
||||||
|
|
||||||
void PadData::UpdateControllerData(u16 bufIndex, u8 const &bufVal)
|
void PadData::UpdateControllerData(u16 bufIndex, u8 const& bufVal)
|
||||||
{
|
{
|
||||||
const BufferIndex index = static_cast<BufferIndex>(bufIndex);
|
const BufferIndex index = static_cast<BufferIndex>(bufIndex);
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case BufferIndex::PressedFlagsGroupOne:
|
case BufferIndex::PressedFlagsGroupOne:
|
||||||
leftPressed = IsButtonPressed(LEFT, bufVal);
|
leftPressed = IsButtonPressed(LEFT, bufVal);
|
||||||
downPressed = IsButtonPressed(DOWN, bufVal);
|
downPressed = IsButtonPressed(DOWN, bufVal);
|
||||||
rightPressed = IsButtonPressed(RIGHT, bufVal);
|
rightPressed = IsButtonPressed(RIGHT, bufVal);
|
||||||
upPressed = IsButtonPressed(UP, bufVal);
|
upPressed = IsButtonPressed(UP, bufVal);
|
||||||
start = IsButtonPressed(START, bufVal);
|
start = IsButtonPressed(START, bufVal);
|
||||||
r3 = IsButtonPressed(R3, bufVal);
|
r3 = IsButtonPressed(R3, bufVal);
|
||||||
l3 = IsButtonPressed(L3, bufVal);
|
l3 = IsButtonPressed(L3, bufVal);
|
||||||
select = IsButtonPressed(SELECT, bufVal);
|
select = IsButtonPressed(SELECT, bufVal);
|
||||||
break;
|
break;
|
||||||
case BufferIndex::PressedFlagsGroupTwo:
|
case BufferIndex::PressedFlagsGroupTwo:
|
||||||
squarePressed = IsButtonPressed(SQUARE, bufVal);
|
squarePressed = IsButtonPressed(SQUARE, bufVal);
|
||||||
crossPressed = IsButtonPressed(CROSS, bufVal);
|
crossPressed = IsButtonPressed(CROSS, bufVal);
|
||||||
circlePressed = IsButtonPressed(CIRCLE, bufVal);
|
circlePressed = IsButtonPressed(CIRCLE, bufVal);
|
||||||
trianglePressed = IsButtonPressed(TRIANGLE, bufVal);
|
trianglePressed = IsButtonPressed(TRIANGLE, bufVal);
|
||||||
r1Pressed = IsButtonPressed(R1, bufVal);
|
r1Pressed = IsButtonPressed(R1, bufVal);
|
||||||
l1Pressed = IsButtonPressed(L1, bufVal);
|
l1Pressed = IsButtonPressed(L1, bufVal);
|
||||||
r2Pressed = IsButtonPressed(R2, bufVal);
|
r2Pressed = IsButtonPressed(R2, bufVal);
|
||||||
l2Pressed = IsButtonPressed(L2, bufVal);
|
l2Pressed = IsButtonPressed(L2, bufVal);
|
||||||
break;
|
break;
|
||||||
case BufferIndex::RightAnalogXVector:
|
case BufferIndex::RightAnalogXVector:
|
||||||
rightAnalogX = bufVal;
|
rightAnalogX = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::RightAnalogYVector:
|
case BufferIndex::RightAnalogYVector:
|
||||||
rightAnalogY = bufVal;
|
rightAnalogY = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::LeftAnalogXVector:
|
case BufferIndex::LeftAnalogXVector:
|
||||||
leftAnalogX = bufVal;
|
leftAnalogX = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::LeftAnalogYVector:
|
case BufferIndex::LeftAnalogYVector:
|
||||||
leftAnalogY = bufVal;
|
leftAnalogY = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::RightPressure:
|
case BufferIndex::RightPressure:
|
||||||
rightPressure = bufVal;
|
rightPressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::LeftPressure:
|
case BufferIndex::LeftPressure:
|
||||||
leftPressure = bufVal;
|
leftPressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::UpPressure:
|
case BufferIndex::UpPressure:
|
||||||
upPressure = bufVal;
|
upPressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::DownPressure:
|
case BufferIndex::DownPressure:
|
||||||
downPressure = bufVal;
|
downPressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::TrianglePressure:
|
case BufferIndex::TrianglePressure:
|
||||||
trianglePressure = bufVal;
|
trianglePressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::CirclePressure:
|
case BufferIndex::CirclePressure:
|
||||||
circlePressure = bufVal;
|
circlePressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::CrossPressure:
|
case BufferIndex::CrossPressure:
|
||||||
crossPressure = bufVal;
|
crossPressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::SquarePressure:
|
case BufferIndex::SquarePressure:
|
||||||
squarePressure = bufVal;
|
squarePressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::L1Pressure:
|
case BufferIndex::L1Pressure:
|
||||||
l1Pressure = bufVal;
|
l1Pressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::R1Pressure:
|
case BufferIndex::R1Pressure:
|
||||||
r1Pressure = bufVal;
|
r1Pressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::L2Pressure:
|
case BufferIndex::L2Pressure:
|
||||||
l2Pressure = bufVal;
|
l2Pressure = bufVal;
|
||||||
break;
|
break;
|
||||||
case BufferIndex::R2Pressure:
|
case BufferIndex::R2Pressure:
|
||||||
r2Pressure = bufVal;
|
r2Pressure = bufVal;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,68 +103,68 @@ u8 PadData::PollControllerData(u16 bufIndex)
|
||||||
BufferIndex index = static_cast<BufferIndex>(bufIndex);
|
BufferIndex index = static_cast<BufferIndex>(bufIndex);
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case BufferIndex::PressedFlagsGroupOne:
|
case BufferIndex::PressedFlagsGroupOne:
|
||||||
// Construct byte by combining flags if the buttons are pressed
|
// Construct byte by combining flags if the buttons are pressed
|
||||||
byte |= BitmaskOrZero(leftPressed, LEFT);
|
byte |= BitmaskOrZero(leftPressed, LEFT);
|
||||||
byte |= BitmaskOrZero(downPressed, DOWN);
|
byte |= BitmaskOrZero(downPressed, DOWN);
|
||||||
byte |= BitmaskOrZero(rightPressed, RIGHT);
|
byte |= BitmaskOrZero(rightPressed, RIGHT);
|
||||||
byte |= BitmaskOrZero(upPressed, UP);
|
byte |= BitmaskOrZero(upPressed, UP);
|
||||||
byte |= BitmaskOrZero(start, START);
|
byte |= BitmaskOrZero(start, START);
|
||||||
byte |= BitmaskOrZero(r3, R3);
|
byte |= BitmaskOrZero(r3, R3);
|
||||||
byte |= BitmaskOrZero(l3, L3);
|
byte |= BitmaskOrZero(l3, L3);
|
||||||
byte |= BitmaskOrZero(select, SELECT);
|
byte |= BitmaskOrZero(select, SELECT);
|
||||||
// We flip the bits because as mentioned below, 0 = pressed
|
// We flip the bits because as mentioned below, 0 = pressed
|
||||||
return ~byte;
|
return ~byte;
|
||||||
case BufferIndex::PressedFlagsGroupTwo:
|
case BufferIndex::PressedFlagsGroupTwo:
|
||||||
// Construct byte by combining flags if the buttons are pressed
|
// Construct byte by combining flags if the buttons are pressed
|
||||||
byte |= BitmaskOrZero(squarePressed, SQUARE);
|
byte |= BitmaskOrZero(squarePressed, SQUARE);
|
||||||
byte |= BitmaskOrZero(crossPressed, CROSS);
|
byte |= BitmaskOrZero(crossPressed, CROSS);
|
||||||
byte |= BitmaskOrZero(circlePressed, CIRCLE);
|
byte |= BitmaskOrZero(circlePressed, CIRCLE);
|
||||||
byte |= BitmaskOrZero(trianglePressed, TRIANGLE);
|
byte |= BitmaskOrZero(trianglePressed, TRIANGLE);
|
||||||
byte |= BitmaskOrZero(r1Pressed, R1);
|
byte |= BitmaskOrZero(r1Pressed, R1);
|
||||||
byte |= BitmaskOrZero(l1Pressed, L1);
|
byte |= BitmaskOrZero(l1Pressed, L1);
|
||||||
byte |= BitmaskOrZero(r2Pressed, R2);
|
byte |= BitmaskOrZero(r2Pressed, R2);
|
||||||
byte |= BitmaskOrZero(l2Pressed, L2);
|
byte |= BitmaskOrZero(l2Pressed, L2);
|
||||||
// We flip the bits because as mentioned below, 0 = pressed
|
// We flip the bits because as mentioned below, 0 = pressed
|
||||||
return ~byte;
|
return ~byte;
|
||||||
case BufferIndex::RightAnalogXVector:
|
case BufferIndex::RightAnalogXVector:
|
||||||
return rightAnalogX;
|
return rightAnalogX;
|
||||||
case BufferIndex::RightAnalogYVector:
|
case BufferIndex::RightAnalogYVector:
|
||||||
return rightAnalogY;
|
return rightAnalogY;
|
||||||
case BufferIndex::LeftAnalogXVector:
|
case BufferIndex::LeftAnalogXVector:
|
||||||
return leftAnalogX;
|
return leftAnalogX;
|
||||||
case BufferIndex::LeftAnalogYVector:
|
case BufferIndex::LeftAnalogYVector:
|
||||||
return leftAnalogY;
|
return leftAnalogY;
|
||||||
case BufferIndex::RightPressure:
|
case BufferIndex::RightPressure:
|
||||||
return rightPressure;
|
return rightPressure;
|
||||||
case BufferIndex::LeftPressure:
|
case BufferIndex::LeftPressure:
|
||||||
return leftPressure;
|
return leftPressure;
|
||||||
case BufferIndex::UpPressure:
|
case BufferIndex::UpPressure:
|
||||||
return upPressure;
|
return upPressure;
|
||||||
case BufferIndex::DownPressure:
|
case BufferIndex::DownPressure:
|
||||||
return downPressure;
|
return downPressure;
|
||||||
case BufferIndex::TrianglePressure:
|
case BufferIndex::TrianglePressure:
|
||||||
return trianglePressure;
|
return trianglePressure;
|
||||||
case BufferIndex::CirclePressure:
|
case BufferIndex::CirclePressure:
|
||||||
return circlePressure;
|
return circlePressure;
|
||||||
case BufferIndex::CrossPressure:
|
case BufferIndex::CrossPressure:
|
||||||
return crossPressure;
|
return crossPressure;
|
||||||
case BufferIndex::SquarePressure:
|
case BufferIndex::SquarePressure:
|
||||||
return squarePressure;
|
return squarePressure;
|
||||||
case BufferIndex::L1Pressure:
|
case BufferIndex::L1Pressure:
|
||||||
return l1Pressure;
|
return l1Pressure;
|
||||||
case BufferIndex::R1Pressure:
|
case BufferIndex::R1Pressure:
|
||||||
return r1Pressure;
|
return r1Pressure;
|
||||||
case BufferIndex::L2Pressure:
|
case BufferIndex::L2Pressure:
|
||||||
return l2Pressure;
|
return l2Pressure;
|
||||||
case BufferIndex::R2Pressure:
|
case BufferIndex::R2Pressure:
|
||||||
return r2Pressure;
|
return r2Pressure;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PadData::IsButtonPressed(ButtonResolver buttonResolver, u8 const &bufVal)
|
bool PadData::IsButtonPressed(ButtonResolver buttonResolver, u8 const& bufVal)
|
||||||
{
|
{
|
||||||
// Rather than the flags being SET if the button is pressed, it is the opposite
|
// Rather than the flags being SET if the button is pressed, it is the opposite
|
||||||
// For example: 0111 1111 with `left` being the first bit indicates `left` is pressed.
|
// For example: 0111 1111 with `left` being the first bit indicates `left` is pressed.
|
||||||
|
@ -180,24 +180,29 @@ u8 PadData::BitmaskOrZero(bool pressed, ButtonResolver buttonInfo)
|
||||||
wxString PadData::RawPadBytesToString(int start, int end)
|
wxString PadData::RawPadBytesToString(int start, int end)
|
||||||
{
|
{
|
||||||
wxString str;
|
wxString str;
|
||||||
for (int i = start; i < end; i++) {
|
for (int i = start; i < end; i++)
|
||||||
|
{
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PadData::LogPadData(u8 const &port) {
|
void PadData::LogPadData(u8 const& port)
|
||||||
|
{
|
||||||
wxString pressedBytes = RawPadBytesToString(0, 2);
|
wxString pressedBytes = RawPadBytesToString(0, 2);
|
||||||
wxString rightAnalogBytes = RawPadBytesToString(2, 4);
|
wxString rightAnalogBytes = RawPadBytesToString(2, 4);
|
||||||
wxString leftAnalogBytes = RawPadBytesToString(4, 6);
|
wxString leftAnalogBytes = RawPadBytesToString(4, 6);
|
||||||
wxString pressureBytes = RawPadBytesToString(6, 17);
|
wxString pressureBytes = RawPadBytesToString(6, 17);
|
||||||
wxString fullLog =
|
wxString fullLog =
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Pressed = [%s]\n", port + 1, pressedBytes) +
|
wxString::Format("[PAD %d] Raw Bytes: Pressed = [%s]\n", port + 1, pressedBytes) +
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Right Analog = [%s]\n", port + 1, rightAnalogBytes) +
|
wxString::Format("[PAD %d] Raw Bytes: Right Analog = [%s]\n", port + 1, rightAnalogBytes) +
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Left Analog = [%s]\n", port + 1, leftAnalogBytes) +
|
wxString::Format("[PAD %d] Raw Bytes: Left Analog = [%s]\n", port + 1, leftAnalogBytes) +
|
||||||
wxString::Format("[PAD %d] Raw Bytes: Pressure = [%s]\n", port + 1, pressureBytes);
|
wxString::Format("[PAD %d] Raw Bytes: Pressure = [%s]\n", port + 1, pressureBytes);
|
||||||
controlLog(fullLog);
|
controlLog(fullLog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -15,12 +15,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
class PadData
|
class PadData
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/// Constants
|
/// Constants
|
||||||
static const u8 ANALOG_VECTOR_NEUTRAL = 127;
|
static const u8 ANALOG_VECTOR_NEUTRAL = 127;
|
||||||
static const u16 END_INDEX_CONTROLLER_BUFFER = 17;
|
static const u16 END_INDEX_CONTROLLER_BUFFER = 17;
|
||||||
|
|
||||||
enum class BufferIndex
|
enum class BufferIndex
|
||||||
{
|
{
|
||||||
|
@ -62,36 +64,36 @@ public:
|
||||||
/// NOTE - It shouldn't be possible to depress a button while also having no pressure
|
/// NOTE - It shouldn't be possible to depress a button while also having no pressure
|
||||||
/// But for the sake of completeness, it should be tracked.
|
/// But for the sake of completeness, it should be tracked.
|
||||||
bool circlePressed = false;
|
bool circlePressed = false;
|
||||||
bool crossPressed = false;
|
bool crossPressed = false;
|
||||||
bool squarePressed = false;
|
bool squarePressed = false;
|
||||||
bool trianglePressed = false;
|
bool trianglePressed = false;
|
||||||
bool downPressed = false;
|
bool downPressed = false;
|
||||||
bool leftPressed = false;
|
bool leftPressed = false;
|
||||||
bool rightPressed = false;
|
bool rightPressed = false;
|
||||||
bool upPressed = false;
|
bool upPressed = false;
|
||||||
bool l1Pressed = false;
|
bool l1Pressed = false;
|
||||||
bool l2Pressed = false;
|
bool l2Pressed = false;
|
||||||
bool r1Pressed = false;
|
bool r1Pressed = false;
|
||||||
bool r2Pressed = false;
|
bool r2Pressed = false;
|
||||||
|
|
||||||
/// Normal (un)pressed buttons
|
/// Normal (un)pressed buttons
|
||||||
bool select = false;
|
bool select = false;
|
||||||
bool start = false;
|
bool start = false;
|
||||||
bool l3 = false;
|
bool l3 = false;
|
||||||
bool r3 = false;
|
bool r3 = false;
|
||||||
|
|
||||||
/// Analog Sticks - 0-255 (127 center)
|
/// Analog Sticks - 0-255 (127 center)
|
||||||
u8 leftAnalogX = ANALOG_VECTOR_NEUTRAL;
|
u8 leftAnalogX = ANALOG_VECTOR_NEUTRAL;
|
||||||
u8 leftAnalogY = ANALOG_VECTOR_NEUTRAL;
|
u8 leftAnalogY = ANALOG_VECTOR_NEUTRAL;
|
||||||
u8 rightAnalogX = ANALOG_VECTOR_NEUTRAL;
|
u8 rightAnalogX = ANALOG_VECTOR_NEUTRAL;
|
||||||
u8 rightAnalogY = ANALOG_VECTOR_NEUTRAL;
|
u8 rightAnalogY = ANALOG_VECTOR_NEUTRAL;
|
||||||
|
|
||||||
// Given the input buffer and the current index, updates the correct field(s)
|
// Given the input buffer and the current index, updates the correct field(s)
|
||||||
void UpdateControllerData(u16 bufIndex, u8 const &bufVal);
|
void UpdateControllerData(u16 bufIndex, u8 const& bufVal);
|
||||||
u8 PollControllerData(u16 bufIndex);
|
u8 PollControllerData(u16 bufIndex);
|
||||||
|
|
||||||
// Prints current PadData to the Controller Log filter which disabled by default
|
// Prints current PadData to the Controller Log filter which disabled by default
|
||||||
void LogPadData(u8 const &port);
|
void LogPadData(u8 const& port);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct ButtonResolver
|
struct ButtonResolver
|
||||||
|
@ -99,28 +101,29 @@ private:
|
||||||
u8 buttonBitmask;
|
u8 buttonBitmask;
|
||||||
};
|
};
|
||||||
|
|
||||||
const ButtonResolver LEFT = ButtonResolver{ 0b10000000 };
|
const ButtonResolver LEFT = ButtonResolver{0b10000000};
|
||||||
const ButtonResolver DOWN = ButtonResolver{ 0b01000000 };
|
const ButtonResolver DOWN = ButtonResolver{0b01000000};
|
||||||
const ButtonResolver RIGHT = ButtonResolver{ 0b00100000 };
|
const ButtonResolver RIGHT = ButtonResolver{0b00100000};
|
||||||
const ButtonResolver UP = ButtonResolver{ 0b00010000 };
|
const ButtonResolver UP = ButtonResolver{0b00010000};
|
||||||
const ButtonResolver START = ButtonResolver{ 0b00001000 };
|
const ButtonResolver START = ButtonResolver{0b00001000};
|
||||||
const ButtonResolver R3 = ButtonResolver{ 0b00000100 };
|
const ButtonResolver R3 = ButtonResolver{0b00000100};
|
||||||
const ButtonResolver L3 = ButtonResolver{ 0b00000010 };
|
const ButtonResolver L3 = ButtonResolver{0b00000010};
|
||||||
const ButtonResolver SELECT = ButtonResolver{ 0b00000001 };
|
const ButtonResolver SELECT = ButtonResolver{0b00000001};
|
||||||
|
|
||||||
const ButtonResolver SQUARE = ButtonResolver{ 0b10000000 };
|
const ButtonResolver SQUARE = ButtonResolver{0b10000000};
|
||||||
const ButtonResolver CROSS = ButtonResolver{ 0b01000000 };
|
const ButtonResolver CROSS = ButtonResolver{0b01000000};
|
||||||
const ButtonResolver CIRCLE = ButtonResolver{ 0b00100000 };
|
const ButtonResolver CIRCLE = ButtonResolver{0b00100000};
|
||||||
const ButtonResolver TRIANGLE = ButtonResolver{ 0b00010000 };
|
const ButtonResolver TRIANGLE = ButtonResolver{0b00010000};
|
||||||
const ButtonResolver R1 = ButtonResolver{ 0b00001000 };
|
const ButtonResolver R1 = ButtonResolver{0b00001000};
|
||||||
const ButtonResolver L1 = ButtonResolver{ 0b00000100 };
|
const ButtonResolver L1 = ButtonResolver{0b00000100};
|
||||||
const ButtonResolver R2 = ButtonResolver{ 0b00000010 };
|
const ButtonResolver R2 = ButtonResolver{0b00000010};
|
||||||
const ButtonResolver L2 = ButtonResolver{ 0b00000001 };
|
const ButtonResolver L2 = ButtonResolver{0b00000001};
|
||||||
|
|
||||||
// Checks and returns if button a is pressed or not
|
// Checks and returns if button a is pressed or not
|
||||||
bool IsButtonPressed(ButtonResolver buttonResolver, u8 const &bufVal);
|
bool IsButtonPressed(ButtonResolver buttonResolver, u8 const& bufVal);
|
||||||
u8 BitmaskOrZero(bool pressed, ButtonResolver buttonInfo);
|
u8 BitmaskOrZero(bool pressed, ButtonResolver buttonInfo);
|
||||||
|
|
||||||
wxString RawPadBytesToString(int start, int end);
|
wxString RawPadBytesToString(int start, int end);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -47,9 +47,8 @@
|
||||||
#include "Recording/VirtualPad/img/upPressed.h"
|
#include "Recording/VirtualPad/img/upPressed.h"
|
||||||
|
|
||||||
// TODO - Store position of frame in an (possibly the main) .ini file
|
// TODO - Store position of frame in an (possibly the main) .ini file
|
||||||
|
VirtualPad::VirtualPad(wxWindow* parent, wxWindowID id, const wxString& title, int controllerPort, const wxPoint& pos, const wxSize& size, long style)
|
||||||
VirtualPad::VirtualPad(wxWindow* parent, wxWindowID id, const wxString& title, int controllerPort, const wxPoint& pos, const wxSize& size, long style) :
|
: wxFrame(parent, id, title, pos, size, wxDEFAULT_FRAME_STYLE)
|
||||||
wxFrame(parent, id, title, pos, size, wxDEFAULT_FRAME_STYLE)
|
|
||||||
{
|
{
|
||||||
// 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
|
||||||
|
@ -57,15 +56,15 @@ VirtualPad::VirtualPad(wxWindow* parent, wxWindowID id, const wxString& title, i
|
||||||
// integer scaling) this is likely not reliable.
|
// integer scaling) 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();
|
||||||
if (screen.height > 1080 && screen.height <= 1440) // 1440p display
|
if (screen.height > 1080 && screen.height <= 1440) // 1440p display
|
||||||
{
|
{
|
||||||
scalingFactor = 0.75;
|
scalingFactor = 0.75;
|
||||||
}
|
}
|
||||||
else if (screen.height <= 1080) // 1080p display
|
else if (screen.height <= 1080) // 1080p display
|
||||||
{
|
{
|
||||||
scalingFactor = 0.5;
|
scalingFactor = 0.5;
|
||||||
} // otherwise use default 1.0 scaling
|
} // otherwise use default 1.0 scaling
|
||||||
|
|
||||||
virtualPadData = VirtualPadData();
|
virtualPadData = VirtualPadData();
|
||||||
|
@ -73,78 +72,80 @@ VirtualPad::VirtualPad(wxWindow* parent, wxWindowID id, const wxString& title, i
|
||||||
// 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(968, 498)), this, wxPoint(1062, 660));
|
InitPressureButtonGuiElements(virtualPadData.cross, NewBitmap(EmbeddedImage<res_crossPressed>().Get(), wxPoint(938, 369)), this, wxPoint(1055, 525));
|
||||||
InitPressureButtonGuiElements(virtualPadData.circle, NewBitmap(EmbeddedImage<res_circlePressed>().Get(), wxPoint(1057, 413)), this, wxPoint(1062, 700));
|
InitPressureButtonGuiElements(virtualPadData.circle, NewBitmap(EmbeddedImage<res_circlePressed>().Get(), wxPoint(1024, 286)), this, wxPoint(1055, 565));
|
||||||
InitPressureButtonGuiElements(virtualPadData.triangle, NewBitmap(EmbeddedImage<res_trianglePressed>().Get(), wxPoint(968, 325)), this, wxPoint(1062, 740));
|
InitPressureButtonGuiElements(virtualPadData.triangle, NewBitmap(EmbeddedImage<res_trianglePressed>().Get(), wxPoint(938, 201)), this, wxPoint(1055, 605));
|
||||||
InitPressureButtonGuiElements(virtualPadData.square, NewBitmap(EmbeddedImage<res_squarePressed>().Get(), wxPoint(879, 413)), this, wxPoint(1062, 780));
|
InitPressureButtonGuiElements(virtualPadData.square, NewBitmap(EmbeddedImage<res_squarePressed>().Get(), wxPoint(852, 287)), this, wxPoint(1055, 645));
|
||||||
InitPressureButtonGuiElements(virtualPadData.down, NewBitmap(EmbeddedImage<res_downPressed>().Get(), wxPoint(191, 488)), this, wxPoint(199, 660), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.right, NewBitmap(EmbeddedImage<res_rightPressed>().Get(), wxPoint(255, 429)), this, wxPoint(199, 700), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.up, NewBitmap(EmbeddedImage<res_upPressed>().Get(), wxPoint(191, 354)), this, wxPoint(199, 740), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.left, NewBitmap(EmbeddedImage<res_leftPressed>().Get(), wxPoint(115, 429)), this, wxPoint(199, 780), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.l1, NewBitmap(EmbeddedImage<res_l1Pressed>().Get(), wxPoint(166, 8)), this, wxPoint(294, 20));
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.l2, NewBitmap(EmbeddedImage<res_l2Pressed>().Get(), wxPoint(166, 81)), this, wxPoint(294, 100));
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.r1, NewBitmap(EmbeddedImage<res_r1Pressed>().Get(), wxPoint(958, 7)), this, wxPoint(940, 20), true);
|
|
||||||
InitPressureButtonGuiElements(virtualPadData.r2, NewBitmap(EmbeddedImage<res_r2Pressed>().Get(), wxPoint(958, 81)), this, wxPoint(940, 100), true);
|
|
||||||
|
|
||||||
InitNormalButtonGuiElements(virtualPadData.select, NewBitmap(EmbeddedImage<res_selectPressed>().Get(), wxPoint(473, 441)), this, wxPoint(545, 448));
|
InitPressureButtonGuiElements(virtualPadData.down, NewBitmap(EmbeddedImage<res_downPressed>().Get(), wxPoint(186, 359)), this, wxPoint(175, 525), true);
|
||||||
InitNormalButtonGuiElements(virtualPadData.start, NewBitmap(EmbeddedImage<res_startPressed>().Get(), wxPoint(710, 440)), this, wxPoint(675, 448));
|
InitPressureButtonGuiElements(virtualPadData.right, NewBitmap(EmbeddedImage<res_rightPressed>().Get(), wxPoint(248, 302)), this, wxPoint(175, 565), true);
|
||||||
InitNormalButtonGuiElements(virtualPadData.l3, NewBitmap(EmbeddedImage<res_r3Pressed>().Get(), wxPoint(347, 585)), this, wxPoint(440, 835));
|
InitPressureButtonGuiElements(virtualPadData.up, NewBitmap(EmbeddedImage<res_upPressed>().Get(), wxPoint(186, 227)), this, wxPoint(175, 605), true);
|
||||||
InitNormalButtonGuiElements(virtualPadData.r3, NewBitmap(EmbeddedImage<res_l3Pressed>().Get(), wxPoint(750, 585)), this, wxPoint(844, 835));
|
InitPressureButtonGuiElements(virtualPadData.left, NewBitmap(EmbeddedImage<res_leftPressed>().Get(), wxPoint(110, 302)), this, wxPoint(175, 645), true);
|
||||||
|
|
||||||
InitAnalogStickGuiElements(virtualPadData.leftAnalog, this, wxPoint(418, 656), 105, wxPoint(326, 782), wxPoint(545, 568), false, wxPoint(522, 800), wxPoint(522, 760));
|
InitPressureButtonGuiElements(virtualPadData.l1, NewBitmap(EmbeddedImage<res_l1Pressed>().Get(), wxPoint(156, 98)), this, wxPoint(170, 135));
|
||||||
InitAnalogStickGuiElements(virtualPadData.rightAnalog, this, wxPoint(821, 656), 105, wxPoint(730, 782), wxPoint(672, 568), true, wxPoint(720, 800), wxPoint(720, 760), true);
|
InitPressureButtonGuiElements(virtualPadData.l2, NewBitmap(EmbeddedImage<res_l2Pressed>().Get(), wxPoint(156, 57)), this, wxPoint(170, 18));
|
||||||
|
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);
|
||||||
|
|
||||||
ignoreRealControllerBox = new wxCheckBox(this, wxID_ANY, wxEmptyString, ScaledPoint(605, 256), wxDefaultSize);
|
InitNormalButtonGuiElements(virtualPadData.select, NewBitmap(EmbeddedImage<res_selectPressed>().Get(), wxPoint(457, 313)), this, wxPoint(530, 320));
|
||||||
Bind(wxEVT_CHECKBOX, &VirtualPad::OnIgnoreRealController, this, ignoreRealControllerBox->GetId());
|
InitNormalButtonGuiElements(virtualPadData.start, NewBitmap(EmbeddedImage<res_startPressed>().Get(), wxPoint(688, 311)), this, wxPoint(650, 320));
|
||||||
|
InitNormalButtonGuiElements(virtualPadData.l3, NewBitmap(EmbeddedImage<res_r3Pressed>().Get(), wxPoint(726, 453)), this, wxPoint(440, 835)); // TODO - text for L3 / R3
|
||||||
|
InitNormalButtonGuiElements(virtualPadData.r3, NewBitmap(EmbeddedImage<res_l3Pressed>().Get(), wxPoint(336, 453)), this, wxPoint(844, 835)); // TODO - text for L3 / R3
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
ignoreRealControllerBox = new wxCheckBox(this, wxID_ANY, wxEmptyString, ScaledPoint(575, 135), wxDefaultSize);
|
||||||
|
Bind(wxEVT_CHECKBOX, &VirtualPad::OnIgnoreRealController, this, ignoreRealControllerBox->GetId());
|
||||||
|
|
||||||
// Bind Window Events
|
// Bind Window Events
|
||||||
Bind(wxEVT_ERASE_BACKGROUND, &VirtualPad::OnEraseBackground, this);
|
Bind(wxEVT_ERASE_BACKGROUND, &VirtualPad::OnEraseBackground, this);
|
||||||
Bind(wxEVT_CLOSE_WINDOW, &VirtualPad::OnClose, this);
|
Bind(wxEVT_CLOSE_WINDOW, &VirtualPad::OnClose, this);
|
||||||
Bind(wxEVT_ICONIZE, &VirtualPad::OnIconize, this);
|
Bind(wxEVT_ICONIZE, &VirtualPad::OnIconize, this);
|
||||||
// Temporary Paint event handler so the window displays properly before the controller-interrupt routine takes over with manual drawing.
|
// Temporary Paint event handler so the window displays properly before the controller-interrupt routine takes over with manual drawing.
|
||||||
// The reason for this is in order to minimize the performance impact, we need total control over when render is called
|
// The reason for this is in order to minimize the performance impact, we need total control over when render is called
|
||||||
// Windows redraws the window _alot_ otherwise which leads to major performance problems (when GS is using the software renderer)
|
// Windows redraws the window _alot_ otherwise which leads to major performance problems (when GS is using the software renderer)
|
||||||
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
||||||
// DevCon.WriteLn("Paint Event Bound");
|
// DevCon.WriteLn("Paint Event Bound");
|
||||||
|
|
||||||
// Finalize layout
|
// Finalize layout
|
||||||
SetIcons(wxGetApp().GetIconBundle());
|
SetIcons(wxGetApp().GetIconBundle());
|
||||||
SetTitle(wxString::Format("Virtual Pad - Port %d", controllerPort + 1));
|
SetTitle(wxString::Format("Virtual Pad - Port %d", controllerPort + 1));
|
||||||
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(style & ~wxRESIZE_BORDER);
|
SetWindowStyle(style & ~wxRESIZE_BORDER);
|
||||||
SetDoubleBuffered(true);
|
SetDoubleBuffered(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnClose(wxCloseEvent &event)
|
void VirtualPad::OnClose(wxCloseEvent& event)
|
||||||
{
|
{
|
||||||
// Re-bind the Paint event in case this is due to a game being opened/closed
|
// Re-bind the Paint event in case this is due to a game being opened/closed
|
||||||
manualRedrawMode = false;
|
manualRedrawMode = false;
|
||||||
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
||||||
// DevCon.WriteLn("Paint Event Bound");
|
// DevCon.WriteLn("Paint Event Bound");
|
||||||
Hide();
|
Hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnIconize(wxIconizeEvent &event)
|
void VirtualPad::OnIconize(wxIconizeEvent& event)
|
||||||
{
|
{
|
||||||
if (event.IsIconized())
|
if (event.IsIconized())
|
||||||
{
|
{
|
||||||
manualRedrawMode = false;
|
manualRedrawMode = false;
|
||||||
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
Bind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
||||||
// DevCon.WriteLn("Paint Event Bound");
|
// DevCon.WriteLn("Paint Event Bound");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnEraseBackground(wxEraseEvent &event)
|
void VirtualPad::OnEraseBackground(wxEraseEvent& event)
|
||||||
{
|
{
|
||||||
// Intentionally Empty
|
// Intentionally Empty
|
||||||
// See - https://wiki.wxwidgets.org/Flicker-Free_Drawing
|
// See - https://wiki.wxwidgets.org/Flicker-Free_Drawing
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnPaint(wxPaintEvent &event)
|
void VirtualPad::OnPaint(wxPaintEvent& event)
|
||||||
{
|
{
|
||||||
// DevCon.WriteLn("Paint Event Called");
|
// DevCon.WriteLn("Paint Event Called");
|
||||||
wxPaintDC dc(this);
|
wxPaintDC dc(this);
|
||||||
Render(dc);
|
Render(dc);
|
||||||
}
|
}
|
||||||
|
@ -155,176 +156,150 @@ void VirtualPad::Redraw()
|
||||||
Render(dc);
|
Render(dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::Render(wxDC &dc)
|
void VirtualPad::Render(wxDC& dc)
|
||||||
{
|
{
|
||||||
// Update GUI Elements and figure out what needs to be rendered
|
// Update GUI Elements and figure out what needs to be rendered
|
||||||
virtualPadData.circle.UpdateGuiElement(renderQueue, clearScreenRequired);
|
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
||||||
virtualPadData.cross.UpdateGuiElement(renderQueue, clearScreenRequired);
|
{
|
||||||
virtualPadData.square.UpdateGuiElement(renderQueue, clearScreenRequired);
|
virtualPadElement->UpdateGuiElement(renderQueue, clearScreenRequired);
|
||||||
virtualPadData.triangle.UpdateGuiElement(renderQueue, clearScreenRequired);
|
}
|
||||||
virtualPadData.down.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.left.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.right.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.up.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.l1.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.l2.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.r1.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.r2.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
|
|
||||||
virtualPadData.select.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.start.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.l3.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.r3.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
|
|
||||||
virtualPadData.leftAnalog.UpdateGuiElement(renderQueue, clearScreenRequired);
|
|
||||||
virtualPadData.rightAnalog.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());
|
wxBufferedDC bdc(&dc, dc.GetSize());
|
||||||
bdc.SetBrush(*wxRED);
|
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);
|
||||||
clearScreenRequired = false;
|
clearScreenRequired = false;
|
||||||
|
|
||||||
// Switch to Manual Rendering once the first user action on the VirtualPad is taken
|
// Switch to Manual Rendering once the first user action on the VirtualPad is taken
|
||||||
if (!manualRedrawMode && !renderQueue.empty()) {
|
if (!manualRedrawMode && !renderQueue.empty())
|
||||||
// DevCon.WriteLn("Paint Event Unbound");
|
{
|
||||||
Unbind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
// DevCon.WriteLn("Paint Event Unbound");
|
||||||
manualRedrawMode = true;
|
Unbind(wxEVT_PAINT, &VirtualPad::OnPaint, this);
|
||||||
}
|
manualRedrawMode = true;
|
||||||
|
}
|
||||||
|
|
||||||
// NOTE - there is yet another (and I think final) micro-optimization that can be done:
|
// NOTE - there is yet another (and I think final) micro-optimization that can be done:
|
||||||
// It can be assumed that if the element has already been drawn to the screen (and not cleared) that we can skip rendering it
|
// It can be assumed that if the element has already been drawn to the screen (and not cleared) that we can skip rendering it
|
||||||
//
|
//
|
||||||
// For example - you hold a single button for several frames, it will currently draw that every frame
|
// For example - you hold a single button for several frames, it will currently draw that every frame
|
||||||
// despite the screen never being cleared, this is not strictly necessary.
|
// despite the screen never being cleared - so this is not strictly necessary.
|
||||||
//
|
//
|
||||||
// After some tests, the performance impact is well within reason, and on the hardware renderer modes, is almost non-existant.
|
// Though after some tests, the performance impact is well within reason, and on the hardware renderer modes, is almost non-existant.
|
||||||
while (!renderQueue.empty()) {
|
while (!renderQueue.empty())
|
||||||
VirtualPadElement *element = renderQueue.front();
|
{
|
||||||
if (element)
|
VirtualPadElement* element = renderQueue.front();
|
||||||
|
if (element)
|
||||||
{
|
{
|
||||||
element->Render(bdc);
|
element->Render(bdc);
|
||||||
}
|
}
|
||||||
renderQueue.pop();
|
renderQueue.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VirtualPad::UpdateControllerData(u16 const bufIndex, PadData *padData)
|
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::enablePadElements(bool enable)
|
||||||
{
|
{
|
||||||
virtualPadData.circle.EnableWidgets(enable);
|
for (VirtualPadElement* virtualPadElement : virtualPadElements)
|
||||||
virtualPadData.cross.EnableWidgets(enable);
|
{
|
||||||
virtualPadData.square.EnableWidgets(enable);
|
virtualPadElement->EnableWidgets(enable);
|
||||||
virtualPadData.triangle.EnableWidgets(enable);
|
}
|
||||||
virtualPadData.down.EnableWidgets(enable);
|
|
||||||
virtualPadData.left.EnableWidgets(enable);
|
|
||||||
virtualPadData.right.EnableWidgets(enable);
|
|
||||||
virtualPadData.up.EnableWidgets(enable);
|
|
||||||
virtualPadData.l1.EnableWidgets(enable);
|
|
||||||
virtualPadData.l2.EnableWidgets(enable);
|
|
||||||
virtualPadData.r1.EnableWidgets(enable);
|
|
||||||
virtualPadData.r2.EnableWidgets(enable);
|
|
||||||
|
|
||||||
virtualPadData.select.EnableWidgets(enable);
|
|
||||||
virtualPadData.start.EnableWidgets(enable);
|
|
||||||
virtualPadData.l3.EnableWidgets(enable);
|
|
||||||
virtualPadData.r3.EnableWidgets(enable);
|
|
||||||
|
|
||||||
virtualPadData.leftAnalog.EnableWidgets(enable);
|
|
||||||
virtualPadData.rightAnalog.EnableWidgets(enable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::SetReadOnlyMode()
|
void VirtualPad::SetReadOnlyMode()
|
||||||
{
|
{
|
||||||
enablePadElements(false);
|
enablePadElements(false);
|
||||||
readOnlyMode = true;
|
readOnlyMode = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::ClearReadOnlyMode()
|
void VirtualPad::ClearReadOnlyMode()
|
||||||
{
|
{
|
||||||
enablePadElements(true);
|
enablePadElements(true);
|
||||||
readOnlyMode = false;
|
readOnlyMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnIgnoreRealController(wxCommandEvent const &event)
|
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::OnNormalButtonPress(wxCommandEvent &event)
|
|
||||||
{
|
|
||||||
const wxCheckBox* pressedButton = (wxCheckBox*) event.GetEventObject();
|
|
||||||
ControllerNormalButton *eventBtn = buttonElements[pressedButton->GetId()];
|
|
||||||
|
|
||||||
if (pressedButton)
|
|
||||||
{
|
|
||||||
eventBtn->pressed = pressedButton->GetValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!eventBtn->isControllerPressBypassed) {
|
|
||||||
eventBtn->isControllerPressBypassed = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent &event)
|
void VirtualPad::OnNormalButtonPress(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
const wxSpinCtrl* pressureSpinner = (wxSpinCtrl*) event.GetEventObject();
|
const wxCheckBox* pressedButton = (wxCheckBox*)event.GetEventObject();
|
||||||
ControllerPressureButton *eventBtn = pressureElements[pressureSpinner->GetId()];
|
ControllerNormalButton* eventBtn = buttonElements[pressedButton->GetId()];
|
||||||
|
|
||||||
|
if (pressedButton)
|
||||||
|
{
|
||||||
|
eventBtn->pressed = pressedButton->GetValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!eventBtn->isControllerPressBypassed)
|
||||||
|
{
|
||||||
|
eventBtn->isControllerPressBypassed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VirtualPad::OnPressureButtonPressureChange(wxCommandEvent& event)
|
||||||
|
{
|
||||||
|
const wxSpinCtrl* pressureSpinner = (wxSpinCtrl*)event.GetEventObject();
|
||||||
|
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)
|
||||||
|
{
|
||||||
eventBtn->isControllerPressureBypassed = true;
|
eventBtn->isControllerPressureBypassed = true;
|
||||||
eventBtn->isControllerPressBypassed = true;
|
eventBtn->isControllerPressBypassed = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::OnAnalogSpinnerChange(wxCommandEvent &event)
|
void VirtualPad::OnAnalogSpinnerChange(wxCommandEvent& event)
|
||||||
{
|
{
|
||||||
const wxSpinCtrl* analogSpinner = (wxSpinCtrl*) event.GetEventObject();
|
const wxSpinCtrl* analogSpinner = (wxSpinCtrl*)event.GetEventObject();
|
||||||
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)
|
||||||
{
|
{
|
||||||
const wxSlider* analogSlider = (wxSlider*) event.GetEventObject();
|
const wxSlider* analogSlider = (wxSlider*)event.GetEventObject();
|
||||||
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -338,28 +313,29 @@ wxPoint VirtualPad::ScaledPoint(wxPoint point, int widgetWidth, bool rightAligne
|
||||||
|
|
||||||
wxPoint VirtualPad::ScaledPoint(int x, int y, int widgetWidth, bool rightAligned)
|
wxPoint VirtualPad::ScaledPoint(int x, int y, int widgetWidth, bool rightAligned)
|
||||||
{
|
{
|
||||||
wxPoint scaledPoint = wxPoint(x * scalingFactor, y * scalingFactor);
|
wxPoint scaledPoint = wxPoint(x * scalingFactor, y * scalingFactor);
|
||||||
if (rightAligned) {
|
if (rightAligned)
|
||||||
scaledPoint.x -= widgetWidth * scalingFactor;
|
{
|
||||||
if (scaledPoint.x < 0)
|
scaledPoint.x -= widgetWidth * scalingFactor;
|
||||||
|
if (scaledPoint.x < 0)
|
||||||
{
|
{
|
||||||
scaledPoint.x = 0;
|
scaledPoint.x = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return scaledPoint;
|
return scaledPoint;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 point)
|
ImageFile VirtualPad::NewBitmap(wxImage resource, wxPoint imgCoord)
|
||||||
{
|
{
|
||||||
return NewBitmap(scalingFactor, resource, point);
|
return NewBitmap(scalingFactor, resource, imgCoord);
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageFile VirtualPad::NewBitmap(float scalingFactor, wxImage resource, wxPoint point)
|
ImageFile VirtualPad::NewBitmap(float scalingFactor, wxImage resource, wxPoint imgCoord)
|
||||||
{
|
{
|
||||||
wxBitmap bitmap = wxBitmap(resource.Rescale(resource.GetWidth() * scalingFactor, resource.GetHeight() * scalingFactor, wxIMAGE_QUALITY_HIGH));
|
wxBitmap bitmap = wxBitmap(resource.Rescale(resource.GetWidth() * scalingFactor, resource.GetHeight() * scalingFactor, wxIMAGE_QUALITY_HIGH));
|
||||||
|
|
||||||
|
@ -367,31 +343,33 @@ ImageFile VirtualPad::NewBitmap(float scalingFactor, wxImage resource, wxPoint p
|
||||||
image.image = bitmap;
|
image.image = bitmap;
|
||||||
image.width = bitmap.GetWidth();
|
image.width = bitmap.GetWidth();
|
||||||
image.height = bitmap.GetHeight();
|
image.height = bitmap.GetHeight();
|
||||||
image.coords = ScaledPoint(point);
|
image.coords = ScaledPoint(imgCoord);
|
||||||
return image;
|
return image;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::InitNormalButtonGuiElements(ControllerNormalButton &button, ImageFile image, wxWindow *parentWindow, wxPoint point)
|
void VirtualPad::InitNormalButtonGuiElements(ControllerNormalButton& button, ImageFile image, wxWindow* parentWindow, wxPoint checkboxCoord)
|
||||||
{
|
{
|
||||||
button.icon = image;
|
button.icon = image;
|
||||||
button.pressedBox = new wxCheckBox(parentWindow, wxID_ANY, wxEmptyString, ScaledPoint(point), wxDefaultSize);
|
button.pressedBox = new wxCheckBox(parentWindow, wxID_ANY, wxEmptyString, ScaledPoint(checkboxCoord), wxDefaultSize);
|
||||||
Bind(wxEVT_CHECKBOX, &VirtualPad::OnNormalButtonPress, this, button.pressedBox->GetId());
|
Bind(wxEVT_CHECKBOX, &VirtualPad::OnNormalButtonPress, this, button.pressedBox->GetId());
|
||||||
buttonElements[button.pressedBox->GetId()] = &button;
|
buttonElements[button.pressedBox->GetId()] = &button;
|
||||||
|
virtualPadElements.push_back(&button);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VirtualPad::InitPressureButtonGuiElements(ControllerPressureButton &button, ImageFile image, wxWindow *parentWindow, wxPoint point, bool rightAlignedPoint)
|
void VirtualPad::InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord)
|
||||||
{
|
{
|
||||||
const int spinnerWidth = 100;
|
const int spinnerWidth = 100;
|
||||||
const wxPoint scaledPoint = ScaledPoint(point.x, point.y, spinnerWidth, rightAlignedPoint);
|
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);
|
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;
|
||||||
Bind(wxEVT_SPINCTRL, &VirtualPad::OnPressureButtonPressureChange, this, button.pressureSpinner->GetId());
|
Bind(wxEVT_SPINCTRL, &VirtualPad::OnPressureButtonPressureChange, this, button.pressureSpinner->GetId());
|
||||||
pressureElements[button.pressureSpinner->GetId()] = &button;
|
pressureElements[button.pressureSpinner->GetId()] = &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);
|
||||||
|
@ -401,12 +379,12 @@ void VirtualPad::InitAnalogStickGuiElements(AnalogStick &analog, wxWindow *paren
|
||||||
|
|
||||||
const int spinnerWidth = 90;
|
const int spinnerWidth = 90;
|
||||||
const wxPoint xSpinnerScaledPoint = ScaledPoint(xSpinnerPoint, spinnerWidth, rightAlignedSpinners);
|
const wxPoint xSpinnerScaledPoint = ScaledPoint(xSpinnerPoint, spinnerWidth, rightAlignedSpinners);
|
||||||
const wxPoint ySpinnerScaledPoint = ScaledPoint(ySpinnerPoint, spinnerWidth, rightAlignedSpinners);
|
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, 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);
|
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* 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);
|
wxSpinCtrl* ySpinner = new wxSpinCtrl(parentWindow, wxID_ANY, wxEmptyString, ySpinnerScaledPoint, ScaledSize(90, wxDefaultSize.GetHeight()), wxSP_ARROW_KEYS, 0, 255, 127);
|
||||||
|
|
||||||
analog.xVector.slider = xSlider;
|
analog.xVector.slider = xSlider;
|
||||||
analog.yVector.slider = ySlider;
|
analog.yVector.slider = ySlider;
|
||||||
|
@ -415,10 +393,13 @@ void VirtualPad::InitAnalogStickGuiElements(AnalogStick &analog, wxWindow *paren
|
||||||
analog.positionGraphic = analogPos;
|
analog.positionGraphic = analogPos;
|
||||||
Bind(wxEVT_SLIDER, &VirtualPad::OnAnalogSliderChange, this, xSlider->GetId());
|
Bind(wxEVT_SLIDER, &VirtualPad::OnAnalogSliderChange, this, xSlider->GetId());
|
||||||
Bind(wxEVT_SLIDER, &VirtualPad::OnAnalogSliderChange, this, ySlider->GetId());
|
Bind(wxEVT_SLIDER, &VirtualPad::OnAnalogSliderChange, this, ySlider->GetId());
|
||||||
Bind(wxEVT_SPINCTRL, &VirtualPad::OnAnalogSpinnerChange, this, xSpinner->GetId());
|
Bind(wxEVT_SPINCTRL, &VirtualPad::OnAnalogSpinnerChange, this, xSpinner->GetId());
|
||||||
Bind(wxEVT_SPINCTRL, &VirtualPad::OnAnalogSpinnerChange, this, ySpinner->GetId());
|
Bind(wxEVT_SPINCTRL, &VirtualPad::OnAnalogSpinnerChange, this, ySpinner->GetId());
|
||||||
analogElements[xSlider->GetId()] = &analog.xVector;
|
analogElements[xSlider->GetId()] = &analog.xVector;
|
||||||
analogElements[ySlider->GetId()] = &analog.yVector;
|
analogElements[ySlider->GetId()] = &analog.yVector;
|
||||||
analogElements[xSpinner->GetId()] = &analog.xVector;
|
analogElements[xSpinner->GetId()] = &analog.xVector;
|
||||||
analogElements[ySpinner->GetId()] = &analog.yVector;
|
analogElements[ySpinner->GetId()] = &analog.yVector;
|
||||||
|
virtualPadElements.push_back(&analog);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
|
@ -34,65 +36,68 @@
|
||||||
class VirtualPad : public wxFrame
|
class VirtualPad : public wxFrame
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
VirtualPad(wxWindow *parent, wxWindowID id, const wxString& title, int controllerPort,
|
VirtualPad(wxWindow* parent, wxWindowID id, const wxString& title, int controllerPort,
|
||||||
const wxPoint &pos = wxDefaultPosition, const wxSize &size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE);
|
const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE);
|
||||||
// Updates the VirtualPad's data if necessary, as well as updates the provided PadData if the VirtualPad overrides it
|
// Updates the VirtualPad's data if necessary, as well as updates the provided PadData if the VirtualPad overrides it
|
||||||
// - 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 ReadOnly mode and disables GUI widgets
|
||||||
void SetReadOnlyMode();
|
void SetReadOnlyMode();
|
||||||
// Disables ReadOnly mode and re-enables GUI widgets
|
// Disables ReadOnly mode and re-enables GUI widgets
|
||||||
void ClearReadOnlyMode();
|
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:
|
||||||
bool clearScreenRequired = false;
|
bool clearScreenRequired = false;
|
||||||
bool ignoreRealController = false;
|
bool ignoreRealController = false;
|
||||||
// When enabled, forces the VirtualPad to be re-rendered even if no updates are made.
|
// When enabled, forces the VirtualPad to be re-rendered even if no updates are made.
|
||||||
// This helps to make sure the UI is rendered prior to receiving data from the controller
|
// This helps to make sure the UI is rendered prior to receiving data from the controller
|
||||||
bool manualRedrawMode = false;
|
bool manualRedrawMode = false;
|
||||||
bool readOnlyMode = false;
|
bool readOnlyMode = false;
|
||||||
|
|
||||||
VirtualPadData virtualPadData;
|
VirtualPadData virtualPadData;
|
||||||
|
|
||||||
std::queue<VirtualPadElement *> renderQueue;
|
std::vector<VirtualPadElement*> virtualPadElements;
|
||||||
|
std::queue<VirtualPadElement*> renderQueue;
|
||||||
|
|
||||||
void enablePadElements(bool enable);
|
void enablePadElements(bool enable);
|
||||||
|
|
||||||
/// GUI Elements
|
/// GUI Elements
|
||||||
wxCheckBox *ignoreRealControllerBox;
|
wxCheckBox* ignoreRealControllerBox;
|
||||||
|
|
||||||
std::map<wxWindowID, ControllerNormalButton *> buttonElements;
|
std::map<wxWindowID, ControllerNormalButton*> buttonElements;
|
||||||
std::map<wxWindowID, ControllerPressureButton *> pressureElements;
|
std::map<wxWindowID, ControllerPressureButton*> pressureElements;
|
||||||
std::map<wxWindowID, AnalogVector *> analogElements;
|
std::map<wxWindowID, AnalogVector*> analogElements;
|
||||||
|
|
||||||
/// Event Listeners
|
/// Event Listeners
|
||||||
void OnClose(wxCloseEvent &event);
|
void OnClose(wxCloseEvent& event);
|
||||||
void OnIconize(wxIconizeEvent &event);
|
void OnIconize(wxIconizeEvent& event);
|
||||||
void OnEraseBackground(wxEraseEvent &event);
|
void OnEraseBackground(wxEraseEvent& event);
|
||||||
void OnPaint(wxPaintEvent &event);
|
void OnPaint(wxPaintEvent& event);
|
||||||
void Render(wxDC &dc);
|
void Render(wxDC& dc);
|
||||||
|
|
||||||
void OnAnalogSliderChange(wxCommandEvent &event);
|
void OnAnalogSliderChange(wxCommandEvent& event);
|
||||||
void OnAnalogSpinnerChange(wxCommandEvent &event);
|
void OnAnalogSpinnerChange(wxCommandEvent& event);
|
||||||
void OnIgnoreRealController(wxCommandEvent const &event);
|
void OnIgnoreRealController(wxCommandEvent const& event);
|
||||||
void OnNormalButtonPress(wxCommandEvent &event);
|
void OnNormalButtonPress(wxCommandEvent& event);
|
||||||
void OnPressureButtonPressureChange(wxCommandEvent &event);
|
void OnPressureButtonPressureChange(wxCommandEvent& event);
|
||||||
|
|
||||||
/// GUI Creation Utility Functions
|
/// GUI Creation Utility Functions
|
||||||
float scalingFactor = 1.0;
|
float scalingFactor = 1.0;
|
||||||
|
|
||||||
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, int widgetWidth = 0, bool rightAligned = false);
|
||||||
wxPoint ScaledPoint(int x, int y, int widgetWidth = 0, bool rightAligned = false);
|
wxPoint ScaledPoint(int x, int y, int widgetWidth = 0, bool rightAligned = false);
|
||||||
|
|
||||||
ImageFile NewBitmap(wxImage resource, wxPoint point);
|
ImageFile NewBitmap(wxImage resource, wxPoint imgCoord);
|
||||||
ImageFile NewBitmap(float scalingFactor, wxImage resource, wxPoint point);
|
ImageFile NewBitmap(float scalingFactor, wxImage resource, wxPoint imgCoord);
|
||||||
|
|
||||||
void InitPressureButtonGuiElements(ControllerPressureButton &button, ImageFile image, wxWindow *parentWindow, wxPoint point, bool rightAlignedPoint = false);
|
void InitPressureButtonGuiElements(ControllerPressureButton& button, ImageFile image, wxWindow* parentWindow, wxPoint pressureSpinnerCoord, bool rightAlignedCoord = false);
|
||||||
void InitNormalButtonGuiElements(ControllerNormalButton &btn, ImageFile image, wxWindow *parentWindow, wxPoint point);
|
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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -19,64 +19,66 @@
|
||||||
|
|
||||||
#include "Recording/VirtualPad/VirtualPadData.h"
|
#include "Recording/VirtualPad/VirtualPadData.h"
|
||||||
|
|
||||||
bool VirtualPadData::UpdateVirtualPadData(u16 bufIndex, PadData *padData, bool ignoreRealController, bool readOnly)
|
bool VirtualPadData::UpdateVirtualPadData(u16 bufIndex, PadData* padData, bool ignoreRealController, bool readOnly)
|
||||||
{
|
{
|
||||||
bool changeDetected = false;
|
bool changeDetected = false;
|
||||||
PadData::BufferIndex index = static_cast<PadData::BufferIndex>(bufIndex);
|
PadData::BufferIndex index = static_cast<PadData::BufferIndex>(bufIndex);
|
||||||
switch (index)
|
switch (index)
|
||||||
{
|
{
|
||||||
case PadData::BufferIndex::PressedFlagsGroupOne:
|
case PadData::BufferIndex::PressedFlagsGroupOne:
|
||||||
changeDetected |= left.UpdateData(padData->leftPressed, ignoreRealController, readOnly);
|
changeDetected |= left.UpdateData(padData->leftPressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= down.UpdateData(padData->downPressed, ignoreRealController, readOnly);
|
changeDetected |= down.UpdateData(padData->downPressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= right.UpdateData(padData->rightPressed, ignoreRealController, readOnly);
|
changeDetected |= right.UpdateData(padData->rightPressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= up.UpdateData(padData->upPressed, ignoreRealController, readOnly);
|
changeDetected |= up.UpdateData(padData->upPressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= start.UpdateData(padData->start, ignoreRealController, readOnly);
|
changeDetected |= start.UpdateData(padData->start, ignoreRealController, readOnly);
|
||||||
changeDetected |= r3.UpdateData(padData->r3, ignoreRealController, readOnly);
|
changeDetected |= r3.UpdateData(padData->r3, ignoreRealController, readOnly);
|
||||||
changeDetected |= l3.UpdateData(padData->l3, ignoreRealController, readOnly);
|
changeDetected |= l3.UpdateData(padData->l3, ignoreRealController, readOnly);
|
||||||
changeDetected |= select.UpdateData(padData->select, ignoreRealController, readOnly);
|
changeDetected |= select.UpdateData(padData->select, ignoreRealController, readOnly);
|
||||||
return changeDetected;
|
return changeDetected;
|
||||||
case PadData::BufferIndex::PressedFlagsGroupTwo:
|
case PadData::BufferIndex::PressedFlagsGroupTwo:
|
||||||
changeDetected |= square.UpdateData(padData->squarePressed, ignoreRealController, readOnly);
|
changeDetected |= square.UpdateData(padData->squarePressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= cross.UpdateData(padData->crossPressed, ignoreRealController, readOnly);
|
changeDetected |= cross.UpdateData(padData->crossPressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= circle.UpdateData(padData->circlePressed, ignoreRealController, readOnly);
|
changeDetected |= circle.UpdateData(padData->circlePressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= triangle.UpdateData(padData->trianglePressed, ignoreRealController, readOnly);
|
changeDetected |= triangle.UpdateData(padData->trianglePressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= r1.UpdateData(padData->r1Pressed, ignoreRealController, readOnly);
|
changeDetected |= r1.UpdateData(padData->r1Pressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= l1.UpdateData(padData->l1Pressed, ignoreRealController, readOnly);
|
changeDetected |= l1.UpdateData(padData->l1Pressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= r2.UpdateData(padData->r2Pressed, ignoreRealController, readOnly);
|
changeDetected |= r2.UpdateData(padData->r2Pressed, ignoreRealController, readOnly);
|
||||||
changeDetected |= l2.UpdateData(padData->l2Pressed, ignoreRealController, readOnly);
|
changeDetected |= l2.UpdateData(padData->l2Pressed, ignoreRealController, readOnly);
|
||||||
return changeDetected;
|
return changeDetected;
|
||||||
case PadData::BufferIndex::RightAnalogXVector:
|
case PadData::BufferIndex::RightAnalogXVector:
|
||||||
return rightAnalog.xVector.UpdateData(padData->rightAnalogX, ignoreRealController, readOnly);
|
return rightAnalog.xVector.UpdateData(padData->rightAnalogX, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::RightAnalogYVector:
|
case PadData::BufferIndex::RightAnalogYVector:
|
||||||
return rightAnalog.yVector.UpdateData(padData->rightAnalogY, ignoreRealController, readOnly);
|
return rightAnalog.yVector.UpdateData(padData->rightAnalogY, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::LeftAnalogXVector:
|
case PadData::BufferIndex::LeftAnalogXVector:
|
||||||
return leftAnalog.xVector.UpdateData(padData->leftAnalogX, ignoreRealController, readOnly);
|
return leftAnalog.xVector.UpdateData(padData->leftAnalogX, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::LeftAnalogYVector:
|
case PadData::BufferIndex::LeftAnalogYVector:
|
||||||
return leftAnalog.yVector.UpdateData(padData->leftAnalogY, ignoreRealController, readOnly);
|
return leftAnalog.yVector.UpdateData(padData->leftAnalogY, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::RightPressure:
|
case PadData::BufferIndex::RightPressure:
|
||||||
return right.UpdateData(padData->rightPressure, ignoreRealController, readOnly);
|
return right.UpdateData(padData->rightPressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::LeftPressure:
|
case PadData::BufferIndex::LeftPressure:
|
||||||
return left.UpdateData(padData->leftPressure, ignoreRealController, readOnly);
|
return left.UpdateData(padData->leftPressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::UpPressure:
|
case PadData::BufferIndex::UpPressure:
|
||||||
return up.UpdateData(padData->upPressure, ignoreRealController, readOnly);
|
return up.UpdateData(padData->upPressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::DownPressure:
|
case PadData::BufferIndex::DownPressure:
|
||||||
return down.UpdateData(padData->downPressure, ignoreRealController, readOnly);
|
return down.UpdateData(padData->downPressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::TrianglePressure:
|
case PadData::BufferIndex::TrianglePressure:
|
||||||
return triangle.UpdateData(padData->trianglePressure, ignoreRealController, readOnly);
|
return triangle.UpdateData(padData->trianglePressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::CirclePressure:
|
case PadData::BufferIndex::CirclePressure:
|
||||||
return circle.UpdateData(padData->circlePressure, ignoreRealController, readOnly);
|
return circle.UpdateData(padData->circlePressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::CrossPressure:
|
case PadData::BufferIndex::CrossPressure:
|
||||||
return cross.UpdateData(padData->crossPressure, ignoreRealController, readOnly);
|
return cross.UpdateData(padData->crossPressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::SquarePressure:
|
case PadData::BufferIndex::SquarePressure:
|
||||||
return square.UpdateData(padData->squarePressure, ignoreRealController, readOnly);
|
return square.UpdateData(padData->squarePressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::L1Pressure:
|
case PadData::BufferIndex::L1Pressure:
|
||||||
return l1.UpdateData(padData->l1Pressure, ignoreRealController, readOnly);
|
return l1.UpdateData(padData->l1Pressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::R1Pressure:
|
case PadData::BufferIndex::R1Pressure:
|
||||||
return r1.UpdateData(padData->r1Pressure, ignoreRealController, readOnly);
|
return r1.UpdateData(padData->r1Pressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::L2Pressure:
|
case PadData::BufferIndex::L2Pressure:
|
||||||
return l2.UpdateData(padData->l2Pressure, ignoreRealController, readOnly);
|
return l2.UpdateData(padData->l2Pressure, ignoreRealController, readOnly);
|
||||||
case PadData::BufferIndex::R2Pressure:
|
case PadData::BufferIndex::R2Pressure:
|
||||||
return r2.UpdateData(padData->r2Pressure, ignoreRealController, readOnly);
|
return r2.UpdateData(padData->r2Pressure, ignoreRealController, readOnly);
|
||||||
}
|
}
|
||||||
return changeDetected;
|
return changeDetected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
#include "Pcsx2Types.h"
|
#include "Pcsx2Types.h"
|
||||||
|
|
||||||
#include "Recording/PadData.h"
|
#include "Recording/PadData.h"
|
||||||
|
@ -55,5 +57,7 @@ public:
|
||||||
// - If ignoreRealController is true (and readOnly is false) PadData will always be updated
|
// - If ignoreRealController is true (and readOnly is false) PadData will always be updated
|
||||||
// - else if the VirtualPad has overwritten the value, and the real controller has not changed since that moment in time
|
// - else if the VirtualPad has overwritten the value, and the real controller has not changed since that moment in time
|
||||||
// returns a boolean to indicate if it has updated the PadData
|
// returns a boolean to indicate if it has updated the PadData
|
||||||
bool UpdateVirtualPadData(u16 bufIndex, PadData *padData, bool ignoreRealController = false, bool readOnly = false);
|
bool UpdateVirtualPadData(u16 bufIndex, PadData* padData, bool ignoreRealController = false, bool readOnly = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -22,226 +22,245 @@
|
||||||
#include "Recording/VirtualPad/VirtualPadResources.h"
|
#include "Recording/VirtualPad/VirtualPadResources.h"
|
||||||
#include "Recording/PadData.h"
|
#include "Recording/PadData.h"
|
||||||
|
|
||||||
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
|
||||||
// As no other elements will trigger a clear
|
// As no other elements will trigger a clear
|
||||||
else if (button.currentlyRendered)
|
else if (button.currentlyRendered)
|
||||||
{
|
{
|
||||||
button.currentlyRendered = false;
|
button.currentlyRendered = false;
|
||||||
clearScreenRequired = true;
|
clearScreenRequired = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerPressureButton::UpdateGuiElement(std::queue<VirtualPadElement *> &renderQueue, bool &clearScreenRequired)
|
void ControllerPressureButton::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired)
|
||||||
{
|
{
|
||||||
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;
|
||||||
clearScreenRequired = true;
|
clearScreenRequired = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogStick::UpdateGuiElement(std::queue<VirtualPadElement *> &renderQueue, bool &clearScreenRequired)
|
void AnalogStick::UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired)
|
||||||
{
|
{
|
||||||
AnalogStick &analogStick = *this;
|
AnalogStick& analogStick = *this;
|
||||||
if (analogStick.xVector.widgetUpdateRequired)
|
if (analogStick.xVector.widgetUpdateRequired)
|
||||||
{
|
{
|
||||||
analogStick.xVector.slider->SetValue(analogStick.xVector.val);
|
analogStick.xVector.slider->SetValue(analogStick.xVector.val);
|
||||||
analogStick.xVector.spinner->SetValue(analogStick.xVector.val);
|
analogStick.xVector.spinner->SetValue(analogStick.xVector.val);
|
||||||
}
|
}
|
||||||
if (analogStick.yVector.widgetUpdateRequired)
|
if (analogStick.yVector.widgetUpdateRequired)
|
||||||
{
|
{
|
||||||
analogStick.yVector.slider->SetValue(analogStick.yVector.val);
|
analogStick.yVector.slider->SetValue(analogStick.yVector.val);
|
||||||
analogStick.yVector.spinner->SetValue(analogStick.yVector.val);
|
analogStick.yVector.spinner->SetValue(analogStick.yVector.val);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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)
|
||||||
|
{
|
||||||
|
analogStick.currentlyRendered = false;
|
||||||
|
clearScreenRequired = true;
|
||||||
}
|
}
|
||||||
else if (analogStick.currentlyRendered) {
|
|
||||||
analogStick.currentlyRendered = false;
|
|
||||||
clearScreenRequired = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerNormalButton::EnableWidgets(bool enable)
|
void ControllerNormalButton::EnableWidgets(bool enable)
|
||||||
{
|
{
|
||||||
ControllerNormalButton &button = *this;
|
ControllerNormalButton& button = *this;
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
button.pressedBox->Enable();
|
button.pressedBox->Enable();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
button.pressedBox->Disable();
|
button.pressedBox->Disable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerPressureButton::EnableWidgets(bool enable)
|
void ControllerPressureButton::EnableWidgets(bool enable)
|
||||||
{
|
{
|
||||||
ControllerPressureButton &button = *this;
|
ControllerPressureButton& button = *this;
|
||||||
if (enable) {
|
if (enable)
|
||||||
button.pressureSpinner->Enable();
|
{
|
||||||
} else {
|
button.pressureSpinner->Enable();
|
||||||
button.pressureSpinner->Disable();
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
button.pressureSpinner->Disable();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogStick::EnableWidgets(bool enable)
|
void AnalogStick::EnableWidgets(bool enable)
|
||||||
{
|
{
|
||||||
AnalogStick &analog = *this;
|
AnalogStick& analog = *this;
|
||||||
if (enable) {
|
if (enable)
|
||||||
analog.xVector.slider->Enable();
|
{
|
||||||
analog.yVector.slider->Enable();
|
analog.xVector.slider->Enable();
|
||||||
analog.xVector.spinner->Enable();
|
analog.yVector.slider->Enable();
|
||||||
analog.yVector.spinner->Enable();
|
analog.xVector.spinner->Enable();
|
||||||
} else {
|
analog.yVector.spinner->Enable();
|
||||||
analog.xVector.slider->Disable();
|
}
|
||||||
analog.yVector.slider->Disable();
|
else
|
||||||
analog.xVector.spinner->Disable();
|
{
|
||||||
analog.yVector.spinner->Disable();
|
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)
|
||||||
{
|
{
|
||||||
ControllerNormalButton &button = *this;
|
ControllerNormalButton& button = *this;
|
||||||
ImageFile &img = button.icon;
|
ImageFile& img = button.icon;
|
||||||
dc.DrawBitmap(img.image, img.coords, true);
|
dc.DrawBitmap(img.image, img.coords, true);
|
||||||
button.currentlyRendered = true;
|
button.currentlyRendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ControllerPressureButton::Render(wxDC &dc)
|
void ControllerPressureButton::Render(wxDC& dc)
|
||||||
{
|
{
|
||||||
ControllerPressureButton &button = *this;
|
ControllerPressureButton& button = *this;
|
||||||
ImageFile &img = button.icon;
|
ImageFile& img = button.icon;
|
||||||
dc.DrawBitmap(img.image, img.coords, true);
|
dc.DrawBitmap(img.image, img.coords, true);
|
||||||
button.currentlyRendered = true;
|
button.currentlyRendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AnalogStick::Render(wxDC &dc)
|
void AnalogStick::Render(wxDC& dc)
|
||||||
{
|
{
|
||||||
AnalogStick &analogStick = *this;
|
AnalogStick& analogStick = *this;
|
||||||
// Render graphic
|
// Render graphic
|
||||||
AnalogPosition analogPos = analogStick.positionGraphic;
|
AnalogPosition analogPos = analogStick.positionGraphic;
|
||||||
// Determine new end coordinates
|
// Determine new end coordinates
|
||||||
int newXCoord = analogPos.centerCoords.x + ((analogStick.xVector.val - 127) / 127.0) * analogPos.radius;
|
int newXCoord = analogPos.centerCoords.x + ((analogStick.xVector.val - 127) / 127.0) * analogPos.radius;
|
||||||
int newYCoord = analogPos.centerCoords.y + ((analogStick.yVector.val - 127) / 127.0) * analogPos.radius;
|
int newYCoord = analogPos.centerCoords.y + ((analogStick.yVector.val - 127) / 127.0) * analogPos.radius;
|
||||||
// We want to ensure the line segment length is capped at the defined radius
|
// We want to ensure the line segment length is capped at the defined radius
|
||||||
// NOTE - The conventional way to do this is using arctan2, but the analog values that come out
|
// NOTE - The conventional way to do this is using arctan2, but the analog values that come out
|
||||||
// of the Pad plugins in pcsx2 do not permit this, the coordinates returned do not define a circle.
|
// of the Pad plugins in pcsx2 do not permit this, the coordinates returned do not define a circle.
|
||||||
const float lengthOfLine = sqrt(pow(newXCoord - analogPos.centerCoords.x, 2) + pow(newYCoord - analogPos.centerCoords.y, 2));
|
const float lengthOfLine = sqrt(pow(newXCoord - analogPos.centerCoords.x, 2) + pow(newYCoord - analogPos.centerCoords.y, 2));
|
||||||
if (lengthOfLine > analogPos.radius) {
|
if (lengthOfLine > analogPos.radius)
|
||||||
newXCoord = ((1 - analogPos.radius / lengthOfLine) * analogPos.centerCoords.x) + analogPos.radius / lengthOfLine * newXCoord;
|
{
|
||||||
newYCoord = ((1 - analogPos.radius / lengthOfLine) * analogPos.centerCoords.y) + analogPos.radius / lengthOfLine * newYCoord;
|
newXCoord = ((1 - analogPos.radius / lengthOfLine) * analogPos.centerCoords.x) + analogPos.radius / lengthOfLine * newXCoord;
|
||||||
}
|
newYCoord = ((1 - analogPos.radius / lengthOfLine) * analogPos.centerCoords.y) + analogPos.radius / lengthOfLine * newYCoord;
|
||||||
// Set the new end coordinate
|
}
|
||||||
analogPos.endCoords = wxPoint(newXCoord, newYCoord);
|
// Set the new end coordinate
|
||||||
// Draw line and tip
|
analogPos.endCoords = wxPoint(newXCoord, newYCoord);
|
||||||
dc.SetPen(wxPen(*wxBLUE, analogPos.lineThickness));
|
// Draw line and tip
|
||||||
dc.DrawLine(analogPos.centerCoords, analogPos.endCoords);
|
dc.SetPen(wxPen(*wxBLUE, analogPos.lineThickness));
|
||||||
dc.DrawCircle(analogPos.endCoords, wxCoord(analogPos.lineThickness));
|
dc.DrawLine(analogPos.centerCoords, analogPos.endCoords);
|
||||||
dc.SetPen(wxNullPen);
|
dc.DrawCircle(analogPos.endCoords, wxCoord(analogPos.lineThickness));
|
||||||
analogStick.currentlyRendered = true;
|
dc.SetPen(wxNullPen);
|
||||||
|
analogStick.currentlyRendered = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ControllerPressureButton::UpdateData(bool &padDataVal, bool ignoreRealController, bool readOnly)
|
bool ControllerPressureButton::UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly)
|
||||||
{
|
{
|
||||||
return this->UpdateButtonData(padDataVal, ignoreRealController, readOnly);
|
return this->UpdateButtonData(padDataVal, ignoreRealController, readOnly);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ControllerButton::UpdateButtonData(bool &padDataVal, bool ignoreRealController, bool readOnly)
|
bool ControllerButton::UpdateButtonData(bool& padDataVal, bool ignoreRealController, bool readOnly)
|
||||||
{
|
{
|
||||||
ControllerButton &button = *this;
|
ControllerButton& button = *this;
|
||||||
if (!ignoreRealController || readOnly) {
|
if (!ignoreRealController || readOnly)
|
||||||
// If controller is being bypassed and controller's state has changed
|
{
|
||||||
const bool bypassedWithChangedState = button.isControllerPressBypassed && padDataVal != button.prevPressedVal;
|
// If controller is being bypassed and controller's state has changed
|
||||||
if (bypassedWithChangedState) {
|
const bool bypassedWithChangedState = button.isControllerPressBypassed && padDataVal != button.prevPressedVal;
|
||||||
button.prevPressedVal = padDataVal;
|
if (bypassedWithChangedState)
|
||||||
button.isControllerPressBypassed = false;
|
{
|
||||||
}
|
button.prevPressedVal = padDataVal;
|
||||||
// If we aren't bypassing the controller OR the previous condition was met
|
button.isControllerPressBypassed = false;
|
||||||
if (bypassedWithChangedState || !button.isControllerPressBypassed || readOnly) {
|
}
|
||||||
button.widgetUpdateRequired = button.pressed != padDataVal;
|
// If we aren't bypassing the controller OR the previous condition was met
|
||||||
button.pressed = padDataVal;
|
if (bypassedWithChangedState || !button.isControllerPressBypassed || readOnly)
|
||||||
return false;
|
{
|
||||||
}
|
button.widgetUpdateRequired = button.pressed != padDataVal;
|
||||||
}
|
button.pressed = padDataVal;
|
||||||
// Otherwise, we update the real PadData value, which will in turn be used to update the interrupt's buffer
|
return false;
|
||||||
button.prevPressedVal = padDataVal;
|
}
|
||||||
padDataVal = button.pressed;
|
}
|
||||||
return button.prevPressedVal != button.pressed;
|
// Otherwise, we update the real PadData value, which will in turn be used to update the interrupt's buffer
|
||||||
|
button.prevPressedVal = padDataVal;
|
||||||
|
padDataVal = button.pressed;
|
||||||
|
return button.prevPressedVal != button.pressed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ControllerPressureButton::UpdateData(u8 &padDataVal, bool ignoreRealController, bool readOnly)
|
bool ControllerPressureButton::UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly)
|
||||||
{
|
{
|
||||||
ControllerPressureButton &button = *this;
|
ControllerPressureButton& button = *this;
|
||||||
if (!ignoreRealController || readOnly) {
|
if (!ignoreRealController || readOnly)
|
||||||
const bool bypassedWithChangedState = button.isControllerPressureBypassed && padDataVal != button.prevPressureVal;
|
{
|
||||||
if (bypassedWithChangedState) {
|
const bool bypassedWithChangedState = button.isControllerPressureBypassed && padDataVal != button.prevPressureVal;
|
||||||
button.prevPressureVal = padDataVal;
|
if (bypassedWithChangedState)
|
||||||
button.isControllerPressureBypassed = false;
|
{
|
||||||
}
|
button.prevPressureVal = padDataVal;
|
||||||
if (bypassedWithChangedState || !button.isControllerPressureBypassed || readOnly) {
|
button.isControllerPressureBypassed = false;
|
||||||
button.widgetUpdateRequired = button.pressure != padDataVal;
|
}
|
||||||
button.pressure = padDataVal;
|
if (bypassedWithChangedState || !button.isControllerPressureBypassed || readOnly)
|
||||||
return false;
|
{
|
||||||
}
|
button.widgetUpdateRequired = button.pressure != padDataVal;
|
||||||
}
|
button.pressure = padDataVal;
|
||||||
button.prevPressureVal = padDataVal;
|
return false;
|
||||||
padDataVal = button.pressure;
|
}
|
||||||
return button.prevPressureVal != button.pressure;
|
}
|
||||||
|
button.prevPressureVal = padDataVal;
|
||||||
|
padDataVal = button.pressure;
|
||||||
|
return button.prevPressureVal != button.pressure;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AnalogVector::UpdateData(u8 &padDataVal, bool ignoreRealController, bool readOnly)
|
bool AnalogVector::UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly)
|
||||||
{
|
{
|
||||||
AnalogVector &vector = *this;
|
AnalogVector& vector = *this;
|
||||||
if (!ignoreRealController || readOnly) {
|
if (!ignoreRealController || readOnly)
|
||||||
const bool bypassedWithChangedState = vector.isControllerBypassed && padDataVal != vector.prevVal;
|
{
|
||||||
if (bypassedWithChangedState) {
|
const bool bypassedWithChangedState = vector.isControllerBypassed && padDataVal != vector.prevVal;
|
||||||
vector.prevVal = padDataVal;
|
if (bypassedWithChangedState)
|
||||||
vector.isControllerBypassed = false;
|
{
|
||||||
}
|
vector.prevVal = padDataVal;
|
||||||
if (bypassedWithChangedState || !vector.isControllerBypassed || readOnly) {
|
vector.isControllerBypassed = false;
|
||||||
vector.widgetUpdateRequired = vector.val != padDataVal;
|
}
|
||||||
vector.val = padDataVal;
|
if (bypassedWithChangedState || !vector.isControllerBypassed || readOnly)
|
||||||
return false;
|
{
|
||||||
}
|
vector.widgetUpdateRequired = vector.val != padDataVal;
|
||||||
}
|
vector.val = padDataVal;
|
||||||
vector.prevVal = padDataVal;
|
return false;
|
||||||
padDataVal = vector.val;
|
}
|
||||||
return vector.prevVal != vector.val;
|
}
|
||||||
|
vector.prevVal = padDataVal;
|
||||||
|
padDataVal = vector.val;
|
||||||
|
return vector.prevVal != vector.val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifndef DISABLE_RECORDING
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
|
||||||
#include "Pcsx2Types.h"
|
#include "Pcsx2Types.h"
|
||||||
|
@ -34,16 +36,16 @@ struct ImageFile
|
||||||
|
|
||||||
struct AnalogVector
|
struct AnalogVector
|
||||||
{
|
{
|
||||||
wxSlider *slider = 0;
|
wxSlider* slider = 0;
|
||||||
wxSpinCtrl *spinner = 0;
|
wxSpinCtrl* spinner = 0;
|
||||||
|
|
||||||
u8 val = 127;
|
u8 val = 127;
|
||||||
|
|
||||||
bool isControllerBypassed = false;
|
bool isControllerBypassed = false;
|
||||||
bool widgetUpdateRequired = false;
|
bool widgetUpdateRequired = false;
|
||||||
u8 prevVal = 127;
|
u8 prevVal = 127;
|
||||||
|
|
||||||
bool UpdateData(u8 &padDataVal, bool ignoreRealController, bool readOnly);
|
bool UpdateData(u8& padDataVal, bool ignoreRealController, bool readOnly);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,52 +61,52 @@ struct AnalogPosition
|
||||||
class VirtualPadElement
|
class VirtualPadElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool currentlyRendered = false;
|
bool currentlyRendered = false;
|
||||||
|
|
||||||
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 UpdateGuiElement(std::queue<VirtualPadElement *> &renderQueue, bool &clearScreenRequired) = 0;
|
virtual void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ControllerButton
|
class ControllerButton
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool isControllerPressBypassed = false;
|
bool isControllerPressBypassed = false;
|
||||||
bool pressed = false;
|
bool pressed = false;
|
||||||
bool prevPressedVal = false;
|
bool prevPressedVal = false;
|
||||||
bool widgetUpdateRequired = false;
|
bool widgetUpdateRequired = false;
|
||||||
|
|
||||||
bool UpdateButtonData(bool &padDataVal, bool ignoreRealController, bool readOnly);
|
bool UpdateButtonData(bool& padDataVal, bool ignoreRealController, bool readOnly);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ControllerNormalButton : public ControllerButton, public VirtualPadElement
|
class ControllerNormalButton : public ControllerButton, public VirtualPadElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageFile icon;
|
ImageFile icon;
|
||||||
wxCheckBox *pressedBox = 0;
|
wxCheckBox* pressedBox = 0;
|
||||||
|
|
||||||
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 UpdateGuiElement(std::queue<VirtualPadElement *> &renderQueue, bool &clearScreenRequired) override;
|
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ControllerPressureButton : public ControllerButton, public VirtualPadElement
|
class ControllerPressureButton : public ControllerButton, public VirtualPadElement
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ImageFile icon;
|
ImageFile icon;
|
||||||
wxSpinCtrl *pressureSpinner = 0;
|
wxSpinCtrl* pressureSpinner = 0;
|
||||||
|
|
||||||
u8 pressure = 0;
|
u8 pressure = 0;
|
||||||
|
|
||||||
bool isControllerPressureBypassed = false;
|
bool isControllerPressureBypassed = false;
|
||||||
u8 prevPressureVal = 0;
|
u8 prevPressureVal = 0;
|
||||||
|
|
||||||
bool UpdateData(bool &padDataVal, bool ignoreRealController, bool readOnly);
|
bool UpdateData(bool& padDataVal, bool ignoreRealController, bool readOnly);
|
||||||
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 UpdateGuiElement(std::queue<VirtualPadElement *> &renderQueue, bool &clearScreenRequired) override;
|
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AnalogStick : public VirtualPadElement
|
class AnalogStick : public VirtualPadElement
|
||||||
|
@ -115,7 +117,9 @@ public:
|
||||||
|
|
||||||
AnalogPosition positionGraphic;
|
AnalogPosition positionGraphic;
|
||||||
|
|
||||||
void EnableWidgets(bool enable) override;
|
void EnableWidgets(bool enable) override;
|
||||||
void Render(wxDC &dc) override;
|
void Render(wxDC& dc) override;
|
||||||
void UpdateGuiElement(std::queue<VirtualPadElement *> &renderQueue, bool &clearScreenRequired) override;
|
void UpdateGuiElement(std::queue<VirtualPadElement*>& renderQueue, bool& clearScreenRequired) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
*.h
|
|
@ -0,0 +1,18 @@
|
||||||
|
|
||||||
|
:: Probably self-explanatory: This batch file compiles a single souce image into a
|
||||||
|
:: CPP header file for use by pcsx2.
|
||||||
|
::
|
||||||
|
:: bin2cpp.cmd SrcImage
|
||||||
|
::
|
||||||
|
:: Parameters
|
||||||
|
:: SrcImage - Complete filename with extension.
|
||||||
|
::
|
||||||
|
|
||||||
|
@echo off
|
||||||
|
|
||||||
|
SETLOCAL ENABLEEXTENSIONS
|
||||||
|
|
||||||
|
cd "%~0\..\"
|
||||||
|
"..\..\..\..\tools\bin\bin2cpp.exe" %1
|
||||||
|
|
||||||
|
ENDLOCAL
|
|
@ -1,12 +0,0 @@
|
||||||
# ----
|
|
||||||
# Runs all *.png files in the current directory
|
|
||||||
# through tools/bin/bin2cpp.exe
|
|
||||||
# which creates a header file with the image data to be used
|
|
||||||
# with wxWidgets (wxBitmap / wxImage specifically)
|
|
||||||
# ----
|
|
||||||
|
|
||||||
$files = Get-ChildItem -Path $PSScriptRoot -Filter *.png
|
|
||||||
|
|
||||||
foreach ($f in $files ) {
|
|
||||||
..\..\..\..\tools\bin\bin2cpp.exe $f.Name
|
|
||||||
}
|
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 7.4 KiB |
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 121 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 699 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 625 B After Width: | Height: | Size: 836 B |
Before Width: | Height: | Size: 844 B After Width: | Height: | Size: 1017 B |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 663 B After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 639 B After Width: | Height: | Size: 1.0 KiB |
Before Width: | Height: | Size: 854 B After Width: | Height: | Size: 1.2 KiB |
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 694 B After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 168 B After Width: | Height: | Size: 302 B |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 4.1 KiB |
Before Width: | Height: | Size: 676 B After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 4.5 KiB |
Before Width: | Height: | Size: 694 B After Width: | Height: | Size: 1.6 KiB |
|
@ -79,11 +79,11 @@ void Pcsx2App::OpenMainFrame()
|
||||||
|
|
||||||
#ifndef DISABLE_RECORDING
|
#ifndef DISABLE_RECORDING
|
||||||
VirtualPad* virtualPad0 = new VirtualPad(mainFrame, wxID_ANY, wxEmptyString, 0);
|
VirtualPad* virtualPad0 = new VirtualPad(mainFrame, wxID_ANY, wxEmptyString, 0);
|
||||||
g_inputRecording.setVirtualPadPtr(virtualPad0, 0);
|
g_InputRecording.setVirtualPadPtr(virtualPad0, 0);
|
||||||
m_id_VirtualPad[0] = virtualPad0->GetId();
|
m_id_VirtualPad[0] = virtualPad0->GetId();
|
||||||
|
|
||||||
VirtualPad *virtualPad1 = new VirtualPad(mainFrame, wxID_ANY, wxEmptyString, 1);
|
VirtualPad *virtualPad1 = new VirtualPad(mainFrame, wxID_ANY, wxEmptyString, 1);
|
||||||
g_inputRecording.setVirtualPadPtr(virtualPad1, 1);
|
g_InputRecording.setVirtualPadPtr(virtualPad1, 1);
|
||||||
m_id_VirtualPad[1] = virtualPad1->GetId();
|
m_id_VirtualPad[1] = virtualPad1->GetId();
|
||||||
|
|
||||||
NewRecordingFrame* newRecordingFrame = new NewRecordingFrame(mainFrame);
|
NewRecordingFrame* newRecordingFrame = new NewRecordingFrame(mainFrame);
|
||||||
|
|
|
@ -144,6 +144,75 @@
|
||||||
<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>
|
||||||
|
<!-- Generate Recording GUI Image Headers -->
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\controller.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\circlePressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\crossPressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\downPressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\l1Pressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\l2Pressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\l3Pressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\leftPressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\r1Pressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\r2Pressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\r3Pressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\rightPressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\selectPressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\squarePressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\startPressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\trianglePressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="..\..\Recording\VirtualPad\img\upPressed.png">
|
||||||
|
<Command>cmd.exe /c %(RelativeDir)bin2cpp.cmd %(Filename)%(Extension)</Command>
|
||||||
|
<Outputs>%(RelativeDir)%(Filename).h</Outputs>
|
||||||
|
</CustomBuild>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\CDVD\BlockdumpFileReader.cpp" />
|
<ClCompile Include="..\..\CDVD\BlockdumpFileReader.cpp" />
|
||||||
|
|