Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/core/input/input_event_codec.cpp
9903 views
1
/**************************************************************************/
2
/* input_event_codec.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "input_event_codec.h"
32
33
#include "core/input/input.h"
34
#include "core/io/marshalls.h"
35
#include "core/os/os.h"
36
37
enum class BoolShift : uint8_t {
38
SHIFT = 0,
39
CTRL,
40
ALT,
41
META,
42
ECHO,
43
PRESSED,
44
DOUBLE_CLICK,
45
PEN_INVERTED,
46
};
47
48
// cast operator for BoolShift to uint8_t
49
inline uint8_t operator<<(uint8_t a, BoolShift b) {
50
return a << static_cast<uint8_t>(b);
51
}
52
53
uint8_t encode_key_modifier_state(Ref<InputEventWithModifiers> p_event) {
54
uint8_t bools = 0;
55
bools |= (uint8_t)p_event->is_shift_pressed() << BoolShift::SHIFT;
56
bools |= (uint8_t)p_event->is_ctrl_pressed() << BoolShift::CTRL;
57
bools |= (uint8_t)p_event->is_alt_pressed() << BoolShift::ALT;
58
bools |= (uint8_t)p_event->is_meta_pressed() << BoolShift::META;
59
return bools;
60
}
61
62
void decode_key_modifier_state(uint8_t bools, Ref<InputEventWithModifiers> p_event) {
63
p_event->set_shift_pressed(bools & (1 << BoolShift::SHIFT));
64
p_event->set_ctrl_pressed(bools & (1 << BoolShift::CTRL));
65
p_event->set_alt_pressed(bools & (1 << BoolShift::ALT));
66
p_event->set_meta_pressed(bools & (1 << BoolShift::META));
67
}
68
69
int encode_vector2(const Vector2 &p_vector, uint8_t *p_data) {
70
p_data += encode_float(p_vector.x, p_data);
71
encode_float(p_vector.y, p_data);
72
return sizeof(float) * 2;
73
}
74
75
const uint8_t *decode_vector2(Vector2 &r_vector, const uint8_t *p_data) {
76
r_vector.x = decode_float(p_data);
77
p_data += sizeof(float);
78
r_vector.y = decode_float(p_data);
79
p_data += sizeof(float);
80
return p_data;
81
}
82
83
void encode_input_event_key(const Ref<InputEventKey> &p_event, PackedByteArray &r_data) {
84
r_data.resize(19);
85
86
uint8_t *data = r_data.ptrw();
87
*data = (uint8_t)InputEventType::KEY;
88
data++;
89
uint8_t bools = encode_key_modifier_state(p_event);
90
bools |= (uint8_t)p_event->is_echo() << BoolShift::ECHO;
91
bools |= (uint8_t)p_event->is_pressed() << BoolShift::PRESSED;
92
*data = bools;
93
data++;
94
data += encode_uint32((uint32_t)p_event->get_keycode(), data);
95
data += encode_uint32((uint32_t)p_event->get_physical_keycode(), data);
96
data += encode_uint32((uint32_t)p_event->get_key_label(), data);
97
data += encode_uint32(p_event->get_unicode(), data);
98
*data = (uint8_t)p_event->get_location();
99
data++;
100
101
// Assert we had enough space.
102
DEV_ASSERT(data - r_data.ptrw() >= r_data.size());
103
}
104
105
Error decode_input_event_key(const PackedByteArray &p_data, Ref<InputEventKey> &r_event) {
106
const uint8_t *data = p_data.ptr();
107
DEV_ASSERT(static_cast<InputEventType>(*data) == InputEventType::KEY);
108
data++; // Skip event type.
109
110
uint8_t bools = *data;
111
data++;
112
decode_key_modifier_state(bools, r_event);
113
r_event->set_echo(bools & (1 << BoolShift::ECHO));
114
r_event->set_pressed(bools & (1 << BoolShift::PRESSED));
115
116
Key keycode = (Key)decode_uint32(data);
117
data += sizeof(uint32_t);
118
Key physical_keycode = (Key)decode_uint32(data);
119
data += sizeof(uint32_t);
120
Key key_label = (Key)decode_uint32(data);
121
data += sizeof(uint32_t);
122
char32_t unicode = (char32_t)decode_uint32(data);
123
data += sizeof(uint32_t);
124
KeyLocation location = (KeyLocation)*data;
125
126
r_event->set_keycode(keycode);
127
r_event->set_physical_keycode(physical_keycode);
128
r_event->set_key_label(key_label);
129
r_event->set_unicode(unicode);
130
r_event->set_location(location);
131
132
return OK;
133
}
134
135
void encode_input_event_mouse_button(const Ref<InputEventMouseButton> &p_event, PackedByteArray &r_data) {
136
r_data.resize(12);
137
138
uint8_t *data = r_data.ptrw();
139
*data = (uint8_t)InputEventType::MOUSE_BUTTON;
140
data++;
141
142
uint8_t bools = encode_key_modifier_state(p_event);
143
bools |= (uint8_t)p_event->is_pressed() << BoolShift::PRESSED;
144
bools |= (uint8_t)p_event->is_double_click() << BoolShift::DOUBLE_CLICK;
145
*data = bools;
146
data++;
147
148
*data = (uint8_t)p_event->get_button_index();
149
data++;
150
151
// Rather than use encode_variant, we explicitly encode the Vector2,
152
// so decoding is easier. Specifically, we don't have to perform additional error
153
// checking for decoding the variant and then checking the variant type.
154
data += encode_vector2(p_event->get_position(), data);
155
*data = (uint8_t)p_event->get_button_mask();
156
data++;
157
158
// Assert we had enough space.
159
DEV_ASSERT(data - r_data.ptrw() >= r_data.size());
160
}
161
162
Error decode_input_event_mouse_button(const PackedByteArray &p_data, Ref<InputEventMouseButton> &r_event) {
163
const uint8_t *data = p_data.ptr();
164
DEV_ASSERT(static_cast<InputEventType>(*data) == InputEventType::MOUSE_BUTTON);
165
data++; // Skip event type.
166
167
uint8_t bools = *data;
168
data++;
169
decode_key_modifier_state(bools, r_event);
170
r_event->set_pressed(bools & (1 << BoolShift::PRESSED));
171
r_event->set_double_click(bools & (1 << BoolShift::DOUBLE_CLICK));
172
173
r_event->set_button_index((MouseButton)*data);
174
data++;
175
176
Vector2 pos;
177
data = decode_vector2(pos, data);
178
r_event->set_position(pos);
179
r_event->set_global_position(pos); // these are the same
180
BitField<MouseButtonMask> button_mask = (MouseButtonMask)*data;
181
r_event->set_button_mask(button_mask);
182
183
return OK;
184
}
185
186
void encode_input_event_mouse_motion(const Ref<InputEventMouseMotion> &p_event, PackedByteArray &r_data) {
187
r_data.resize(31);
188
189
uint8_t *data = r_data.ptrw();
190
*data = (uint8_t)InputEventType::MOUSE_MOTION;
191
data++;
192
193
uint8_t bools = encode_key_modifier_state(p_event);
194
bools |= (uint8_t)p_event->get_pen_inverted() << BoolShift::PEN_INVERTED;
195
*data = bools;
196
data++;
197
198
// Rather than use encode_variant, we explicitly encode the Vector2,
199
// so decoding is easier. Specifically, we don't have to perform additional error
200
// checking for decoding the variant and then checking the variant type.
201
data += encode_vector2(p_event->get_position(), data);
202
data += encode_float(p_event->get_pressure(), data);
203
data += encode_vector2(p_event->get_tilt(), data);
204
data += encode_vector2(p_event->get_relative(), data);
205
*data = (uint8_t)p_event->get_button_mask();
206
data++;
207
208
// Assert we had enough space.
209
DEV_ASSERT(data - r_data.ptrw() >= r_data.size());
210
}
211
212
void decode_input_event_mouse_motion(const PackedByteArray &p_data, Ref<InputEventMouseMotion> &r_event) {
213
Input *input = Input::get_singleton();
214
215
const uint8_t *data = p_data.ptr();
216
DEV_ASSERT(static_cast<InputEventType>(*data) == InputEventType::MOUSE_MOTION);
217
data++; // Skip event type.
218
219
uint8_t bools = *data;
220
data++;
221
decode_key_modifier_state(bools, r_event);
222
r_event->set_pen_inverted(bools & (1 << BoolShift::PEN_INVERTED));
223
224
{
225
Vector2 pos;
226
data = decode_vector2(pos, data);
227
r_event->set_position(pos);
228
r_event->set_global_position(pos); // these are the same
229
}
230
r_event->set_pressure(decode_float(data));
231
data += sizeof(float);
232
{
233
Vector2 tilt;
234
data = decode_vector2(tilt, data);
235
r_event->set_tilt(tilt);
236
}
237
r_event->set_velocity(input->get_last_mouse_velocity());
238
r_event->set_screen_velocity(input->get_last_mouse_screen_velocity());
239
{
240
Vector2 relative;
241
data = decode_vector2(relative, data);
242
r_event->set_relative(relative);
243
r_event->set_relative_screen_position(relative);
244
}
245
BitField<MouseButtonMask> button_mask = (MouseButtonMask)*data;
246
r_event->set_button_mask(button_mask);
247
data++;
248
249
// Assert we had enough space.
250
DEV_ASSERT(data - p_data.ptr() >= p_data.size());
251
}
252
253
void encode_input_event_joypad_button(const Ref<InputEventJoypadButton> &p_event, PackedByteArray &r_data) {
254
r_data.resize(11);
255
256
uint8_t *data = r_data.ptrw();
257
*data = (uint8_t)InputEventType::JOY_BUTTON;
258
data++;
259
260
uint8_t bools = 0;
261
bools |= (uint8_t)p_event->is_pressed() << BoolShift::PRESSED;
262
*data = bools;
263
data++;
264
265
data += encode_uint64(p_event->get_device(), data);
266
*data = (uint8_t)p_event->get_button_index();
267
data++;
268
269
// Assert we had enough space.
270
DEV_ASSERT(data - r_data.ptrw() >= r_data.size());
271
}
272
273
void decode_input_event_joypad_button(const PackedByteArray &p_data, Ref<InputEventJoypadButton> &r_event) {
274
const uint8_t *data = p_data.ptr();
275
DEV_ASSERT(static_cast<InputEventType>(*data) == InputEventType::JOY_BUTTON);
276
data++; // Skip event type.
277
278
uint8_t bools = *data;
279
data++;
280
r_event->set_pressed(bools & (1 << BoolShift::PRESSED));
281
r_event->set_device(decode_uint64(data));
282
data += sizeof(uint64_t);
283
r_event->set_button_index((JoyButton)*data);
284
data++;
285
286
// Assert we had enough space.
287
DEV_ASSERT(data - p_data.ptr() >= p_data.size());
288
}
289
290
void encode_input_event_joypad_motion(const Ref<InputEventJoypadMotion> &p_event, PackedByteArray &r_data) {
291
r_data.resize(14);
292
293
uint8_t *data = r_data.ptrw();
294
*data = (uint8_t)InputEventType::JOY_MOTION;
295
data++;
296
297
data += encode_uint64(p_event->get_device(), data);
298
*data = (uint8_t)p_event->get_axis();
299
data++;
300
data += encode_float(p_event->get_axis_value(), data);
301
302
// Assert we had enough space.
303
DEV_ASSERT(data - r_data.ptrw() >= r_data.size());
304
}
305
306
void decode_input_event_joypad_motion(const PackedByteArray &p_data, Ref<InputEventJoypadMotion> &r_event) {
307
const uint8_t *data = p_data.ptr();
308
DEV_ASSERT(static_cast<InputEventType>(*data) == InputEventType::JOY_MOTION);
309
data++; // Skip event type.
310
311
r_event->set_device(decode_uint64(data));
312
data += sizeof(uint64_t);
313
r_event->set_axis((JoyAxis)*data);
314
data++;
315
r_event->set_axis_value(decode_float(data));
316
data += sizeof(float);
317
318
// Assert we had enough space.
319
DEV_ASSERT(data - p_data.ptr() >= p_data.size());
320
}
321
322
void encode_input_event_gesture_pan(const Ref<InputEventPanGesture> &p_event, PackedByteArray &r_data) {
323
r_data.resize(18);
324
325
uint8_t *data = r_data.ptrw();
326
*data = (uint8_t)InputEventType::PAN_GESTURE;
327
data++;
328
329
uint8_t bools = encode_key_modifier_state(p_event);
330
*data = bools;
331
data++;
332
data += encode_vector2(p_event->get_position(), data);
333
data += encode_vector2(p_event->get_delta(), data);
334
335
// Assert we had enough space.
336
DEV_ASSERT(data - r_data.ptrw() >= r_data.size());
337
}
338
339
void decode_input_event_gesture_pan(const PackedByteArray &p_data, Ref<InputEventPanGesture> &r_event) {
340
const uint8_t *data = p_data.ptr();
341
DEV_ASSERT(static_cast<InputEventType>(*data) == InputEventType::PAN_GESTURE);
342
data++; // Skip event type.
343
344
uint8_t bools = *data;
345
data++;
346
decode_key_modifier_state(bools, r_event);
347
348
Vector2 pos;
349
data = decode_vector2(pos, data);
350
r_event->set_position(pos);
351
Vector2 delta;
352
data = decode_vector2(delta, data);
353
r_event->set_delta(delta);
354
355
// Assert we had enough space.
356
DEV_ASSERT(data - p_data.ptr() >= p_data.size());
357
}
358
359
void encode_input_event_gesture_magnify(const Ref<InputEventMagnifyGesture> &p_event, PackedByteArray &r_data) {
360
r_data.resize(14);
361
362
uint8_t *data = r_data.ptrw();
363
*data = (uint8_t)InputEventType::MAGNIFY_GESTURE;
364
data++;
365
366
uint8_t bools = encode_key_modifier_state(p_event);
367
*data = bools;
368
data++;
369
data += encode_vector2(p_event->get_position(), data);
370
data += encode_float(p_event->get_factor(), data);
371
372
// Assert we had enough space.
373
DEV_ASSERT(data - r_data.ptrw() >= r_data.size());
374
}
375
376
void decode_input_event_gesture_magnify(const PackedByteArray &p_data, Ref<InputEventMagnifyGesture> &r_event) {
377
const uint8_t *data = p_data.ptr();
378
DEV_ASSERT(static_cast<InputEventType>(*data) == InputEventType::MAGNIFY_GESTURE);
379
data++; // Skip event type.
380
381
uint8_t bools = *data;
382
data++;
383
decode_key_modifier_state(bools, r_event);
384
385
Vector2 pos;
386
data = decode_vector2(pos, data);
387
r_event->set_position(pos);
388
r_event->set_factor(decode_float(data));
389
data += sizeof(float);
390
391
// Assert we had enough space.
392
DEV_ASSERT(data - p_data.ptr() >= p_data.size());
393
}
394
395
bool encode_input_event(const Ref<InputEvent> &p_event, PackedByteArray &r_data) {
396
switch (p_event->get_type()) {
397
case InputEventType::KEY:
398
encode_input_event_key(p_event, r_data);
399
break;
400
case InputEventType::MOUSE_BUTTON:
401
encode_input_event_mouse_button(p_event, r_data);
402
break;
403
case InputEventType::MOUSE_MOTION:
404
encode_input_event_mouse_motion(p_event, r_data);
405
break;
406
case InputEventType::JOY_MOTION:
407
encode_input_event_joypad_motion(p_event, r_data);
408
break;
409
case InputEventType::JOY_BUTTON:
410
encode_input_event_joypad_button(p_event, r_data);
411
break;
412
case InputEventType::MAGNIFY_GESTURE:
413
encode_input_event_gesture_magnify(p_event, r_data);
414
break;
415
case InputEventType::PAN_GESTURE:
416
encode_input_event_gesture_pan(p_event, r_data);
417
break;
418
default:
419
return false;
420
}
421
return true;
422
}
423
424
void decode_input_event(const PackedByteArray &p_data, Ref<InputEvent> &r_event) {
425
const uint8_t *data = p_data.ptr();
426
427
switch (static_cast<InputEventType>(*data)) {
428
case InputEventType::KEY: {
429
Ref<InputEventKey> event;
430
event.instantiate();
431
decode_input_event_key(p_data, event);
432
r_event = event;
433
} break;
434
case InputEventType::MOUSE_BUTTON: {
435
Ref<InputEventMouseButton> event;
436
event.instantiate();
437
decode_input_event_mouse_button(p_data, event);
438
r_event = event;
439
} break;
440
case InputEventType::MOUSE_MOTION: {
441
Ref<InputEventMouseMotion> event;
442
event.instantiate();
443
decode_input_event_mouse_motion(p_data, event);
444
r_event = event;
445
} break;
446
case InputEventType::JOY_BUTTON: {
447
Ref<InputEventJoypadButton> event;
448
event.instantiate();
449
decode_input_event_joypad_button(p_data, event);
450
r_event = event;
451
} break;
452
case InputEventType::JOY_MOTION: {
453
Ref<InputEventJoypadMotion> event;
454
event.instantiate();
455
decode_input_event_joypad_motion(p_data, event);
456
r_event = event;
457
} break;
458
case InputEventType::PAN_GESTURE: {
459
Ref<InputEventPanGesture> event;
460
event.instantiate();
461
decode_input_event_gesture_pan(p_data, event);
462
r_event = event;
463
} break;
464
case InputEventType::MAGNIFY_GESTURE: {
465
Ref<InputEventMagnifyGesture> event;
466
event.instantiate();
467
decode_input_event_gesture_magnify(p_data, event);
468
r_event = event;
469
} break;
470
default: {
471
WARN_PRINT(vformat("Unknown event type %d.", static_cast<int>(*data)));
472
} break;
473
}
474
}
475
476