> For the complete documentation index, see [llms.txt](https://docs.augelab.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.augelab.com/spanish/caracteristicas-clave/create-plugins-with-designer-window/coding-reference.md).

# Referencia de codificación

Esta página explica cómo escribir **Custom Blocks** para AugeLab Studio Designer.

Los Custom Blocks son clases Python simples que heredan de `Block`, definen sockets/componentes en `init()` y procesan datos en `run()`.

## Quick Start

* Empieza tu script con `from studio.custom_block import *` (obligatorio).
* Crea una clase que herede de `Block`.
* Establece `op_code` con el **nombre exacto de la clase**.
* Implementa `init()` para configurar sockets y componentes de la UI.
* Implementa `run()` para leer entradas y escribir salidas.
* Registra el bloque al final con `add_block(...)`.

{% hint style="info" %}
Designer Window extrae el nombre de tu bloque a partir de la primera declaración `class MyBlock(Block):` que encuentre, reemplaza tabs por 4 espacios, escribe `<BlockName>.py`, y luego lo importa para validar.
{% endhint %}

```python
# Example Custom Block (copy/paste friendly)
from studio.custom_block import *

try:
    import numpy as np
except ImportError:
    np = None


class Example_Block(Block):
    op_code = "Example_Block"  # Must match the class name

    def init(self) -> None:
        self.width = 200
        self.height = 150
        self.tooltip = "Adds a constant to the input image."

        # Socket names become keys for self.input[...] and self.output[...]
        self.input_sockets = [SocketTypes.ImageAny("Input Image")]
        self.output_sockets = [SocketTypes.ImageAny("Output Image")]

        # Components are stored by name in self.param
        self.param["Increment"] = TextInput(
            text="1",
            place_holder="integer",
            tool_tip="Value added to every pixel.",
        )

    def run(self) -> None:
        if np is None:
            return

        img = self.input["Input Image"].data
        inc = int(self.param["Increment"].value)
        self.output["Output Image"].data = img + inc


add_block(Example_Block.op_code, Example_Block)
```

!\[Example Custom Block]\(../../../.assets/gitbook/image (50).png)\
\&#xNAN;*Example Custom Block*

## Bootstrap Phase

### Mandatory Imports

Todo script de Custom Block debe comenzar con `from studio.custom_block import *`.

Esto proporciona `Block`, `SocketTypes`, componentes del Designer (TextInput, Slider, …) y `add_block`.

### Importing Community Modules

Puedes importar paquetes de terceros (NumPy, OpenCV, …) y usarlos dentro de `run()`.

Si instalas paquetes mediante la ventana **Import Package Window**, asegúrate de que funcionen en todas las plataformas objetivo donde se ejecutará tu escenario.

{% hint style="warning" %}
Todos los bloques que vienen con AugeLab Studio son compatibles entre plataformas. Instalar o importar módulos de la comunidad puede reducir la portabilidad.
{% endhint %}

## Class Definition

El nombre de la clase se convierte en el nombre del bloque que aparece en la lista de Custom Blocks.

Puedes añadir métodos auxiliares y estado interno según lo necesites.

### Core Attributes & Methods

#### `Block.op_code: str`

Identificador único para tu bloque.

Para los bloques generados por Designer, `op_code` debe coincidir con el nombre de la clase.

{% hint style="info" %}
Mantener `op_code` y los nombres de sockets estables ayuda a Studio a reconectar nodos cuando actualizas un bloque.
{% endhint %}

#### `Block.tooltip: str`

Texto del tooltip que se muestra cuando el usuario pasa el cursor sobre el bloque.

!\[Tooltip shown on custom block]\(../../../.assets/gitbook/image (58).png)\
\&#xNAN;*Tooltip mostrado en un bloque personalizado*

#### `Block.init(self) -> None`

Llamado cuando el bloque se crea (drag-drop), se duplica (copy/paste) o se carga desde un archivo de escenario.

Usa este método para configurar la UI del bloque y los sockets:

* Define `input_sockets` y `output_sockets`
* Crea componentes en `self.param` (TextInput, DropDown, Slider, ...)
* Carga y registra rutas de recursos si es necesario

#### `Block.run(self) -> None`

Ejecutado en cada paso del escenario.

Lee desde `self.input`, escribe en `self.output` y (opcionalmente) actualiza el estado de los componentes.

## Sockets & Data Flow

### `Block.input_sockets: list[SocketType]`

Define qué entradas acepta el bloque.

Cada socket tiene un **nombre** visible; ese mismo nombre se convierte en la clave que usas en `self.input[...]`.

<details>

<summary><strong>Socket constructor</strong></summary>

```python
SomeSocketClass(SocketTypes.BaseSocketClass):
    def __init__(self, name: str = "", multiple: bool = False):
        """ 
        name: texto mostrado junto al gráfico del socket
        multiple: dibuja una línea horizontal para indicar un socket tipo lista
        """
        ...
```

</details>

<details>

<summary><strong>Available socket types</strong></summary>

| Socket type                                   | Typical payload           |
| --------------------------------------------- | ------------------------- |
| `ImageAny`, `ImageRGB`, `ImageGray`           | `numpy.ndarray`           |
| `Mask`                                        | `numpy.ndarray`           |
| `Integer`                                     | `int`                     |
| `Number`                                      | `int` o `float`           |
| `Boolean`                                     | `bool`                    |
| `String`                                      | `str`                     |
| `Generic`                                     | cualquier objeto          |
| `Shape`, `Contour`, `Range`, `Pixel`, `Point` | depende del nodo upstream |

</details>

{% hint style="info" %}
Los tipos exactos de payload dependen del runtime y de los nodos upstream. Comúnmente verás `numpy.ndarray` para imágenes/máscaras y primitivos Python (`int`, `float`, `bool`, `str`) para sockets numéricos/texto.
{% endhint %}

### `Block.output_sockets: list[SocketType]`

Mismo concepto que las entradas: define salidas y luego escribe datos por el nombre del socket usando `self.output["Name"].data = ...`.

### `Block.input: dict[str, object]`

Mapa en tiempo de ejecución de nombres de sockets de entrada a objetos que llevan el payload en `.data`.

Cada input también rastrea el estado de la conexión en `.is_connected`. Si una entrada no está conectada, `.data` se establece en `None`.

```python
class Example_Block(Block):
    def init(self) -> None:
        self.input_sockets = [
            SocketTypes.ImageAny("Image"),
            SocketTypes.Number("Constant"),
        ]

    def run(self) -> None:
        image = self.input["Image"].data
        constant = self.input["Constant"].data
        ...
```

### `Block.output: dict[str, object]`

Mapa en tiempo de ejecución de nombres de sockets de salida a objetos que llevan el payload en `.data`.

```python
class Example_Block(Block):
    def init(self) -> None:
        self.output_sockets = [
            SocketTypes.ImageAny("Result"),
            SocketTypes.Number("Detections"),
        ]

    def run(self) -> None:
        self.output["Result"].data = img_detections_drawn
        self.output["Detections"].data = n_detections
```

## Components (Block UI)

### `Block.param: dict[str, Component]`

Los componentes se almacenan en `self.param` por un nombre único que elijas.

Úsalos para configurar la UI de tu bloque (campos de texto, sliders, botones, imágenes, tablas, etc.).

* [Text Input](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#text-input)
* [Drop Down List](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#drop-down-list)
* [Label](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#label)
* [Slider](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#slider) / [Slider Labeled](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#slider-labeled)
* [Check Box](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#checkbox)
* [Button](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#button)
* [Image](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#image)
* [Table](/spanish/caracteristicas-clave/create-plugins-with-designer-window/components.md#table)

## Resource Paths

### `Block.register_resource(name: str = "", path: str = "") -> str`

Registra la ruta de un archivo/carpeta para que se almacene con el escenario y pueda ser reubicada con el proyecto.\
Esto evita que rutas absolutas codificadas fallen cuando un escenario se mueve a otro equipo.

| Argument | Significado                         |
| -------- | ----------------------------------- |
| `name`   | Identificador único para el recurso |
| `path`   | Ruta de archivo/carpeta a registrar |

Devuelve: `str` (la ruta registrada)

Para recuperar la ruta guardada más tarde, usa `get_resource()`.

<details>

<summary><strong>Ejemplo: permitir al usuario elegir un archivo una sola vez</strong></summary>

```python
from studio.custom_block import *


class LoadImage(Block):
    op_code = "LoadImage"

    def init(self):
        self.width = 220
        self.height = 180

        self.output_sockets = [SocketTypes.ImageAny("Image")]

        self.param["Pick File"] = Button(text="Pick File")
        self.param["Pick File"].set_clicked_callback(self._pick_file)

    def _pick_file(self):
        path = QAFileDialog.getOpenFileName(
            caption="Choose an image",
            directory="",
            filter="Image Files (*.png *.jpg *.jpeg *.bmp)",
        )
        if path:
            self.register_resource("image_path", path)

    def run(self):
        path = self.get_resource("image_path")
        if not path:
            return
        # TODO: load the image from 'path' and set self.output["Image"].data


add_block(LoadImage.op_code, LoadImage)
```

</details>

### `Block.get_resource(name: str = "") -> str`

Devuelve la ruta registrada para un nombre de recurso dado.

## File Dialogs

### `QAFileDialog`

Helper estático para mostrar selectores de archivo/carpeta.\
Estos diálogos retornan una ruta elegida por el usuario.

{% hint style="info" %}
Usa los file dialogs dentro de callbacks (por ejemplo, el click de un `Button`), no dentro de `run()`.
{% endhint %}

#### `QAFileDialog.getOpenFileName(**kwargs)`

| Argument              | Significado                                                          |
| --------------------- | -------------------------------------------------------------------- |
| `caption: str = ""`   | Título del diálogo                                                   |
| `directory: str = ""` | Directorio inicial                                                   |
| `filter: str = ""`    | Filtro de archivos, por ejemplo: `"Image Files (*.png *.jpg *.bmp)"` |

Devuelve: `str` (ruta del archivo seleccionado)

#### `QAFileDialog.getExistingDirectory(**kwargs)`

| Argument              | Significado        |
| --------------------- | ------------------ |
| `caption: str = ""`   | Título del diálogo |
| `directory: str = ""` | Directorio inicial |

Devuelve: `str` (ruta del directorio seleccionado)

## Registration

### `add_block(My_Block.op_code, My_Block)`

Registra tu bloque para que aparezca en el Designer. Esto normalmente lo genera la Designer Window.\
Si lo modificas, mantén `op_code` y el nombre de la clase consistentes.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.augelab.com/spanish/caracteristicas-clave/create-plugins-with-designer-window/coding-reference.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
