mirror of
https://github.com/copyrighttxt/watrbx-game-engine.git
synced 2026-09-05 13:17:49 +00:00
189 lines
5.4 KiB
Lua
189 lines
5.4 KiB
Lua
--Dialog: 3D dialogs for ROBLOX in VR
|
|
--written by 0xBAADF00D
|
|
--6/30/2016
|
|
|
|
local CoreGui = game:GetService("CoreGui")
|
|
local RobloxGui = CoreGui:WaitForChild("RobloxGui")
|
|
local InputService = game:GetService("UserInputService")
|
|
local Utility = require(RobloxGui.Modules.Settings.Utility)
|
|
local Panel3D = require(RobloxGui.Modules.VR.Panel3D)
|
|
|
|
local DIALOG_BG_COLOR = Color3.new(0.2, 0.2, 0.2)
|
|
local DIALOG_BG_TRANSPARENCY = 0.3
|
|
local DIALOG_TITLE_HEIGHT = 66
|
|
local DIALOG_COLOR_HEIGHT = 8
|
|
local DIALOG_TITLE_TEXT_SIZE = Enum.FontSize.Size36
|
|
local DIALOG_CONTENT_PADDING = 48
|
|
local TITLE_COLOR = Color3.new(1, 1, 1)
|
|
|
|
local PANEL_OFFSET_CF = CFrame.new(0, 0, -7) * CFrame.Angles(0, math.pi, 0)
|
|
|
|
local emptySelectionImage = Utility:Create "ImageLabel" {
|
|
Name = "EmptySelectionImage",
|
|
Image = "",
|
|
BackgroundTransparency = 1,
|
|
ImageTransparency = 1
|
|
}
|
|
|
|
local DialogPanel = Panel3D.Get("Dialog")
|
|
DialogPanel:SetType(Panel3D.Type.Fixed)
|
|
DialogPanel.localCF = PANEL_OFFSET_CF
|
|
DialogPanel:SetCanFade(true)
|
|
|
|
local dialogPanelAngle = 0
|
|
local opacityLookup = {}
|
|
local resetBaseAngle = false
|
|
local baseAngle = 0
|
|
|
|
|
|
local PANEL_FADE_ANGLE_0, PANEL_FADE_ANGLE_1 = math.rad(37.5), math.rad(44)
|
|
local PANEL_FADE_RANGE = PANEL_FADE_ANGLE_1 - PANEL_FADE_ANGLE_0
|
|
local PANEL_REAPPEAR_ANGLE = math.rad(90)
|
|
|
|
local function positionDialogPanel(desiredAngle)
|
|
dialogPanelAngle = desiredAngle
|
|
local headCF = InputService:GetUserCFrame(Enum.UserCFrame.Head)
|
|
local headPos = headCF.p
|
|
DialogPanel.localCF = CFrame.new(headPos) * CFrame.Angles(0, desiredAngle, 0) * PANEL_OFFSET_CF
|
|
end
|
|
|
|
function DialogPanel:CalculateTransparency()
|
|
local headCF = InputService:GetUserCFrame(Enum.UserCFrame.Head)
|
|
local headLook = headCF.lookVector * Vector3.new(1, 0, 1)
|
|
local vertAngle = math.asin(headCF.lookVector.Y)
|
|
local vectorToPanel = Vector3.new(math.cos(baseAngle + dialogPanelAngle + math.rad(90)), 0, -math.sin(baseAngle + dialogPanelAngle + math.rad(90)))
|
|
|
|
if math.abs(vertAngle) > PANEL_FADE_ANGLE_1 then
|
|
resetBaseAngle = true
|
|
end
|
|
|
|
local angleToPanel = math.acos(headLook:Dot(vectorToPanel))
|
|
|
|
return math.min(math.max(0, (angleToPanel - PANEL_FADE_ANGLE_0) / PANEL_FADE_RANGE), 1)
|
|
end
|
|
|
|
|
|
local function updatePanelPosition()
|
|
local headCF = InputService:GetUserCFrame(Enum.UserCFrame.Head)
|
|
local headLook = headCF.lookVector * Vector3.new(1, 0, 1)
|
|
local headAngle = (math.atan2(-headLook.Z, headLook.X) - math.rad(90)) % math.rad(360)
|
|
local newPanelAngle = baseAngle + math.floor((headAngle / PANEL_REAPPEAR_ANGLE) + 0.5) * PANEL_REAPPEAR_ANGLE
|
|
|
|
if resetBaseAngle then
|
|
resetBaseAngle = false
|
|
baseAngle = headAngle
|
|
end
|
|
|
|
positionDialogPanel(newPanelAngle)
|
|
end
|
|
|
|
|
|
game:GetService("RunService"):BindToRenderStep("DialogPanel", Enum.RenderPriority.First.Value, function()
|
|
if DialogPanel.transparency == 1 or resetBaseAngle then
|
|
updatePanelPosition()
|
|
end
|
|
|
|
--update the transparency of gui elements
|
|
local opacityMult = 1 - DialogPanel.transparency
|
|
for guiElement, baseOpacity in pairs(opacityLookup) do
|
|
local transparency = 1 - (baseOpacity * opacityMult)
|
|
if guiElement:IsA("TextLabel") or guiElement:IsA("TextButton") then
|
|
guiElement.TextTransparency = transparency
|
|
elseif guiElement:IsA("ImageLabel") or guiElement:IsA("ImageButton") then
|
|
guiElement.ImageTransparency = transparency
|
|
elseif guiElement:IsA("Frame") then
|
|
guiElement.BackgroundTransparency = transparency
|
|
end
|
|
end
|
|
end)
|
|
|
|
local DialogQueue = {}
|
|
|
|
local currentDescendantConn = nil
|
|
local lastDialogShown = nil
|
|
local function updatePanel()
|
|
local currentDialog = DialogQueue[1]
|
|
if lastDialogShown and lastDialogShown.content then
|
|
lastDialogShown.content.Parent = nil
|
|
end
|
|
if not currentDialog or not currentDialog.content then
|
|
DialogPanel:SetVisible(false)
|
|
opacityLookup = {}
|
|
if currentDescendantConn then
|
|
currentDescendantConn:disconnect()
|
|
currentDescendantConn = nil
|
|
end
|
|
else
|
|
currentDialog.content.Parent = DialogPanel:GetGUI()
|
|
lastDialogShown = currentDialog
|
|
|
|
local contentSize = currentDialog.content.AbsoluteSize
|
|
DialogPanel:ResizePixels(contentSize.X, contentSize.Y, 100)
|
|
|
|
resetBaseAngle = true
|
|
updatePanelPosition()
|
|
DialogPanel:SetVisible(true)
|
|
|
|
opacityLookup = {}
|
|
local function search(parent)
|
|
if parent:IsA("ImageLabel") or parent:IsA("ImageButton") then
|
|
opacityLookup[parent] = 1 - parent.ImageTransparency
|
|
elseif parent:IsA("TextLabel") or parent:IsA("TextButton") then
|
|
opacityLookup[parent] = 1 - parent.TextTransparency
|
|
elseif parent:IsA("Frame") then
|
|
opacityLookup[parent] = 1 - parent.BackgroundTransparency
|
|
end
|
|
for i, v in pairs(parent:GetChildren()) do
|
|
search(v)
|
|
end
|
|
end
|
|
search(DialogPanel:GetGUI())
|
|
if currentDescendantConn then
|
|
currentDescendantConn:disconnect()
|
|
currentDescendantConn = nil
|
|
end
|
|
currentDescendantConn = DialogPanel:GetGUI().DescendantAdded:connect(function(descendant)
|
|
search(descendant)
|
|
end)
|
|
|
|
|
|
end
|
|
end
|
|
|
|
|
|
|
|
local Dialog = {}
|
|
Dialog.__index = Dialog
|
|
function Dialog.new(content)
|
|
local self = setmetatable({}, Dialog)
|
|
self.content = content
|
|
return self
|
|
end
|
|
|
|
function Dialog:SetContent(guiElement)
|
|
if not guiElement and self.content then
|
|
self.content.Parent = nil
|
|
end
|
|
self.content = guiElement
|
|
end
|
|
|
|
function Dialog:Show(shouldTakeover)
|
|
if shouldTakeover then
|
|
table.insert(DialogQueue, 1, self)
|
|
else
|
|
table.insert(DialogQueue, self)
|
|
end
|
|
updatePanel()
|
|
end
|
|
|
|
function Dialog:Close()
|
|
for idx, dialog in pairs(DialogQueue) do
|
|
if dialog == self then
|
|
table.remove(DialogQueue, idx)
|
|
break
|
|
end
|
|
end
|
|
updatePanel()
|
|
end
|
|
|
|
return Dialog |