Construção de Widgets do Studio

O Studio dá a você a possibilidade de criar widgets personalizados e usá-los como ferramentas e extensões do Studio. Esses widgets funcionam como janelas/painéis personalizados no Studio e você pode incorporá-los na sua interface ou deixá-los flutuando como janelas separadas.

Criação de UIs do Widget

Todos os widgets do Studio começam como objetos Class. DockWidgetPluginGui que você pode preencher com Class. GuiObject|GuiObjects, como etiquetas textuais e botões. Para criar uma interface gráfica do Widget vazia, use a função Class. Plugin:CreateDockWidgetPluginGui()|CreateDockWidgetPluginGui(), passando em uma ID e um objeto Datatype.

Observe que o Datatype. DockWidgetPluginGuiInfo.new() construtor espera seus parâmetros em uma ordem específica, da seguinte forma:

#PropriedadeTipoDescrição
1Enum. InitialDockStateEnumeraçãoUma das enumerações Enum. InitialDockState.
2InitialEnabledBooleanoO estado habilitado (visível) inicial da interface gráfica do widget.
3InitialEnabledShouldOverrideRestoreBooleanoSe for verdadeiro, o valor de InitialEnabled substitui o estado habilitado salvo anteriormente.
4FloatingXSizeInteiroA largura inicial da interface gráfica quando InitialDockState está definido como Enum. InitialDockState. Float.
5FloatingYSizeInteiroA altura inicial da interface gráfica quando InitialDockState está definido como Enum. InitialDockState. Float.
6MinWidthInteiroA largura mínima da interface gráfica com algumas variações específicas da plataforma.
7MinHeightInteiroA altura mínima da interface gráfica com algumas variações específicas da plataforma.

-- Create new "DockWidgetPluginGuiInfo" object
local widgetInfo = DockWidgetPluginGuiInfo.new(
Enum. InitialDockState. Float, -- Widget will be initialized in floating panel
true, -- Widget will be initially enabled
false, -- Don't override the previous enabled state
200, -- Default width of the floating window
300, -- Default height of the floating window
150, -- Minimum width of the floating window
150 -- Minimum height of the floating window
)
-- Create new widget GUI
local testWidget = plugin:CreateDockWidgetPluginGui("TestWidget", widgetInfo)
testWidget. Title = "Test Widget" -- Optional widget title

Personalização da UI do Widget

Depois de criar o Widget, você pode personalizar a interface do usuário com Class. GuiObject|GuiObjects, como Class. TextLabel|TextLabels informativo ou Class. ImageButton|ImageButtons interativo. Por exemplo, o seguinte código adiciona uma Class. TextButton básica à janela da interface gráfica:


-- Create new widget GUI
local testWidget = plugin:CreateDockWidgetPluginGui("TestWidget", widgetInfo)
testWidget. Title = "Test Widget" -- Optional widget title
local testButton = Instance.new("TextButton")
testButton. BorderSizePixel = 0
testButton. TextSize = 20
testButton. TextColor3 = Color3.new(1,0.2,0.4)
testButton. AnchorPoint = Vector2.new(0.5,0.5)
testButton. Size = UDim2.new(1,0,1,0)
testButton. Position = UDim2.new(0.5,0,0.5,0)
testButton. SizeConstraint = Enum. SizeConstraint. RelativeYY
testButton. Text = "Click Me"
testButton. Parent = testWidget

Alteração de temas de cor do Studio

Os widgets do Studio eficazes normalmente combinam com a configuração do tema do Studio e se ajustam dinamicamente quando o tema é alterado. Por exemplo, se um desenvolvedor estiver usando um tema escuro, a cor de fundo do widget, as imagens e as etiquetas textuais devem ser agradáveis junto com as cores temáticas padrão do Studio.

A seguinte adição de código usa uma função syncGuiColors() que inicialmente é usada junto com uma tabela de objetos de interface gráfica para sincronizar. Dentro da função, uma função setColors() aninhada faz o ciclo sucessivo de objetos e sincroniza aspectos específicos deles usando Class. StudioTheme:GetColor()|GetColor() com enumerações Enum. StudioStyleGuideColor. Essa função setColors() é imediatamente executada para sincronizar o tema do Studio, então ela é conectada ao evento Class. Studio. ThemeChanged|ThemeChanged para detectar futuras alterações de tema.


testButton. Parent = testWidget
local function syncGuiColors(objects)
local function setColors()
for _, guiObject in pairs(objects) do
-- Sync background color
guiObject. BackgroundColor3 = settings(). Studio. Theme:GetColor(Enum. StudioStyleGuideColor. MainBackground)
-- Sync text color
guiObject. TextColor3 = settings(). Studio. Theme:GetColor(Enum. StudioStyleGuideColor. MainText)
end
end
-- Run 'setColors()' function to initially sync colors
setColors()
-- Connect 'ThemeChanged' event to the 'setColors()' function
settings(). Studio. ThemeChanged:Connect(setColors)
end
-- Run 'syncGuiColors()' function to sync colors of provided objects
syncGuiColors({testButton})

Personalização de cursores de mouse

Para melhorar a interação esperada com elementos widget, você pode definir cursores de mouse específicos do sistema para eventos de interface gráfica, como Class. GuiObject. MouseEnter|MouseEnter e Class. GuiObject. MouseLeave|MouseLeave. O seguinte código demonstra como conectar uma função aos eventos Class. GuiObject. MouseEnter|MouseEnter e Class. GuiObject. MouseLeave|MouseLeave do testButton para alterar o cursor de mouse:


local function setCursor(cursorAsset)
plugin:GetMouse(). Icon = cursorAsset
end
testButton. MouseEnter:Connect(function()
setCursor("rbxasset://SystemCursors/PointingHand")
end)
testButton. MouseLeave:Connect(function()
setCursor("")
end)

Consulte a tabela a seguir para uma lista de cursores de mouse e seus casos potenciais de uso:

Ícone do cursor de mouseAtivoCaso de uso
rbxasset://SystemCursors/ArrowClique e seleção padrão.
rbxasset://SystemCursors/PointingHandPassar o mouse sobre um link/botão ativo.
rbxasset://SystemCursors/OpenHandPassar o mouse sobre um item arrastável.
rbxasset://SystemCursors/ClosedHandArrastar um item.
rbxasset://SystemCursors/IBeamPassar o mouse sobre o campo de texto.
rbxasset://SystemCursors/SizeNSPassar o mouse sobre um manipulador de redimensionamento vertical.
rbxasset://SystemCursors/SizeEWPassar o mouse sobre um manipulador de redimensionamento horizontal.
rbxasset://SystemCursors/SizeNESWPassar o mouse sobre um manipulador de redimensionamento de canto.
rbxasset://SystemCursors/SizeNWSEPassar o mouse sobre um manipulador de redimensionamento de canto.
rbxasset://SystemCursors/SizeAllPassar o mouse sobre um manipulador de redimensionamento multi-direções.
rbxasset://SystemCursors/SplitNSPassar o mouse sobre um manipulador vertical de "divisão".
rbxasset://SystemCursors/SplitEWPassar o mouse sobre um manipulador horizontal de "divisão".
rbxasset://SystemCursors/ForbiddenPassar o mouse sobre um item bloqueado/proibido.
rbxasset://SystemCursors/WaitIndicar uma ação em andamento.
rbxasset://SystemCursors/Busy Indicar que o sistema está ocupado.
rbxasset://SystemCursors/CrossPassar o mouse sobre uma área de seleção de identificação.

Acumular entradas do usuário

Elementos de interface do usuário, como TextBox e TextButton funcionam normalmente em widgets do Studio e você pode construir interfaces normalmente na Roblox. No entanto, Class. UserInputService e Class. ContextActionService não funcionam, já que esses serviços esperam que a janela de jogo principal esteja em foco.

Uma solução alternativa para eventos de entrada genéricos é criar um Class. Frame transparente e sobrepôr sobre a tela inteira. O exemplo de código a seguir cria um quadro e quando o usuário clicar no quadro, o evento Class. GuiObject. InputBegan captura a entrada do teclado no quadro até o usuário clicar fora:


local frame = Instance.new("Frame")
frame. BackgroundTransparency = 1 -- Hide the frame
frame. Size = UDim2.new(1, 0, 1, 0) -- Cover the screen
frame. Position = UDim2.new(0, 0, 0, 0)
frame. Parent = testWidget
local function onInputBegan(inputObject)
-- Process the input object here, for example detect key presses
end
frame. InputBegan:Connect(onInputBegan)

Interação de arrastar e soltar

Usar interações de arrastar e soltar para os seus widgets é uma maneira simples de melhorar o fluxo de dados. Para criar essa interação, você deve definir o elemento para arrastar, iniciar o arrastar, criar um alvo para soltar e processar a ação de soltar.

Criar uma fonte de arrasto

Você pode iniciar uma ação de arrastar chamando Class. Plugin:StartDrag()quando o usuário pressionar um botão do mouse em algum elemento da interface de usuário, normalmente um Class. TextButtonou Class. ImageButtondentro de um widget. O exemplo de código a seguir cria um único widget de janela com um botão de texto dentro dele.


-- Create the widget first
local widgetInfo = DockWidgetPluginGuiInfo.new(Enum. InitialDockState. Float, true, true, 300, 200)
local dragSourceWidget = plugin:CreateDockWidgetPluginGui("Drag Source", widgetInfo)
dragSourceWidget. Title = "Drag Source"
-- Create a TextButton that will initiate the drag
local dragButton = Instance.new("TextButton")
dragButton. Size = UDim2.new(1, 0, 1, 0)
dragButton. Text = "Drag me!"
dragButton. Parent = dragSourceWidget

Iniciar o arrastar

Quando o usuário clica em Class. TextButton, você pode iniciar o arrastar por meio do evento Class. GuiButton. MouseButton1Down|MouseButton1Down() que é disparado assim que o usuário pressionar o botão do mouse.

Dentro da função conectada, determine os dados para arrastar. O tipo de dado deve ser refletivo na chave MimeType, o conteúdo do arrastar deve ser refletido na Data chave e o remetente deve se descrever na chave Sender. Consulte a página Class. Plugin:StartDrag() para mais detalhes.


local function onButton1Down()
local dragInfo = {
Data = "Hello, world", -- The data being dragged
MimeType = "text/plain", -- Describes the MIME type of the data
Sender = "SomeDragSource", -- Describes from where the data originated
MouseIcon = "", -- Image content to use for the cursor
DragIcon = "", -- Image content to render under the cursor during drag
HotSpot = Vector2.new(0, 0) -- Where on the DragIcon to center the cursor
}
plugin:StartDrag(dragInfo)
end
dragButton. MouseButton1Down:Connect(onButton1Down)

Criar um alvo de suspensão

O evento Class. PluginGui. PluginDragDropped é acionado quando o usuário libera o mouse em uma janela durante o arrastar. Quando isso acontece, você precisa definir um alvo de suspensão, como um segundo widget com um Class. TextLabel para detectar suspensões.


local dragTargetWidget = plugin:CreateDockWidgetPluginGui("Drop Target", widgetInfo)
dragTargetWidget. Title = "Drop Target"
-- This TextLabel will display what was dropped
local textLabel = Instance.new("TextLabel")
textLabel. Size = UDim2.new(1, 0, 1, 0)
textLabel. Text = "Drop here..."
textLabel. Parent = dragTargetWidget

Processamento da ação de suspensão

Depois de criar um alvo de suspensão, conecte o evento Class. PluginGui. PluginDragDropped com o widget do alvo de suspensão:


local function onDragDrop(dragData)
print("PluginDragDropped")
if dragData. MimeType == "text/plain" then
textLabel. Text = dragData. Data
else
textLabel. Text = dragData. MimeType
end
end
dragTargetWidget. PluginDragDropped:Connect(onDragDrop)

Enquanto o arrastar estiver em andamento, esses três eventos são acionados conforme o usuário movimenta o mouse sobre o widget:

  • Class. PluginGui. PluginDragEntered|PluginDragEntered– é acionado quando o usuário passa o mouse sobre uma janela
  • Class. PluginGui. PluginDragMoved|PluginDragMoved– é acionado repetidamente conforme o usuário movimenta o mouse sobre uma janela. Isso é útil para exibir uma mensagem "Solte aqui!" .
  • Class. PluginGui. PluginDragLeft|PluginDragLeft– é acionado quando o cursor do usuário sair de uma janela. Isso é útil para ocultar uma mensagem de "Solte aqui!" .