local A=game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")local p=A:WaitForChild("\077\111\100\117\108\101\115")local f=require(p.src.utils.Logger)local R=require(p.src.AudioPlayer)local u=game:GetService("\082\117\110\083\101\114\118\105\099\101")local K=game:GetService("\087\111\114\107\115\112\097\099\101")local d=require(p.Roact)local i=d.createElement local g=d.PureComponent:extend("\089\065\120\105\115\066\105\108\108\098\111\097\114\100")function g.init(A)A.partRef=d.createRef()end function g._updatePosition(A)local p=K.CurrentCamera.CFrame local f=math.atan2(A.props.position.x-p.p.x,A.props.position.z-p.p.z)local R=CFrame.Angles(0,f,0)+A.props.position A.partRef.current.CFrame=R end function g.render(A)local p=A.props.size return i("\080\097\114\116",{Size=Vector3.new(p.X,p.Y,.1),Transparency=1,Anchored=true;CanCollide=false;[d.Ref]=A.partRef},{ClickDetector=i("\067\108\105\099\107\068\101\116\101\099\116\111\114",{[d.Event.MouseClick]=function()R.playAudio("\083\105\109\112\108\101\095\067\108\105\099\107")A.props.onClicked()end});UI=i("\083\117\114\102\097\099\101\071\117\105",{Face=Enum.NormalId.Front,CanvasSize=100*p},A.props[d.Children])})end function g.didMount(A)A._connection=u.RenderStepped:Connect(function()A:_updatePosition()end)A:_updatePosition()end function g.didUpdate(A)A:_updatePosition()end function g.willUnmount(A)A._connection:Disconnect()end return g
--[[
	A SurfaceGui-based billboard that only pivots on the Y axis.

	The primary UI container is rendered with Roact, but the pivoting is handled
	by manually changing the containing part's CFrame directly every frame.

	This file is a good example of mutating properties manually on an otherwise
	Roact-owned object. It's a very powerful way to get a performance boost at
	the cost of some readability and potentially some bugs.
]]

local ReplicatedStorage = game:GetService('ReplicatedStorage')
local Modules = ReplicatedStorage:WaitForChild('Modules')
local logger = require(Modules.src.utils.Logger)
local AudioPlayer = require(Modules.src.AudioPlayer)
local RunService = game:GetService('RunService')
local Workspace = game:GetService('Workspace')

local Roact = require(Modules.Roact)
local createElement = Roact.createElement

local YAxisBillboard = Roact.PureComponent:extend('YAxisBillboard')

function YAxisBillboard:init()
	self.partRef = Roact.createRef()
end

function YAxisBillboard:_updatePosition()
	-- This function gets invoked on initial mount, every time the component is
	-- updated via Roact, and every frame. That helps make sure that we won't
	-- be out-of-sync with our props.

	local cameraCFrame = Workspace.CurrentCamera.CFrame

	local angle =
		math.atan2(
			self.props.position.x - cameraCFrame.p.x,
			self.props.position.z - cameraCFrame.p.z
		)

	local uiLocation = CFrame.Angles(0, angle, 0) + self.props.position

	self.partRef.current.CFrame = uiLocation
end

function YAxisBillboard:render()
	local size = self.props.size

	return createElement(
		'Part',
		{
			-- When doing manual mutation alongside Roact, it's important to avoid
			-- setting the properties we're managing manually from inside render.
			-- Otherwise, the reconciler will fight you!

			Size = Vector3.new(size.X, size.Y, 0.1),
			Transparency = 1,
			Anchored = true,
			CanCollide = false,
			[Roact.Ref] = self.partRef,
		},
		{
			-- If we wanted interaction with our ScreenGui, this is where we could
			-- use Roact.Portal to jump into the local player's PlayerGui
			ClickDetector = createElement('ClickDetector', { [Roact.Event.MouseClick] = function()
				AudioPlayer.playAudio('Simple_Click')
				self.props.onClicked()
			end }),
			UI = createElement(
				'SurfaceGui',
				{
					Face = Enum.NormalId.Front,
					CanvasSize = 100 * size,
				},
				self.props[Roact.Children]
			),
		}
	)
end

function YAxisBillboard:didMount()
	self._connection = RunService.RenderStepped:Connect(function()
		self:_updatePosition()
	end)

	self:_updatePosition()
end

function YAxisBillboard:didUpdate()
	self:_updatePosition()
end

function YAxisBillboard:willUnmount()
	self._connection:Disconnect()
end

return YAxisBillboard