|
|
|
@ -5,6 +5,7 @@ |
|
|
|
|
namespace olc |
|
|
|
|
{ |
|
|
|
|
enum class InputType{ |
|
|
|
|
NONE, |
|
|
|
|
KEY, |
|
|
|
|
MOUSE, |
|
|
|
|
MOUSE_MOVE, |
|
|
|
@ -18,10 +19,14 @@ namespace olc |
|
|
|
|
float delay; |
|
|
|
|
vi2d mousePos; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
Input(int32_t key,bool press,InputType type,float delay); |
|
|
|
|
Input(int32_t key,bool press,InputType type,float delay,vi2d mousePos); //MOUSE_MOVE
|
|
|
|
|
friend std::ostream&operator<<(std::ostream&os,const Input&rhs){os<<"Input(Key="<<rhs.key<<",Press="<<rhs.press<<",Type="<<int(rhs.type)<<",Delay="<<rhs.delay<<",MousePos="<<rhs.mousePos;return os;}; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
Input(Key k); |
|
|
|
|
Input(int mouseButton); |
|
|
|
|
Input(InputType type); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Recording{ |
|
|
|
@ -30,14 +35,16 @@ namespace olc |
|
|
|
|
std::vector<Input>inputs; |
|
|
|
|
float lastKeyTime; |
|
|
|
|
vi2d prevMousePos; |
|
|
|
|
float waitTime; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class ReplayFile{ |
|
|
|
|
friend class Replay; |
|
|
|
|
std::string filename; |
|
|
|
|
std::vector<Input>inputs; |
|
|
|
|
float accTime; |
|
|
|
|
float nextKeyTime; |
|
|
|
|
double accTime; |
|
|
|
|
double nextKeyTime; |
|
|
|
|
size_t currentKeyInd; |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class Replay : public olc::PGEX |
|
|
|
@ -46,6 +53,13 @@ namespace olc |
|
|
|
|
bool isReplaying=false; |
|
|
|
|
Recording currentRecording; |
|
|
|
|
ReplayFile currentReplay; |
|
|
|
|
std::vector<Input>ignoredInputs; |
|
|
|
|
HWButton pKeyboardState[256] = { 0 }; |
|
|
|
|
HWButton pMouseState[nMouseButtons] = { 0 }; |
|
|
|
|
vi2d vMousePos = {0,0}; |
|
|
|
|
int32_t nMouseWheelDelta = 0; |
|
|
|
|
|
|
|
|
|
void ResetStates(); |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
Replay(); |
|
|
|
@ -55,6 +69,14 @@ namespace olc |
|
|
|
|
void StartReplay(const std::string filename); |
|
|
|
|
void StopReplay(); |
|
|
|
|
|
|
|
|
|
bool RecordingIsActive(); |
|
|
|
|
bool ReplayIsActive(); |
|
|
|
|
|
|
|
|
|
HWButton GetKey(Key k); |
|
|
|
|
HWButton GetMouse(uint32_t button); |
|
|
|
|
const vi2d& GetMousePos(); |
|
|
|
|
int32_t GetMouseWheel(); |
|
|
|
|
|
|
|
|
|
protected: |
|
|
|
|
virtual void OnAfterUserCreate() override; |
|
|
|
|
virtual bool OnBeforeUserUpdate(float& fElapsedTime) override; |
|
|
|
@ -75,45 +97,162 @@ namespace olc{ |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Replay::RecordingIsActive(){ |
|
|
|
|
return isRecording; |
|
|
|
|
} |
|
|
|
|
bool Replay::ReplayIsActive(){ |
|
|
|
|
return isReplaying; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
HWButton Replay::GetKey(Key k){ |
|
|
|
|
return ReplayIsActive()?pKeyboardState[k]:pge->GetKey(k); |
|
|
|
|
} |
|
|
|
|
HWButton Replay::GetMouse(uint32_t button){ |
|
|
|
|
return ReplayIsActive()?pMouseState[button]:pge->GetMouse(button); |
|
|
|
|
} |
|
|
|
|
const vi2d& Replay::GetMousePos(){ |
|
|
|
|
return ReplayIsActive()?vMousePos:pge->GetMousePos(); |
|
|
|
|
} |
|
|
|
|
int32_t Replay::GetMouseWheel(){ |
|
|
|
|
return ReplayIsActive()?nMouseWheelDelta:pge->GetMouseWheel(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool Replay::OnBeforeUserUpdate(float& fElapsedTime){ |
|
|
|
|
if (isRecording){ |
|
|
|
|
if (RecordingIsActive()){ |
|
|
|
|
bool keyChanged=false; |
|
|
|
|
for (int i=0;i<256;i++){ |
|
|
|
|
if (pge->GetKey(Key(i)).bPressed){ |
|
|
|
|
bool found=false; |
|
|
|
|
for (Input&input:ignoredInputs){ |
|
|
|
|
if (input.type==InputType::KEY&&input.key==i){ |
|
|
|
|
found=true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (found) continue; |
|
|
|
|
if (GetKey(Key(i)).bPressed){ |
|
|
|
|
currentRecording.inputs.push_back({i,true,InputType::KEY,currentRecording.lastKeyTime}); |
|
|
|
|
currentRecording.lastKeyTime=0; |
|
|
|
|
keyChanged=true; |
|
|
|
|
} |
|
|
|
|
if (pge->GetKey(Key(i)).bReleased){ |
|
|
|
|
if (GetKey(Key(i)).bReleased){ |
|
|
|
|
currentRecording.inputs.push_back({i,false,InputType::KEY,currentRecording.lastKeyTime}); |
|
|
|
|
currentRecording.lastKeyTime=0; |
|
|
|
|
keyChanged=true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
for (int i=0;i<5;i++){ |
|
|
|
|
if (pge->GetMouse(i).bPressed){ |
|
|
|
|
bool found=false; |
|
|
|
|
for (Input&input:ignoredInputs){ |
|
|
|
|
if (input.type==InputType::MOUSE&&input.key==i){ |
|
|
|
|
found=true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (found) continue; |
|
|
|
|
if (GetMouse(i).bPressed){ |
|
|
|
|
currentRecording.inputs.push_back({i,true,InputType::MOUSE,currentRecording.lastKeyTime}); |
|
|
|
|
currentRecording.lastKeyTime=0; |
|
|
|
|
keyChanged=true; |
|
|
|
|
} |
|
|
|
|
if (pge->GetMouse(i).bReleased){ |
|
|
|
|
if (GetMouse(i).bReleased){ |
|
|
|
|
currentRecording.inputs.push_back({i,false,InputType::MOUSE,currentRecording.lastKeyTime}); |
|
|
|
|
currentRecording.lastKeyTime=0; |
|
|
|
|
keyChanged=true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (pge->GetMousePos()!=currentRecording.prevMousePos){ |
|
|
|
|
currentRecording.prevMousePos=pge->GetMousePos(); |
|
|
|
|
currentRecording.inputs.push_back({0,false,InputType::MOUSE_MOVE,currentRecording.lastKeyTime,pge->GetMousePos()}); |
|
|
|
|
if (GetMousePos()!=currentRecording.prevMousePos){ |
|
|
|
|
bool found=false; |
|
|
|
|
for (Input&input:ignoredInputs){ |
|
|
|
|
if (input.type==InputType::MOUSE_MOVE){ |
|
|
|
|
found=true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (found) goto mouseWheelCheck; |
|
|
|
|
//GetWindowSize() = vWindowSize
|
|
|
|
|
//GetScreenSize() = vScreenSize
|
|
|
|
|
vi2d vScreenSize=pge->GetScreenSize(); |
|
|
|
|
vi2d vPixelSize=pge->GetPixelSize(); |
|
|
|
|
vi2d vWindowSize=pge->GetWindowSize(); |
|
|
|
|
int32_t ww = vScreenSize.x * vPixelSize.x; |
|
|
|
|
int32_t wh = vScreenSize.y * vPixelSize.y; |
|
|
|
|
float wasp = (float)ww / (float)wh; |
|
|
|
|
vi2d vViewSize={0,0}; |
|
|
|
|
vViewSize.x=vWindowSize.x; |
|
|
|
|
vViewSize.y=(int32_t)((float)vViewSize.x/wasp); |
|
|
|
|
if (vViewSize.y>vWindowSize.y){ |
|
|
|
|
vViewSize.y = vWindowSize.y; |
|
|
|
|
vViewSize.x=(int32_t)((float)vViewSize.y*wasp); |
|
|
|
|
} |
|
|
|
|
vi2d vViewPos=(vWindowSize-vViewSize)/2; |
|
|
|
|
vi2d vMousePos=GetMousePos(); |
|
|
|
|
vMousePos.x+=vViewPos.x; |
|
|
|
|
vMousePos.y+=vViewPos.y; |
|
|
|
|
//currentRecording.prevMousePos=;
|
|
|
|
|
currentRecording.inputs.push_back({0,false,InputType::MOUSE_MOVE,currentRecording.lastKeyTime,GetMousePos()}); |
|
|
|
|
currentRecording.lastKeyTime=0; |
|
|
|
|
keyChanged=true; |
|
|
|
|
} |
|
|
|
|
if (pge->GetMouseWheel()!=0){ |
|
|
|
|
currentRecording.inputs.push_back({pge->GetMouseWheel(),false,InputType::MOUSE_WHEEL,currentRecording.lastKeyTime}); |
|
|
|
|
mouseWheelCheck: |
|
|
|
|
if (GetMouseWheel()!=0){ |
|
|
|
|
bool found=false; |
|
|
|
|
for (Input&input:ignoredInputs){ |
|
|
|
|
if (input.type==InputType::MOUSE_WHEEL){ |
|
|
|
|
found=true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if (found) goto keyTimeUpdate; |
|
|
|
|
currentRecording.inputs.push_back({GetMouseWheel(),false,InputType::MOUSE_WHEEL,currentRecording.lastKeyTime}); |
|
|
|
|
currentRecording.lastKeyTime=0; |
|
|
|
|
keyChanged=true; |
|
|
|
|
} |
|
|
|
|
keyTimeUpdate: |
|
|
|
|
if (!keyChanged){ |
|
|
|
|
currentRecording.lastKeyTime+=fElapsedTime; |
|
|
|
|
} else { |
|
|
|
|
currentRecording.lastKeyTime=fElapsedTime; |
|
|
|
|
} |
|
|
|
|
} else { |
|
|
|
|
|
|
|
|
|
} else
|
|
|
|
|
if (ReplayIsActive()){ |
|
|
|
|
if (currentReplay.accTime+fElapsedTime>=currentReplay.nextKeyTime){ |
|
|
|
|
fElapsedTime=currentReplay.nextKeyTime-currentReplay.accTime; |
|
|
|
|
Input¤tInput=currentReplay.inputs[currentReplay.currentKeyInd]; |
|
|
|
|
switch(currentInput.type){ |
|
|
|
|
case InputType::KEY:{ |
|
|
|
|
if (currentInput.press){ |
|
|
|
|
pKeyboardState[currentInput.key].bPressed=pKeyboardState[currentInput.key].bHeld=true; |
|
|
|
|
} else { |
|
|
|
|
pKeyboardState[currentInput.key].bReleased=true; |
|
|
|
|
pKeyboardState[currentInput.key].bHeld=false; |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
case InputType::MOUSE:{ |
|
|
|
|
if (currentInput.press){ |
|
|
|
|
pMouseState[currentInput.key].bPressed=pMouseState[currentInput.key].bHeld=true; |
|
|
|
|
} else { |
|
|
|
|
pMouseState[currentInput.key].bReleased=true; |
|
|
|
|
pMouseState[currentInput.key].bHeld=false; |
|
|
|
|
} |
|
|
|
|
}break; |
|
|
|
|
case InputType::MOUSE_MOVE:{ |
|
|
|
|
vMousePos={currentInput.mousePos.x,currentInput.mousePos.y}; |
|
|
|
|
}break; |
|
|
|
|
case InputType::MOUSE_WHEEL:{ |
|
|
|
|
nMouseWheelDelta=currentInput.key; |
|
|
|
|
}break; |
|
|
|
|
} |
|
|
|
|
currentReplay.currentKeyInd++; |
|
|
|
|
if (currentReplay.inputs.size()==currentReplay.currentKeyInd){ |
|
|
|
|
isReplaying=false; |
|
|
|
|
std::cout<<"Replay finished"<<std::endl; |
|
|
|
|
} else { |
|
|
|
|
currentReplay.nextKeyTime=currentReplay.inputs[currentReplay.currentKeyInd].delay; |
|
|
|
|
} |
|
|
|
|
currentReplay.accTime=0; |
|
|
|
|
} else { |
|
|
|
|
currentReplay.accTime+=fElapsedTime; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
@ -129,6 +268,7 @@ namespace olc{ |
|
|
|
|
currentRecording.lastKeyTime=0; |
|
|
|
|
currentRecording.prevMousePos=pge->GetMousePos(); |
|
|
|
|
isRecording=true; |
|
|
|
|
ResetStates(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Replay::StopRecording(){ |
|
|
|
@ -143,6 +283,7 @@ namespace olc{ |
|
|
|
|
file.close(); |
|
|
|
|
isRecording=false; |
|
|
|
|
std::cout<<"Recording has stopped. Recording saved to "<<currentRecording.filename<<"."<<std::endl; |
|
|
|
|
ResetStates(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Replay::StartReplay(const std::string filename){ |
|
|
|
@ -151,11 +292,15 @@ namespace olc{ |
|
|
|
|
currentReplay.inputs.clear(); |
|
|
|
|
currentReplay.accTime=0; |
|
|
|
|
currentReplay.nextKeyTime=0; |
|
|
|
|
currentReplay.currentKeyInd=0; |
|
|
|
|
while (file.good()){ |
|
|
|
|
Input newInput(0,false,InputType::KEY,0); |
|
|
|
|
Input newInput(0,false,InputType::NONE,0); |
|
|
|
|
int type; |
|
|
|
|
file >> newInput.key; |
|
|
|
|
file >> newInput.delay; |
|
|
|
|
if (currentReplay.nextKeyTime==0){ |
|
|
|
|
currentReplay.nextKeyTime=newInput.delay; |
|
|
|
|
} |
|
|
|
|
file >> type; |
|
|
|
|
newInput.type = InputType(type); |
|
|
|
|
file >> newInput.press; |
|
|
|
@ -170,14 +315,31 @@ namespace olc{ |
|
|
|
|
} |
|
|
|
|
std::cout<<"Read "<<currentReplay.inputs.size()<<" inputs from "<<filename<<"."<<std::endl; |
|
|
|
|
isReplaying=true; |
|
|
|
|
ResetStates(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Replay::StopReplay(){ |
|
|
|
|
isReplaying=false; |
|
|
|
|
std::cout<<"Replay has halted."<<std::endl; |
|
|
|
|
ResetStates(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Replay::ResetStates(){ |
|
|
|
|
for (int i=0;i<256;i++){ |
|
|
|
|
pKeyboardState[i]={false,false,false}; |
|
|
|
|
} |
|
|
|
|
for (int i=0;i<nMouseButtons;i++){ |
|
|
|
|
pMouseState[i]={false,false,false}; |
|
|
|
|
} |
|
|
|
|
vMousePos={0,0}; |
|
|
|
|
nMouseWheelDelta=0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Input::Input(int32_t key,bool press,InputType type,float delay):key(key),type(type),delay(delay),press(press){}; |
|
|
|
|
Input::Input(int32_t key,bool press,InputType type,float delay,vi2d mousePos):key(key),type(type),delay(delay),press(press),mousePos(mousePos){}; |
|
|
|
|
|
|
|
|
|
Input::Input(Key k):key(int(k)),type(InputType::KEY){}; |
|
|
|
|
Input::Input(int mouseButton):key(mouseButton),type(InputType::MOUSE){}; |
|
|
|
|
Input::Input(InputType type):type(type){}; |
|
|
|
|
} |
|
|
|
|
#endif |