Last active
April 16, 2023 21:02
-
-
Save CheezusChrust/e30ae2cf0a0001bb013218f63aae62e0 to your computer and use it in GitHub Desktop.
A Starfall script to make setting up joystick-like devices easier. Requires the joystick module, binaries can be found here: https://github.com/thegrb93/StarfallEx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--@name Joystick Controller | |
--@shared | |
--[[ | |
INSTRUCTIONS/INFO: | |
1. Spawn this chip on a Starfall screen and move your input device around/press buttons on it | |
2. Fill the axes and buttons tables below using the formats described below | |
- Wire outputs will automatically be created based on table names | |
- DeviceID is displayed on the top of the screen | |
- AxisID/ButtonID is the number displayed next to each axis/button | |
- Invert is a boolean (true or false) which, when true, will invert the output (-1 to 1 becomes 1 to -1) | |
- MinValue is what the chip outputs when the axis is at its LOWEST value | |
- MaxValue is what the chip outputs when the axis is at its HIGHEST value | |
--]] | |
-- FORMAT: WireOutputName = {DeviceID, AxisID, Invert, MinValue, MaxValue} | |
local axes = { | |
Pitch = {1, 1, false, -1, 1}, | |
Yaw = {0, 3, false, -1, 1}, | |
Roll = {1, 0, false, -1, 1}, | |
Throttle = {1, 2, true, 0, 100}, | |
} | |
-- FORMAT: WireOutputName = {DeviceID, ButtonID} | |
local buttons = { | |
Fire = {1, 21} | |
} | |
-- Don't edit anything below here | |
if SERVER then | |
local names = {} | |
local types = {} | |
for outputName in pairs(axes) do | |
table.insert(names, outputName) | |
table.insert(types, "number") | |
end | |
for outputName in pairs(buttons) do | |
table.insert(names, outputName) | |
table.insert(types, "number") | |
end | |
wire.adjustOutputs(names, types) | |
net.receive("joystickData", function() | |
local count = net.readUInt(8) | |
for _ = 1, count do | |
local outputName = net.readString() | |
local value = net.readFloat() | |
wire.ports[outputName] = value | |
end | |
end) | |
local ent = chip():isWeldedTo() | |
if isValid(ent) and ent:getClass() == "starfall_screen" then | |
ent:linkComponent(chip()) | |
end | |
else | |
if not joystick then | |
print(Color(255, 0, 0), "Joystick module not installed!") | |
print(Color(255, 0, 0), "Get the binaries here: https://github.com/thegrb93/StarfallEx") | |
return | |
end | |
local joystickGetAxis, joystickGetButton = joystick.getAxis, joystick.getButton | |
local remap = math.remap | |
local function getDiff(old, new) | |
local diff = {} | |
for k, v in pairs(new) do | |
if old[k] ~= v then | |
diff[k] = v | |
end | |
end | |
return diff | |
end | |
local function getJoystickData() | |
local data = {} | |
for outputName, outputData in pairs(axes) do | |
local value = joystickGetAxis(outputData[1], outputData[2]) | |
if outputData[3] then | |
value = 65535 - value | |
end | |
if outputData[4] and outputData[5] then | |
value = remap(value, 0, 65535, outputData[4], outputData[5]) | |
end | |
data[outputName] = value | |
end | |
for outputName, outputData in pairs(buttons) do | |
local value = joystickGetButton(outputData[1], outputData[2]) > 0 and 1 or 0 | |
data[outputName] = value | |
end | |
return data | |
end | |
if player() == owner() then | |
local oldData = {} | |
hook.add("tick", "getJoystickData", function() | |
local data = getJoystickData() | |
local diff = getDiff(oldData, data) | |
if next(diff) then | |
local count = table.count(diff) | |
net.start("joystickData") | |
net.writeUInt(count, 8) | |
for outputName, value in pairs(diff) do | |
net.writeString(outputName) | |
net.writeFloat(value) | |
end | |
net.send(nil, true) | |
end | |
oldData = data | |
end) | |
end | |
-- Joystick helper functionality | |
local function getJoystickDataHelper(deviceID) | |
local data = {} | |
data.axes = {} | |
data.buttons = {} | |
data.povs = {} | |
for i = 0, 31 do | |
data.axes[i] = joystick.getAxis(deviceID, i) | |
end | |
for i = 0, 31 do | |
data.buttons[i] = joystick.getButton(deviceID, i) | |
end | |
for i = 0, 31 do | |
data.povs[i] = joystick.getPov(deviceID, i) | |
end | |
return data | |
end | |
local devices = {} | |
-- Get default device values to compare against later | |
for i = 0, 2 do | |
devices[i] = {} | |
devices[i].joystickData = getJoystickDataHelper(i) | |
local detectedInputs = {} | |
detectedInputs.axes = {} | |
detectedInputs.buttons = {} | |
detectedInputs.povs = {} | |
devices[i].detectedInputs = detectedInputs | |
end | |
timer.create("detectAxes", 0.1, 0, function() | |
for deviceID, device in pairs(devices) do | |
local newData = getJoystickDataHelper(deviceID) | |
local axesDiff = getDiff(device.joystickData.axes, newData.axes) | |
local buttonsDiff = getDiff(device.joystickData.buttons, newData.buttons) | |
--local povsDiff = getDiff(device.joystickData.povs, newData.povs) | |
for k, v in pairs(axesDiff) do | |
device.detectedInputs.axes[k] = v | |
end | |
for k, v in pairs(buttonsDiff) do | |
device.detectedInputs.buttons[k] = v | |
end | |
--for k, v in pairs(povsDiff) do | |
-- device.detectedInputs.povs[k] = v | |
--end | |
end | |
end) | |
local WHITE = Color(255, 255, 255) | |
local RED = Color(255, 100, 100) | |
local GREEN = Color(100, 255, 100) | |
--local BLUE = Color(100, 100, 255) | |
hook.add("render", "data", function() | |
for deviceID, device in pairs(devices) do | |
render.setColor(WHITE) | |
render.drawText(deviceID * 256, 0, "Device " .. deviceID, deviceID) | |
render.drawText(deviceID * 256, 14, joystick.getName(deviceID), deviceID) | |
render.drawLine(0, 30, 512, 30) | |
local row = 0 | |
for dataSetName, dataSet in pairs(device.detectedInputs) do | |
for inputID in pairs(dataSet) do | |
local value | |
if dataSetName == "axes" then | |
value = string.format("Axis %s: %d", inputID, joystick.getAxis(deviceID, inputID)) | |
render.setColor(RED) | |
elseif dataSetName == "buttons" then | |
value = string.format("Button %s: %d", inputID, joystick.getButton(deviceID, inputID) > 0 and 1 or 0) | |
render.setColor(GREEN) | |
end --elseif dataSetName == "povs" then | |
-- value = string.format("POV %s: %d", inputID, joystick.getPov(deviceID, inputID)) | |
-- render.setColor(BLUE) | |
--end | |
render.drawText(deviceID * 256, 32 + row * 12, value, deviceID) | |
row = row + 1 | |
end | |
end | |
end | |
end) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment