Clients/Client2018/content/scripts/CoreScripts/Modules/LoadingScreen3D.lua

373 lines
9.4 KiB
Lua

-- LoadingScreen3D.lua --
-- Written by Kip Turner, copyright ROBLOX 2016 --
local GUI_DISTANCE_FROM_CAMERA = 6
local VERTICAL_SCREEN_PERCENT = 1/3
local HORIZONTAL_SCREEN_PERCENT = 1/3
local SECOND_TO_FADE = 2.5
local ROTATIONS_PER_SECOND = 0.5
local TEXT_SCROLL_SPEED = 25
local CoreGui = game:GetService('CoreGui')
local RunService = game:GetService('RunService')
local MarketPlaceService = game:GetService('MarketplaceService')
local UserInputService = game:GetService('UserInputService')
local ReplicatedFirst = game:GetService('ReplicatedFirst')
local GuiService = game:GetService('GuiService')
local RobloxGui = CoreGui:WaitForChild("RobloxGui")
local Util = require(RobloxGui.Modules.Settings.Utility)
local function FadeElements(element, newValue, duration)
duration = duration or 0.5
if element == nil then return end
if element:IsA('ImageLabel') or element:IsA('ImageButton') then
Util:TweenProperty(element, 'ImageTransparency', element.ImageTransparency, newValue, duration, Util:GetEaseInOutQuad())
end
if element:IsA('GuiObject') then
Util:TweenProperty(element, 'BackgroundTransparency', element.BackgroundTransparency, newValue, duration, Util:GetEaseInOutQuad())
end
if element:IsA('TextLabel') or element:IsA('TextBox') or element:IsA('TextButton') then
Util:TweenProperty(element, 'TextTransparency', element.TextTransparency, newValue, duration, Util:GetEaseInOutQuad())
end
for _, child in pairs(element:GetChildren()) do
FadeElements(child, newValue, duration)
end
end
local GameInfoProvider = {}
do
local LoadingFinishedSignal = Instance.new('BindableEvent')
GameInfoProvider.Finished = false
GameInfoProvider.GameAssetInfo = nil
GameInfoProvider.LoadingFinishedEvent = LoadingFinishedSignal.Event
function GameInfoProvider:GetGameName()
if self.GameAssetInfo ~= nil then
return self.GameAssetInfo.Name
else
return ''
end
end
function GameInfoProvider:GetCreatorName()
if self.GameAssetInfo ~= nil then
return self.GameAssetInfo.Creator.Name
else
return ''
end
end
function GameInfoProvider:IsReady()
return self.Finished
end
function GameInfoProvider:LoadAssetsAsync()
spawn(function()
while game.PlaceId <= 0 do
wait()
end
-- load game asset info
local success, result = pcall(function()
self.GameAssetInfo = MarketPlaceService:GetProductInfo(game.PlaceId)
end)
if not success then
print("LoadingScript->GameInfoProvider:LoadAssets:", result)
end
self.Finished = true
LoadingFinishedSignal:Fire()
end)
end
end
local LoadingScreen = {}
local surfaceGuiAdorn = Util:Create'Part'
{
Name = "LoadingGui";
Transparency = 1;
CanCollide = false;
Anchored = true;
Archivable = false;
FormFactor = Enum.FormFactor.Custom;
RobloxLocked = true;
Parent = RobloxGui;
}
local loadingSurfaceGui = Util:Create'SurfaceGui'
{
Name = "LoadingSurfaceGui";
Adornee = surfaceGuiAdorn;
ToolPunchThroughDistance = 1000;
CanvasSize = Vector2.new(500, 500);
Archivable = false;
Parent = CoreGui;
}
local backgroundImage = Util:Create'ImageLabel'
{
Name = 'LoadingBackground';
Size = UDim2.new(1,0,1,0);
Image = 'rbxasset://textures/ui/LoadingScreen/BackgroundLight.png';
ScaleType = Enum.ScaleType.Slice;
SliceCenter = Rect.new(70,70,110,110);
BackgroundTransparency = 1;
Parent = loadingSurfaceGui;
}
local spinnerRotation = 0
local spinnerImage = Util:Create'ImageLabel'
{
Name = 'Spinner';
Size = UDim2.new(0.25,0,0.25,0);
Position = UDim2.new(0.5 - (0.25/2), 0, 0.45 - (0.25/2), 0);
Image = 'rbxasset://textures/ui/LoadingScreen/LoadingSpinner.png';
BackgroundTransparency = 1;
Parent = backgroundImage;
}
local loadingText = Util:Create'TextLabel'
{
Name = 'LoadingText';
Text = 'Loading...';
BackgroundTransparency = 1;
Font = Enum.Font.SourceSans;
FontSize = Enum.FontSize.Size60;
Position = UDim2.new(0.5,0,0.2,0);
Parent = backgroundImage;
}
local gameNameText = Util:Create'TextLabel'
{
Name = 'GameNameText';
Text = '';
BackgroundTransparency = 1;
Font = Enum.Font.SourceSans;
FontSize = Enum.FontSize.Size60;
Size = UDim2.new(0.9, 0, 0.1, 0);
Position = UDim2.new(0.05,0,0.65,0);
ClipsDescendants = true;
Parent = backgroundImage;
}
local creatorTextContainer = Util:Create'Frame'
{
Name = 'CreatorTextContainer';
Size = UDim2.new(0.9, 0, 0.1, 0);
Position = UDim2.new(0.05,0,0.77,0);
BackgroundTransparency = 1;
ClipsDescendants = true;
Parent = backgroundImage;
}
local creatorTextPosition = 0
local creatorText = Util:Create'TextLabel'
{
Name = 'CreatorText';
Text = '';
BackgroundTransparency = 1;
Font = Enum.Font.SourceSans;
FontSize = Enum.FontSize.Size42;
Size = UDim2.new(1, 0, 1, 0);
Parent = creatorTextContainer;
}
local function ScreenDimsAtDepth(depth)
local camera = workspace.CurrentCamera
if camera then
local aspectRatio = camera.ViewportSize.x / camera.ViewportSize.y
local studHeight = 2 * depth * math.tan(math.rad(camera.FieldOfView/2))
local studWidth = studHeight * aspectRatio
return Vector2.new(studWidth, studHeight)
end
return Vector2.new(0,0)
end
local CleanedUp = false
local freeze = true
delay(2.5, function()
freeze = false
end)
local function UpdateLayout(delta)
local screenDims = ScreenDimsAtDepth(GUI_DISTANCE_FROM_CAMERA)
surfaceGuiAdorn.Size = Vector3.new(screenDims.x * HORIZONTAL_SCREEN_PERCENT, screenDims.y * VERTICAL_SCREEN_PERCENT, 1)
local camera = workspace.CurrentCamera
if camera then
surfaceGuiAdorn.Parent = camera
end
if creatorText.TextBounds.X < creatorTextContainer.AbsoluteSize.X then
creatorText.Position = UDim2.new(0, 0, 0, 0)
creatorText.Size = UDim2.new(1, 0, 1, 0)
elseif delta ~= nil then
creatorText.Size = UDim2.new(0, creatorText.TextBounds.X, 1, 0)
if not freeze then
local newX = (creatorTextPosition - delta * TEXT_SCROLL_SPEED)
if newX + creatorText.AbsoluteSize.X < creatorTextContainer.AbsoluteSize.X then
freeze = true
spawn(function()
Util:TweenProperty(creatorText, 'TextTransparency', creatorText.TextTransparency, 1, 1, Util:GetEaseInOutQuad())
wait(1.5)
if CleanedUp then return end
creatorTextPosition = 0
Util:TweenProperty(creatorText, 'TextTransparency', creatorText.TextTransparency, 0, 1, Util:GetEaseInOutQuad())
wait(1.5)
freeze = false
end)
else
creatorTextPosition = newX
end
end
creatorText.Position = UDim2.new(0, creatorTextPosition, 0, 0)
end
if not gameNameText.TextFits then
gameNameText.Size = UDim2.new(0.9, 0, 0.3, 0)
gameNameText.Position = UDim2.new(0.05,0,0.5,0)
gameNameText.TextScaled = true
gameNameText.TextWrapped = true
spinnerImage.Position = UDim2.new(0.5 - (0.25/2), 0, 0.225, 0)
loadingText.Position = UDim2.new(0.5,0,0.15,0)
end
end
local CameraChangedConn = nil
local WorkspaceChangedConn = nil
local function CleanUp()
if CleanedUp then return end
CleanedUp = true
FadeElements(loadingSurfaceGui, 1, SECOND_TO_FADE)
wait(SECOND_TO_FADE)
RunService:UnbindFromRenderStep("LoadingGui3D")
surfaceGuiAdorn.Parent = nil
if CameraChangedConn then
CameraChangedConn:disconnect()
CameraChangedConn = nil
end
if WorkspaceChangedConn then
WorkspaceChangedConn:disconnect()
WorkspaceChangedConn = nil
end
end
local function OnGameInfoLoaded()
local creatorName = GameInfoProvider:GetCreatorName()
if creatorName and creatorName ~= '' then
creatorName = string.format("By %s", tostring(creatorName))
end
gameNameText.Text = GameInfoProvider:GetGameName()
creatorText.Text = creatorName
end
local function OnReplicatingFinishedAsync()
local function OnGameLoaded()
CleanUp()
end
if game:IsLoaded() then
OnGameLoaded()
else
game.Loaded:wait()
OnGameLoaded()
end
end
local function OnDefaultLoadingGuiRemoved()
CleanUp()
end
local function UpdateSurfaceGuiPosition()
local camera = workspace.CurrentCamera
if camera then
local cameraCFrame = camera.CFrame
local cameraLook = cameraCFrame.lookVector
surfaceGuiAdorn.CFrame = (cameraCFrame * CFrame.Angles(0,math.pi,0)) + cameraLook * GUI_DISTANCE_FROM_CAMERA
end
end
do
local lastUpdate = tick()
RunService:BindToRenderStep("LoadingGui3D", Enum.RenderPriority.Last.Value, function()
local now = tick()
local delta = now - lastUpdate
UpdateSurfaceGuiPosition()
UpdateLayout(delta)
local rotation = delta * ROTATIONS_PER_SECOND * 360
spinnerRotation = spinnerRotation + rotation
spinnerImage.Rotation = spinnerRotation
lastUpdate = now
end)
UpdateSurfaceGuiPosition()
UpdateLayout()
local function connectCameraEvent()
if workspace.CurrentCamera then
if CameraChangedConn then
CameraChangedConn:disconnect()
end
CameraChangedConn = workspace.CurrentCamera:GetPropertyChangedSignal("CFrame"):connect(function()
UpdateSurfaceGuiPosition()
end)
end
end
WorkspaceChangedConn = workspace.Changed:connect(function(prop)
if prop == 'CurrentCamera' then
connectCameraEvent()
end
end)
connectCameraEvent()
end
GameInfoProvider:LoadAssetsAsync()
if GameInfoProvider:IsReady() then
OnGameInfoLoaded()
end
GameInfoProvider.LoadingFinishedEvent:connect(OnGameInfoLoaded)
if ReplicatedFirst:IsFinishedReplicating() then
spawn(OnReplicatingFinishedAsync)
else
ReplicatedFirst.FinishedReplicating:connect(OnReplicatingFinishedAsync)
end
if ReplicatedFirst:IsDefaultLoadingGuiRemoved() then
OnDefaultLoadingGuiRemoved()
else
ReplicatedFirst.RemoveDefaultLoadingGuiSignal:connect(OnDefaultLoadingGuiRemoved)
end
GuiService.ErrorMessageChanged:connect(function()
-- TODO
end)
GuiService.UiMessageChanged:connect(function(type, newMessage)
-- TODO
end)
return LoadingScreen