3D GUI Module

I wrote a small module library using stravant’s 3D Gui functions. Its a bit advanced in terms of handling 3D snapped objects, but the api is easy to use.
When you call require on the module, it returns a userdata with a few functions in it.


The main method of the module is [b]3DModule:Attach3D(Instance guiObj, Instance model) [/b] The module will create a clone of the model you want to snap to the GUI's location, and it will handle the CFrame & distance to make it look like its part of the GUI.

guiObj must be any kind of Gui object that contains a UDim2 Position property, such as a Frame, ImageLabel, etc.
model can be either a Model, or a BasePart (Part, Wedge, Truss, etc)

When the function is called, it will return a userdata (3dController) with two functions and one property.

3dController:SetActive(boolean active)
Toggles whether or not the 3D Object should be shown or not

3dController:SetCFrame(CoordinateFrame Offset)
Sets a CFrame offset from the location its trying to place the 3D Model.

3dController.Object3D
The model in use by the controller [read only]


There are a few additional functions found inside of it, but most of them are just used by Attach3D itself.

Module:GetScreenResolution()
Returns a Vector2 of the client’s resolution

ModuleAPI:PointToScreenSpace(Vector3 at)
Converts a Vector3 location into a Vector2 location on the client’s screen

ModuleAPI:ScreenSpaceToWorld(number x, number y,number depth)
Converts an X/Y coordinate on the client’s screen into a Vector3 using the depth to determine how small/far away or large/close it should be

ModuleAPI:GetDepthForWidth(number partWidth,int visibleSize)
Takes the width of a part (partWidth) and the absolute pixel width of a gui object (visibleSize) and converts it into a depth to be used with ScreenSpaceToWorld


Here's a picture I took of my module simply applying the effect to a 200x200 Frame (don't mind the guy in the background, I was debugging) [spoiler]

[/spoiler]

PLEASE NOTE: The API assumes there is nothing in front of the model being displayed (whether its a GUI, or anything in the workspace). You need to manually put a BillBoardGui behind your 3D Display as well as handle a camera system for showing it properly. Also note that this does not support character models too well.

Enjoy!


3 Likes

Why are you returning an userdata?

API seems nice. I only don’t see why you use 3D and 3d (note the case) names - that’s quite confusing :slight_smile:

I guess this is a very handy API for anyone who would like to use those (pretty advanced) 3D GUI features.

1 MB low quality gif incoming

Shiiiiny

Edit: The models in currentcamera randomly empty out after a while

Cool. I don’t see the point of returning userdata though, a metatable would be perfectly fine.

This is very nice, I like it.

Would be great if ROBLOX added something official for this though, very hacky using this method. :stuck_out_tongue_winking_eye:

If I were to use this for interstellar would that be okay or?

Yeah no problem.

A useful technique to use along with such a module in real GUIs, that we are using in Age of Glory:

local TestHoleCoords = {
	Size = Vector2.new(895,602);
	Position = Vector2.new(0,64);
}
local function CutHole(imageGui, holeCoords)
	local totalWidth = imageGui.Size.X.Offset
	local totalHeight = imageGui.Size.Y.Offset

	local frame = Instance.new('Frame', imageGui)
	frame.BackgroundTransparency = 1
	frame.Size = UDim2.new(1, 0, 1, 0)
	frame.Name = 'HoleContainer'
	frame.Visible = false

	local containerTop = imageGui:Clone()
	containerTop.Parent = frame
	containerTop.ZIndex = imageGui.ZIndex
	containerTop.Position = UDim2.new(0, 0, 0, 0);
	containerTop.Size = UDim2.new(1, 0, 0, holeCoords.Position.Y)
	containerTop.ImageRectSize = Vector2.new(totalWidth, holeCoords.Position.Y)

	local bottomAt = holeCoords.Position.Y + holeCoords.Size.Y
	local containerBottom = imageGui:Clone()
	containerBottom.Parent = frame
	containerBottom.ZIndex = imageGui.ZIndex
	containerBottom.Position = UDim2.new(0, 0, 0, bottomAt);
	containerBottom.Size = UDim2.new(1, 0, 0, totalHeight - bottomAt)
	containerBottom.ImageRectSize = Vector2.new(totalWidth, totalHeight - bottomAt)
	containerBottom.ImageRectOffset = containerBottom.ImageRectOffset + Vector2.new(0, bottomAt)

	local containerRight = imageGui:Clone()
	containerRight.Parent = frame
	containerRight.ZIndex = imageGui.ZIndex
	containerRight.Position = UDim2.new(0, 0, 0, 0);
	containerRight.Size = UDim2.new(0, holeCoords.Position.X, 1, 0)
	containerRight.ImageRectSize = Vector2.new(holeCoords.Position.X, totalHeight)

	local leftAt = holeCoords.Position.X + holeCoords.Size.X
	local containerLeft = imageGui:Clone()
	containerLeft.Parent = frame
	containerLeft.ZIndex = imageGui.ZIndex
	containerLeft.Position = UDim2.new(0, leftAt, 0, 0);
	containerLeft.Size = UDim2.new(0, totalWidth - leftAt, 1, 0)
	containerLeft.ImageRectSize = Vector2.new(totalWidth - leftAt, totalHeight)
	containerLeft.ImageRectOffset = containerLeft.ImageRectOffset + Vector2.new(leftAt, 0)

	return frame
end

Basically, this will generate a copy of an ImageButton or ImageLabel, but use the ImageRectSize and ImageRectOffset in order to “cut” a hole out of it at specified coordinates, in particular, the coordinates that you want to display the 3D GUI element at. Once you have a hole there you can attach a Billboard GUI to the 3D thing that you are showing, in order to make it look like the GUI is “behind” it, with a seamless transition to the rest of the background. It returns back the cut GUI inside of a frame, so that you can easily show or hide the “hole” along with showing or hiding the 3D GUI element as the user interacts with the GUI.

UPDATE:
Fixed a pretty critical issue with 3dDisplay:SetActive(false)
It was causing an error due to the script believing it was nil (since it was not true or an object)

Someone should hitsquad this. It is soo amazing.