-- ContextActionTouch.lua -- 2014, created by Ben Tkacheff -- this script controls ui and firing of lua functions that are bound in ContextActionService for touch inputs -- Essentially a user can bind a lua function to a key code, input type (mousebutton1 etc.) and this -- Variables local contextActionService = Game:GetService "ContextActionService" local isTouchDevice = Game:GetService("UserInputService").TouchEnabled local functionTable = {} local buttonVector = {} local buttonScreenGui = nil local buttonFrame = nil local ContextDownImage = "http://www.banland.xyz/asset/?id=97166756" local ContextUpImage = "http://www.banland.xyz/asset/?id=97166444" local oldTouches = {} local buttonPositionTable = { [1] = UDim2.new(0, 123, 0, 70), [2] = UDim2.new(0, 30, 0, 60), [3] = UDim2.new(0, 180, 0, 160), [4] = UDim2.new(0, 85, 0, -25), [5] = UDim2.new(0, 185, 0, -25), [6] = UDim2.new(0, 185, 0, 260), [7] = UDim2.new(0, 216, 0, 65), } local maxButtons = #buttonPositionTable -- Preload images Game:GetService("ContentProvider"):Preload(ContextDownImage) Game:GetService("ContentProvider"):Preload(ContextUpImage) while not Game.Players do wait() end while not Game.Players.LocalPlayer do wait() end function createContextActionGui() if not buttonScreenGui and isTouchDevice then buttonScreenGui = Instance.new "ScreenGui" buttonScreenGui.Name = "ContextActionGui" buttonFrame = Instance.new "Frame" buttonFrame.BackgroundTransparency = 1 buttonFrame.Size = UDim2.new(0.3, 0, 0.5, 0) buttonFrame.Position = UDim2.new(0.7, 0, 0.5, 0) buttonFrame.Name = "ContextButtonFrame" buttonFrame.Parent = buttonScreenGui end end -- functions -- function setButtonSizeAndPosition(object) -- local buttonSize = 55 -- local xOffset = 10 -- local yOffset = 95 -- -- todo: better way to determine mobile sized screens -- local onSmallScreen = (game.CoreGui.RobloxGui.AbsoluteSize.X < 600) -- if not onSmallScreen then -- buttonSize = 85 -- xOffset = 40 -- end -- object.Size = UDim2.new(0, buttonSize, 0, buttonSize) -- end function contextButtonDown(button, inputObject, actionName) if inputObject.UserInputType == Enum.UserInputType.Touch then button.Image = ContextDownImage contextActionService:CallFunction(actionName, Enum.UserInputState.Begin, inputObject) end end function contextButtonMoved(button, inputObject, actionName) if inputObject.UserInputType == Enum.UserInputType.Touch then button.Image = ContextDownImage contextActionService:CallFunction(actionName, Enum.UserInputState.Change, inputObject) end end function contextButtonUp(button, inputObject, actionName) button.Image = ContextUpImage if inputObject.UserInputType == Enum.UserInputType.Touch and inputObject.UserInputState == Enum.UserInputState.End then contextActionService:CallFunction(actionName, Enum.UserInputState.End, inputObject) end end function isSmallScreenDevice() return Game:GetService("GuiService"):GetScreenResolution().y <= 320 end function createNewButton(actionName, functionInfoTable) local contextButton = Instance.new "ImageButton" contextButton.Name = "ContextActionButton" contextButton.BackgroundTransparency = 1 contextButton.Size = UDim2.new(0, 90, 0, 90) contextButton.Active = true if isSmallScreenDevice() then contextButton.Size = UDim2.new(0, 70, 0, 70) end contextButton.Image = ContextUpImage contextButton.Parent = buttonFrame local currentButtonTouch = nil Game:GetService("UserInputService").InputEnded:connect(function(inputObject) oldTouches[inputObject] = nil end) contextButton.InputBegan:connect(function(inputObject) if oldTouches[inputObject] then return end if inputObject.UserInputState == Enum.UserInputState.Begin and currentButtonTouch == nil then currentButtonTouch = inputObject contextButtonDown(contextButton, inputObject, actionName) end end) contextButton.InputChanged:connect(function(inputObject) if oldTouches[inputObject] then return end if currentButtonTouch ~= inputObject then return end contextButtonMoved(contextButton, inputObject, actionName) end) contextButton.InputEnded:connect(function(inputObject) if oldTouches[inputObject] then return end if currentButtonTouch ~= inputObject then return end currentButtonTouch = nil oldTouches[inputObject] = true contextButtonUp(contextButton, inputObject, actionName) end) local actionIcon = Instance.new "ImageLabel" actionIcon.Name = "ActionIcon" actionIcon.Position = UDim2.new(0.175, 0, 0.175, 0) actionIcon.Size = UDim2.new(0.65, 0, 0.65, 0) actionIcon.BackgroundTransparency = 1 if functionInfoTable["image"] and type(functionInfoTable["image"]) == "string" then actionIcon.Image = functionInfoTable["image"] end actionIcon.Parent = contextButton local actionTitle = Instance.new "TextLabel" actionTitle.Name = "ActionTitle" actionTitle.Size = UDim2.new(1, 0, 1, 0) actionTitle.BackgroundTransparency = 1 actionTitle.Font = Enum.Font.SourceSansBold actionTitle.TextColor3 = Color3.new(1, 1, 1) actionTitle.TextStrokeTransparency = 0 actionTitle.FontSize = Enum.FontSize.Size18 actionTitle.TextWrapped = true actionTitle.Text = "" if functionInfoTable["title"] and type(functionInfoTable["title"]) == "string" then actionTitle.Text = functionInfoTable["title"] end actionTitle.Parent = contextButton return contextButton end function createButton(actionName, functionInfoTable) local button = createNewButton(actionName, functionInfoTable) local position = nil for i = 1, #buttonVector do if buttonVector[i] == "empty" then position = i break end end if not position then position = #buttonVector + 1 end if position > maxButtons then return -- todo: let user know we have too many buttons already? end buttonVector[position] = button functionTable[actionName]["button"] = button button.Position = buttonPositionTable[position] button.Parent = buttonFrame if buttonScreenGui and buttonScreenGui.Parent == nil then buttonScreenGui.Parent = Game.Players.LocalPlayer.PlayerGui end end function removeAction(actionName) if not functionTable[actionName] then return end local actionButton = functionTable[actionName]["button"] if actionButton then actionButton.Parent = nil for i = 1, #buttonVector do if buttonVector[i] == actionButton then buttonVector[i] = "empty" break end end actionButton:Destroy() end functionTable[actionName] = nil end function addAction(actionName, createTouchButton, functionInfoTable) if functionTable[actionName] then removeAction(actionName) end functionTable[actionName] = { functionInfoTable } if createTouchButton and isTouchDevice then createContextActionGui() createButton(actionName, functionInfoTable) end end -- Connections contextActionService.BoundActionChanged:connect(function(actionName, changeName, changeTable) if functionTable[actionName] and changeTable then local button = functionTable[actionName]["button"] if button then if changeName == "image" then button.ActionIcon.Image = changeTable[changeName] elseif changeName == "title" then button.ActionTitle.Text = changeTable[changeName] -- elseif changeName == "description" then -- -- todo: add description to menu elseif changeName == "position" then button.Position = changeTable[changeName] end end end end) contextActionService.BoundActionAdded:connect(function(actionName, createTouchButton, functionInfoTable) addAction(actionName, createTouchButton, functionInfoTable) end) contextActionService.BoundActionRemoved:connect(function(actionName, _) removeAction(actionName) end) contextActionService.GetActionButtonEvent:connect(function(actionName) if functionTable[actionName] then contextActionService:FireActionButtonFoundSignal(actionName, functionTable[actionName]["button"]) end end) -- make sure any bound data before we setup connections is handled local boundActions = contextActionService:GetAllBoundActionInfo() for actionName, actionData in pairs(boundActions) do addAction(actionName, actionData["createTouchButton"], actionData) end