Crear widgets en Studio

Puedes crear widgets personalizados para usarlos como herramientas y extensiones de Studio. Estos widgets se comportan como ventanas o paneles personalizados en Studio y puedes anclarlos dentro de tu interfaz o hacer que se presenten como ventanas flotantes separadas.

Creación de la interfaz de usuario de los widgets

Todos los widgets de Studio comienzan siendo objetos DockWidgetPluginGui que puedes completar con GuiObjects, como etiquetas de texto y botones. Para crear una GUI vacía para un widget, llama a la función CreateDockWidgetPluginGui() y pasa una identificación y un objeto DockWidgetPluginGuiInfo.

Ten en cuenta que el constructor DockWidgetPluginGuiInfo.new() espera sus parámetros en un orden específico, de la siguiente manera:

.PropiedadTipoDescripción
1Enum.InitialDockStateEnumeraciónUna de las enumeraciones de Enum.InitialDockState.
2InitialEnabledBooleanoEl estado inicial activado (visible) de la GUI del widget.
3InitialEnabledShouldOverrideRestoreBooleanoSi es verdadero, el valor de InitialEnabled reemplaza el estado activado guardado anteriormente.
4FloatingXSizeEnteroEl ancho inicial de la GUI cuando InitialDockState está establecida en Enum.InitialDockState.Float.
5FloatingYSizeEnteroLa altura inicial de la GUI cuando InitialDockState está establecida en Enum.InitialDockState.Float.
6MinWidthEnteroEl ancho mínimo de la GUI con algunas variaciones específicas de la plataforma.
7MinHeightEnteroLa altura mínima de la GUI con algunas variaciones específicas de la 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

Personalización de la interfaz de usuario de los widgets

Una vez que hayas creado un widget, puedes personalizar su interfaz de usuario con GuiObjects , como TextLabels informativas o ImageButtons interactivos. Por ejemplo, el siguiente código añade un TextButton básico a la ventana de la GUI:


-- 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

Modificación de los temas de color de Studio

Para que un widget sea eficaz, lo ideal es que coincida con la configuración del tema de Studio y se ajuste de forma dinámica cuando este cambie. Por ejemplo, si un desarrollador está usando el tema oscuro, el color de fondo, las imágenes y las etiquetas de texto del widget deben verse bien con los colores del tema nativo de Studio.

En la siguiente adición de código, se utiliza una función syncGuiColors() que se llama inicialmente junto con una tabla de objetos de la GUI para sincronizarlos. Dentro de esta función, una función setColors() anidada recorre los objetos y sincroniza algunos de sus aspectos específicos mediante el uso de GetColor() con enumeraciones Enum.StudioStyleGuideColor. Esta función setColors() se ejecuta de inmediato para realizar la sincronización con el tema de Studio y, luego, se conecta al evento ThemeChanged para detectar futuros cambios 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})

Personalización de los cursores del mouse

Para mejorar las interacciones esperadas con los elementos de los widgets, puedes establecer cursores del mouse específicos del sistema en eventos de la GUI, como MouseEnter y MouseLeave. En el siguiente código, se muestra cómo conectar una función a los eventos MouseEnter y MouseLeave de testButton para cambiar el cursor del 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)

Consulta una lista de los cursores del mouse y sus posibles casos de uso en la siguiente tabla:

Ícono del cursor del mouseRecursoCaso de uso
rbxasset://SystemCursors/ArrowAl hacer clics y seleccionar de forma predeterminada.
rbxasset://SystemCursors/PointingHandAl pasar el mouse sobre un enlace o un botón activo.
rbxasset://SystemCursors/OpenHandAl pasar el mouse sobre un artículo que se puede arrastrar.
rbxasset://SystemCursors/ClosedHandAl arrastrar un objeto.
rbxasset://SystemCursors/IBeamAl pasar el mouse sobre un campo de texto.
rbxasset://SystemCursors/SizeNSAl pasar el mouse sobre un controlador de cambio de tamaño vertical.
rbxasset://SystemCursors/SizeEWAl pasar el mouse sobre un controlador de cambio de tamaño horizontal.
rbxasset://SystemCursors/SizeNESWAl pasar el mouse sobre un controlador de cambio de tamaño de esquina.
rbxasset://SystemCursors/SizeNWSEAl pasar el mouse sobre un controlador de cambio de tamaño de esquina.
rbxasset://SystemCursors/SizeAllAl pasar el mouse sobre un controlador de cambio de tamaño en varias direcciones.
rbxasset://SystemCursors/SplitNSAl pasar el mouse sobre un controlador de “división” vertical.
rbxasset://SystemCursors/SplitEWAl pasar el mouse sobre un controlador de “división” horizontal.
rbxasset://SystemCursors/ForbiddenAl pasar el mouse sobre un artículo bloqueado o prohibido.
rbxasset://SystemCursors/WaitPara indicar que hay una acción en curso.
rbxasset://SystemCursors/Busy Para indicar que el sistema está ocupado.
rbxasset://SystemCursors/CrossAl pasar el mouse sobre un área de selección de puntos.

Obtención de entradas de los usuarios

Los elementos de la interfaz de usuario, como TextBox y TextButton, funcionan con normalidad en los widgets de Studio y puedes crear interfaces como lo harías habitualmente en Roblox. Sin embargo, UserInputService y ContextActionService no funcionan, dado que estos servicios esperan que se enfoque la ventana principal del juego.

Una solución alternativa para los eventos de entrada genéricos es crear un Frame transparente y superponerlo en toda la pantalla. En el siguiente código de ejemplo, se crea un marco, y cuando el usuario hace clic en él, el evento GuiObject.InputBegan registra las entradas del teclado en el marco hasta que el usuario hace clic en otro sitio:


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)

Interacción de arrastrar y soltar

El uso de interacciones de arrastrar y soltar en tus widgets es una forma sencilla de mejorar el flujo de datos. Para crear este tipo de interacciones, debes definir el elemento que se debe arrastrar, iniciar el arrastre, crear un destino de colocación y procesar la acción de soltar.

Creación de un origen de arrastre

Puedes iniciar una acción de arrastre al realizar una llamada a Plugin:StartDrag() cuando el usuario presiona un botón del mouse en algún elemento de la interfaz de usuario, en general, un TextButton o un ImageButton dentro de un widget. En el siguiente código de ejemplo, se crea un widget de una sola ventana con un botón de texto en su interior.


-- 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

Inicio del arrastre

Cuando el usuario hace clic en el TextButton, puedes iniciar el arrastre a través del evento MouseButton1Down(), que se activa en cuanto el usuario presiona el botón del mouse.

Determina los datos que se deben arrastrar dentro de la función conectada. El tipo de datos se debe reflejar en la clave MimeType, el contenido que se arrastra, en la clave Data, y el remitente se debe describir a sí mismo en la clave Sender . Consulta la página Plugin:StartDrag() para obtener más detalles.


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)

Creación de un destino de colocación

El evento PluginGui.PluginDragDropped se activa cuando el usuario suelta el mouse en una ventana mientras está arrastrando un elemento. Debes definir un destino de colocación para cuando esto suceda, como un segundo widget con una TextLabelque detecte las colocaciones.


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

Procesamiento de la acción de soltar

Después de crear un destino de colocación, conecta el evento PluginGui.PluginDragDropped en el widget del destino de colocación:


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)

Cuando hay una acción de arrastre en curso, estos tres eventos se activan a medida que el usuario mueve el mouse sobre un widget:

  • PluginDragEntered: se activa cuando el usuario pasa el mouse sobre una ventana.
  • PluginDragMoved: se activa repetidamente cuando el usuario mueve el mouse sobre una ventana. Este evento es útil para mostrar un mensaje de tipo “Soltar aquí” .
  • PluginDragLeft: se activa cuando el usuario retira el cursor de una ventana. Es útil para ocultar un mensaje de tipo “Soltar aquí” .