Dynamo
Primer for v2.0
Português (Brasil)
Português (Brasil)
  • Sobre
  • Introdução
    • O que é o Dynamo e como ele funciona?
    • Guia do Usuário do Primer, Comunidade e plataforma do Dynamo
  • Configuração do Dynamo
  • Interface do usuário
    • Área de trabalho
    • Biblioteca
  • Nós e fios
  • Nós e conceitos essenciais
    • Índice de nós
    • Geometria do projeto computacional
      • Visão geral da geometria
      • Vetor, plano e sistema de coordenadas
      • Pontos
      • Curvas
      • Superfícies
      • Sólidos
      • Malhas
    • Os blocos de construção de programas
      • Dados
      • Matemática
      • Lógica
      • Sequências de caracteres
      • Cor
    • Projetar com listas
      • O que é uma lista?
      • Trabalhar com listas
      • Listas de listas
      • Listas n-dimensionais
    • Dicionários no Dynamo
      • O que é um dicionário
      • Nós de dicionário
      • Dicionários em blocos de código
      • Casos de uso do Revit
  • Nós e pacotes personalizados
    • Nós personalizados
      • Introdução ao nó personalizado
      • Criar um nó personalizado
      • Publicar na biblioteca
    • Pacotes
      • Introdução aos pacotes
      • Estudo de caso do pacote – Kit de ferramentas de malha
      • Desenvolver um pacote
      • Publicar um pacote
      • Importação sem toque
  • Dynamo para Revit
    • A conexão do Revit
    • Selecionar
    • Editar
    • Criar
    • Personalizar
    • Documentação
  • Dynamo for Civil 3D
    • Conexão do Civil 3D
    • Guia de Introdução
    • Biblioteca de nós
    • Exemplos de fluxos de trabalho
      • Estradas
        • Posicionamento de postes de luz
      • Terra
        • Posicionamento de serviço
      • Utilitários
        • Renomear estruturas
      • Ferrovia
        • Estrutura da altura livre
      • Levantamento topográfico
        • Gerenciamento de grupo de pontos
    • Tópicos avançados
      • Vinculação de objetos
      • Python e Civil 3D
    • Dynamo Player
    • Pacotes úteis
    • Recursos
  • Dynamo no Forma Beta
    • Configurar o Dynamo Player no Forma
    • Adicionar e compartilhar gráficos no Dynamo Player
    • Executar gráficos no Dynamo Player
    • O Dynamo calcula diferenças de serviço com o Dynamo Desktop
  • Codificação no Dynamo
    • Blocos de código e DesignScript
      • O que é um bloco de código
      • Sintaxe do DesignScript
      • Abreviação
      • Funções
    • Geometria com o DesignScript
      • Conceitos básicos da geometria DesignScript
      • Primitivas geométricas
      • Matemática de vetores
      • Curvas: interpoladas e pontos de controle
      • Transformações de conversão, de rotação e outras
      • Superfícies: interpoladas, pontos de controle, elevação, revolução
      • Parametrização geométrica
      • Interseção e aparar
      • Booleanos geométricos
      • Geradores de pontos do Python
    • Python
      • Nós do Python
      • Python e Revit
      • Configurar seu próprio modelo Python
    • Alterações de linguagem
  • Práticas recomendadas
    • Estratégias de gráfico
    • Estratégias de script
    • Referência dos scripts
    • Gerenciar o programa
    • Trabalhar de forma eficiente com grandes conjuntos de dados no Dynamo
  • Exemplos de fluxos de trabalho
    • Fluxos de trabalho de introdução
      • Vaso paramétrico
      • Pontos de atração
    • Índice conceitual
  • Manual do Desenvolvedor
    • Compilar o Dynamo da origem
      • Compilar o DynamoRevit da origem
      • Gerenciar e atualizar dependências no Dynamo
    • Desenvolvimento do Dynamo
      • Guia de Introdução
      • Estudo de caso sem toque – Nó de grade
      • Executar scripts Python em nós Sem toque (C#)
      • Aprofundar o conhecimento sobre o nó Sem toque
      • Personalização avançada de nós do Dynamo
      • Usar tipos COM (interoperabilidade) em pacotes do Dynamo
      • Estudo de caso do NodeModel – Interface do usuário personalizada
      • Atualizar os pacotes e as bibliotecas do Dynamo para Dynamo 2.x
      • Atualizar os pacotes e as bibliotecas do Dynamo para Dynamo 3.x
      • Extensões
      • Definir a organização de pacotes personalizados no Dynamo 2.0 e superior
      • Interface de linha de comando do Dynamo
      • Integração do Dynamo
      • Desenvolvimento do Dynamo para Revit
      • Publicar um pacote
      • Compilar um pacote do Visual Studio
      • Extensões como pacotes
    • Solicitações de extração
    • Expectativas de testes
    • Exemplos
  • Apêndice
    • Perguntas frequentes
    • Programação visual e Dynamo
    • Recursos
    • Notas de versão
    • Pacotes úteis
    • Arquivos de exemplo
    • Mapa de integração do hospedeiro
    • Fazer o download do PDF
    • Atalhos de teclado do Dynamo
Powered by GitBook
On this page
Edit on GitHub
Export as PDF
  1. Manual do Desenvolvedor
  2. Desenvolvimento do Dynamo

Estudo de caso do NodeModel – Interface do usuário personalizada

PreviousUsar tipos COM (interoperabilidade) em pacotes do DynamoNextAtualizar os pacotes e as bibliotecas do Dynamo para Dynamo 2.x

Last updated 2 months ago

Os nós baseados no NodeModel fornecem significativamente mais flexibilidade e potência do que os nós Sem toque. Neste exemplo, levaremos o nó de grade Sem toque para o próximo nível ao adicionar um controle deslizante integrado que randomiza o tamanho do retângulo.

O controle deslizante dimensiona as células em relação a seu tamanho, de modo que o usuário não precise fornecer um controle deslizante com o intervalo correto.

Padrão “Model-View-Viewmodel”

Em um alto nível, há duas partes para estabelecer uma relação de vista de modelo no Dynamo:

  • Uma classe NodeModel para estabelecer a lógica central do nó (o “modelo”)

  • Uma classe INodeViewCustomization para personalizar como o NodeModel está sendo visualizado (a “vista”)

Os objetos NodeModel já têm um modelo de vista associado (NodeViewModel), portanto, podemos nos concentrar no modelo e na vista para a interface do usuário personalizada.

Como implementar o NodeModel

Os nós NodeModel têm diversas diferenças significativas dos nós Sem toque que abordaremos neste exemplo. Antes de passarmos para a personalização da interface do usuário, vamos começar compilando a lógica do NodeModel.

1. Criar a estrutura do projeto:

Um nó NodeModel pode chamar somente funções, portanto, precisamos separar o NodeModel e as funções em diferentes bibliotecas. A forma padrão de fazer isso para pacotes do Dynamo é criar projetos separados para cada um. Comece criando uma nova solução para englobar os projetos.

  1. Selecionar File > New > Project

  2. Selecionar Other Project Types para ativar a opção Solução

  3. Selecionar Blank Solution

  4. Nomear a solução CustomNodeModel

  5. Selecionar Ok

Crie dois projetos de biblioteca de classes C# na solução: um para as funções e outro para implementar a interface NodeModel.

  1. Clicar com o botão direito do mouse na Solução e selecionar Add > New Project

  2. Escolher a biblioteca de classes

  3. Nomeá-la CustomNodeModel

  4. Clicar em Ok

  5. Repita o processo para adicionar outro projeto nomeado CustomNodeModelFunctions

Em seguida, precisamos renomear as bibliotecas de classes que foram criadas automaticamente e adicionar uma ao projeto CustomNodeModel. A classe GridNodeModel implementa a classe NodeModel abstrata, GridNodeView é usada para personalizar a vista e GridFunction contém as funções que precisamos chamar.

  1. Adicionar outra classe clicando com o botão direito do mouse no projeto CustomNodeModel, selecionando Add > New Item... e escolhendo Class.

  2. No projeto CustomNodeModel, precisamos das classes GridNodeModel.cs e GridNodeView.cs

  3. No projeto CustomNodeModelFunction, precisamos de uma classe GridFunctions.cs

Antes de adicionarmos qualquer código às classes, adicione os pacotes necessários para este projeto. CustomNodeModel precisará de ZeroTouchLibrary e WpfUILibrary e CustomNodeModelFunction só precisará de ZeroTouchLibrary. A biblioteca WpfUIL será usada na personalização da interface do usuário que faremos mais tarde, e a biblioteca ZeroTouchLibrary será usada para criar a geometria. É possível adicionar os pacotes individualmente para os projetos. Como esses pacotes têm dependências, o Core e o DynamoServices serão instalados automaticamente.

  1. Clicar com o botão direito do mouse em um projeto e selecionar Manage NuGet Packages

  2. Instalar somente os pacotes necessários para aquele projeto

O Visual Studio copiará os pacotes NuGet aos quais fizemos referência para o diretório de compilação. Isso pode ser definido como false, para que não tenhamos arquivos desnecessários no pacote.

  1. Selecionar pacotes do Dynamo NuGet

  2. Definir Copy Local como false

2. Herdar a classe NodeModel

Como mencionado anteriormente, o aspecto principal que torna um nó NodeModel diferente de um nó Sem toque é a implementação da classe NodeModel. Um nó NodeModel precisa de diversas funções dessa classe, e podemos obtê-las adicionando :NodeModel após o nome da classe.

Copie o seguinte código para o GridNodeModel.cs.

using System;
using System.Collections.Generic;
using Dynamo.Graph.Nodes;
using CustomNodeModel.CustomNodeModelFunction;
using ProtoCore.AST.AssociativeAST;
using Autodesk.DesignScript.Geometry;

namespace CustomNodeModel.CustomNodeModel
{
    [NodeName("RectangularGrid")]
    [NodeDescription("An example NodeModel node that creates a rectangular grid. The slider randomly scales the cells.")]
    [NodeCategory("CustomNodeModel")]
    [InPortNames("xCount", "yCount")]
    [InPortTypes("double", "double")]
    [InPortDescriptions("Number of cells in the X direction", "Number of cells in the Y direction")]
    [OutPortNames("Rectangles")]
    [OutPortTypes("Autodesk.DesignScript.Geometry.Rectangle[]")]
    [OutPortDescriptions("A list of rectangles")]
    [IsDesignScriptCompatible]
    public class GridNodeModel : NodeModel
    {
        private double _sliderValue;
        public double SliderValue
        {
            get { return _sliderValue; }
            set
            {
                _sliderValue = value;
                RaisePropertyChanged("SliderValue");
                OnNodeModified(false);
            }
        }
        public GridNodeModel()
        {
            RegisterAllPorts();
        }
        public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
        {
            if (!HasConnectedInput(0) || !HasConnectedInput(1))
            {
                return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
            }
            var sliderValue = AstFactory.BuildDoubleNode(SliderValue);
            var functionCall =
              AstFactory.BuildFunctionCall(
                new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid),
                new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue });

            return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), functionCall) };
        }
    }
}

Isso é diferente dos nós Sem toque. Vamos entender o que cada parte está fazendo.

  • Especificar os atributos do nó, como nomes Name, Category, InPort/OutPort, tipos InPort/OutPort e descrições.

  • public class GridNodeModel : NodeModel é uma classe que herda a classe NodeModel de Dynamo.Graph.Nodes.

  • public GridNodeModel() { RegisterAllPorts(); } é um construtor que registra as entradas e saídas do nó.

  • BuildOutputAst() retorna um AST (Abstract Syntax Tree), a estrutura necessária para retornar os dados de um nó NodeModel.

  • AstFactory.BuildFunctionCall() chama a função RetangularGrid de GridFunctions.cs.

  • new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid) especifica a função e seus parâmetros.

  • new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue }); mapeia as entradas do nó para parâmetros de função

  • AstFactory.BuildNullNode() compilará um nó nulo se as portas de entrada não estiverem conectadas. Isso é para evitar a exibição de um aviso no nó.

  • RaisePropertyChanged("SliderValue") notifica a interface do usuário quando o valor do controle deslizante é alterado

  • var sliderValue = AstFactory.BuildDoubleNode(SliderValue) compila um nó no AST que representa o valor do controle deslizante

  • Alterar uma entrada para a variável sliderValue na variável functionCall new List<AssociativeNode> { inputAstNodes[0], sliderValue });

3. Chamar uma função

O projeto CustomNodeModelFunction será compilado em uma montagem separada de CustomNodeModel para que possa ser chamado.

Copie o seguinte código para GridFunction.cs.

using Autodesk.DesignScript.Geometry;
using Autodesk.DesignScript.Runtime;
using System;
using System.Collections.Generic;

namespace CustomNodeModel.CustomNodeModelFunction
{
    [IsVisibleInDynamoLibrary(false)]
    public class GridFunction
    {
        [IsVisibleInDynamoLibrary(false)]
        public static List<Rectangle> RectangularGrid(int xCount = 10, int yCount = 10, double rand = 1)
        {
            double x = 0;
            double y = 0;

            Point pt = null;
            Vector vec = null;
            Plane bP = null;

            Random rnd = new Random(2);

            var pList = new List<Rectangle>();
            for (int i = 0; i < xCount; i++)
            {
                y++;
                x = 0;
                for (int j = 0; j < yCount; j++)
                {
                    double rNum = rnd.NextDouble();
                    double scale = rNum * (1 - rand) + rand;
                    x++;
                    pt = Point.ByCoordinates(x, y);
                    vec = Vector.ZAxis();
                    bP = Plane.ByOriginNormal(pt, vec);
                    Rectangle rect = Rectangle.ByWidthLength(bP, scale, scale);
                    pList.Add(rect);
                }
            }
            pt.Dispose();
            vec.Dispose();
            bP.Dispose();
            return pList;
        }
    }
}

Essa classe de função é muito similar ao estudo de caso de Grade sem Toque, com uma diferença:

  • [IsVisibleInDynamoLibrary(false)] impede que o Dynamo “veja” o seguinte método e classe, já que a função já está sendo chamada de CustomNodeModel.

Assim como adicionamos referências para pacotes NuGet, CustomNodeModel precisará fazer referência a CustomNodeModelFunction para chamar a função.

A declaração de uso para CustomNodeModel estará inativa até que a função seja referenciada

  1. Clicar com o botão direito do mouse em CustomNodeModel e selecionar Add > Reference

  2. Escolher Projects > Solution

  3. Marcar CustomNodeModelFunction

  4. Clicar em Ok

4. Personalizar a vista

Para criar um controle deslizante, é preciso personalizar a interface do usuário implementando a interface do INodeViewCustomization.

Copie o seguinte código para GridNodeView.cs

using Dynamo.Controls;
using Dynamo.Wpf;

namespace CustomNodeModel.CustomNodeModel
{
    public class CustomNodeModelView : INodeViewCustomization<GridNodeModel>
    {
        public void CustomizeView(GridNodeModel model, NodeView nodeView)
        {
            var slider = new Slider();
            nodeView.inputGrid.Children.Add(slider);
            slider.DataContext = model;
        }

        public void Dispose()
        {
        }
    }
}
  • public class CustomNodeModelView : INodeViewCustomization<GridNodeModel> define as funções necessárias para personalizar a interface do usuário.

Após a estrutura do projeto ter sido configurada, use o ambiente de projeto do Visual Studio para compilar um controle de usuário e definir seus parâmetros em um arquivo .xaml. Na caixa de ferramentas, adicione um controle deslizante a <Grid>...</Grid>.

  1. Clicar com o botão direito do mouse em CustomNodeModel e selecionar Add > New Item

  2. Selecionar WPF

  3. Nomear o controle de usuário Slider

  4. Clicar em Add

Copie o seguinte código para Slider.xaml

<UserControl x:Class="CustomNodeModel.CustomNodeModel.Slider"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CustomNodeModel.CustomNodeModel"
             mc:Ignorable="d" 
             d:DesignHeight="75" d:DesignWidth="100">
    <Grid Margin="10">
        <Slider Grid.Row="0" Width="80" Minimum="0" Maximum="1" IsSnapToTickEnabled="True" TickFrequency="0.01" Value="{Binding SliderValue}"/>
    </Grid>
</UserControl>
  • Os parâmetros do controle deslizante são definidos no arquivo .xaml. Os atributos Mínimo e Máximo definem o intervalo numérico dessa barra deslizante.

  • Dentro de <Grid>...</Grid>, podemos colocar diferentes controles de usuário na caixa de ferramentas do Visual Studio

Quando criamos o arquivo Slider.xaml, o Visual Studio criou automaticamente um arquivo C# chamado Slider.xaml.cs que inicializa o controle deslizante. Altere o namespace nesse arquivo.

using System.Windows.Controls;

namespace CustomNodeModel.CustomNodeModel
{
    /// <summary>
    /// Interaction logic for Slider.xaml
    /// </summary>
    public partial class Slider : UserControl
    {
        public Slider()
        {
            InitializeComponent();
        }
    }
}
  • O namespace deve ser CustomNodeModel.CustomNodeModel

O GridNodeModel.cs define a lógica de cálculo do controle deslizante.

5. Configurar como um pacote

Antes de compilarmos o projeto, a etapa final é adicionar um arquivo pkg.json para que o Dynamo possa ler o pacote.

  1. Clicar com o botão direito do mouse em CustomNodeModel e selecionar Add > New Item

  2. Selecionar Web

  3. Selecionar JSON File

  4. Nomear o arquivo pkg.json

  5. Clicar em Add

  • Copie o seguinte código para pkg.json

{
  "license": "MIT",
  "file_hash": null,
  "name": "CustomNodeModel",
  "version": "1.0.0",
  "description": "Sample node",
  "group": "CustomNodes",
  "keywords": [ "grid", "random" ],
  "dependencies": [],
  "contents": "Sample node",
  "engine_version": "1.3.0",
  "engine": "dynamo",
  "engine_metadata": "",
  "site_url": "",
  "repository_url": "",
  "contains_binaries": true,
  "node_libraries": [
    "CustomNodeModel, Version=1.0.0, Culture=neutral, PublicKeyToken=null",
    "CustomNodeModelFunction, Version=1.0.0, Culture=neutral, PublicKeyToken=null"
  ]
}
  • "name": determina o nome do pacote e seu grupo na biblioteca do Dynamo

  • "keywords": fornece termos de pesquisa para pesquisar na biblioteca do Dynamo

  • "node_libraries": [] as bibliotecas associadas ao pacote

    A última etapa é compilar a solução e publicar como um pacote do Dynamo. Consulte o capítulo Implantação do pacote para saber como criar um pacote local antes de publicar on-line e como compilar um pacote diretamente do Visual Studio.

O Dynamo é baseado no padrão de arquitetura do software (MVVM) para manter a interface do usuário separada do back-end. Ao criar nós Sem toque, o Dynamo faz a associação de dados entre os dados de um nó e sua interface de usuário. Para criar uma interface de usuário personalizada, é preciso adicionar a lógica de vinculação de dados.

model-view-viewmodel
Gráfico de grade retangular
Adicionar uma nova biblioteca de classes
Gerenciador de soluções
Instalar os pacotes
Desativar a cópia do pacote local
Adicionar uma referência
Adicionar um novo controle deslizante
Adicionar um arquivo JSON