Revision Difference
Introduction_To_Using_Derma#564592
<cat>Dev.UI</cat>
<title>Introduction To Using Derma</title>
# Introduction
This is the first in a series of tutorials that aim to take you from zero knowledge on derma, through all the essentials, to a solid foundation towards creating your first UI project.
Welcome to world of [User Interfaces (UI)](https://en.wikipedia.org/wiki/User_interface) specifically within Garry's Mod. Before we begin lets define a clear vocabulary. The source engine by default draws its UI using [VGUI (Valves Graphical User Interface)](https://developer.valvesoftware.com/wiki/VGUI_Documentation) and CPP. In Garry's Mod We Use Lua and Derma. Derma was created by Garry and TAD2020 to make drawing UI's easier. Under the hood our Lua code will access the VGUI code allowing us to create, customize, and destroy UI elements.
# Chapter 1: Panel (DPanel)
Panels are the root to root to everything, most (not all) other elements that you use and create will be comprised of these panels. The engine provides a VGUI control called "Panel" this is a control that has almost no default properties by default. Derma introduces "DPanel" a control that inherits from the engine panel while extending its functionality to be more flexible. Most of the time it will be better to use `DPanel` so that will be our focus.
## Creating a Panel
In order to use a panel you will need to create one. The most common method is <page>vgui.Create</page> like so
```lua
local myFirstPanel = vgui.Create( "DPanel" )
```
This code snippet creates a `DPanel` object in Lua and stores in the variable `myFirstPanel` so that we may access it. We can then use this variable to run functions or adjust properties like:
* Size - Width and Height of the Panel
* Position - Where the top-left corner is
* Draw Settings - Color and similar properties
## Adjusting Properties
Panels don't make up much on their own, instead they act similarly to Lego bricks, allowing you to combine and connect multiple instances of them to create bigger components.
As mentioned before Panels have properties like Size, Position, and Draw Settings (better known as the Paint function, which we'll get to later). Part of what Derma does is provide us with Lua functions to adjust these properties.
Here is an example of some of the more common functions so you can experiment with them.
```lua
myFirstPanel:SetSize( 200, 100 ) -- Makes the width 200 pixels and the height 100 pixels
myFirstPanel:SetPos( 50, 50 ) -- Sets the Panel 50 pixels from the left, then 50 from the top.
myFirstPanel:Center() -- Move the panel to the center of its parent (useful for locating)
```
These should be fairly self-explanatory, however, its important to keep in mind how these functions use their numbers. Panels are drawn from the top-left, to the bottom-right. This means that when you use `:SetSize()`, the position of the top-left pixel will remain in the same spot while the bottom right pixel shoots out. Same thing with `:SetPos()`, this function will move the top-left pixel to those local coordinates on the screen _(top-left of your screen being 0,0)_
These functions are interpreted as they are read. If i use `:Center()` then `:SetSize( w, h )` the panel will not appear center since it was centered first then the size changed.
## Controlling Visibility
As you read this section, use `vgui_visualizelayout 1` to help you spot any hidden panels. This function will make panels flash red when they **UPDATE**.
Visibility is important for controlling what you can and cant see within the elements. Derma provides us with a simple command <page>Panel:SetVisible</page>. Panels will automatically be shown and hidden based off of their parents state. Meaning if you hide a panel, all its children will hide to.
The visibility of panel is different than a transparent panel. A transparent panel will still update and act as though it is visible, while a hidden panel will not update correctly.
a `DPanel` can be made transparent by using <page>DPanel:SetPaintBackground</page>
## Conclusion
That's it, everything you need to get started.
That's it, everything you need to get started. Before starting the next chapter, experiment with different functions found in the <page>Panel</page> class to see what is possible. A good checkpoint is figuring out how to remove any created panels with <page>Panel:Remove</page> before continuing to more complex areas.
Here is a codeblock detailing everything we covered in this chapter:
```lua
-- Create the DPanel
local myFirstPanel = vgui.Create( "DPanel" )
-- Set its size (Width: 200px, Height: 100px)
myFirstPanel:SetSize( 200, 100 )
-- Set its position (X: 300px from left, Y: 200px from top)
-- (Trying slightly different coords for visibility)
myFirstPanel:SetPos( 300, 200 )
-- Make it paint its background
myFirstPanel:SetPaintBackground( true )
-- Set the background color to blue (R=0, G=0, B=255, Alpha=255)
myFirstPanel:SetBackgroundColor( Color( 0, 0, 255, 255 ) )
-- Make sure it's visible (usually is by default if not parented to hidden)
myFirstPanel:SetVisible( true )
```⤶
# Chapter 2: Labels & Buttons (DLabel / DButton)⤶
The last chapter was all about creating rectangles, however, UI's do not just consist of rectangles. We want our UI to have text and some interaction with it, that's where Labels and Buttons come into play. For derma these elements are <page>DLabel</page> and <page>DButton</page>.⤶
⤶
Now before we get started using these elements its crucial to remember inheritance. <page>DLabel</page> derives from an engine based panel called <page>Label</page> while the element, <page>DButton</page> derives from <page>DLabel</page>. Its important to remember this cascading inheritance as it will help you remember what functions you can and cannot access within these panels. That is why These elements were separated into the next chapter. ⤶
⤶
While there are are exceptions, elements that derive from the engine panel, are typically used for things like layout and grouping. Elements that derive from the engine label panel, are more used for mouse interaction.⤶
⤶
## Adding a Label⤶
⤶
Before we add our labels and buttons lets create a base panel:⤶
```lua⤶
-- Any functions explained in previous examples will not be commented for clarity⤶
local myBasePanel = vgui.Create( "DPanel" )⤶
myBasePanel:SetSize( 300, 150 )⤶
myBasePanel:Center()⤶
myBasePanel:SetPaintBackground( true )⤶
myBasePanel:SetBackgroundColor( Color( 0, 0, 255, 255 ) )⤶
myBasePanel:MakePopup() -- Make it stay on top and release the mouse for to capture clicks.⤶
```⤶
⤶
Now to add a <page>DLabel</page>⤶
```lua⤶
local myTitleLabel = vgui.Create( "DLabel", myBasePanel ) -- Using the second arg to parent it 'myBasePanel'⤶
⤶
-- Set the text it should display⤶
myTitleLabel:SetText( "My Awesome Panel" )⤶
⤶
-- Set its position *relative* to the top-left corner of myBasePanel⤶
myTitleLabel:SetPos( 10, 10 )⤶
⤶
-- Automatically adjust the label's width to fit the text⤶
myTitleLabel:SizeToContents()⤶
⤶
-- Optional: Change the text color⤶
myTitleLabel:SetTextColor( color_white ) -- Using built in default color to get white⤶
```⤶
⤶
Adding text to your panel is really that simple!⤶
⤶
## Adding a Button⤶
⤶
Now lets add a <page>DButton</page> somewhere on `myBasePanel` that will close the panel for us. Hopefully you found some way of triggering panel removal in chapter 1, so this will make panel management easier.⤶
```lua⤶
local myCloseButton = vgui.Create( "DButton", myBasePanel )⤶
myCloseButton:SetText( "Close Me" )⤶
⤶
-- Set its size (Buttons often need an explicit size unlike how we set our label)⤶
myCloseButton:SetSize( 100, 30 )⤶
⤶
-- Position it near the bottom right of the panel⤶
-- We calculate position based on the panel's size⤶
local panelW, panelH = myBasePanel:GetSize()⤶
myCloseButton:SetPos( panelW - 110, panelH - 40 ) -- 10px padding from right/bottom⤶
-- we got the offset numbers from doing 'size + padding',⤶
```⤶
Easy! now that we have our button setup, if you click it, you'll notice it does nothing. This is because we have not setup any behavior in the relevant hooks.⤶
⤶
Since <page>DButton</page> inherits its methods from <page>DLabel</page>, and <page>DLabel</page> has the <page>DLabel:DoClick</page> method. We can use that hook for our button. If this doesn't make complete sense take a moment to break down how and why we are able to use this hook. Understanding inheritance now is crucial as controls get more complex.⤶
⤶
Lets define this function somewhere below the creation of our `myCloseButton` panel.⤶
```lua⤶
-- Define what happens when myCloseButton is clicked⤶
myCloseButton.DoClick = function( theButton )⤶
-- 'theButton' is the button that was clicked (myCloseButton in this case)⤶
print( "Close button clicked!" )⤶
⤶
-- Let's make the button remove the whole panel⤶
myBasePanel:Remove()⤶
end⤶
```⤶
<note> the function can also be written like⤶
```lua⤶
function myCloseButton:DoClick()⤶
...⤶
end⤶
```
the only difference between these two is how the [Lua Self Keyword](Beginner_Tutorial_Self) is handled⤶
</note>⤶
⤶
The button we created is very simple, it simply prints our message then removes our base panel, causing it and all children to be marked for deletion.⤶
⤶
## Conclusion⤶
You should now have an even stronger understanding of basic panel control. Experiment around with creating buttons that do different things. Maybe a calculator? we will cover the layout system in Chapter 3⤶
⤶
All together the code looks like:⤶
```lua⤶
-- Any functions explained in previous examples will not be commented for clarity⤶
local myBasePanel = vgui.Create( "DPanel" )⤶
myBasePanel:SetSize( 300, 150 )⤶
myBasePanel:Center()⤶
myBasePanel:SetPaintBackground( true )⤶
myBasePanel:SetBackgroundColor( Color( 0, 0, 255, 255 ) )⤶
myBasePanel:MakePopup()⤶
⤶
local myTitleLabel = vgui.Create( "DLabel", myBasePanel )⤶
myTitleLabel:SetText( "My Awesome Panel" )⤶
myTitleLabel:SetPos( 10, 10 )⤶
myTitleLabel:SizeToContents()⤶
myTitleLabel:SetTextColor( color_white )⤶
⤶
local myCloseButton = vgui.Create( "DButton", myBasePanel )⤶
myCloseButton:SetText( "Close Me" )⤶
myCloseButton:SetSize( 100, 30 )⤶
local panelW, panelH = myBasePanel:GetSize()⤶
myCloseButton:SetPos( panelW - 110, panelH - 40 )⤶
⤶
myCloseButton.DoClick = function( theButton )⤶
print( "Close button clicked!" )⤶
myBasePanel:Remove()⤶
end⤶
⤶
```⤶