1 module re.input.virtual.axis;
2 
3 import re.input;
4 import std.algorithm;
5 
6 /// a virtual axis
7 class VirtualAxis : VirtualInput {
8     /// monitors a pair of inputs to make an axis
9     static abstract class Node : VirtualInput.Node {
10         @property public float value();
11     }
12 
13     /// logic-controllable axis
14     static class LogicAxis : Node {
15         public float logic_value = 0;
16 
17         @property public override float value() {
18             return logic_value;
19         }
20     }
21 
22     /// monitors a pair of keyboard keys
23     static class KeyboardKeys : Node {
24         public OverlapBehavior overlap_behavior;
25         public Keys positive;
26         public Keys negative;
27         private float _value;
28         private bool _turned;
29 
30         /// creates a keyboard keys node
31         this(Keys positive, Keys negative, OverlapBehavior overlap_behavior = OverlapBehavior.init) {
32             this.positive = positive;
33             this.negative = negative;
34             this.overlap_behavior = overlap_behavior;
35         }
36 
37         @property public override float value() {
38             return _value;
39         }
40 
41         public override void update() {
42             if (Input.is_key_down(positive)) {
43                 if (Input.is_key_down(negative)) {
44                     switch (overlap_behavior) {
45                     case OverlapBehavior.Cancel:
46                         _value = 0;
47                         break;
48                     case OverlapBehavior.Newer:
49                         if (!_turned) {
50                             _value *= -1;
51                             _turned = true;
52                         }
53                         break;
54                     case OverlapBehavior.Older:
55                         break; // we don't touch the value
56                     default:
57                         assert(0);
58                     }
59                 } else {
60                     _turned = false;
61                     _value = 1;
62                 }
63             } else if (Input.is_key_down(negative)) {
64                 _turned = false;
65                 _value = -1;
66             } else {
67                 _turned = false;
68                 _value = 0;
69             }
70         }
71     }
72 
73     @property public float value() {
74         foreach (node; nodes) {
75             auto val = (cast(Node) node).value;
76             if (val != 0) {
77                 return val;
78             }
79         }
80         return 0;
81     }
82 }
83 
84 @("input-axis")
85 unittest {
86     auto the_axis = new VirtualAxis();
87     the_axis.nodes ~= new VirtualAxis.KeyboardKeys(Keys.KEY_LEFT, Keys.KEY_RIGHT);
88 
89     assert(the_axis.nodes.length > 0);
90 }