PerspeGui, a Way to make Perspective Transitions!

PerspeGui

This will act as Documentation and Tutorial for usage.
Download Links are available at the end of the post.


Intro

I made this one time because I was bored, and it’s mostly done for fun, but why not release it to the public? dunno ¯\_(ツ)_/¯

Sample:


Questions and Answers

  • What Is It?

It’s a module that could be easily integrated onto existing systems (except Roact systems or other stuff) that allows you to make prompts/menus have a 3d transition effect

  • What Does it Do?

It takes a frame as input and utilizes Viewport Frames to create the effect

  • Will This Change the Way I Make My UI Framework?

Probably not, it’s made only for visual purposes. It may break some things here and there, but it’s a nice thing to have on your arsenal.

  • Limitations?

Yes. UI will not show up inside the Viewport Frame, this is only for Visuals.


Documentation

Open
[Controller: Table] FrameworkGui.CreateElement(Container: Frame)
[nil] Controller.Destroy()
[nil] Controller.Graphics.FadeIn(duration: number, tiltedSide: string)
or
[nil] Controller.Graphics.FadeOut(duration: number, tiltedSide: string)

Input for tiltedSide are "up", "down", "left", "right"


Tutorial

Remember; This should only be used for specific GUIs, this isn’t a Framework system. You could think of it as a component, but not an interpreter.

Step 0; Getting Things Ready

Open

Import the Module by downloading from here or going to the downloads section or by copying the source code in the sources section

Place it anywhere inside your directories
image

Require it in your Script

To follow along, use the .rbxl file as well to help you figure out
image

There should be Content inside the Container that you want to have, with the Content being the actual thing inside.

To Transform your Normal Framework to use this, you have to create a new frame inside the original one, Name it to Content, and then move all of the original Children of the Original Frame inside the Content Frame
image

You can modify the settings in the Module to tweak the visuals

Step 1; Creating a Controller

Open

“A controller is the most basic thing you could use! It’s ergonomic!” -me at 3 am

You can create a controller by referencing the loaded module with;
image
CreateElement() returns a Controller which has indexes of .Graphics: table and .Destroy(): nil

The Controller could only be used with the Graphics Index, I haven’t added anything else. You can index FadeIn() or FadeOut() to handle the Perspective Stuff which we will get on later

Example:


I will explain the parameters of the .Graphics.FadeOut() later

Step 2; Using the Controller

Open

You can use the controller to run the Perspective GUI Effect

Its parameters are the duration of the effect, and where should it be tilted (it’s not case sensitive)

The frame auto-updates the size whenever the screen size is changed. this probably has a side-effect of destroying itself for no reason, I’m not sure


Sources

Source Code:

Code
--module created by shiroi
--this creates a 3d gui interface that allows you to create 3d like gui elements

--prerequisites/services
local TweenService = game:GetService("TweenService")
local RunService = game:GetService("RunService")

--settings that you can mod
local Angle = 1 --DEF 1 --the angle of the part when being faded in or out
local Distance = 0.25 --DEF 0.25 --how far the gui is from the camera + 3 studs
--this is how far the part will go back away from the camera when it's fading in/out
--distance is used in (3 + Distance) to set the correct distance for it to fit in the Frame

--no touchy touchy touchy touchy touchy touchy touchy touchy touchy
local Offset = 3 --DEF -3 --the offset of the gui from the camera
local PartOffset = 0.001



-->>i would've used an external library for this but i'm lazy so i'll just integrate it here
local Graphics = {}

Graphics.ColorPart = function(Object, Goal: Color3, EasingStyle: Enum.EasingStyle, EasingDirection: Enum.EasingDirection, duration)
	local tween = TweenService:Create(Object, TweenInfo.new(duration, EasingStyle, EasingDirection), {
		Color = Goal
	})
	return tween
end

Graphics.Fade = function(Object, In: boolean, EasingStyle: Enum.EasingStyle, EasingDirection: Enum.EasingDirection, duration)
	local tween = TweenService:Create(Object, TweenInfo.new(duration, EasingStyle, EasingDirection), {
		Transparency = In and 0 or 1
	})
	return tween
end

Graphics.Move = function(Object, Goal: Vector3 | CFrame, EasingStyle: Enum.EasingStyle, EasingDirection: Enum.EasingDirection, duration)
	local tween = TweenService:Create(Object, TweenInfo.new(duration, EasingStyle, EasingDirection), {
		Position = Goal
	})
	return tween
end

Graphics.Orient = function(Object, Goal: Vector3, EasingStyle: Enum.EasingStyle, EasingDirection: Enum.EasingDirection, duration)
	local tween = TweenService:Create(Object, TweenInfo.new(duration, EasingStyle, EasingDirection), {
		Orientation = Goal
	})
	return tween
end

--tiny algorithm for turning tiltedSide into actual orientation
local function GetOrientation(tiltedSide: string)
	local orientation = Vector3.new(0, 0, 0)
	local tiltedSide = tiltedSide:lower()

	if tiltedSide == "left" then
		orientation = Vector3.new(0, -1, 0)
	elseif tiltedSide == "right" then
		orientation = Vector3.new(0, 1, 0)
	elseif tiltedSide == "up" then
		orientation = Vector3.new(-1, 0, 0)
	elseif tiltedSide == "down" then
		orientation = Vector3.new(1, 0, 0)
	end

	return orientation
end



local GuiModule = {}



function GuiModule.CreateElement(Container: Frame)
	--random name generator i made for no reason other than to make sure that the name is unique
	local name = "3dgui_"..Container:GetFullName()..tostring(math.random(1, 100))

	local DefaultPosition = Vector3.new(0, 0, -(Offset + PartOffset))
	local RetractedPosition = Vector3.new(0, 0, -(Offset + PartOffset + Distance))

	local ui = script["3dfx"]:Clone()   --this clones the viewport frame
	local ui3d = ui.Part                --this gets the 3d part of the viewport frame
	ui.Name = "3dgui"
	ui.Parent = Container
	ui3d.Transparency = 1
	ui3d.Position = RetractedPosition

	local Controller = {}
	Controller.Graphics = {}

	Controller.Graphics.FadeIn = function(duration: number, tiltedSide: string)
		Container.Transparency = 1
		ui3d.Transparency = 1
		ui3d.Orientation = GetOrientation(tiltedSide)
		ui3d.Position = RetractedPosition
		ui3d.Color = Color3.fromRGB(200, 200, 200)
		
		Graphics.ColorPart(ui3d, Color3.fromRGB(240, 240, 240), Enum.EasingStyle.Quad, Enum.EasingDirection.Out, duration):Play()
		Graphics.Fade(ui3d, true, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, duration):Play()
		Graphics.Move(ui3d, DefaultPosition, Enum.EasingStyle.Quad, Enum.EasingDirection.Out, duration):Play()
		Graphics.Orient(ui3d, Vector3.new(0, 0, 0), Enum.EasingStyle.Quad, Enum.EasingDirection.Out, duration):Play()

		task.delay(duration, function()
			Container.Content.Visible = true
			Container.Transparency = 0
			ui3d.Transparency = 1
		end)
	end

	Controller.Graphics.FadeOut = function(duration: number, tiltedSide: string)
		Container.Transparency = 1
		Container.Content.Visible = false
		ui3d.Transparency = 0
		ui3d.Position = DefaultPosition
		ui3d.Color = Container.BackgroundColor3
		
		Graphics.ColorPart(ui3d, Container.BackgroundColor3, Enum.EasingStyle.Quad, Enum.EasingDirection.In, duration):Play()
		Graphics.Fade(ui3d, false, Enum.EasingStyle.Quad, Enum.EasingDirection.In, duration):Play()
		Graphics.Move(ui3d, RetractedPosition, Enum.EasingStyle.Quad, Enum.EasingDirection.In, duration):Play()
		Graphics.Orient(ui3d, GetOrientation(tiltedSide), Enum.EasingStyle.Quad, Enum.EasingDirection.In, duration):Play()

		task.delay(duration, function()
			ui3d.Transparency = 1
		end)
	end

	Controller.Destroy = function()
		RunService:UnbindFromRenderStep(name)
		ui:Destroy()
	end

	RunService:BindToRenderStep(name, Enum.RenderPriority.Camera.Value, function()
		if not Container then
			print("ERROR: 3dgui element is no longer valid || frame is nil")
			RunService:UnbindFromRenderStep(name)
			ui:Destroy()
		end

		--since the part doesn't change size whenever the frame is rescaled,
		--we calculate the new size based on the frame's size or with the scale factor
		local scale = Container.AbsoluteSize.X / Container.AbsoluteSize.Y

		ui.Size = UDim2.new(1, 0, 1, 0)
		ui.Position = UDim2.new(0, 0, 0, 0)
		ui.BackgroundColor3 = Container.BackgroundColor3
		ui.ZIndex = Container.ZIndex + 1

		ui3d.Size = Vector3.new(4.2 * scale, 4.2, 0.002)
		-- ui3d.Position = Vector3.new(0, 0, -3.002)
		ui3d.Color = Container.BackgroundColor3
	end)

	return Controller
end

return GuiModule

Files:
DemoPlace.rbxl (54.5 KB)
DemoModel.rbxm (22.2 KB)

PerspeGui.rbxm (6.7 KB)

10 Likes