1 module prova.input.binding; 2 3 import prova.input; 4 import prova.math; 5 6 /// Allows representation of input from multiple sources in a uniform way 7 class Binding 8 { 9 private Controller controller; 10 private Input input; 11 private Key[][int] boundKeyButtons; 12 private ControllerButton[][int] boundControllerButtons; 13 private Key[4][][int] boundKeySticks; 14 private ThumbStick[][int] boundControllerSticks; 15 16 /// Forward of deadzone on Controller 17 @property float deadzone() 18 { 19 return controller.deadzone; 20 } 21 22 /// Forward of deadzone on Controller 23 @property void deadzone(float deadzone) 24 { 25 controller.deadzone = deadzone; 26 } 27 28 /// Must be called before using any other method 29 void bindInput(Input input) 30 { 31 assert(input, "Input should not be null. Did you bind in a constructor rather than during setup()?"); 32 33 this.input = input; 34 } 35 36 /// 37 void bindController(int index) 38 { 39 assert(input, "Input should be bound"); 40 41 controller = input.getController(index); 42 } 43 44 /// 45 void bindButton(int button, Key key) 46 { 47 boundKeyButtons[button] ~= key; 48 } 49 50 /// 51 void bindButton(int button, ControllerButton controllerButton) 52 { 53 boundControllerButtons[button] ~= controllerButton; 54 } 55 56 /** 57 * Simulates a joystick using four keys 58 * 59 * Uses a WASD format for ordering directions 60 */ 61 void bindStick(int stick, Key up, Key left, Key down, Key right) 62 { 63 Key[4] simulatedStick = [up, left, down, right]; 64 boundKeySticks[stick] ~= simulatedStick; 65 } 66 67 /// 68 void bindStick(int stick, ThumbStick joystick) 69 { 70 boundControllerSticks[stick] ~= joystick; 71 } 72 73 /// 74 bool isButtonDown(int button) 75 { 76 assert(input, "Input should be bound"); 77 78 return isKeyDown(button) || isControllerButtonDown(button); 79 } 80 81 private bool isKeyDown(int button) 82 { 83 if(!(button in boundKeyButtons)) 84 return false; 85 86 // loop through bound keys and return true if just pressed 87 Key[] keyButtons = boundKeyButtons[button]; 88 89 foreach(Key keyButton; keyButtons) 90 if(input.isKeyDown(keyButton)) 91 return true; 92 93 return false; 94 } 95 96 private bool isControllerButtonDown(int button) 97 { 98 // do not test controller bindings if the controller isn't set 99 // or if there are no buttons bound 100 if(!controller || !(button in boundControllerButtons)) 101 return false; 102 103 // loop through bound buttons and return true if just pressed 104 ControllerButton[] controllerButtons = boundControllerButtons[button]; 105 106 foreach(ControllerButton controllerButton; controllerButtons) 107 if(controller.isButtonDown(controllerButton)) 108 return true; 109 110 return false; 111 } 112 113 /// 114 bool isButtonUp(int button) 115 { 116 return !isButtonDown(button); 117 } 118 119 /// 120 bool buttonJustPressed(int button) 121 { 122 assert(input, "Input should be bound"); 123 124 return keyJustPressed(button) || controllerButtonJustPressed(button); 125 } 126 127 private bool keyJustPressed(int button) 128 { 129 if(!(button in boundKeyButtons)) 130 return false; 131 132 // loop through bound keys and return true if just pressed 133 Key[] keyButtons = boundKeyButtons[button]; 134 135 foreach(Key keyButton; keyButtons) 136 if(input.keyJustPressed(keyButton)) 137 return true; 138 139 return false; 140 } 141 142 private bool controllerButtonJustPressed(int button) 143 { 144 // do not test controller bindings if the controller isn't set 145 // or if there are no buttons bound 146 if(!controller || !(button in boundControllerButtons)) 147 return false; 148 149 // loop through bound buttons and return true if just pressed 150 ControllerButton[] controllerButtons = boundControllerButtons[button]; 151 152 foreach(ControllerButton controllerButton; controllerButtons) 153 if(controller.buttonJustPressed(controllerButton)) 154 return true; 155 156 return false; 157 } 158 159 /// 160 Vector2 getStick(int stick) 161 { 162 assert(input, "Input must be bound"); 163 164 Vector2 result; 165 Vector2 zero; 166 167 result = getSimulatedStick(stick); 168 169 if(result != zero) 170 return result; 171 172 result = getJoyStick(stick); 173 174 if(result != zero) 175 return result; 176 177 return zero; 178 } 179 180 private Vector2 getSimulatedStick(int stick) 181 { 182 Vector2 zero; 183 184 if(!(stick in boundKeySticks)) 185 return zero; 186 187 // loop through bound sticks and return only if it does not equal zero 188 Key[4][] keySticks = boundKeySticks[stick]; 189 190 foreach(Key[4] keyStick; keySticks) { 191 Vector2 vector = input.simulateStick( 192 keyStick[0], keyStick[1], keyStick[2], keyStick[3] 193 ); 194 195 if(vector != zero) 196 return vector; 197 } 198 199 return zero; 200 } 201 202 private Vector2 getJoyStick(int stick) 203 { 204 Vector2 zero; 205 206 // do not test controller bindings if the controller isn't set, 207 // or if there are no sticks bound to the controller 208 if(!controller || !(stick in boundControllerSticks)) 209 return zero; 210 211 // loop through bound sticks and return only if it does not equal zero 212 ThumbStick[] thumbsticks = boundControllerSticks[stick]; 213 214 foreach(ThumbStick thumbstick; thumbsticks) { 215 Vector2 vector = controller.getStick(thumbstick); 216 217 if(vector != zero) 218 return vector; 219 } 220 221 return zero; 222 } 223 }