Cookbook (Chapter 3): Difference between revisions
>JulienDethurens No edit summary |
>JulienDethurens No edit summary |
(No difference)
|
Latest revision as of 23:22, 27 February 2012
Introduction
In the last chapter we covered how to position GUI, but let's answer a very important question. What is GUI? A GUI is a graphic user interface (usually pronounced gooey). The “Leave” button, leaderboard, “Report” button, zoom-in and zoom-out buttons are all GUI. Above character's heads are their name and health, these are also GUI (special GUI that are placed within the 3D world as opposed to on the display itself).
There are many times of GUI that exists, here are a list of all the objects that make up custom GUI.
- BillboardGui - A container for 2D GUI to be placed within the 3D world.
- ScreenGui - A container for all 2D GUI.
- Frame - A GUI object that creates a rectangle.
- ImageButton - A GUI button that is an image.
- TextButton - A GUI button that is text.
- ImageLabel - A GUI image.
- TextLabel - A piece of GUI text.
- TextBox - A GUI input field.
- ArcHandles - A 3D GUI used for rotation.
- Handles - A 3D GUI used for re-size and positioning.
- SurfaceSelection - A 3D GUI used for selecting a part's surface.
- SelectionBox - A 3D GUI selected an entire part.
- SelectionPartLasso - A 3D GUI used to link a part and a character.
- SelectionPointLasso - A 3D GUI used to link a point and a character.
For every character there is a directory called PlayerGui inside of each Player object. This is where all of that player's GUI can go. There is a directory inside of game called StarterGui. Any GUI placed in the StarterGui will be distributed to all the player's PlayerGui's once they are added to the game.
Text Label Instantiation
Problem
You want to create a piece of GUI text.
Solution
Use the Instance.new function to create a TextLabel and change its Text, and Position properties.
local screen, text = Instance.new('ScreenGui'), Instance.new('TextLabel')
screen.Parent = game.StarterGui
text.Parent = screen
text.Text = 'Hello world'
text.Position = UDim2.new(.5, 0, .5, 0)
Discussion
Make sure that this code runs at the very start of the game. If it doesn't then the new ScreenGui will be inserted into the StarterGui after players may have been loaded. This means that some people would see the GUI, others would not.
We set the TextLabel's Text property to a string with what our text is. We then positioning the text label in the center and parent it to the ScreenGui. The ScreenGui serves as a container for all 2D GUI. You must put 2D GUI into a ScreenGui in order for it to render.
I mentioned previously that if this code loads after some time, some players may not see the GUI. What if you want the GUI to be shown to all players after 30 seconds has passed. You could iterate through all the players and add it to the PlayerGui of each player.
local screen, text = Instance.new('ScreenGui'), Instance.new('TextLabel')
text.Text = 'Hello world'
text.Position = UDim2.new(.5, 0, .5, 0)
wait(30)
for i,v in ipairs(game.Players:GetPlayers()) do
local lscreen, ltext = screen:clone(), text:clone()
ltext.Parent = lscreen
lscreen.Parent = v.PlayerGui
end
Text Style
Problem
You want to change the style of the text of a TextLabel.
Solution
Use several style properties of the TextLabel.
local screen, text = Instance.new('ScreenGui'), Instance.new('TextLabel')
screen.Parent = game.StarterGui
text.Parent = screen
text.Text = 'Hello world'
text.Position = UDim2.new(.375, 0, .375, 0)
text.Size = UDim2.new(.25, 0, .25, 0)
text.Font = 'Arial'
text.FontSize = 'Size36'
Discussion
The first thing we did was center the text. Using the trick we learnt in Recipe 2.11, we took ½ and subtracted it by ½ of the width and height so ½ - ¼ * ½ = ? or .375. So we set the position to be a UDim2 with both scale components to be ? and the Size to be ¼. Now what does Size do in a TextLabel. Isn't a TextLabel just text? Size will create a rectangle around your text. There are many properties that control the attributes of this rectangle, but those will be discussed later on.
The next thing we did we set the font to be “Arial”. There are 3 options in which you can set Font to be, Arial, Legacy, and ArialBold. We then set FontSize to be “Size36”. These are the sizes avilable to you, Size8, Size9, Size10, Size11, Size12, Size14, Size18, Size24, Size36, and Size48.
Frame Styling
Problem
You want to change the style of a Frame.
Solution
Use several style properties of the Frame.
local screen, frame = Instance.new('ScreenGui'), Instance.new('Frame')
screen.Parent = game.StarterGui
frame.Parent = screen
frame.Position = UDim2.new(.375, 0, .375, 0)
frame.Size = UDim2.new(.25, 0, .25, 0)
frame.BackgroundColor3 = Color3.new(1, 1, 1)
frame.BackgroundTransparency = .5
frame.BorderSizePixel = 0
Discussion
A Frame is a rectangle (the above example creates a square, and indeed squares are rectangles). We center the Frame as we did with the TextLabel previously. We then use a new property called BackgroundColor3 which controls the frame's color. A Color3 value is another type that is used to represent colors in RGB format. The Color.new function takes 3 arguments, the R, G, and B between 0 and 1 (as opposed to the traditional 0 to 255 range). Color3 values will be covered in depth in a future chapter, however just know for now that Color3.new(1, 1, 1) creates a value of white.
We then have the BackgroundTransparency property which works like the Transparency property in a part, except this applies to the background of the frame. The last property is the BorderSizePixel property. This should be either 1 or 0, 1 meaning the border has a frame, 0 meaning it doesn't. In this case we don't want a Border so we set it to 0.
Image Instantiation
Problem
You want to create a GUI image.
Solution
Create an ImageLabel and change its Image property.
local screen, image = Instance.new('ScreenGui'), Instance.new('ImageLabel')
screen.Parent = game.StarterGui
image.Parent = screen
image.Position = UDim2.new(.375, 0, .375, 0)
image.Size = UDim2.new(.25, 0, .25, 0)
image.Image = 'http://www.roblox.com/asset/?id=1234'
Discussion
We create a new ImageLabel whose Image property is set to an asset ID. To get this asset ID goto the Insert panel (under Insert --> ROBLOX Insert Panel). Then click “My Decals” or “Free Decals” and pick out an image. Then click the image you want and look at the Properties inspector. You'll see a Texture property. Copy the value of the Texture property and that is your image asset ID.
Creating a Button
Problem
You want to create a text button when once clicked, it will toggle its text.
Solution
Create a TextButton and connect the MouseButton1Down event.
local button, state = script.Parent, false
button.MouseButton1Down:connect(function()
if state == false then
button.Text = 'Hello World'
state = true
else
button.Text = 'Foo Bar'
state = false
end
end)
Discussion
In order to use events with GUI we cannot control a GUI from one script, we must have a GUI for all the instances of the GUI. Therefore we're going to have to build the GUI with ROBLOX Studio. While selecting the StarterGui click Insert -> Object -> ScreenGui, and then Insert -> Object -> TextButton. Now change all the properties of the TextButton as wanted. Be sure to change the Text property to the first state text “Foo Bar”. Then click Insert -> Object -> LocalScript inside of the TextButton and paste the solution code. Its a good idea to use LocalScript because it can give you helpful shortcuts in writing GUI that we will take advantage of later.
In the script we first connect a new MouseButton1Down event to “button” (script.Parent because the script is inside the TextButton we access its parent to get to the TextButton itself) which fires when the left mouse button is down on the GUI. To do the toggling we use the “state” variable and just check if its false then set the text to one thing, otherwise set it to something else.
Creating a Fading GUI
Problem
You want to create a GUI that when you hover over it, it fades out, then when you hover out of it, it fades back in with a random color.
Solution
Use the MouseEnter and MouseLeave events.
local button = script.Parent
button.MouseEnter:connect(function()
for i = 0, 1, .1 do
button.BackgroundTransparency = i
wait()
end
end)
button.MouseLeave:connect(function()
button.BackgroundColor3 = BrickColor.random().Color
for i = 1, 0, -.1 do
button.BackgroundTransparency = i
wait()
end
end)
Discussion
Since we're using events we must put this code into a LocalScript which should be within a TextButton (which gives us these events unlike a Frame or TextLabel), and that TextButton should be in a ScreenGui (in order for it to be rendered), and then that should be inside of the StarterGui so once the game starts up, all players have this. Now you can feel free to change the properties of the TextButton as you wish.
Inside the script we first connect the MouseEnter event which fires when the player hovers over the GUI. We animate the button's BackgroundTransparency so it fades out. Do note if you actually have Text in the TextButton set, if you want to fade out the Text as well, you need to add this line of code wherever you see BackgroundTransparency.
button.TextTransparency = i
You need this because a TextButton has two separate properties controlling the transparency of the background and text.
In the MouseLeave event where the player hovers off the GUI, we set the color of the background to a random color. We've used BrickColor before, but now we're getting a random BrickColor and getting a Color3 from it (don't worry this will be covered in depth later on). Then we just fade out the GUI.
Text Box Input
Problem
You want to read input from a TextBox.
Solution
Create a TextBox and use the Changed event.
script.Parent.Changed:connect(function(p)
if p == 'Text' then
print(script.Parent[p])
end
end)
Discussion
Make sure you put this code inside of a LocalScript inside of a TextBox inside of a ScreenGui which is inside of the StarterGui.
The Changed event fires when a property of an object has changed. This will be covered in depth later on. We check to see if the property that changed was the 'Text'. We then print the value of the Text property of the TextBox. Note that Changed will only trigger once the user has finished typing and has either hit Enter or has deselected the TextBox.
Using Adornment GUI
Problem
You want to use a 3D GUI like SelectionBox.
Solution
Create the GUI and set its Adornee property.
local screen, box = Instance.new('ScreenGui'), Instance.new('SelectionBox')
screen.Parent = game.StarterGui
box.Parent = screen
box.Adornee = game.Workspace.Part
Discussion
Make sure that game.Workspace.Part exists. Create the instance (in this case we're using a SelectionBox). Then we set the Adornee property to the part to adorn the GUI to the part. This will create a SelectionBox on game.Workspace.Part.
There are an array of 3D GUI types (listed in Recipe 3.0). You can find information on how to use each one individual on the ROBLOX Wiki.
Creating a Resize GUI
Problem
You want to use the Handles to create a resize GUI.
Solution
Create the GUI setup in the StarterGui and then in a LocalScript use MouseDrag on the Handles object.
local handles, origin = script.Parent, 0
handles.Adornee = game.Workspace.Part
handles.MouseDrag:connect(function(norm, dist)
handles.Adornee:Resize(norm, math.floor(dist - origin / handles.Adornee.ResizeIncrement + .5) * handles.Adornee.ResizeIncrement)
origin = dist
end)
handles.MouseButton1Down:connect(function()
origin = 0
end)
Discussion
Since we're using events with the Handles object we're going to have to create the GUI itself in studio. Therefore create a ScreenGui like normal inside of the StarterGui. However notice that you cannot create the Handles object inside of the ScreenGui. In order to remedy this click the Workspace and then insert the Handles object. Then right click the object and choose “Cut”. Then right click the ScreenGui you created and click “Paste Into”. Then put a LocalScript into the Handles to get started.
We set the Handles Adornee to be a part in the Workspace. Then we connect the Handles MouseDrag event. This event fires when the handles GUI has been dragged. We use the parameters given to the GUI in order to re-size the part accordingly. Basically we call the Resize method on the Adornee of the Handles (which in this case is game.Workspace.Part). Then we pass Resize norm (this identities the side that is to be resized) and we do some math with the amount dragged and the point we started from. Then we also connect the MouseButton1Down event (which is what is fired before MouseDragged is fired). With this we just reset the “origin” variable.
Creating Custom 3D GUI
Problem
You want to create custom 3D GUI like the health bar above character's heads or like the names that float above character's heads.
Solution
Use the BillboardGui as the container instead of ScreenGui.
repeat wait() until game.Players.LocalPlayer.Character and game.Players.LocalPlayer.Character:findFirstChild('Head')
script.Parent.Adornee = game.Players.LocalPlayer.Character.Head
script.Parent.TextLabel.Text = string.reverse(game.Players.LocalPlayer.Name)
Discussion
Create a BillboardGui in the StarterGui and inside of there put a TextLabel and a LocalScript. The BillboardGui Size property should be set to {.5, 0, .5, 0} and the StudsOffset should be set to (0, 2, 0).
In our script we can use some of the LocalScript shortcuts I had mentioned previously. Instead of saying script.Parent.Parent.Parent to get to the Player directory, we can just say game.Players.LocalPlayer. We wait until the LocalPlayer (the user using the GUI) has a Character and Head, then we set the Adornee of the BillboardGui to that Head. We then take the TextLabel and set its text to the reverse of the new of the LocalPlayer.
The result is the reverse of your name appearing above your head. Do note that all GUI is local meaning that it appears only to the Player using the GUI. Therefore the text hovering above your head is only seen to you. Other players see their reversed names hovering over their respective heads, but they cannot set each others.
Also note that at the time of this writing BillboardGui is still being developed. Therefore there are bugs with it. One of these is when you zoom out the text is scaled up instead of the expected behavior of scaling down.