-- ContextActionTouch.lua -- Copyright ROBLOX 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.syntax.eco/asset/?id=97166756" local ContextUpImage = "http://www.syntax.eco/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, functionInfoTable) 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