forked from EasyRPG/Player
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinput_source.h
198 lines (162 loc) · 5.15 KB
/
input_source.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
/*
* This file is part of EasyRPG Player.
*
* EasyRPG Player is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* EasyRPG Player is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with EasyRPG Player. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef EP_INPUT_SOURCE_H
#define EP_INPUT_SOURCE_H
#include <bitset>
#include <fstream>
#include <memory>
#include "filesystem_stream.h"
#include "game_config.h"
#include "game_clock.h"
#include "input_buttons.h"
#include "keys.h"
#include "point.h"
namespace Input {
using KeyStatus = std::bitset<Input::Keys::KEYS_COUNT>;
enum class RecordingData : char {
CommandLine = 'C',
EventCommand = 'E', // unused - reserved
Hash = 'L',
MoveRoute = 'M', // unused - reserved
GameTitle = 'N'
};
/**
* Primary and Secondary range from -1.0 to +1.0
* ^ -1
* |
* -1 <-----> 1
* |
* v 1
* Trigger range from 0.0 (neutral) to 1.0 (pressed)
*/
struct AnalogInput {
PointF primary;
PointF secondary;
float trigger_left = 0;
float trigger_right = 0;
static constexpr float kMaxValue = 1.0f;
static constexpr float kMinValue = -1.0f;
};
struct TouchInput {
void Down(int id, int x, int y);
void Up();
// Do not alter the fields from the Ui class, use Down and Up
int id = -1;
Point position;
bool pressed = false;
bool prev_frame_pressed = false;
Game_Clock::time_point touch_begin;
Game_Clock::time_point touch_end;
};
/**
* A source for button presses.
*/
class Source {
public:
static std::unique_ptr<Source> Create(
const Game_ConfigInput& cfg,
DirectionMappingArray directions,
const std::string& replay_from_path);
Source(const Game_ConfigInput& cfg, DirectionMappingArray directions)
: cfg(cfg), direction_mappings(std::move(directions)) {}
virtual ~Source() = default;
/** Called once each logical frame to update pressed_buttons. */
virtual void Update() = 0;
/** Called once each physical frame when no logical frames occured to update pressed_buttons for system buttons. */
virtual void UpdateSystem() = 0;
/**
* Used to submit additional metadata for input recording
* @param type type of data sent
* @param data Sent data
*/
void AddRecordingData(RecordingData type, StringView data);
/** @return If the input is recorded */
bool IsRecording() const {
return bool(record_log);
}
const std::bitset<BUTTON_COUNT>& GetPressedButtons() const {
return pressed_buttons;
}
std::bitset<BUTTON_COUNT> GetPressedNonSystemButtons() const {
auto pressed = pressed_buttons;
for(unsigned i = 0; i < BUTTON_COUNT; ++i) {
if (IsSystemButton(static_cast<InputButton>(i))) {
pressed[i] = false;
}
}
return pressed;
}
/** @return Returns raw keystates for reading the keyboard directly.*/
const std::bitset<Input::Keys::KEYS_COUNT>& GetPressedKeys() const {
return keystates;
}
ButtonMappingArray& GetButtonMappings() { return cfg.buttons; }
const ButtonMappingArray& GetButtonMappings() const { return cfg.buttons; }
DirectionMappingArray& GetDirectionMappings() { return direction_mappings; }
const DirectionMappingArray& GetDirectionMappings() const { return direction_mappings; }
Game_ConfigInput& GetConfig() { return cfg; }
const Game_ConfigInput& GetConfig() const { return cfg; }
bool InitRecording(const std::string& record_to_path);
const Point& GetMousePosition() const { return mouse_pos; }
const AnalogInput& GetAnalogInput() const { return analog_input; };
const KeyStatus& GetMask() const { return keymask; }
KeyStatus& GetMask() { return keymask; }
protected:
void Record();
void UpdateGamepad();
void UpdateTouch();
Game_ConfigInput cfg;
std::bitset<BUTTON_COUNT> pressed_buttons;
DirectionMappingArray direction_mappings;
std::unique_ptr<Filesystem_Stream::OutputStream> record_log;
KeyStatus keystates;
KeyStatus keymask;
Point mouse_pos;
AnalogInput analog_input;
int last_written_frame = -1;
};
/**
* Source that maps key presses from the UI to button
* presses.
*/
class UiSource : public Source {
public:
using Source::Source;
void Update() override;
void UpdateSystem() override;
private:
void DoUpdate(bool system_only);
};
/**
* Source that replays button presses from a log file.
*/
class LogSource : public Source {
public:
LogSource(const char* log_path, const Game_ConfigInput& cfg, DirectionMappingArray directions);
void Update() override;
void UpdateSystem() override;
operator bool() const { return bool(log_file); }
private:
Filesystem_Stream::InputStream log_file;
int version = 1;
int last_read_frame = -1;
// NOTE: First field is the frame number
std::vector<std::string> keys;
};
extern std::unique_ptr<Source> source;
}
#endif