-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinput.odin
More file actions
136 lines (123 loc) · 3.8 KB
/
input.odin
File metadata and controls
136 lines (123 loc) · 3.8 KB
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
package extra
//Input map system for rebinding, compositie actions and named action using an enum
import "base:intrinsics"
import "core:encoding/json"
import "core:log"
import os "core:os/os2"
import rl "vendor:raylib"
InputAction :: union #no_nil {
InputAxisAction,
InputBoolAction,
}
//Represents a float32 action with 2 keys and 1 gamepad axis
InputAxisAction :: struct {
positiveKey: rl.KeyboardKey,
negativeKey: rl.KeyboardKey,
gamePadAxis: rl.GamepadAxis,
value: i8,
}
//Represents a bool action with a key and gamepad button
InputBoolAction :: struct {
key: rl.KeyboardKey,
gamePadButton: rl.GamepadButton,
value: bool,
}
//Saves input map to json, 'fileName can be different to have different input maps'
SaveInputMap :: proc(fileName: string, inputMap: ^[$T]InputAction) {
file, f_err := os.create(fileName)
assert(f_err == nil)
defer os.close(file)
writer := os.to_writer(file)
opt := json.Marshal_Options {
use_enum_names = true,
}
json.marshal_to_writer(writer, inputMap^, &opt)
}
//Loads an input map, returns a bool declaring whether it was a success or not
//Also logs if failure
//Bool can be used to load map if created, and create if not created
LoadInputMap :: proc(
fileName: string,
$T: typeid,
) -> (
^T,
bool,
) where intrinsics.type_is_enum(T) #optional_ok {
file, open_error := os.open(fileName)
if open_error != nil {
log.errorf("Failed to load input map at {0} due to {1}", fileName, open_error)
return nil, false
}
inputMap, allocator_error := new([T]InputAction)
if allocator_error != nil{
log.errorf("Failed to allocated memory for input map {0} due to {1}", fileName, allocator_error)
return nil, false
}
data, read_error := os.read_entire_file(fileName, context.temp_allocator)
if read_error != nil {
log.errorf("Failed to load input map at {0} due to {1}", fileName, read_error)
return nil, false
}
err := json.unmarshal(data, inputMap, allocator = context.temp_allocator)
if err != nil {
log.errorf("Failed to unmarshal {0} due to {1}", fileName, err)
return nil, false
}
return inputMap, true
}
//Updates the input values of the actions, should be called once per frame
InputUpdate :: proc(inputMap: ^[$T]InputAction) where intrinsics.type_is_enum(T) {
for &action in inputMap {
switch &e in action {
case InputAxisAction:
e.value = i8(rl.GetGamepadAxisMovement(1, e.gamePadAxis))
if rl.IsKeyDown(e.positiveKey) do e.value += 1.0
if rl.IsKeyDown(e.negativeKey) do e.value -= 1.0
e.value = clamp(e.value, -1, 1)
case InputBoolAction:
e.value = rl.IsKeyDown(e.key) || rl.IsGamepadButtonDown(1, e.gamePadButton)
}
}
}
//Gets float value from input action, returns 0.0 if action is not a float value
InputGetAxis :: proc(
inputMap: ^[$T]InputAction,
inputName: T,
) -> f32 where intrinsics.type_is_enum(T) {
if action, ok := inputMap[inputName].(InputAxisAction); ok do return f32(action.value)
return 0.0
}
//Gets bool value from input action, returns false if action is not a bool value
InputGetBool :: proc(
inputMap: ^[$T]InputAction,
inputName: T,
) -> bool where intrinsics.type_is_enum(T) {
if action, ok := inputMap[inputName].(InputBoolAction); ok do return action.value
return false
}
//Creates an axis action, defaults to invalid for gamepad
CreateAxisAction :: proc(
positiveKey: rl.KeyboardKey,
negativeKey: rl.KeyboardKey,
gamePadAxis := rl.GamepadAxis(-1),
) -> InputAxisAction {
action := InputAxisAction {
positiveKey = positiveKey,
negativeKey = negativeKey,
gamePadAxis = gamePadAxis,
value = 0,
}
return action
}
//Creates a button action, defaults to unknown for gamepad
CreateButtonAction :: proc(
key: rl.KeyboardKey,
gamePadButton := rl.GamepadButton.UNKNOWN,
) -> InputBoolAction {
action := InputBoolAction {
key = key,
gamePadButton = gamePadButton,
value = false,
}
return action
}