githubEdit

Caso real de NodeModel (interfaz de usuario personalizada)

Los nodos basados en NodeModel proporcionan una flexibilidad y una eficacia mucho mayores que los nodos Zero-Touch. En este ejemplo, vamos a llevar el nodo de rejilla Zero-Touch al siguiente nivel mediante la adición de un control deslizante integrado que determina aleatoriamente el tamaño del rectángulo.

El control deslizante ajusta la escala de las celdas en relación con su tamaño para que el usuario no tenga que proporcionar un control deslizante con el rango correcto.

El patrón Model-View-Viewmodel

Dynamo se basa en el patrón de arquitectura de software Model-View-Viewmodelarrow-up-right (MVVM) para mantener separada la interfaz de usuario del back-end. Al crear nodos Zero-Touch, Dynamo establece el enlace entre los datos de un nodo y su interfaz de usuario. Para crear una interfaz de usuario personalizada, debemos añadir la lógica de enlace de datos.

En un nivel superior, existen dos partes para establecer una relación de modelo-vista en Dynamo, como se indica a continuación:

  • Una clase NodeModel para establecer la lógica del núcleo del nodo (el "modelo").

  • Una clase INodeViewCustomization para personalizar cómo se visualiza el NodeModel (la "vista").

Los objetos NodeModel ya tienen asociada una relación de vista-modelo (NodeViewModel), por lo que podemos centrarnos en el modelo y la vista para la interfaz de usuario personalizada.

Cómo implementar NodeModel

Los nodos NodeModel presentan varias diferencias significativas con respecto a los nodos Zero-Touch que se abordarán en este ejemplo. Antes de pasar a la personalización de la interfaz de usuario, vamos a empezar por generar la lógica de NodeModel.

1. Crear la estructura del proyecto

Un nodo NodeModel solo puede llamar a funciones, por lo que es necesario separar el NodeModel y las funciones en bibliotecas diferentes. El método estándar para los paquetes de Dynamo es crear proyectos independientes para cada uno de ellos. Comience por crear una nueva solución para englobar los proyectos.

  1. Seleccione File > New > Project.

  2. Seleccione Other Project Types para abrir la opción de solución.

  3. Seleccione Blank Solution.

  4. Asigne el nombre CustomNodeModel a la solución.

  5. Seleccione Ok.

Cree dos proyectos de biblioteca de clases de C# en la solución: uno para las funciones y otro para implementar la interfaz de NodeModel.

  1. Haga clic con el botón derecho en la solución y seleccione Add > New Project.

  2. Seleccione Biblioteca de clases.

  3. Asígnele un nombre a CustomNodeModel.

  4. Haga clic en Ok.

  5. Repita el proceso para añadir otro proyecto denominado CustomNodeModelFunctions.

A continuación, debemos cambiar el nombre de las bibliotecas de clases que se han creado automáticamente y añadir una al proyecto CustomNodeModel. La clase GridNodeModel implementa la clase abstracta NodeModel; GridNodeView se utiliza para personalizar la vista, y GridFunction contiene las funciones a las que se debe llamar.

  1. Añada otra clase. Para ello, haga clic con el botón derecho en el proyecto CustomNodeModel, seleccione Add > New Item... y, a continuación, elija Class.

  2. En el proyecto CustomNodeModel, necesitamos las clases GridNodeModel.cs y GridNodeView.cs.

  3. En el proyecto CustomNodeModelFunction, necesitamos una clase GridFunctions.cs.

Antes de agregar código a las clases, añada los paquetes necesarios para este proyecto. CustomNodeModel necesitará ZeroTouchLibrary y WpfUILibrary, y CustomNodeModelFunction solo necesitará ZeroTouchLibrary. WpfUILibrary se utilizará en la personalización de la interfaz de usuario que realizaremos más adelante y ZeroTouchLibrary se empleará para crear geometría. Los paquetes se pueden añadir individualmente para los proyectos. Como estos paquetes presentan dependencias, Core y DynamoServices se instalarán automáticamente.

  1. Haga clic con el botón derecho en un proyecto y seleccione Manage NuGet Packages.

  2. Instale solo los paquetes necesarios para ese proyecto.

Visual Studio copiará los paquetes NuGet a los que hemos hecho referencia en el directorio de compilación. Esto se puede establecer en "false" (falso) para que no tengamos ningún archivo innecesario en el paquete.

  1. Seleccione paquetes NuGet de Dynamo.

  2. Establezca Copy Local en "false" (falso).

2. Heredar la clase NodeModel

Como se ha mencionado anteriormente, el aspecto principal que diferencia un nodo NodeModel de un nodo Zero-Touch es su implementación de la clase NodeModel. Un nodo NodeModel necesita varias funciones de esta clase y podemos obtenerlas mediante la adición de :NodeModel después del nombre de la clase.

Copie el código siguiente en GridNodeModel.cs.

Esto es diferente a los nodos Zero-Touch. Vamos a conocer lo que realiza cada parte.

  • Especifique los atributos del nodo como nombre, categoría, nombres de puerto de entrada/salida, tipos de puerto de entrada/salida y descripciones.

  • public class GridNodeModel : NodeModel es una clase que hereda la clase NodeModel de Dynamo.Graph.Nodes.

  • public GridNodeModel() { RegisterAllPorts(); } es un constructor que registra las entradas y las salidas del nodo.

  • BuildOutputAst() devuelve un AST (árbol de sintaxis abstracta), la estructura necesaria para devolver datos de un nodo NodeModel.

  • AstFactory.BuildFunctionCall() llama a la función RectangularGrid desde GridFunctions.cs.

  • new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid) especifica la función y sus parámetros.

  • new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue }); asigna las entradas del nodo a los parámetros de función.

  • AstFactory.BuildNullNode() genera un nodo nulo si los puertos de entrada no están conectados. Esto se hace para evitar que se muestre una advertencia en el nodo.

  • RaisePropertyChanged("SliderValue") notifica a la interfaz de usuario cuando cambia el valor del control deslizante.

  • var sliderValue = AstFactory.BuildDoubleNode(SliderValue) compila un nodo en AST que representa el valor del control deslizante

  • Cambie una entrada a la variable sliderValue en la variable functionCall new List<AssociativeNode> { inputAstNodes[0], sliderValue });.

3. Llamar a una función

El proyecto CustomNodeModelFunction se creará en un montaje independiente de CustomNodeModel para que se pueda llamar a él.

Copie el siguiente código en GridFunction.cs.

Esta clase de función es muy similar al caso real de rejilla de Zero-Touch con una diferencia:

  • [IsVisibleInDynamoLibrary(false)] impide que Dynamo "vea" el siguiente método y clase, ya que la función ya se está llamando desde CustomNodeModel.

Al igual que hemos añadido referencias para los paquetes NuGet, CustomNodeModel deberá hacer referencia a CustomNodeModelFunction para llamar a la función.

La instrucción "using" de CustomNodeModel estará inactiva hasta que hagamos referencia a la función

  1. Haga clic con el botón derecho en CustomNodeModel y seleccione Add > Reference.

  2. Seleccione Projects > Solution.

  3. Active CustomNodeModelFunction.

  4. Haga clic en Ok.

4. Personalizar la vista

Para crear un control deslizante, debemos personalizar la interfaz de usuario mediante la implementación de la interfaz de INodeViewCustomization.

Copie el siguiente código en GridNodeView.cs.

  • public class CustomNodeModelView : INodeViewCustomization<GridNodeModel> define las funciones necesarias para personalizar la interfaz de usuario.

Una vez configurada la estructura del proyecto, utilice el entorno de diseño de Visual Studio para generar un control de usuario y definir sus parámetros en un archivo .xaml. En el cuadro de herramientas, añada un control deslizante a <Grid>...</Grid>.

  1. Haga clic con el botón derecho en CustomNodeModel y seleccione Add > New Item.

  2. Seleccione WPF.

  3. Asigne el nombre Slider al control de usuario.

  4. Haga clic en Add.

Copie el siguiente código en Slider.xaml.

  • Los parámetros del control deslizante se definen en el archivo .xaml. Los atributos Mínimo y Máximo definen el rango numérico de este control deslizante.

  • En <Grid>...</Grid>, podemos colocar diferentes controles de usuario desde el cuadro de herramientas de Visual Studio.

Cuando creamos el archivo Slider.xaml, Visual Studio creó automáticamente un archivo de C# llamado Slider.xaml.cs que inicializa el control deslizante. Cambie el espacio de nombres de este archivo.

  • El espacio de nombres debe ser CustomNodeModel.CustomNodeModel.

GridNodeModel.cs define la lógica de cálculo del control deslizante.

5. Configurar como paquete

Antes de generar el proyecto, el último paso es añadir un archivo pkg.json para que Dynamo pueda leer el paquete.

  1. Haga clic con el botón derecho en CustomNodeModel y seleccione Add > New Item.

  2. Seleccione Web.

  3. Seleccione JSON File.

  4. Asigne al archivo el nombre pkg.json.

  5. Haga clic en Add.

  • Copie el siguiente código en pkg.json.

  • "name": determina el nombre del paquete y su grupo en la biblioteca de Dynamo.

  • "keywords": proporciona términos para realizar búsquedas en la biblioteca de Dynamo.

  • "node_libraries": [] las bibliotecas asociadas con el paquete.

    El último paso es generar la solución y publicarla como un paquete de Dynamo. Consulte el capítulo Implementación de paquetes para obtener información sobre cómo crear un paquete local antes de la publicación en línea y cómo generar un paquete directamente desde Visual Studio.

Problemas frecuentes

  1. Al abrir un gráfico, algunos nodos tienen varios puertos con el mismo nombre, pero el gráfico presenta un aspecto correcto al guardar. Este problema puede tener varias causas.

La principal causa habitual es que el nodo se ha creado con un constructor que ha vuelto a crear los puertos. En su lugar, debería haberse utilizado un constructor que cargara los puertos. Estos constructores suelen estar marcados con [JsonConstructor]. Consulte los ejemplos siguientes:

!JSON interrumpidoarrow-up-right

Esto puede deberse a lo siguiente:

  • No se ha encontrado ningún [JsonConstructor] coincidente o no se han transferido los archivos Inports y Outports del archivo .dyn de JSON.

  • Había dos versiones de JSON.net cargadas en el mismo proceso al mismo tiempo, lo que provocaba fallos en el tiempo de ejecución de .net, por lo que el atributo [JsonConstructor] no podía utilizarse correctamente para marcar el constructor.

  • DynamoServices.dll con una versión diferente a la versión actual de Dynamo se ha incluido con el paquete, lo que provoca que el tiempo de ejecución de .net no identifique el atributo [MultiReturn], por lo que los nodos Zero-Touch marcados con varios atributos no podrán aplicarlos. Es posible que un nodo devuelva una única salida de diccionario en lugar de varios puertos.

  1. Faltan completamente nodos al cargar el gráfico con algunos errores en la consola.

  • Esto puede producirse si la deserialización falla por algún motivo. Es recomendable serializar solo las propiedades necesarias. Podemos utilizar [JsonIgnore] en propiedades complejas que no sea necesario cargar o guardar para omitirlas como, por ejemplo, function pointer, delegate, action, o event, etc. No deben serializarse, ya que normalmente fallarán durante la deserialización y provocarán un error de ejecución.

Last updated