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