Code archives/User Input/Input Class/Lua Script
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
This is a small class and script for use with LuGI - although you could probably make it work without. The script should be loaded after LuGI is initialized and the Input global is set, at which point this takes the global and hides it away in a table and provides a wrapper for it that handles more than just Key/MouseDown, but also allows you to hook functions to keys based on priority and the type of event they want to receive (whether it's when the key is pressed or release) and so on. | |||||
' input.bmx SuperStrict Import LuGI.Core Type Input {expose static} Method l_KeyDown:Int(key:Int) {rename="KeyDown" bool} Return KeyDown(key) End Method Method l_MouseDown:Int(button:Int) {rename="MouseDown" bool} Return MouseDown(button) End Method Method l_MouseX:Int() Return MouseX() End Method Method l_MouseY:Int() Return MouseY() End Method Method l_MouseZ:Int() Return MouseZ() End Method Method l_MouseXSpeed:Int() Return MouseXSpeed() End Method Method l_MouseYSpeed:Int() Return MouseYSpeed() End Method Method l_MouseZSpeed:Int() Return MouseZSpeed() End Method End Type -- input.lua -- Borrowing values from the keycodes module Mouse = { Left = 1, Right = 2, Middle = 3, } Modifier = { Shift = 1, Control = 2, Option = 4, System = 8, LeftMouse = 16, RightMouse = 32, MiddleMouse = 64, } Key = { Backspace = 8, Tab = 9, Clear = 12, Return = 13, Enter = 13, Escape = 27, Space = 32, PageUp = 33, PageDown = 34, End = 35, Home = 36, Left = 37, Up = 38, Right = 39, Down = 40, Select = 41, Print = 42, Execute = 43, PrintScreen = 44, Insert = 45, Delete = 46, ["0"] = 48, ["1"] = 49, ["2"] = 50, ["3"] = 51, ["4"] = 52, ["5"] = 53, ["6"] = 54, ["7"] = 55, ["8"] = 56, ["9"] = 57, A = 65, a = 65, B = 66, b = 66, C = 67, c = 67, D = 68, d = 68, E = 69, e = 69, F = 70, f = 70, G = 71, g = 71, H = 72, h = 72, I = 73, i = 73, J = 74, j = 74, K = 75, k = 75, L = 76, l = 76, M = 77, m = 77, N = 78, n = 78, O = 79, o = 79, P = 80, p = 80, Q = 81, q = 81, R = 82, r = 82, S = 83, s = 83, T = 84, t = 84, U = 85, u = 85, V = 86, v = 86, W = 87, w = 87, X = 88, x = 88, Y = 89, y = 89, Z = 90, z = 90, Numpad0 = 96, Numpad1 = 97, Numpad2 = 98, Numpad3 = 99, Numpad4 = 100, Numpad5 = 101, Numpad6 = 102, Numpad7 = 103, Numpad8 = 104, Numpad9 = 105, NumpadMultiply = 106, NumpadPlus = 107, NumpadMinus = 109, NumpadPeriod = 110, NumpadSlash = 111, F1 = 112, F2 = 113, F3 = 114, F4 = 115, F5 = 116, F6 = 117, F7 = 118, F8 = 119, F9 = 120, F10 = 121, F11 = 122, F12 = 123, Tilde = 192, Minus = 189, Equals = 187, OpenBracket = 219, CloseBracket = 221, Backslash = 226, Semicolon = 186, Quotes = 222, Comma = 188, Period = 190, Slash = 191, LeftShift = 160, RightShift = 161, LeftControl = 162, RightControl = 163, LeftOption = 164, RightOption = 165, LeftSystem = 91, RightSystem = 92, -- typing this wasn't fun. should've used a regex. } local function _stateCheck(self, current_name, previous_name, comp) return function(self, ...) buttons = {...} for key,button in next, buttons, nil do buttons[button] = comp(self[current_name][button], self[previous_name][button]) end return unpack(buttons) end end local function _downState(self, current_name, previous_name) return _stateCheck(self, current_name, previous_name, function(c,p) return c end) end local function _hitState(self, current_name, previous_name) return _stateCheck(self, current_name, previous_name, function(c,p) return (c and not p) end) end local function _upState(self, current_name, previous_name) return _stateCheck(self, current_name, previous_name, function(c,p) return (not c and p) end) end local function _bind(name) return function(self) return self._input[name]() end end _G.Input = { _input = (type(Input) == "table" and Input._input) or Input, -- store old Input singleton object (bmx) and wrap it keys_previous = {}, keys_current = {}, mouse_current = {}, mouse_previous = {}, bindings_keys = { --[[ key = { closure = function(key, depressed) ... end -> handled onPress = true|false onRelease = true|false priority = number } ]] }, bindings_mouse = { --[[ same model as above ]] }, -- Get key state KeyDown = _downState(self, "keys_current", "keys_previous"), KeyHit = _hitState(self, "keys_current", "keys_previous"), KeyUp = _upState(self, "keys_current", "keys_previous"), MouseDown = _downState(self, "mouse_current", "mouse_previous"), MouseHit = _hitState(self, "mouse_current", "mouse_previous"), MouseUp = _upState(self, "mouse_current", "mouse_previous"), MousePosition = function(self) return self._input:MouseX(), self._input:MouseY(), self._input:MouseZ() end, MouseSpeed = function(self) return self._input:MouseXSpeed(), self._input:MouseYSpeed(), self._input:MouseZSpeed() end, MouseX = _bind("MouseX"), MouseY = _bind("MouseY"), MouseZ = _bind("MouseZ"), MouseXSpeed = _bind("MouseXSpeed"), MouseYSpeed = _bind("MouseYSpeed"), MouseZSpeed = _bind("MouseZSpeed"), -- Update _runBindings = function(self, binder, current, previous) for k,v in next, current, nil do if v ~= (previous[k] or false) then bindings = binder[k] if bindings then for bk, binding in next, bindings, nil do if ((v and binding.onPress) or (not v and binding.onRelease)) and binding.closure(k, v) then break end end end end end end, _updateState = function(self, states, buttons, buttonStatus) for k,button in next, buttons, nil do states[button] = buttonStatus(self._input, button) end end, Update = function(self) do local t = self.keys_previous self.keys_previous = self.keys_current self.keys_current = t t = self.mouse_current self.mouse_current = self.mouse_previous self.mouse_previous = t end self:_updateState(self.keys_current, Key, self._input.KeyDown) self:_updateState(self.mouse_current, Mouse, self._input.MouseDown) self:_runBindings(self.bindings_mouse, self.mouse_current, self.mouse_previous) self:_runBindings(self.bindings_keys, self.keys_current, self.keys_previous) end, -- Bindings _setBinding = function(self, binder, button, binding, onPress, onRelease, priority) local old_binding = binder[button] priority = priority or 0 bindings = binder[button] if not bindings then binder[button] = {} bindings = binder[button] end if binding and (onPress or onRelease) then table.insert(bindings, { closure = binding, ["onPress"] = onPress, ["onRelease"] = onRelease, ["priority"] = priority }) table.sort(bindings, function(left, right) return left.priority > right.priority end) end return old_binding and unpack(old_binding) end, _removeBinding = function(self, binder, button, binding) bindings = binder[button] if bindings then for i,v in ipairs(bindings) do if v.closure == binding then table.remove(bindings, i) return unpack(v) end end end end, AddKeyBinding = function(self, key, binding, onPress, onRelease, priority) return self:_setBinding(self.bindings_keys, key, binding, onPress, onRelease, priority) end, RemoveKeyBinding = function(self, key, binding) return self:_removeBinding(self.bindings_keys, key, binding) end, ClearKeyBindings = function(self, key) self.bindings_keys[key] = {} end, AddMouseBinding = function(self, button, binding, onPress, onRelease, priority) return self:_setBinding(self.bindings_mouse, button, binding, onPress, onRelease, priority) end, RemoveMouseBinding = function(self, button, binding) return self:_removeBinding(self.bindings_mouse, button, binding) end, ClearMouseBindings = function(self, button) self.bindings_mouse[button] = {} end, } |
Comments
| ||
I say again.. Yoink! Thanks Nilium |
Code Archives Forum