function DynamicThumbstick.OnInputEnded(M)M.moveTouchObject=nil M.moveVector=ZERO_VECTOR3 M:FadeThumbstick(false)end function DynamicThumbstick.FadeThumbstick(o,M)if not M and o.moveTouchObject then return end if o.isFirstTouch then return end if o.startImageFadeTween then o.startImageFadeTween:Cancel()end if o.endImageFadeTween then o.endImageFadeTween:Cancel()end for M=1,#o.middleImages,1 do if o.middleImageFadeTweens[M]then o.middleImageFadeTweens[M]:Cancel()end end if M then o.startImageFadeTween=TweenService:Create(o.startImage,ThumbstickFadeTweenInfo,{ImageTransparency=0})o.startImageFadeTween:Play()o.endImageFadeTween=TweenService:Create(o.endImage,ThumbstickFadeTweenInfo,{ImageTransparency=.2})o.endImageFadeTween:Play()for M=1,#o.middleImages,1 do o.middleImageFadeTweens[M]=TweenService:Create(o.middleImages[M],ThumbstickFadeTweenInfo,{ImageTransparency=MIDDLE_TRANSPARENCIES[M]})o.middleImageFadeTweens[M]:Play()end else o.startImageFadeTween=TweenService:Create(o.startImage,ThumbstickFadeTweenInfo,{ImageTransparency=1})o.startImageFadeTween:Play()o.endImageFadeTween=TweenService:Create(o.endImage,ThumbstickFadeTweenInfo,{ImageTransparency=1})o.endImageFadeTween:Play()for M=1,#o.middleImages,1 do o.middleImageFadeTweens[M]=TweenService:Create(o.middleImages[M],ThumbstickFadeTweenInfo,{ImageTransparency=1})o.middleImageFadeTweens[M]:Play()end end end function DynamicThumbstick.FadeThumbstickFrame(I,M,o)I.fadeInAndOutHalfDuration=M*.5 I.fadeInAndOutBalance=o I.tweenInAlphaStart=tick()end function DynamicThumbstick.InputInFrame(o,M)local I=o.thumbstickFrame.AbsolutePosition local l=I+o.thumbstickFrame.AbsoluteSize local U=M.Position if U.X>=I.X and U.Y>=I.Y then if U.X<=l.X and U.Y<=l.Y then return true end end return false end function DynamicThumbstick.DoFadeInBackground(M)local o=LocalPlayer:FindFirstChildOfClass("\080\108\097\121\101\114\071\117\105")local I=false if o then if o.CurrentScreenOrientation==Enum.ScreenOrientation.LandscapeLeft or o.CurrentScreenOrientation==Enum.ScreenOrientation.LandscapeRight then I=M.hasFadedBackgroundInLandscape M.hasFadedBackgroundInLandscape=true elseif o.CurrentScreenOrientation==Enum.ScreenOrientation.Portrait then I=M.hasFadedBackgroundInPortrait M.hasFadedBackgroundInPortrait=true end end if not I then M.fadeInAndOutHalfDuration=FADE_IN_OUT_HALF_DURATION_DEFAULT M.fadeInAndOutBalance=FADE_IN_OUT_BALANCE_DEFAULT M.tweenInAlphaStart=tick()end end function DynamicThumbstick.DoMove(o,M)local I=M local l=I.magnitude if l<o.radiusOfDeadZone then I=ZERO_VECTOR3 else I=I.unit*(1-math.max(0,(o.radiusOfMaxSpeed-I.magnitude)/o.radiusOfMaxSpeed))I=Vector3.new(I.x,0,I.y)end o.moveVector=I end function DynamicThumbstick.LayoutMiddleImages(I,M,o)local l=I.thumbstickSize/2+I.middleSize local U=o-M local Y=(U.magnitude-I.thumbstickRingSize/2)-I.middleSize local D=U.unit local t=I.middleSpacing*NUM_MIDDLE_IMAGES local k=I.middleSpacing if t<Y then k=Y/NUM_MIDDLE_IMAGES end for M=1,NUM_MIDDLE_IMAGES,1 do local U=I.middleImages[M]local t=l+k*(M-2)local i=l+k*(M-1)if t<Y then local M=o-D*i local l=math.clamp(1-(i-Y)/k,0,1)U.Visible=true U.Position=UDim2.new(0,M.X,0,M.Y)U.Size=UDim2.new(0,I.middleSize*l,0,I.middleSize*l)else U.Visible=false end end end function DynamicThumbstick.MoveStick(o,M)local I=Vector2.new(o.moveTouchStartPosition.X,o.moveTouchStartPosition.Y)local l=I-o.thumbstickFrame.AbsolutePosition local U=Vector2.new(M.X,M.Y)-o.thumbstickFrame.AbsolutePosition o.endImage.Position=UDim2.new(0,U.X,0,U.Y)o:LayoutMiddleImages(l,U)end function DynamicThumbstick.BindContextActions(M)local function o(o)if M.moveTouchObject then return Enum.ContextActionResult.Pass end if not M:InputInFrame(o)then return Enum.ContextActionResult.Pass end if M.isFirstTouch then M.isFirstTouch=false local o=TweenInfo.new(.5,Enum.EasingStyle.Quad,Enum.EasingDirection.Out,0,false,0);(TweenService:Create(M.startImage,o,{Size=UDim2.new(0,0,0,0)})):Play();(TweenService:Create(M.endImage,o,{Size=UDim2.new(0,M.thumbstickSize,0,M.thumbstickSize),ImageColor3=Color3.new(0,0,0)})):Play()end M.moveTouchLockedIn=false M.moveTouchObject=o M.moveTouchStartPosition=o.Position M.moveTouchFirstChanged=true if FADE_IN_OUT_BACKGROUND then M:DoFadeInBackground()end return Enum.ContextActionResult.Pass end local function I(o)if o==M.moveTouchObject then if M.moveTouchFirstChanged then M.moveTouchFirstChanged=false local I=Vector2.new(o.Position.X-M.thumbstickFrame.AbsolutePosition.X,o.Position.Y-M.thumbstickFrame.AbsolutePosition.Y)M.startImage.Visible=true M.startImage.Position=UDim2.new(0,I.X,0,I.Y)M.endImage.Visible=true M.endImage.Position=M.startImage.Position M:FadeThumbstick(true)M:MoveStick(o.Position)end M.moveTouchLockedIn=true local I=Vector2.new(o.Position.x-M.moveTouchStartPosition.x,o.Position.y-M.moveTouchStartPosition.y)if math.abs(I.x)>0 or math.abs(I.y)>0 then M:DoMove(I)M:MoveStick(o.Position)end return Enum.ContextActionResult.Sink end return Enum.ContextActionResult.Pass end local function l(o)if o==M.moveTouchObject then M:OnInputEnded()if M.moveTouchLockedIn then return Enum.ContextActionResult.Sink end end return Enum.ContextActionResult.Pass end local function U(U,Y,D)if Y==Enum.UserInputState.Begin then return o(D)elseif Y==Enum.UserInputState.Change then return I(D)elseif Y==Enum.UserInputState.End then return l(D)elseif Y==Enum.UserInputState.Cancel then M:OnInputEnded()end end ContextActionService:BindActionAtPriority(DYNAMIC_THUMBSTICK_ACTION_NAME,U,false,DYNAMIC_THUMBSTICK_ACTION_PRIORITY,Enum.UserInputType.Touch)end function DynamicThumbstick.Create(o,M)if o.thumbstickFrame then o.thumbstickFrame:Destroy()o.thumbstickFrame=nil if o.onRenderSteppedConn then o.onRenderSteppedConn:Disconnect()o.onRenderSteppedConn=nil end end o.thumbstickSize=45 o.thumbstickRingSize=20 o.middleSize=10 o.middleSpacing=o.middleSize+4 o.radiusOfDeadZone=2 o.radiusOfMaxSpeed=20 local I=M.AbsoluteSize local l=math.min(I.x,I.y)>500 if l then o.thumbstickSize=o.thumbstickSize*2 o.thumbstickRingSize=o.thumbstickRingSize*2 o.middleSize=o.middleSize*2 o.middleSpacing=o.middleSpacing*2 o.radiusOfDeadZone=o.radiusOfDeadZone*2 o.radiusOfMaxSpeed=o.radiusOfMaxSpeed*2 end local function U(M)if M then o.thumbstickFrame.Size=UDim2.new(1,0,.4,0)o.thumbstickFrame.Position=UDim2.new(0,0,.6,0)else o.thumbstickFrame.Size=UDim2.new(.4,0,.66666666666667,0)o.thumbstickFrame.Position=UDim2.new(0,0,.33333333333333,0)end end o.thumbstickFrame=Instance.new("\070\114\097\109\101")o.thumbstickFrame.BorderSizePixel=0 o.thumbstickFrame.Name="\068\121\110\097\109\105\099\084\104\117\109\098\115\116\105\099\107\070\114\097\109\101"o.thumbstickFrame.Visible=false o.thumbstickFrame.BackgroundTransparency=1.0 o.thumbstickFrame.BackgroundColor3=Color3.fromRGB(0,0,0)o.thumbstickFrame.Active=false U(false)o.startImage=Instance.new("\073\109\097\103\101\076\097\098\101\108")o.startImage.Name="\084\104\117\109\098\115\116\105\099\107\083\116\097\114\116"o.startImage.Visible=true o.startImage.BackgroundTransparency=1 o.startImage.Image=TOUCH_CONTROLS_SHEET o.startImage.ImageRectOffset=Vector2.new(1,1)o.startImage.ImageRectSize=Vector2.new(144,144)o.startImage.ImageColor3=Color3.new(0,0,0)o.startImage.AnchorPoint=Vector2.new(.5,.5)o.startImage.Position=UDim2.new(0,o.thumbstickRingSize*3.3,1,-o.thumbstickRingSize*2.8)o.startImage.Size=UDim2.new(0,o.thumbstickRingSize*3.7,0,o.thumbstickRingSize*3.7)o.startImage.ZIndex=10 o.startImage.Parent=o.thumbstickFrame o.endImage=Instance.new("\073\109\097\103\101\076\097\098\101\108")o.endImage.Name="\084\104\117\109\098\115\116\105\099\107\069\110\100"o.endImage.Visible=true o.endImage.BackgroundTransparency=1 o.endImage.Image=TOUCH_CONTROLS_SHEET o.endImage.ImageRectOffset=Vector2.new(1,1)o.endImage.ImageRectSize=Vector2.new(144,144)o.endImage.AnchorPoint=Vector2.new(.5,.5)o.endImage.Position=o.startImage.Position o.endImage.Size=UDim2.new(0,o.thumbstickSize*.8,0,o.thumbstickSize*.8)o.endImage.ZIndex=10 o.endImage.Parent=o.thumbstickFrame for M=1,NUM_MIDDLE_IMAGES,1 do o.middleImages[M]=Instance.new("\073\109\097\103\101\076\097\098\101\108")o.middleImages[M].Name="\084\104\117\109\098\115\116\105\099\107\077\105\100\100\108\101"o.middleImages[M].Visible=false o.middleImages[M].BackgroundTransparency=1 o.middleImages[M].Image=TOUCH_CONTROLS_SHEET o.middleImages[M].ImageRectOffset=Vector2.new(1,1)o.middleImages[M].ImageRectSize=Vector2.new(144,144)o.middleImages[M].ImageTransparency=MIDDLE_TRANSPARENCIES[M]o.middleImages[M].AnchorPoint=Vector2.new(.5,.5)o.middleImages[M].ZIndex=9 o.middleImages[M].Parent=o.thumbstickFrame end local Y=nil local function D()if Y then Y:Disconnect()Y=nil end local M=workspace.CurrentCamera if M then local function o()local o=M.ViewportSize local I=o.X<o.Y U(I)end Y=(M:GetPropertyChangedSignal("\086\105\101\119\112\111\114\116\083\105\122\101")):Connect(o)o()end end;(workspace:GetPropertyChangedSignal("\067\117\114\114\101\110\116\067\097\109\101\114\097")):Connect(D)if workspace.CurrentCamera then D()end o.moveTouchStartPosition=nil o.startImageFadeTween=nil o.endImageFadeTween=nil o.middleImageFadeTweens={}o.onRenderSteppedConn=RunService.RenderStepped:Connect(function()if o.tweenInAlphaStart~=nil then local M=tick()-o.tweenInAlphaStart local I=(o.fadeInAndOutHalfDuration*2)*o.fadeInAndOutBalance o.thumbstickFrame.BackgroundTransparency=1-FADE_IN_OUT_MAX_ALPHA*math.min(M/I,1)if M>I then o.tweenOutAlphaStart=tick()o.tweenInAlphaStart=nil end elseif o.tweenOutAlphaStart~=nil then local M=tick()-o.tweenOutAlphaStart local I=o.fadeInAndOutHalfDuration*2-(o.fadeInAndOutHalfDuration*2)*o.fadeInAndOutBalance o.thumbstickFrame.BackgroundTransparency=(1-FADE_IN_OUT_MAX_ALPHA)+FADE_IN_OUT_MAX_ALPHA*math.min(M/I,1)if M>I then o.tweenOutAlphaStart=nil end end end)o.onTouchEndedConn=UserInputService.TouchEnded:connect(function(M)if M==o.moveTouchObject then o:OnInputEnded()end end)GuiService.MenuOpened:connect(function()if o.moveTouchObject then o:OnInputEnded()end end)local t=LocalPlayer:FindFirstChildOfClass("\080\108\097\121\101\114\071\117\105")while not t do LocalPlayer.ChildAdded:wait()t=LocalPlayer:FindFirstChildOfClass("\080\108\097\121\101\114\071\117\105")end local k=nil local i=t.CurrentScreenOrientation==Enum.ScreenOrientation.LandscapeLeft or t.CurrentScreenOrientation==Enum.ScreenOrientation.LandscapeRight local function P()o.fadeInAndOutHalfDuration=2.5 o.fadeInAndOutBalance=.05 o.tweenInAlphaStart=tick()end k=(t:GetPropertyChangedSignal("\067\117\114\114\101\110\116\083\099\114\101\101\110\079\114\105\101\110\116\097\116\105\111\110")):Connect(function()if i and t.CurrentScreenOrientation==Enum.ScreenOrientation.Portrait or not i and t.CurrentScreenOrientation~=Enum.ScreenOrientation.Portrait then k:disconnect()P()if i then o.hasFadedBackgroundInPortrait=true else o.hasFadedBackgroundInLandscape=true end end end)o.thumbstickFrame.Parent=M if FFlagUserDTFastInit then if game:IsLoaded()then P()else(coroutine.wrap(function()game.Loaded:Wait()P()end))()end else spawn(function()if game:IsLoaded()then P()else game.Loaded:wait()P()end end)end end return DynamicThumbstick

function DynamicThumbstick:OnInputEnded()
	self.moveTouchObject = nil
	self.moveVector = ZERO_VECTOR3
	self:FadeThumbstick(false)
end

function DynamicThumbstick:FadeThumbstick(visible)
	if not visible and self.moveTouchObject then
		return
	end
	if self.isFirstTouch then return end

	if self.startImageFadeTween then
		self.startImageFadeTween:Cancel()
	end
	if self.endImageFadeTween then
		self.endImageFadeTween:Cancel()
	end
	for i = 1, #self.middleImages do
		if self.middleImageFadeTweens[i] then
			self.middleImageFadeTweens[i]:Cancel()
		end
	end

	if visible then
		self.startImageFadeTween = TweenService:Create(self.startImage, ThumbstickFadeTweenInfo, { ImageTransparency = 0 })
		self.startImageFadeTween:Play()

		self.endImageFadeTween = TweenService:Create(self.endImage, ThumbstickFadeTweenInfo, { ImageTransparency = 0.2 })
		self.endImageFadeTween:Play()

		for i = 1, #self.middleImages do
			self.middleImageFadeTweens[i] = TweenService:Create(self.middleImages[i], ThumbstickFadeTweenInfo, { ImageTransparency = MIDDLE_TRANSPARENCIES[i] })
			self.middleImageFadeTweens[i]:Play()
		end
	else
		self.startImageFadeTween = TweenService:Create(self.startImage, ThumbstickFadeTweenInfo, { ImageTransparency = 1 })
		self.startImageFadeTween:Play()

		self.endImageFadeTween = TweenService:Create(self.endImage, ThumbstickFadeTweenInfo, { ImageTransparency = 1 })
		self.endImageFadeTween:Play()

		for i = 1, #self.middleImages do
			self.middleImageFadeTweens[i] = TweenService:Create(self.middleImages[i], ThumbstickFadeTweenInfo, { ImageTransparency = 1 })
			self.middleImageFadeTweens[i]:Play()
		end
	end
end

function DynamicThumbstick:FadeThumbstickFrame(fadeDuration, fadeRatio)
	self.fadeInAndOutHalfDuration = fadeDuration * 0.5
	self.fadeInAndOutBalance = fadeRatio
	self.tweenInAlphaStart = tick()
end

function DynamicThumbstick:InputInFrame(inputObject)
	local frameCornerTopLeft = self.thumbstickFrame.AbsolutePosition
	local frameCornerBottomRight = frameCornerTopLeft + self.thumbstickFrame.AbsoluteSize
	local inputPosition = inputObject.Position
	if inputPosition.X >= frameCornerTopLeft.X and inputPosition.Y >= frameCornerTopLeft.Y then
		if inputPosition.X <= frameCornerBottomRight.X and inputPosition.Y <= frameCornerBottomRight.Y then
			return true
		end
	end
	return false
end

function DynamicThumbstick:DoFadeInBackground()
	local playerGui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
	local hasFadedBackgroundInOrientation = false

	-- only fade in/out the background once per orientation
	if playerGui then
		if playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeLeft or
			playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeRight then
				hasFadedBackgroundInOrientation = self.hasFadedBackgroundInLandscape
				self.hasFadedBackgroundInLandscape = true
		elseif playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.Portrait then
				hasFadedBackgroundInOrientation = self.hasFadedBackgroundInPortrait
				self.hasFadedBackgroundInPortrait = true
		end
	end

	if not hasFadedBackgroundInOrientation then
		self.fadeInAndOutHalfDuration = FADE_IN_OUT_HALF_DURATION_DEFAULT
		self.fadeInAndOutBalance = FADE_IN_OUT_BALANCE_DEFAULT
		self.tweenInAlphaStart = tick()
	end
end

function DynamicThumbstick:DoMove(direction)
	local currentMoveVector = direction

	-- Scaled Radial Dead Zone
	local inputAxisMagnitude = currentMoveVector.magnitude
	if inputAxisMagnitude < self.radiusOfDeadZone then
		currentMoveVector = ZERO_VECTOR3
	else
		currentMoveVector = currentMoveVector.unit*(
			1 - math.max(0, (self.radiusOfMaxSpeed - currentMoveVector.magnitude)/self.radiusOfMaxSpeed)
		)
		currentMoveVector = Vector3.new(currentMoveVector.x, 0, currentMoveVector.y)
	end

	self.moveVector = currentMoveVector
end


function DynamicThumbstick:LayoutMiddleImages(startPos, endPos)
	local startDist = (self.thumbstickSize / 2) + self.middleSize
	local vector = endPos - startPos
	local distAvailable = vector.magnitude - (self.thumbstickRingSize / 2) - self.middleSize
	local direction = vector.unit

	local distNeeded = self.middleSpacing * NUM_MIDDLE_IMAGES
	local spacing = self.middleSpacing

	if distNeeded < distAvailable then
		spacing = distAvailable / NUM_MIDDLE_IMAGES
	end

	for i = 1, NUM_MIDDLE_IMAGES do
		local image = self.middleImages[i]
		local distWithout = startDist + (spacing * (i - 2))
		local currentDist = startDist + (spacing * (i - 1))

		if distWithout < distAvailable then
			local pos = endPos - direction * currentDist
			local exposedFraction = math.clamp(1 - ((currentDist - distAvailable) / spacing), 0, 1)

			image.Visible = true
			image.Position = UDim2.new(0, pos.X, 0, pos.Y)
			image.Size = UDim2.new(0, self.middleSize * exposedFraction, 0, self.middleSize * exposedFraction)
		else
			image.Visible = false
		end
	end
end

function DynamicThumbstick:MoveStick(pos)
	local vector2StartPosition = Vector2.new(self.moveTouchStartPosition.X, self.moveTouchStartPosition.Y)
	local startPos = vector2StartPosition - self.thumbstickFrame.AbsolutePosition
	local endPos = Vector2.new(pos.X, pos.Y) - self.thumbstickFrame.AbsolutePosition
	self.endImage.Position = UDim2.new(0, endPos.X, 0, endPos.Y)
	self:LayoutMiddleImages(startPos, endPos)
end

function DynamicThumbstick:BindContextActions()
	local function inputBegan(inputObject)
		if self.moveTouchObject then
			return Enum.ContextActionResult.Pass
		end

		if not self:InputInFrame(inputObject) then
			return Enum.ContextActionResult.Pass
		end

		if self.isFirstTouch then
			self.isFirstTouch = false
			local tweenInfo = TweenInfo.new(0.5, Enum.EasingStyle.Quad, Enum.EasingDirection.Out,0,false,0)
			TweenService:Create(self.startImage, tweenInfo, {Size = UDim2.new(0, 0, 0, 0)}):Play()
			TweenService:Create(
				self.endImage,
				tweenInfo,
				{Size = UDim2.new(0, self.thumbstickSize, 0, self.thumbstickSize), ImageColor3 = Color3.new(0,0,0)}
			):Play()
		end

		self.moveTouchLockedIn = false
		self.moveTouchObject = inputObject
		self.moveTouchStartPosition = inputObject.Position
		self.moveTouchFirstChanged = true

		if FADE_IN_OUT_BACKGROUND then
			self:DoFadeInBackground()
		end

		return Enum.ContextActionResult.Pass
	end

	local function inputChanged(inputObject)
		if inputObject == self.moveTouchObject then
			if self.moveTouchFirstChanged then
				self.moveTouchFirstChanged = false

				local startPosVec2 = Vector2.new(
					inputObject.Position.X - self.thumbstickFrame.AbsolutePosition.X,
					inputObject.Position.Y - self.thumbstickFrame.AbsolutePosition.Y
				)
				self.startImage.Visible = true
				self.startImage.Position = UDim2.new(0, startPosVec2.X, 0, startPosVec2.Y)
				self.endImage.Visible = true
				self.endImage.Position = self.startImage.Position

				self:FadeThumbstick(true)
				self:MoveStick(inputObject.Position)
			end

			self.moveTouchLockedIn = true

			local direction = Vector2.new(
				inputObject.Position.x - self.moveTouchStartPosition.x,
				inputObject.Position.y - self.moveTouchStartPosition.y
			)
			if math.abs(direction.x) > 0 or math.abs(direction.y) > 0 then
				self:DoMove(direction)
				self:MoveStick(inputObject.Position)
			end
			return Enum.ContextActionResult.Sink
		end
		return Enum.ContextActionResult.Pass
	end

	local function inputEnded(inputObject)
		if inputObject == self.moveTouchObject then
			self:OnInputEnded()
			if self.moveTouchLockedIn then
				return Enum.ContextActionResult.Sink
			end
		end
		return Enum.ContextActionResult.Pass
	end

	local function handleInput(actionName, inputState, inputObject)
		if inputState == Enum.UserInputState.Begin then
			return inputBegan(inputObject)
		elseif inputState == Enum.UserInputState.Change then
			return inputChanged(inputObject)
		elseif inputState == Enum.UserInputState.End then
			return inputEnded(inputObject)
		elseif inputState == Enum.UserInputState.Cancel then
			self:OnInputEnded()
		end
	end

	ContextActionService:BindActionAtPriority(
		DYNAMIC_THUMBSTICK_ACTION_NAME,
		handleInput,
		false,
		DYNAMIC_THUMBSTICK_ACTION_PRIORITY,
		Enum.UserInputType.Touch)
end

function DynamicThumbstick:Create(parentFrame)
	if self.thumbstickFrame then
		self.thumbstickFrame:Destroy()
		self.thumbstickFrame = nil
		if self.onRenderSteppedConn then
			self.onRenderSteppedConn:Disconnect()
			self.onRenderSteppedConn = nil
		end
	end

	self.thumbstickSize = 45
	self.thumbstickRingSize = 20
	self.middleSize = 10
	self.middleSpacing = self.middleSize + 4
	self.radiusOfDeadZone = 2
	self.radiusOfMaxSpeed = 20

	local screenSize = parentFrame.AbsoluteSize
	local isBigScreen = math.min(screenSize.x, screenSize.y) > 500
	if isBigScreen then
		self.thumbstickSize = self.thumbstickSize * 2
		self.thumbstickRingSize = self.thumbstickRingSize * 2
		self.middleSize = self.middleSize * 2
		self.middleSpacing = self.middleSpacing * 2
		self.radiusOfDeadZone = self.radiusOfDeadZone * 2
		self.radiusOfMaxSpeed = self.radiusOfMaxSpeed * 2
	end

	local function layoutThumbstickFrame(portraitMode)
		if portraitMode then
			self.thumbstickFrame.Size = UDim2.new(1, 0, 0.4, 0)
			self.thumbstickFrame.Position = UDim2.new(0, 0, 0.6, 0)
		else
			self.thumbstickFrame.Size = UDim2.new(0.4, 0, 2/3, 0)
			self.thumbstickFrame.Position = UDim2.new(0, 0, 1/3, 0)
		end
	end

	self.thumbstickFrame = Instance.new("Frame")
	self.thumbstickFrame.BorderSizePixel = 0
	self.thumbstickFrame.Name = "DynamicThumbstickFrame"
	self.thumbstickFrame.Visible = false
	self.thumbstickFrame.BackgroundTransparency = 1.0
	self.thumbstickFrame.BackgroundColor3 = Color3.fromRGB(0, 0, 0)
	self.thumbstickFrame.Active = false
	layoutThumbstickFrame(false)

	self.startImage = Instance.new("ImageLabel")
	self.startImage.Name = "ThumbstickStart"
	self.startImage.Visible = true
	self.startImage.BackgroundTransparency = 1
	self.startImage.Image = TOUCH_CONTROLS_SHEET
	self.startImage.ImageRectOffset = Vector2.new(1,1)
	self.startImage.ImageRectSize = Vector2.new(144, 144)
	self.startImage.ImageColor3 = Color3.new(0, 0, 0)
	self.startImage.AnchorPoint = Vector2.new(0.5, 0.5)
	self.startImage.Position = UDim2.new(0, self.thumbstickRingSize * 3.3, 1, -self.thumbstickRingSize  * 2.8)
	self.startImage.Size = UDim2.new(0, self.thumbstickRingSize  * 3.7, 0, self.thumbstickRingSize  * 3.7)
	self.startImage.ZIndex = 10
	self.startImage.Parent = self.thumbstickFrame

	self.endImage = Instance.new("ImageLabel")
	self.endImage.Name = "ThumbstickEnd"
	self.endImage.Visible = true
	self.endImage.BackgroundTransparency = 1
	self.endImage.Image = TOUCH_CONTROLS_SHEET
	self.endImage.ImageRectOffset = Vector2.new(1,1)
	self.endImage.ImageRectSize =  Vector2.new(144, 144)
	self.endImage.AnchorPoint = Vector2.new(0.5, 0.5)
	self.endImage.Position = self.startImage.Position
	self.endImage.Size = UDim2.new(0, self.thumbstickSize * 0.8, 0, self.thumbstickSize * 0.8)
	self.endImage.ZIndex = 10
	self.endImage.Parent = self.thumbstickFrame

	for i = 1, NUM_MIDDLE_IMAGES do
		self.middleImages[i] = Instance.new("ImageLabel")
		self.middleImages[i].Name = "ThumbstickMiddle"
		self.middleImages[i].Visible = false
		self.middleImages[i].BackgroundTransparency = 1
		self.middleImages[i].Image = TOUCH_CONTROLS_SHEET
		self.middleImages[i].ImageRectOffset = Vector2.new(1,1)
		self.middleImages[i].ImageRectSize = Vector2.new(144, 144)
		self.middleImages[i].ImageTransparency = MIDDLE_TRANSPARENCIES[i]
		self.middleImages[i].AnchorPoint = Vector2.new(0.5, 0.5)
		self.middleImages[i].ZIndex = 9
		self.middleImages[i].Parent = self.thumbstickFrame
	end

	local CameraChangedConn = nil
	local function onCurrentCameraChanged()
		if CameraChangedConn then
			CameraChangedConn:Disconnect()
			CameraChangedConn = nil
		end
		local newCamera = workspace.CurrentCamera
		if newCamera then
			local function onViewportSizeChanged()
				local size = newCamera.ViewportSize
				local portraitMode = size.X < size.Y
				layoutThumbstickFrame(portraitMode)
			end
			CameraChangedConn = newCamera:GetPropertyChangedSignal("ViewportSize"):Connect(onViewportSizeChanged)
			onViewportSizeChanged()
		end
	end
	workspace:GetPropertyChangedSignal("CurrentCamera"):Connect(onCurrentCameraChanged)
	if workspace.CurrentCamera then
		onCurrentCameraChanged()
	end

	self.moveTouchStartPosition = nil

	self.startImageFadeTween = nil
	self.endImageFadeTween = nil
	self.middleImageFadeTweens = {}

	self.onRenderSteppedConn = RunService.RenderStepped:Connect(function()
		if self.tweenInAlphaStart ~= nil then
			local delta = tick() - self.tweenInAlphaStart
			local fadeInTime = (self.fadeInAndOutHalfDuration * 2 * self.fadeInAndOutBalance)
			self.thumbstickFrame.BackgroundTransparency = 1 - FADE_IN_OUT_MAX_ALPHA*math.min(delta/fadeInTime, 1)
			if delta > fadeInTime then
				self.tweenOutAlphaStart = tick()
				self.tweenInAlphaStart = nil
			end
		elseif self.tweenOutAlphaStart ~= nil then
			local delta = tick() - self.tweenOutAlphaStart
			local fadeOutTime = (self.fadeInAndOutHalfDuration * 2) - (self.fadeInAndOutHalfDuration * 2 * self.fadeInAndOutBalance)
			self.thumbstickFrame.BackgroundTransparency = 1 - FADE_IN_OUT_MAX_ALPHA + FADE_IN_OUT_MAX_ALPHA*math.min(delta/fadeOutTime, 1)
			if delta > fadeOutTime  then
				self.tweenOutAlphaStart = nil
			end
		end
	end)

	self.onTouchEndedConn = UserInputService.TouchEnded:connect(function(inputObject)
		if inputObject == self.moveTouchObject then
			self:OnInputEnded()
		end
	end)

	GuiService.MenuOpened:connect(function()
		if self.moveTouchObject then
			self:OnInputEnded()
		end
	end)

	local playerGui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
	while not playerGui do
		LocalPlayer.ChildAdded:wait()
		playerGui = LocalPlayer:FindFirstChildOfClass("PlayerGui")
	end

	local playerGuiChangedConn = nil
	local originalScreenOrientationWasLandscape =	playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeLeft or
													playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.LandscapeRight

	local function longShowBackground()
		self.fadeInAndOutHalfDuration = 2.5
		self.fadeInAndOutBalance = 0.05
		self.tweenInAlphaStart = tick()
	end

	playerGuiChangedConn = playerGui:GetPropertyChangedSignal("CurrentScreenOrientation"):Connect(function()
		if (originalScreenOrientationWasLandscape and playerGui.CurrentScreenOrientation == Enum.ScreenOrientation.Portrait) or
			(not originalScreenOrientationWasLandscape and playerGui.CurrentScreenOrientation ~= Enum.ScreenOrientation.Portrait) then

			playerGuiChangedConn:disconnect()
			longShowBackground()

			if originalScreenOrientationWasLandscape then
				self.hasFadedBackgroundInPortrait = true
			else
				self.hasFadedBackgroundInLandscape = true
			end
		end
	end)

	self.thumbstickFrame.Parent = parentFrame

	if FFlagUserDTFastInit then
		if game:IsLoaded() then
			longShowBackground()
		else
			coroutine.wrap(function()
				game.Loaded:Wait()
				longShowBackground()
			end)()
		end
	else
		spawn(function()
			if game:IsLoaded() then
				longShowBackground()
			else
				game.Loaded:wait()
				longShowBackground()
			end
		end)
	end
end

return DynamicThumbstick
