local R=game:GetService("\087\111\114\107\115\112\097\099\101")local s=require(script.Parent:WaitForChild("\066\097\115\101\084\101\115\116"))local t=require((script.Parent:WaitForChild("\067\111\109\109\111\110")):WaitForChild("\080\114\111\098\108\101\109\072\105\103\104\108\105\103\104\116\115"))local W=s:Extend()W:SetClassName("\083\117\114\102\097\099\101\071\117\105\067\114\097\115\104\084\101\115\116")function W.__new(s)s:InitializeSuper()s.Name="\083\117\114\102\097\099\101\071\117\105 \067\114\097\115\104\105\110\103"s.Icon="\078\079\078\069"s.Status="\078\111\116 \068\101\116\101\099\116\101\100"s.ProblemText="\083\117\114\102\097\099\101\071\117\105\115 \117\110\100\101\114 \087\111\114\107\115\112\097\099\101 \119\105\116\104 \083\101\108\101\099\116\097\098\108\101 \071\117\105\079\098\106\101\099\116\115 \099\097\117\115\101 \086\082 \112\108\097\121\101\114\115 \116\111 \099\114\097\115\104 \119\104\101\110 \108\111\111\107\101\100 \097\116\046"s.SolutionText="\084\104\101\114\101 \097\114\101 \051 \119\111\114\107\097\114\111\117\110\100\115\058\n\049\046 \077\111\118\101 \116\104\101 \083\117\114\102\097\099\101\071\117\105 \117\110\100\101\114 \080\108\097\121\101\114\071\117\105\046\n\050\046 \077\097\107\101 \116\104\101 \071\117\105\079\098\106\101\099\116\115 \117\110\115\101\108\101\099\116\097\098\108\101 \040\115\101\116 \083\101\108\101\099\116\097\098\108\101 \116\111 \102\097\108\115\101\041\046\n\051\046 \085\115\101 \078\101\120\117\115 \086\082 \067\111\114\101 \119\105\116\104 \116\104\101 \083\117\114\102\097\099\101\071\117\105\046"s.SurfaceGuiEvents={}s.SurfaceGuiProblems={}s.Highlights=t.new(s)R.DescendantRemoving:Connect(function(R)if not s.SurfaceGuiEvents[R]then return end for R,s in pairs(s.SurfaceGuiEvents[R])do s:Disconnect()end s.SurfaceGuiEvents[R]=nil s.SurfaceGuiProblems[R]=nil s:UpdateState()end)R.DescendantAdded:Connect(function(R)if s.SurfaceGuiEvents[R]then return end s:ConnectSurfaceGui(R)end)for R,t in pairs(R:GetDescendants())do s:ConnectSurfaceGui(t)end end function W.ConnectSurfaceGui(s,R)if not R:IsA("\083\117\114\102\097\099\101\071\117\105")then return end s.SurfaceGuiEvents[R]={}s.SurfaceGuiProblems[R]={}table.insert(s.SurfaceGuiEvents[R],R.DescendantAdded:Connect(function(t)if not t:IsA("\071\117\105\079\098\106\101\099\116")or not s.SurfaceGuiProblems[R]then return end if t.Selectable then s.SurfaceGuiProblems[R][t]=true s:UpdateState()else table.insert(s.SurfaceGuiEvents[R],(t:GetPropertyChangedSignal("\083\101\108\101\099\116\097\098\108\101")):Connect(function()if t.Selectable then s.SurfaceGuiProblems[R][t]=true s:UpdateState()end end))end end))table.insert(s.SurfaceGuiEvents[R],R.DescendantRemoving:Connect(function(t)if not t:IsA("\071\117\105\079\098\106\101\099\116")or not s.SurfaceGuiProblems[R]then return end s.SurfaceGuiProblems[R][t]=nil s:UpdateState()end))for t,W in pairs(R:GetDescendants())do if W:IsA("\071\117\105\079\098\106\101\099\116")then if W.Selectable then s.SurfaceGuiProblems[R][W]=true s:UpdateState()else table.insert(s.SurfaceGuiEvents[R],(W:GetPropertyChangedSignal("\083\101\108\101\099\116\097\098\108\101")):Connect(function()if W.Selectable then s.SurfaceGuiProblems[R][W]=true s:UpdateState()end end))end end end end function W.UpdateState(R)local s={}for R,t in pairs(R.SurfaceGuiProblems)do for t,W in pairs(t)do table.insert(s,R)break end end if#s>0 then R.Icon="\069\082\082\079\082"R.Status="\080\114\111\098\108\101\109 \068\101\116\101\099\116\101\100"else R.Icon="\078\079\078\069"R.Status="\078\111\116 \068\101\116\101\099\116\101\100"end local t={}local W={}for R,s in pairs(s)do local V=s.Adornee or s.Parent and(s.Parent:IsA("\066\097\115\101\080\097\114\116")and s.Parent)if V and not W[V]then W[V]=true table.insert(t,V)end end R.Highlights.Objects=t end return W
--[[
TheNexusAvenger

Test for SurfaceGuis under Workspace that have Selectable
frames. See:
https://devforum.roblox.com/t/vr-immediately-crashes-when-you-try-to-interact-with-any-surface-gui/498889
https://github.com/Elttob/roblox-vr-tracker/issues/2
--]]

local Workspace = game:GetService("Workspace")

local BaseTest = require(script.Parent:WaitForChild("BaseTest"))
local ProblemHighlights = require(script.Parent:WaitForChild("Common"):WaitForChild("ProblemHighlights"))

local SurfaceGuiCrashTest = BaseTest:Extend()
SurfaceGuiCrashTest:SetClassName("SurfaceGuiCrashTest")



--[[
Creates the test.
--]]
function SurfaceGuiCrashTest:__new()
    self:InitializeSuper()

    --Set up the initial state.
    self.Name = "SurfaceGui Crashing"
    self.Icon = "NONE"
    self.Status = "Not Detected"
    self.ProblemText = "SurfaceGuis under Workspace with Selectable GuiObjects cause VR players to crash when looked at."
    self.SolutionText = "There are 3 workarounds:\n1. Move the SurfaceGui under PlayerGui.\n2. Make the GuiObjects unselectable (set Selectable to false).\n3. Use Nexus VR Core with the SurfaceGui."
    self.SurfaceGuiEvents = {}
    self.SurfaceGuiProblems = {}
    self.Highlights = ProblemHighlights.new(self)

    --Connect SurfaceGuis in Workspace.
    Workspace.DescendantRemoving:Connect(function(Ins)
        if not self.SurfaceGuiEvents[Ins] then return end
        for _,Event in pairs(self.SurfaceGuiEvents[Ins]) do
            Event:Disconnect()
        end
        self.SurfaceGuiEvents[Ins] = nil
        self.SurfaceGuiProblems[Ins] = nil
        self:UpdateState()
    end)
    Workspace.DescendantAdded:Connect(function(Ins)
        if self.SurfaceGuiEvents[Ins] then return end
        self:ConnectSurfaceGui(Ins)
    end)
    for _,Ins in pairs(Workspace:GetDescendants()) do
        self:ConnectSurfaceGui(Ins)
    end
end

--[[
Connects a SurfaceGui.
--]]
function SurfaceGuiCrashTest:ConnectSurfaceGui(SurfaceGui)
    if not SurfaceGui:IsA("SurfaceGui") then return end

    --Connect the events.
    self.SurfaceGuiEvents[SurfaceGui] = {}
    self.SurfaceGuiProblems[SurfaceGui] = {}
    table.insert(self.SurfaceGuiEvents[SurfaceGui],SurfaceGui.DescendantAdded:Connect(function(Ins)
        if not Ins:IsA("GuiObject") or not self.SurfaceGuiProblems[SurfaceGui] then return end
        if Ins.Selectable then
            self.SurfaceGuiProblems[SurfaceGui][Ins] = true
            self:UpdateState()
        else
            table.insert(self.SurfaceGuiEvents[SurfaceGui],Ins:GetPropertyChangedSignal("Selectable"):Connect(function()
                if Ins.Selectable then
                    self.SurfaceGuiProblems[SurfaceGui][Ins] = true
                    self:UpdateState()
                end
            end))
        end
    end))
    table.insert(self.SurfaceGuiEvents[SurfaceGui],SurfaceGui.DescendantRemoving:Connect(function(Ins)
        if not Ins:IsA("GuiObject") or not self.SurfaceGuiProblems[SurfaceGui] then return end
        self.SurfaceGuiProblems[SurfaceGui][Ins] = nil
        self:UpdateState()
    end))

    --Connect the existing instances.
    for _,Ins in pairs(SurfaceGui:GetDescendants()) do
        if Ins:IsA("GuiObject") then
            if Ins.Selectable then
                self.SurfaceGuiProblems[SurfaceGui][Ins] = true
                self:UpdateState()
            else
                table.insert(self.SurfaceGuiEvents[SurfaceGui],Ins:GetPropertyChangedSignal("Selectable"):Connect(function()
                    if Ins.Selectable then
                        self.SurfaceGuiProblems[SurfaceGui][Ins] = true
                        self:UpdateState()
                    end
                end))
            end
        end
    end
end

--[[
Updates the state.
--]]
function SurfaceGuiCrashTest:UpdateState()
    --Determine the problematic SurfaceGuis.
    local SurfaceGuis = {}
    for SurfaceGui,FrameProblemsMap in pairs(self.SurfaceGuiProblems) do
        for _,_ in pairs(FrameProblemsMap) do
            table.insert(SurfaceGuis,SurfaceGui)
            break
        end
    end

    --Set the state if there is a problematic SurfaceGui and it wasn't set already.
    if #SurfaceGuis > 0 then
        self.Icon = "ERROR"
        self.Status = "Problem Detected"
    else
        self.Icon = "NONE"
        self.Status = "Not Detected"
    end

    --Get the parts to adorn.
    local AdornParts = {}
    local AdornPartsMap = {}
    for _,SurfaceGui in pairs(SurfaceGuis) do
        local Adornee = SurfaceGui.Adornee or (SurfaceGui.Parent and SurfaceGui.Parent:IsA("BasePart") and SurfaceGui.Parent)
        if Adornee and not AdornPartsMap[Adornee] then
            AdornPartsMap[Adornee] = true
            table.insert(AdornParts,Adornee)
        end
    end
    self.Highlights.Objects = AdornParts
end



return SurfaceGuiCrashTest