Skip to content

Commit

Permalink
Optimize KeyReplayManager
Browse files Browse the repository at this point in the history
  • Loading branch information
Natashi committed May 1, 2024
1 parent 98308d6 commit caa7714
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 72 deletions.
147 changes: 87 additions & 60 deletions source/GcLib/directx/DirectInput.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ HRESULT DirectInput::InputDeviceHeader::QueryHidPath() {
if (pDevice == nullptr)
return E_FAIL;

DIPROPGUIDANDPATH dip;
DIPROPGUIDANDPATH dip{};
dip.diph.dwSize = sizeof(dip);
dip.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dip.diph.dwObj = 0;
Expand All @@ -107,7 +107,7 @@ HRESULT DirectInput::InputDeviceHeader::QueryVidPid() {
if (pDevice == nullptr)
return E_FAIL;

DIPROPDWORD dip;
DIPROPDWORD dip{};
dip.diph.dwSize = sizeof(dip);
dip.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dip.diph.dwObj = 0;
Expand Down Expand Up @@ -239,7 +239,7 @@ BOOL DirectInput::_GetJoypadCallback(LPDIDEVICEINSTANCE lpddi) {

{
{
DIPROPRANGE diprg;
DIPROPRANGE diprg{};
diprg.diph.dwSize = sizeof(DIPROPRANGE);
diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER);
diprg.diph.dwObj = 0;
Expand All @@ -252,7 +252,7 @@ BOOL DirectInput::_GetJoypadCallback(LPDIDEVICEINSTANCE lpddi) {
}

{
DIPROPDWORD dipdw;
DIPROPDWORD dipdw{};
dipdw.diph.dwSize = sizeof(DIPROPDWORD);
dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER);
dipdw.diph.dwObj = 0;
Expand Down Expand Up @@ -514,15 +514,15 @@ VirtualKeyManager::~VirtualKeyManager() {

void VirtualKeyManager::Update() {
DirectInput::Update();
for (auto itr = mapKey_.begin(); itr != mapKey_.end(); ++itr) {
DIKeyState state = _GetVirtualKeyState(itr->first);
itr->second->SetKeyState(state);
for (auto& [id, vk] : mapKey_) {
DIKeyState state = _GetVirtualKeyState(id);
vk->SetKeyState(state);
}
}
void VirtualKeyManager::ClearKeyState() {
DirectInput::ResetInputState();
for (auto itr = mapKey_.begin(); itr != mapKey_.end(); ++itr) {
itr->second->SetKeyState(KEY_FREE);
for (auto& [id, vk] : mapKey_) {
vk->SetKeyState(KEY_FREE);
}
}
DIKeyState VirtualKeyManager::_GetVirtualKeyState(int16_t id) {
Expand Down Expand Up @@ -555,16 +555,12 @@ ref_count_ptr<VirtualKey> VirtualKeyManager::GetVirtualKey(int16_t id) {
if (itrFind == mapKey_.end()) return nullptr;
return itrFind->second;
}
bool VirtualKeyManager::IsTargetKeyCode(int16_t key) {
bool res = false;
for (auto itr = mapKey_.begin(); itr != mapKey_.end(); ++itr) {
ref_count_ptr<VirtualKey> vKey = itr->second;
if (key == vKey->GetKeyCode()) {
res = true;
break;
}
bool VirtualKeyManager::IsTargetKeyCode(int16_t keyCode) {
for (auto& [_, key] : mapKey_) {
if (keyCode == key->GetKeyCode())
return true;
}
return res;
return false;
}

#if defined(DNH_PROJ_EXECUTOR)
Expand All @@ -576,63 +572,88 @@ KeyReplayManager::KeyReplayManager(VirtualKeyManager* input) {
input_ = input;
state_ = STATE_RECORD;
}
KeyReplayManager::~KeyReplayManager() {}

void KeyReplayManager::_AddData(ReplayData&& data) {
auto itrFind = mapReplayData_.find(data.frame);
if (itrFind != mapReplayData_.end()) {
itrFind->second.push_back(MOVE(data));
}
else {
std::vector<ReplayData> listData;
listData.push_back(MOVE(data));

mapReplayData_.insert({ data.frame, listData });
}
}

void KeyReplayManager::AddTarget(int16_t key) {
mapKeyTarget_[key] = KEY_FREE;
}

void KeyReplayManager::Update() {
if (state_ == STATE_RECORD) {
for (auto itrTarget = mapKeyTarget_.begin(); itrTarget != mapKeyTarget_.end(); ++itrTarget) {
int16_t idKey = itrTarget->first;
DIKeyState keyState = input_->GetVirtualKeyState(idKey);

if (frame_ == 0 || itrTarget->second != keyState) {
ReplayData data;
data.id_ = idKey;
data.frame_ = frame_;
data.state_ = keyState;
listReplayData_.push_back(data);
if (frame_ == 0) {
// In the first frame, store initial states of all keys

for (auto& [idKey, state] : mapKeyTarget_) {
// Read actual state
state = input_->GetVirtualKeyState(idKey);

ReplayData data = {
idKey, frame_, state
};
_AddData(MOVE(data));
}
}
else {
// Record state changes

for (auto& [idKey, oldState] : mapKeyTarget_) {
DIKeyState currentState = input_->GetVirtualKeyState(idKey);

if (currentState != oldState) {
ReplayData data = {
idKey, frame_, currentState
};
_AddData(MOVE(data));

itrTarget->second = keyState;
oldState = currentState;
}
}
}
}
else if (state_ == STATE_REPLAY) {
if (frame_ == 0) replayDataIterator_ = listReplayData_.begin();
for (auto itrTarget = mapKeyTarget_.begin(); itrTarget != mapKeyTarget_.end(); ++itrTarget) {
int16_t idKey = itrTarget->first;
DIKeyState& stateKey = itrTarget->second;

for (auto itrData = replayDataIterator_; itrData != listReplayData_.end(); ++itrData) {
ReplayData& data = *itrData;
if (data.frame_ > frame_) break;

if (idKey == data.id_ && data.frame_ == frame_) {
stateKey = data.state_;
++replayDataIterator_;
}
// Load state changes for the current frame (if one exists)
auto itrCurrentFrame = mapReplayData_.find(frame_);
if (itrCurrentFrame != mapReplayData_.end()) {
auto& [_, listData] = *itrCurrentFrame;

for (auto& keyData : listData) {
mapKeyTarget_[keyData.id] = keyData.state;
}

ref_count_ptr<VirtualKey> key = input_->GetVirtualKey(idKey);
key->SetKeyState(stateKey);
//mapReplayData_.erase(itrCurrentFrame);
}

if (frame_ % 600 == 0)
listReplayData_.erase(listReplayData_.begin(), replayDataIterator_);
// Apply the current replay key state (overwriting existing realtime key data)
for (auto& [idKey, state] : mapKeyTarget_) {
auto vk = input_->GetVirtualKey(idKey);
vk->SetKeyState(state);
}
}

++frame_;
}

bool KeyReplayManager::IsTargetKeyCode(int16_t key) {
bool res = false;
for (auto itrTarget = mapKeyTarget_.begin(); itrTarget != mapKeyTarget_.end(); ++itrTarget) {
ref_count_ptr<VirtualKey> vKey = input_->GetVirtualKey(itrTarget->first);
if (key == vKey->GetKeyCode()) {
res = true;
break;
}
for (auto& [idKey, state] : mapKeyTarget_) {
ref_count_ptr<VirtualKey> vKey = input_->GetVirtualKey(idKey);
if (key == vKey->GetKeyCode())
return true;
}
return res;
return false;
}

void KeyReplayManager::ReadRecord(RecordBuffer& record) {
if (auto data = record.GetRecordAs<uint32_t>("count")) {
auto countReplayData = *data;
Expand All @@ -644,19 +665,25 @@ void KeyReplayManager::ReadRecord(RecordBuffer& record) {
for (size_t iRec = 0; iRec < countReplayData; ++iRec) {
ReplayData data{};
buffer.Read(&data, sizeof(ReplayData));
listReplayData_.push_back(data);

_AddData(MOVE(data));
}
}
}
void KeyReplayManager::WriteRecord(RecordBuffer& record) {
record.SetRecord<uint32_t>("count", listReplayData_.size());
// Flatten frames data from map
std::vector<ReplayData> listDataFlatten;
for (auto& [_, listData] : mapReplayData_) {
listDataFlatten.insert(listDataFlatten.end(), listData.begin(), listData.end());
};

record.SetRecord<uint32_t>("count", listDataFlatten.size());

ByteBuffer buffer;
for (auto itrData = listReplayData_.begin(); itrData != listReplayData_.end(); ++itrData) {
ReplayData& data = *itrData;
for (auto& data : listDataFlatten) {
buffer.Write(&data, sizeof(ReplayData));
}
record.SetRecord("data", buffer.GetPointer(), buffer.GetSize());
}

#endif
#endif
16 changes: 9 additions & 7 deletions source/GcLib/directx/DirectInput.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,23 +204,25 @@ namespace directx {
protected:
#pragma pack(push, 2)
struct ReplayData {
int16_t id_;
uint32_t frame_;
DIKeyState state_;
int16_t id;
uint32_t frame;
DIKeyState state;
};
#pragma pack(pop)

int state_;
uint32_t frame_;

std::list<ReplayData>::iterator replayDataIterator_;

std::map<int16_t, DIKeyState> mapKeyTarget_;

std::list<ReplayData> listReplayData_;
std::map<uint32_t, std::vector<ReplayData>> mapReplayData_;

VirtualKeyManager* input_;
private:
void _AddData(ReplayData&& data);
public:
KeyReplayManager(VirtualKeyManager* input);
virtual ~KeyReplayManager();
virtual ~KeyReplayManager() {}

void SetManageState(int state) { state_ = state; }
void AddTarget(int16_t key);
Expand Down
11 changes: 6 additions & 5 deletions source/TouhouDanmakufu/Common/StgStageController.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ void StgStageController::Initialize(ref_count_ptr<StgStageStartData> startData)
infoStage_->SetReplay(replayStageData != nullptr);

{
int replayState = infoStage_->IsReplay() ? KeyReplayManager::STATE_REPLAY : KeyReplayManager::STATE_RECORD;
int replayState = infoStage_->IsReplay() ?
KeyReplayManager::STATE_REPLAY :
KeyReplayManager::STATE_RECORD;

keyReplayManager_.reset(new KeyReplayManager(EDirectInput::GetInstance()));
keyReplayManager_->SetManageState(replayState);
Expand All @@ -52,10 +54,9 @@ void StgStageController::Initialize(ref_count_ptr<StgStageStartData> startData)
keyReplayManager_->AddTarget(EDirectInput::KEY_OK);
keyReplayManager_->AddTarget(EDirectInput::KEY_CANCEL);

std::set<int16_t> listReplayTargetKey = infoSystem_->GetReplayTargetKeyList();
for (auto itrKey = listReplayTargetKey.begin(); itrKey != listReplayTargetKey.end(); itrKey++) {
int16_t id = *itrKey;
keyReplayManager_->AddTarget(id);
auto& listReplayTargetKey = infoSystem_->GetReplayTargetKeyList();
for (auto& key : listReplayTargetKey) {
keyReplayManager_->AddTarget(key);
}

if (replayStageData == nullptr)
Expand Down

0 comments on commit caa7714

Please sign in to comment.