Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
-o, -O, --OpenFilePath Instrua o Dynamo a abrir um arquivo de comando e execute os comandos contidos no caminho. Essa opção só é suportada quando executada no DynamoSandbox.
-c, -C, --CommandFilePath Instrua o Dynamo a abrir um arquivo de comando e execute os comandos contidos no caminho. Essa opção só é suportada quando executada no DynamoSandbox.
-v, -V, --Verbose Instrua o Dynamo a enviar todas as avaliações que executa para um arquivo XML no caminho especificado.
-g, -G, --Geometry Instrua o Dynamo a gerar a geometria de todas as avaliações para um arquivo JSON nesse caminho.
-h, -H, --help Obtenha ajuda.
-i, -I, --Import Instrua o Dynamo a importar uma montagem como uma biblioteca de nós. Esse argumento deve ser um caminho de arquivo para um único .dll. Se você deseja importar vários .dlls, liste-os separados por um espaço: -i 'assembly1.dll' 'assembly2.dll'.
--GeometryPath Caminho relativo ou absoluto para um diretório que contém o ASM. Quando fornecido, em vez de procurar o ASM no disco rígido, ele será carregado diretamente desse caminho.
-k, -K, --KeepAlive Modo Keepalive, deixe o processo do Dynamo em execução até que uma extensão carregada o desligue.
--HostName Identifique a variação do Dynamo associada ao hospedeiro.
-s, -S, --SessionId Identifique a ID da sessão de análise do hospedeiro do Dynamo.
-p, -P, --ParentId Identifique a ID pai da análise do hospedeiro do Dynamo.
-x, -X, --ConvertFile Quando usado em combinação com o indicador -O, abre um arquivo .dyn no caminho especificado e o converte em .json. O arquivo terá a extensão .json e estará localizado no mesmo diretório que o arquivo original.
-n, -N, --NoConsole Não confie na janela do console para interagir com a CLI no modo Keepalive.
-u, -U, --UserData Especifique a pasta de dados do usuário a ser usada pelo PathResolver com a CLI.
--CommonData Especifique a pasta de dados comuns a ser usada pelo PathResolver com a CLI.
--DisableAnalytics Desativa a análise no Dynamo durante a vida útil do processo.
--CERLocation Especifique a ferramenta de relatório de erros fatais localizada no disco.
--ServiceMode Especifique a inicialização do modo de serviço.
Você pode querer controlar o Dynamo por meio da linha de comando por vários motivos, como:
Automatizar muitas execuções do Dynamo
Testar os gráficos do Dynamo (veja também -c quando usar o DynamoSandbox)
Executar uma sequência de gráficos do Dynamo em uma ordem específica
Escrever arquivos em lote que executam várias execuções de linha de comando
A interface de linha de comando (DynamoCLI) é um suplemento do DynamoSandbox. É um utilitário de linha de comando dos/terminal desenvolvido para fornecer a conveniência de argumentos de linha de comando para executar o Dynamo. Em sua primeira implementação, ela não é executada de forma independente, deve ser executada da pasta onde os binários do Dynamo residem, pois depende das mesmas DLLs principais do Sandbox. Ela não pode interoperar com outras compilações do Dynamo.
Há quatro formas de executar a CLI: em um prompt do Dos, de arquivos em lote do Dos e como um atalho na área de trabalho do Windows cujo caminho é modificado para incluir os indicadores de linha de comando especificados. A especificação do arquivo Dos pode ser totalmente qualificada ou relativa, e as unidades mapeadas e a sintaxe da URL também são suportadas. Ela também pode ser construída com o Mono e ser executada em Linux ou Mac no terminal.
Os pacotes Dynamo são suportados pelo utilitário. No entanto, não é possível carregar nós personalizados (dyf), apenas gráficos independentes (dyn).
Em testes preliminares, o utilitário da CLI oferece suporte a versões localizadas do Windows e é possível especificar argumentos filespec com caracteres Ascii superiores.
A CLI pode ser acessada por meio do aplicativo DynamoCLI.exe. Esse aplicativo permite que um usuário ou outro aplicativo interaja com o modelo de avaliação do Dynamo invocando o DynamoCLI.exe com uma sequência de caracteres de comandos. Isso pode ser algo assim:
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn"
Esse comando dirá ao Dynamo para abrir o arquivo especificado em “C:\someReallyCoolDynamoFile.Dyn”, sem desenhar nenhuma IU, e executá-lo. O Dynamo será encerrado quando a execução do gráfico for concluída.
Novo na versão 2.1: o aplicativo DynamoWPFCLI.exe. Esse aplicativo suporta tudo o que o aplicativo DynamoCLI.exe suporta com a adição da opção Geometria (-g). O aplicativo DynamoWPFCLI.exe está disponível somente para Windows.
O método preferido de interação com o DynamoCLI é por meio de uma interface de prompt do comando.
Neste momento, será necessário executar o DynamoCLI da localização de instalação dentro da pasta [Versão do Dynamo]. A CLI precisa acessar os mesmos .dlls que o Dynamo, então ela não deve ser movida.
Você deverá ser capaz de executar os gráficos que estão atualmente abertos no Dynamo, mas isso poderá causar efeitos colaterais indesejados.
Todos os caminhos de arquivo são totalmente compatíveis com DOS. Portanto, os caminhos relativos e totalmente qualificados devem funcionar, mas certifique-se de colocar os caminhos entre aspas
-o é possível abrir o Dynamo apontando para um .dyn, em um modo headless que executará o gráfico.
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn"
-v pode ser usado quando o Dynamo estiver sendo executado em modo headless (quando usamos -o para abrir um arquivo). Esse indicador iterará todos os nós no gráfico e despejará seus valores de saída em um arquivo XML simples. Como o indicador --ServiceMode pode forçar o Dynamo a executar várias avaliações de gráfico, o arquivo de saída conterá valores para cada avaliação que ocorrer.
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -p "C:\aFileWithPresetsInIt.dyn" --ServiceMode "all" -v "C:\output.xml"
O arquivo de saída XML teria o formato a seguir:
-g pode ser usado quando o Dynamo estiver sendo executado em modo headless (quando usamos -o para abrir um arquivo). Esse indicador gerará o gráfico e despejará a geometria resultante em um arquivo JSON.
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoWPFCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -g "C:\geometry.json"
O arquivo de geometria JSON teria o formato a seguir:
TBD – Trabalho em andamento
-h use essa opção para obter uma lista das possíveis opções
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -h
o indicador -i pode ser usado várias vezes para importar várias montagens que o gráfico que você está tentando abrir precisa para ser executado.
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -i"a.dll" -i"aSecond.dll"
o indicador -l pode ser usado para executar o Dynamo em uma configuração de localidade diferente. Mas, geralmente, a configuração de localidade não afeta os resultados do gráfico
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -l "de-DE"
o indicador --GeometryPath pode ser usado para apontar o DynamoSandbox ou a CLI para um conjunto específico de binários ASM. Use-o como
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoSandbox.exe --GeometryPath "\pathToGeometryBinaries\"
ou
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoSandbox.exe --GeometryPath "\pathToGeometryBinaries\"
o indicador -k pode ser usado para deixar o processo do Dynamo em execução até que uma extensão carregada o desligue.
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -k
o indicador --HostName pode ser usado para identificar a variação do Dynamo associada ao hospedeiro.
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe --HostName "DynamoFormIt"
ou
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoSandbox.exe --HostName "DynamoFormIt"
o indicador -s pode ser usado para identificar a ID da sessão de análise do hospedeiro do Dynamo
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -s [HostSessionId]
o indicador -p pode ser usado para identificar a ID pai da análise do hospedeiro do Dynamo
C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -p "RVT&2022&MUI64&22.0.2.392"
Escrever outro programa para controlar e automatizar a execução de gráficos do Dynamo e fazer coisas interessantes com os resultados desses cálculos
O DynamoCLI é uma nova funcionalidade e atualmente está em evolução: a CLI carrega apenas um subconjunto de bibliotecas padrão do Dynamo no momento. Observe isso se um gráfico não for executado corretamente. Essas bibliotecas estão especificadas aqui
Atualmente, nenhuma saída padrão é fornecida. Se nenhum erro for encontrado, a CLI simplesmente será fechada após a conclusão da execução.
<evaluations>
<evaluation0>
<Node guid="e2a6a828-19cb-40ab-b36c-cde2ebab1ed3">
<output0 value="str" />
</Node>
<Node guid="67139026-e3a5-445c-8ba5-8a28be5d1be0">
<output0 value="C:\Users\Dale\state1.txt" />
</Node>
<Node guid="579ebcb8-dc60-4faa-8fd0-cb361443ed94">
<output0 value="null" />
</Node>
</evaluation0>
<evaluation1>
<Node guid="e2a6a828-19cb-40ab-b36c-cde2ebab1ed3">
<output0 value="str" />
</Node>
<Node guid="67139026-e3a5-445c-8ba5-8a28be5d1be0">
<output0 value="C:\Users\Dale\state2.txt" />
</Node>
<Node guid="579ebcb8-dc60-4faa-8fd0-cb361443ed94">
<output0 value="null" />
</Node>
</evaluation1>
</evaluations>Os pacotes são uma forma conveniente de armazenar e compartilhar nós com a comunidade do Dynamo. Um pacote pode conter tudo, desde nós personalizados criados no espaço de trabalho do Dynamo até nós derivados do NodeModel. Os pacotes são publicados e instalados usando o Gerenciador de pacotes. Além desta página, o Manual tem um guia geral sobre os pacotes.
O Gerenciador de pacotes do Dynamo é um Registro de software (semelhante ao npm) que pode ser acessado no Dynamo ou em um navegador da Web. O Gerenciador de pacotes inclui a instalação, publicação, atualização e visualização de pacotes. Como o npm, ele mantém diferentes versões de pacotes. Também ajuda a gerenciar as dependências do projeto.
No navegador, procure pacotes e visualize as estatísticas:
No Dynamo, o Gerenciador de pacotes inclui pacotes de instalação, publicação e atualização.
Procurar pacotes on-line:
Packages > Search for a Package...Visualizar/editar pacotes instalados:
Packages > Manage Packages...Publicar um novo pacote:
Packages > Publish New Package...
Os pacotes são publicados do Gerenciador de pacotes no Dynamo. O processo recomendado é publicar localmente, testar o pacote e, em seguida, publicar on-line para compartilhar com a comunidade. Usando o estudo de caso NodeModel, vamos passar pelas etapas necessárias para publicar o nó RetangularGrid como um pacote localmente e, em seguida, on-line.
Inicie o Dynamo e selecione Packages > Publish New Package... para abrir a janela Publish a Package.
Selecionar
Add file...para procurar arquivos para adicionar ao pacoteSelecionar os dois arquivos
.dllno estudo de caso NodeModelSelecionar
Ok
Com os arquivos adicionados ao conteúdo do pacote, atribua um nome, uma descrição e uma versão ao pacote. A publicação de um pacote usando o Dynamo cria automaticamente um arquivo pkg.json.
Um pacote pronto para ser publicado.
Fornecer as informações necessárias para o nome, a descrição e a versão.
Publicar clicando em “Publicar localmente” e selecionar a pasta de pacotes do Dynamo:
AppData\Roaming\Dynamo\Dynamo Core\1.3\packagespara ter o nó disponível no Core. Sempre publique localmente até que o pacote esteja pronto para compartilhar.
Após a publicação de um pacote, os nós estarão disponíveis na biblioteca do Dynamo na categoria CustomNodeModel.
O pacote que acabamos de criar na biblioteca do Dynamo
Quando o pacote estiver pronto para publicação on-line, abra o Gerenciador de pacotes, escolha Publish e, em seguida, Publish Online.
Para ver como o Dynamo formatou o pacote, clicar nos três pontos verticais à direita de “CustomNodeModel” e escolher “Mostrar diretório raiz”
Selecionar
Publishe, em seguida,Publish Onlinena janela “Publicar um pacote do Dynamo”.Para excluir um pacote, selecionar
Delete.
A atualização de um pacote é um processo semelhante ao da publicação. Abra o Gerenciador de pacotes e selecione Publish Version... no pacote que precisa ser atualizado e insira uma versão posterior.
Selecionar
Publish Versionpara atualizar um pacote existente com novos arquivos no diretório raiz e, em seguida, escolher se ele deve ser publicado localmente ou on-line.
O cliente Web do Gerenciador de pacotes permite que os usuários pesquisem e visualizem dados de pacotes, incluindo controle de versão, estatísticas de download e outras informações relevantes. Além disso, os autores do pacote podem fazer login para atualizar os detalhes do pacote, como informações de compatibilidade, diretamente por meio do cliente da Web.
Para obter mais informações sobre esses recursos, consulte a postagem do blog aqui: .
É possível acessar o cliente Web do Gerenciador de pacotes neste link: .
Atualizar os detalhes do pacote
Os autores podem editar a descrição do pacote, o link do site e o link do repositório seguindo estas etapas:
Em Meus pacotes, selecione o pacote e clique em Editar detalhes do pacote.
Adicione ou modifique os links do Site e do Repositório usando os respectivos campos.
Atualize a Descrição do pacote conforme necessário.
Observação: As atualizações podem levar até 15 minutos para serem atualizadas no Gerenciador de pacotes no Dynamo, já que as atualizações de servidor levam algum tempo. Há esforços em andamento para reduzir esse atraso.
Editar informações de compatibilidade para versões de pacote publicadas
É possível atualizar as informações de compatibilidade retroativamente para versões de pacotes publicadas anteriormente. Siga estas etapas:
Etapa 1:
Clique na versão do pacote que você deseja atualizar.
A lista Depende será preenchida automaticamente com os pacotes dos quais o pacote depende.
Clique no ícone de lápis ao lado de Compatibilidade para abrir o fluxo de trabalho Editar informações de compatibilidade.
Etapa 2:
Siga o fluxograma abaixo e consulte a tabela abaixo para entender qual opção funciona melhor para o pacote.
Vamos usar alguns exemplos para analisar alguns cenários:
Exemplo de pacote nº 1 – Conexão do Civil: esse pacote tem dependências de APIs com o Revit e o Civil 3D e não inclui uma coleção de nós principais (por exemplo: funções de geometria, funções matemáticas e/ou gerenciamento de lista). Então, neste caso, a opção ideal seria escolher a Opção 1. O pacote que corresponda ao intervalo de versões e/ou à lista de versões individuais será mostrado como compatível no Revit e no Civil 3D.
Exemplo de pacote nº 2 – Ritmo: esse pacote é uma coleção de nós específicos do Revit junto com uma coleção de nós principais. Nesse caso, o pacote tem dependências de hospedeiro. Mas também inclui nós principais que funcionarão no Dynamo Core. Então, nesse caso, a alternativa ideal seria a Opção 2. O pacote será mostrado como compatível no ambiente do Revit e do Dynamo Core (também chamado de Dynamo Sandbox) que corresponde ao intervalo de versões e/ou à lista de versões individuais.
Exemplo de pacote nº 3 – Kit de ferramentas de malha: esse pacote é um pacote do Dynamo Core que é uma coleção de nós de geometria que não tem dependências de hospedeiro. Então, nesse caso, a alternativa ideal seria a Opção 3. O pacote será mostrado como Compatível no Dynamo e em todos os ambientes de hospedeiro que correspondam ao intervalo de versões e/ou à lista de versões individuais.
Dependendo da opção selecionada, os campos específicos do Dynamo e/ou do hospedeiro serão exibidos conforme mostrado na imagem abaixo.
Se você estiver desenvolvendo montagens a serem publicadas como um pacote do Dynamo, o projeto poderá ser configurado para agrupar todos os recursos necessários e colocá-los em uma estrutura de diretório compatível com o pacote. Isso permitirá que o projeto seja rapidamente testado como um pacote e simulará a experiência do usuário.
Há dois métodos para compilar um pacote no Visual Studio:
Adicionar eventos pós-compilação através da caixa de diálogo Configurações do projeto que usam scripts xcopy ou Python para copiar os arquivos necessários
Usar o destino de compilação “AfterBuild” no arquivo .csproj para criar tarefas de cópia de arquivos e diretórios
“AfterBuild” é o método preferido para esses tipos de operações (e o que é abordado neste guia), pois não depende da cópia de arquivos que podem não estar disponíveis no computador de compilação.
Configure a estrutura de diretórios no repositório para que os arquivos de origem sejam separados dos arquivos de pacote. Trabalhando com o estudo de caso CustomNodeModel, coloque o projeto do Visual Studio e todos os arquivos associados em uma nova pasta src. Todos os pacotes gerados pelo projeto serão armazenados nessa pasta. A estrutura de pastas deve ter este aspecto:
Mover os arquivos de projeto para a nova pasta
src
Agora que os arquivos de origem estão em uma pasta separada, adicione um destino AfterBuild ao arquivo CustomNodeModel.csproj no Visual Studio. Isso deve copiar os arquivos necessários para uma nova pasta de pacote. Abra o arquivo CustomNodeModel.csproj em um editor de texto (usamos o ) e coloque o destino da compilação antes do identificador de fechamento </Project>. Esse destino AfterBuild copiará todos os arquivos .dll, .pbd, .xml e .config para uma nova pasta bin e criará as pastas dyf e extras.
Precisamos ter certeza de que o destino foi adicionado ao arquivo
CustomNodeModel.csproj(não a outro arquivo de projeto) e que o projeto não tem nenhuma configuração Pós-compilação existente.
Colocar o destino AfterBuild antes do identificador
</Project>final.
Na seção <ItemGroup>, são definidas um número de variáveis para representar tipos de arquivo específicos. Por exemplo, a variável Dll representa todos os arquivos no diretório de saída cuja extensão é .dll.
O objetivo da tarefa Copy é copiar todos os arquivos .dll para um diretório, especificamente a pasta de pacotes para a qual estamos compilando.
Os pacotes do Dynamo normalmente têm uma pasta dyf e extra para os nós personalizados do Dynamo e outros recursos, como imagens. Para criar essas pastas, é preciso usar uma tarefa MakeDir. Essa tarefa criará uma pasta se ela não existir. É possível adicionar arquivos manualmente a essa pasta.
Se você compilar o projeto, a pasta do projeto agora deverá ter uma pasta packages junto com a pasta src criada anteriormente. Dentro do diretório packages, há uma pasta que contém tudo o que é necessário para o pacote. Também precisamos copiar o arquivo pkg.json para a pasta do pacote para que o Dynamo saiba como carregar o pacote.
A nova pasta de pacotes que o destino AfterBuild criou
A pasta src existente com o projeto
As pastas
dyfeextracriadas no destino AfterBuild
Agora você pode publicar o pacote usando o gerenciador de pacotes do Dynamo ou copiá-lo diretamente para o diretório de pacotes do Dynamo: <user>\AppData\Roaming\Dynamo\1.3\packages.
Com um projeto do Visual Studio ativo e em execução, vamos analisar como compilar um nó personalizado que cria uma grade retangular de células. Embora possamos criar isso com vários nós padrão, é uma ferramenta útil que pode ser facilmente contida em um nó Sem toque. Ao contrário das linhas de grade, as células podem ser dimensionadas em torno de seus pontos centrais, consultadas para seus vértices de canto ou incorporadas em faces.
Este exemplo abordará alguns dos recursos e conceitos a serem considerados ao criar um nó Sem toque. Depois de compilarmos o nó personalizado e adicioná-lo ao Dynamo, verifique se a página “Aprofundar o conhecimento sobre o nó Sem Toque” fornece uma visão mais profunda dos valores de entrada padrão, retornando vários valores, documentação, objetos, usando tipos de geometria do Dynamo e migrações.












pkg.json.


CustomNodeModel
> src
> CustomNodeModel
> CustomNodeModelFunction
> packages
> CustomNodeModel.sln <Target Name="AfterBuild">
<ItemGroup>
<Dlls Include="$(OutDir)*.dll" />
<Pdbs Include="$(OutDir)*.pdb" />
<Xmls Include="$(OutDir)*.xml" />
<Configs Include="$(OutDir)*.config" />
</ItemGroup>
<Copy SourceFiles="@(Dlls)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
<Copy SourceFiles="@(Pdbs)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
<Copy SourceFiles="@(Xmls)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
<Copy SourceFiles="@(Configs)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
<MakeDir Directories="$(SolutionDir)..\packages\CustomNodeModel\dyf" />
<MakeDir Directories="$(SolutionDir)..\packages\CustomNodeModel\extra" />
</Target><ItemGroup>
<Dlls Include="$(OutDir)*.dll" />
</ItemGroup><Copy SourceFiles="@(Dlls)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" /><MakeDir Directories="$(SolutionDir)..\packages\CustomNodeModel\extra" />
Escolher
Class Librarypara o tipo de projetoNomear o projeto
CustomNodes
Como vamos criar geometria, precisamos fazer referência ao pacote NuGet apropriado. Instale o pacote ZeroTouchLibrary do Gerenciador de pacotes NuGet. Esse pacote é necessário para a declaração using Autodesk.DesignScript.Geometry;.
Procure o pacote ZeroTouchLibrary
Usaremos esse nó na compilação atual do Dynamo Studio, que é 1.3. Selecione a versão do pacote que corresponde a isso.
Observe que também renomeamos o arquivo de classe para
Grids.cs
Em seguida, precisamos estabelecer um namespace e uma classe na qual o método RetangularGrid residirá. O nó será nomeado no Dynamo de acordo com o método e os nomes de classe. Ainda não precisamos copiar isso no Visual Studio.
Autodesk.DesignScript.Geometry;faz referência ao arquivo ProtoGeometry.dll no pacote ZeroTouchLibrarySystem.Collections.Generic, que é necessário para criar listas
Agora podemos adicionar o método para desenhar os retângulos. O arquivo de classe deve ter este aspecto e pode ser copiado para o Visual Studio.
Se o projeto for semelhante a este, vá em frente e tente compilar o .dll.
Escolher Compilar > Compilar solução
Verifique a pasta bin do projeto para obter um .dll. Se a compilação tiver sido bem-sucedida, poderemos adicionar o .dll ao Dynamo.
O nó personalizado RectangularGrids na Biblioteca do Dynamo
O nó personalizado na tela
O botão Adicionar para adicionar o
.dllao Dynamo
No exemplo acima, criamos um nó bastante simples que não definiu muito mais fora do método RectangularGrids. No entanto, podemos desejar criar dicas de ferramentas para portas de entrada ou fornecer ao nó um resumo, como os nós padrão do Dynamo. Adicionar esses recursos a nós personalizados facilita seu uso, especialmente se um usuário desejar pesquisá-los na biblioteca.
Um valor de entrada padrão
Uma dica de ferramenta para a entrada xCount
O nó RetangularGrid precisa de alguns desses recursos básicos. No código abaixo, adicionamos descrições de porta de entrada e saída, um resumo e valores de entrada padrão.
Forneça os valores padrão das entradas atribuindo valores aos parâmetros do método: RectangularGrid(int xCount = 10, int yCount = 10)
Crie dicas de ferramentas de entrada e saída, palavras-chave de pesquisa e um resumo com a documentação XML precedida por ///.
Para adicionar dicas de ferramentas, precisamos de um arquivo xml no diretório do projeto. É possível gerar um .xml automaticamente pelo Visual Studio ativando a opção.
Ative o arquivo de documentação XML aqui e especifique um caminho de arquivo. Isso gera um arquivo XML.
E pronto. Criamos um novo nó com vários recursos padrão. O capítulo a seguir, “Noções básicas sobre o nó Sem toque”, entra em mais detalhes sobre o desenvolvimento do nó Sem toque e os problemas dos quais você deve estar ciente.

using Autodesk.DesignScript.Geometry;
using System.Collections.Generic;
namespace CustomNodes
{
public class Grids
{
public static List<Rectangle> RectangularGrid(int xCount, int yCount)
{
//The method for creating a rectangular grid will live in here
}
}
}using Autodesk.DesignScript.Geometry;
using System.Collections.Generic;
namespace CustomNodes
{
public class Grids
{
public static List<Rectangle> RectangularGrid(int xCount, int yCount)
{
double x = 0;
double y = 0;
var pList = new List<Rectangle>();
for (int i = 0; i < xCount; i++)
{
y++;
x = 0;
for (int j = 0; j < yCount; j++)
{
x++;
Point pt = Point.ByCoordinates(x, y);
Vector vec = Vector.ZAxis();
Plane bP = Plane.ByOriginNormal(pt, vec);
Rectangle rect = Rectangle.ByWidthLength(bP, 1, 1);
pList.Add(rect);
}
}
return pList;
}
}
}using Autodesk.DesignScript.Geometry;
using System.Collections.Generic;
namespace CustomNodes
{
public class Grids
{
/// <summary>
/// This method creates a rectangular grid from an X and Y count.
/// </summary>
/// <param name="xCount">Number of grid cells in the X direction</param>
/// <param name="yCount">Number of grid cells in the Y direction</param>
/// <returns>A list of rectangles</returns>
/// <search>grid, rectangle</search>
public static List<Rectangle> RectangularGrid(int xCount = 10, int yCount = 10)
{
double x = 0;
double y = 0;
var pList = new List<Rectangle>();
for (int i = 0; i < xCount; i++)
{
y++;
x = 0;
for (int j = 0; j < yCount; j++)
{
x++;
Point pt = Point.ByCoordinates(x, y);
Vector vec = Vector.ZAxis();
Plane bP = Plane.ByOriginNormal(pt, vec);
Rectangle rect = Rectangle.ByWidthLength(bP, 1, 1);
pList.Add(rect);
Point cPt = rect.Center();
}
}
return pList;
}
}
}






Se você estiver familiarizado com a escrita de scripts no Python e desejar mais funcionalidade dos nós padrão do Dynamo Python, poderemos usar o recurso Sem toque para criar nossos próprios. Vamos começar com um exemplo simples que nos permite passar um script Python como uma sequência de caracteres para um nó Sem toque, onde o script é executado e um resultado é retornado. Este estudo de caso será baseado nos tutoriais virtuais e nos exemplos na seção Introdução. Consulte os exemplos se você for completamente novo na criação de nós Sem toque.
Um nó Sem toque que executará uma sequência de caracteres de script Python
Esse nó depende de uma instância do mecanismo de scripts IronPython. Para fazer isso, precisamos fazer referência a algumas montagens adicionais. Siga as etapas abaixo para configurar um modelo básico no Visual Studio:
Criar um novo projeto de classe do Visual Studio
Adicionar uma referência ao IronPython.dll localizado em C:\Program Files (x86)\IronPython 2.7\IronPython.dll
Adicionar uma referência ao Microsoft.Scripting.dll localizado em C:\Program Files (x86)\IronPython 2.7\Platforms\Net40\Microsoft.Scripting.dll
O código a seguir fornece um exemplo para a etapa mencionada acima. A compilação da solução criará um novo .dll localizado na pasta bin de nosso projeto. Agora, é possível importar este .dll para o Dynamo como parte de um pacote ou navegar para File < Import Library...
O script Python está retornando a variável output, o que significa que precisaremos de uma variável output no script Python. Use esse script de amostra para testar o nó no Dynamo. Se você já tiver usado o nó Python no Dynamo, o seguinte deverá ser familiar. Para obter mais informações, consulte a .
Uma limitação dos nós Python padrão é que eles têm somente uma única porta de saída, portanto, se desejarmos retornar vários objetos, deveremos criar uma lista e recuperar cada objeto. Se modificarmos o exemplo acima para retornar um dicionário, poderemos adicionar quantas portas de saída desejarmos. Consulte a seção Retornar vários valores em “Aprofundar o conhecimento sobre o nó Sem toque” para obter informações mais específicas sobre os dicionários.
Esse nó está nos permitindo retornar o volume do cuboide e seu centroide.
Vamos modificar o exemplo anterior com estas etapas:
Adicionar uma referência ao DynamoServices.dll do gerenciador de pacotes do NuGet
Além das montagens anteriores, incluir System.Collections.Generic e Autodesk.DesignScript.Runtime
Modificar o tipo de retorno em nosso método para retornar um dicionário que conterá nossas saídas
Também adicionamos uma variável de saída (output2) ao script python de amostra. Lembre-se de que essas variáveis podem usar qualquer convenção de nomenclatura Python legal, a saída foi usada estritamente para fins de clareza neste exemplo.
O que são tipos COM? –
A maneira padrão de usar tipos COM em C# é fazer referência e enviar as montagens de interoperabilidade principais (basicamente uma grande coleção de APIs) com o pacote.
Uma alternativa a isso é incorporar as PIA (montagens de interoperabilidade principais) na montagem gerenciada. Isso basicamente inclui apenas os tipos e membros que são realmente usados por uma montagem gerenciada. No entanto, essa abordagem apresenta alguns outros problemas, como a equivalência de tipos.
Esta publicação descreve muito bem o problema:
As extensões do Dynamo podem ser implantadas no gerenciador de pacotes, como as bibliotecas de nós normais do Dynamo. Quando um pacote instalado contém uma extensão de vista, a extensão é carregada no tempo de execução quando o Dynamo é carregado. É possível verificar o console do Dynamo para verificar se a extensão foi carregada corretamente.
Incluir as declarações IronPython.Hosting e Microsoft.Scripting.Hosting using na classe
Adicionar um construtor vazio privado para evitar que um nó adicional seja adicionado à biblioteca do Dynamo com nosso pacote
Criar um novo método que toma uma única sequência de caracteres como um parâmetro de entrada
Dentro desse método, instanciaremos um novo mecanismo Python e criaremos um escopo de script vazio. Você pode imaginar esse escopo como as variáveis globais dentro de uma instância do interpretador Python
Em seguida, chamar Execute no mecanismo que está passando a sequência de entrada e o escopo como parâmetros
Por fim, recuperar e retornar os resultados do script chamando GetVariable no escopo e passando o nome da variável do script Python que contém o valor que você está tentando retornar. (Consulte o exemplo abaixo para obter detalhes adicionais)
Cada saída deve ser individualmente recuperada do escopo (considere a possibilidade de configurar um loop simples para conjuntos maiores de saídas)


O Dynamo delega a equivalência de tipos ao tempo de execução do .NET (dotnet). Um exemplo disso seria que dois tipos com o mesmo nome e namespace, provenientes de montagens diferentes não são considerados equivalentes, e o Dynamo mostrará um erro ao carregar as montagens em conflito. Quanto aos tipos de interoperabilidade, o Dynamo verificará se os tipos de interoperabilidade são equivalentes usando a API IsEquivalentTo
Alguns pacotes já foram criados com tipos de interoperabilidade integrados (ex.: CivilConnection). Carregar dois pacotes com montagens de interoperabilidade integradas que não são consideradas equivalentes (versões diferentes, conforme definido aqui) causará um package load error. Devido a isso, sugerimos que os autores dos pacotes usem a vinculação dinâmica (também conhecida como vinculação tardia) para tipos de interoperabilidade (a solução também é descrita aqui).
Você pode seguir este exemplo:
using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
namespace PythonLibrary
{
public class PythonZT
{
// Unless a constructor is provided, Dynamo will automatically create one and add it to the library
// To avoid this, create a private constructor
private PythonZT() { }
// The method that executes the Python string
public static string executePyString(string pyString)
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
engine.Execute(pyString, scope);
// Return the value of the 'output' variable from the Python script below
var output = scope.GetVariable("output");
return (output);
}
}
}import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
cube = Cuboid.ByLengths(10,10,10);
volume = cube.Volume
output = str(volume)using IronPython.Hosting;
using Microsoft.Scripting.Hosting;
using System.Collections.Generic;
using Autodesk.DesignScript.Runtime;
namespace PythonLibrary
{
public class PythonZT
{
private PythonZT() { }
[MultiReturn(new[] { "output1", "output2" })]
public static Dictionary<string, object> executePyString(string pyString)
{
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
engine.Execute(pyString, scope);
// Return the value of 'output1' from script
var output1 = scope.GetVariable("output1");
// Return the value of 'output2' from script
var output2 = scope.GetVariable("output2");
// Define the names of outputs and the objects to return
return new Dictionary<string, object> {
{ "output1", (output1) },
{ "output2", (output2) }
};
}
}
}import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
cube = Cuboid.ByLengths(10,10,10);
centroid = Cuboid.Centroid(cube);
volume = cube.Volume
output1 = str(volume)
output2 = str(centroid)public class Application
{
string m_sProdID = "SomeNamespace.Application";
public dynamic m_oApp = null; // Use dynamic so you do not need the PIA types
public Application()
{
this.GetApplication();
}
internal void GetApplication()
{
try
{
m_oApp = System.Runtime.InteropServices.Marshal.GetActiveObject(m_sProdID);
}
catch (Exception /*ex*/)
{}
}
}
}A estrutura de um pacote de extensão é a mesma que um pacote normal contendo...
Supondo que você já tenha compilado sua extensão, terá (no mínimo) uma montagem .NET e um arquivo de manifesto. A montagem deve conter uma classe que implementa IViewExtension ou IExtension. O arquivo de manifesto .XML informa ao Dynamo qual classe deve ser instanciada para iniciar a extensão. Para que o gerenciador de pacotes localize corretamente a extensão, o arquivo de manifesto deve corresponder com precisão à localização e à nomenclatura da montagem.
Coloque os arquivos de montagem na pasta bin e o arquivo de manifesto na pasta extra. Também é possível colocar todos os recursos adicionais nessa pasta.
Exemplo de arquivo .XML de manifesto:
Depois que você tiver uma pasta contendo os subdiretórios descritos acima, estará pronto para enviar (carregar) para o gerenciador de pacotes. Um ponto a ter em mente é que não é possível publicar pacotes do Dynamo Sandbox. Isso significa que é necessário estar usando o Dynamo Revit. Uma vez dentro do Dynamo Revit, navegue até Pacotes => Publicar novo pacote. Isso solicitará que o usuário faça login na Autodesk Account com a qual deseja associar o pacote.
Neste ponto, você deve estar na janela normal do pacote de publicação, onde será necessário inserir todos os campos obrigatórios relativos ao pacote/extensão. Há uma etapa adicional muito importante que requer que você assegure que nenhum dos arquivos de montagem esteja marcado como uma biblioteca de nós. Isso é feito clicando com o botão direito do mouse nos arquivos importados (a pasta de pacotes criada acima). Um menu de contexto será exibido, o que lhe dá a opção de marcar (ou desmarcar) essa opção. Todas as montagens de extensão devem estar desmarcadas.
Antes de publicar de forma pública, você deve sempre publicar localmente para assegurar que tudo funcione como esperado. Uma vez que isso tenha sido verificado, você estará pronto para entrar em ação selecionando Publicar.
Para verificar se o pacote foi carregado com êxito, você deverá conseguir pesquisá-lo com base na nomeação e nas palavras-chave especificadas na etapa de publicação. Por fim, é importante observar que as mesmas extensões exigirão uma reinicialização do Dynamo antes de funcionar. Normalmente, essas extensões exigem parâmetros especificados quando o Dynamo é inicializado.
Independentemente do nível de experiência, a plataforma do Dynamo foi projetada para que todos os usuários sejam colaboradores. Há diversas opções de desenvolvimento voltadas para diferentes capacidades e níveis de habilidades, cada uma com seus pontos fortes e fracos, dependendo do objetivo. Abaixo, descreveremos as diferentes opções e como escolher uma em detrimento de outra.
Três ambientes de desenvolvimento: Visual Studio, Editor do Python e DesignScript com Blocos de código
As opções de desenvolvimento do Dynamo são divididas principalmente em duas categorias: para o Dynamo versus no Dynamo. As duas categorias podem ser consideradas semelhantes; “no” Dynamo implica o conteúdo criado usando o IDE do Dynamo para ser usado no Dynamo e “para” o Dynamo implica o uso de ferramentas externas para criar conteúdo a ser importado para o Dynamo para ser usado. Embora este guia se concentre no desenvolvimento para o Dynamo, os recursos para todos os processos são descritos abaixo.
Estes nós permitem o maior grau de personalização. Muitos pacotes são criados com esse método e é necessário para contribuir para a origem do Dynamo. O processo de compilação deles será abordado neste guia.
Nós Sem toque
Nós derivados do NodeModel
Extensões
O Manual tem um guia sobre como .
Para a discussão abaixo, o Visual Studio é usado como o ambiente de desenvolvimento para os nós Sem toque e NodeModel.
A interface do Visual Studio com um projeto que desenvolveremos
Embora esses processos existam no espaço de trabalho de programação visual e sejam relativamente diretos, todos eles são opções viáveis para personalizar o Dynamo. O Manual cobre esses tópicos extensivamente e fornece dicas de scripts e as práticas recomendadas no capítulo .
Os Blocos de código expõem o DesignScript no ambiente de programação visual, permitindo fluxos de trabalho flexíveis de scripts de texto e nós. Uma função em um bloco de código pode ser chamada por qualquer item no espaço de trabalho.
Faça o download de um exemplo de bloco de código (clique com o botão direito do mouse e salve como) ou veja um percurso virtual detalhado no .
Os nós personalizados são contêineres para coleções de nós ou até mesmo gráficos inteiros. Eles são uma forma eficaz de coletar rotinas usadas com frequência e compartilhá-las com a comunidade.
Faça o download de um exemplo de nó personalizado (clique com o botão direito do mouse e salve como) ou veja um percurso virtual detalhado no
O desenvolvimento no espaço de trabalho do Dynamo é uma ferramenta poderosa para obter feedback imediato.
Desenvolvimento no espaço de trabalho do Dynamo com o nó Python
As opções de desenvolvimento do Dynamo foram projetadas para lidar com a complexidade de uma necessidade de personalização. Se o objetivo é escrever um script recursivo no Python ou compilar uma interface de usuário de nó totalmente personalizada, há opções para implementar código que envolvem apenas o que é necessário para começar a trabalhar.
Blocos de código, nó Python e nós personalizados no Dynamo
Essas são opções simples para escrever código no ambiente de programação visual do Dynamo. O espaço de trabalho de programação visual do Dynamo fornece acesso ao Python, ao DesignScript e à capacidade de conter vários nós dentro de um nó personalizado.
Com esses métodos, podemos:
Começar a escrever Python ou DesignScript com pouca ou nenhuma configuração.
Importar bibliotecas Python para o Dynamo.
Compartilhar blocos de código, nós Python e nós personalizados com a comunidade do Dynamo como parte de um pacote.
Nós Sem toque
O nó Sem toque é um método simples de apontar e clicar para importar bibliotecas C#. O Dynamo lê os métodos públicos de um .dll e os converte em nós do Dynamo. É possível usar o nó Sem toque para desenvolver seus próprios nós e pacotes personalizados.
Com esse método, podemos:
Importar uma biblioteca que não foi necessariamente desenvolvida para o Dynamo e criar automaticamente um conjunto de novos nós, como o no Manual
Escrever métodos C# e usar facilmente os métodos como nós no Dynamo
Compartilhar uma biblioteca C# como nós com a comunidade do Dynamo em um pacote
Nós derivados do NodeModel
Esses nós são um passo mais profundo na estrutura do Dynamo. Eles são baseados na classe NodeModel e escritos em C#. Embora esse método forneça a maior flexibilidade e potência, a maioria dos aspectos do nó precisa ser explicitamente definida e as funções precisam residir em uma montagem separada.
Com esse método, podemos:
Criar uma interface de usuário de nó totalmente personalizável com controles deslizantes, imagens, cores etc. (por exemplo, nó ColorRange)
Acessar e afetar o que está acontecendo na tela do Dynamo
Personalizar a amarra
Carregar no Dynamo como um pacote
Como o Dynamo está sendo atualizado regularmente, as alterações podem ser feitas em parte da API que um pacote usa. O rastreamento dessas alterações é importante para garantir que os pacotes existentes continuem a funcionar corretamente.
As alterações da API são rastreadas no . Isso abrange as alterações no DynamoCore, nas bibliotecas e nos espaços de trabalho.
Um exemplo de uma mudança significativa futura é a transição do formato de arquivo XML para o formato JSON na versão 2.0. Os nós derivados do NodeModel agora precisarão de um ; caso contrário, eles não serão abertos no Dynamo 2.0.
A documentação da API do Dynamo atualmente cobre a funcionalidade principal:
Esteja ciente de que os .dll estão incluídos em um pacote que está sendo carregado no gerenciador de pacotes. Se o autor do pacote não tiver criado o .dll, ele deverá ter os direitos para compartilhá-lo.
Se um pacote incluir binários, os usuários deverão ser informados, ao fazer o download, de que o pacote contém binários.
No momento em que este artigo foi escrito, o Dynamo usava principalmente o WPF (Windows Presentation Foundation) para renderizar sua interface do usuário. O WPF é um sistema baseado em xaml/binding complexo e poderoso. Como o Dynamo tem uma interface do usuário complexa, é fácil criar travamentos da interface do usuário, vazamentos de memória ou agrupar a execução do gráfico e as atualizações da interface do usuário de maneiras que degradam o desempenho.
Consulte a , que ajudará você a evitar algumas armadilhas comuns ao fazer alterações no código do Dynamo.
Antes de entrar no desenvolvimento, é importante compilar uma base sólida para um novo projeto. Há vários modelos de projeto na comunidade de desenvolvedores do Dynamo que são excelentes locais para começar, mas uma compreensão de como iniciar um projeto do zero é ainda mais valiosa. A compilação de um projeto desde o início proporcionará uma compreensão mais profunda do processo de desenvolvimento.
O Visual Studio é um IDE poderoso, onde podemos criar um projeto, adicionar referências, compilar .dlls e depurar. Ao criar um novo projeto, o Visual Studio também criará uma Solução, uma estrutura para organizar projetos. Vários projetos podem existir em uma única solução e podem ser compilados juntos. Para criar um nó Sem toque, precisaremos iniciar um novo projeto do Visual Studio no qual gravaremos uma biblioteca de classe C# e compilaremos um
C:\Users\User\AppData\Roaming\Dynamo\Dynamo Core\2.1\packages\Sample View Extension
│ pkg.json
├───bin
│ SampleViewExtension.dll
├───dyf
└───extra
SampleViewExtension_ViewExtensionDefinition.xml<ViewExtensionDefinition>
<AssemblyPath>..\bin\MyViewExtension.dll</AssemblyPath>
<TypeName>MyViewExtension.MyViewExtension</TypeName>
</ViewExtensionDefinition>

Os nós Python são uma interface de scripts no espaço de trabalho de programação visual, semelhante aos blocos de código. As bibliotecas Autodesk.DesignScript usam uma notação de ponto similar ao DesignScript.
Faça o download de um exemplo de nó Python (clique com o botão direito do mouse e salve como) ou veja um percurso virtual detalhado no Manual








.dllJanela Novo projeto no Visual Studio
Começar abrindo o Visual Studio e criando um novo projeto:
File > New > ProjectSelecionar o modelo de projeto
Class LibraryNomear o projeto (nomeamos o projeto MyCustomNode)
Definir o caminho do arquivo para o projeto. Para este exemplo, vamos deixá-lo na localização padrão
Selecionar
Ok
O Visual Studio criará e abrirá automaticamente um arquivo C#. Deve ser atribuído um nome apropriado, deve ser configurado o espaço de trabalho e substituído o código padrão por este método de multiplicação.
Abrir o Gerenciador de soluções e as janelas Saída em
View.Renomear o arquivo
Class1.csSampleFunctions.csno Gerenciador de soluções à direita.Adicionar o código acima para a função de multiplicação. Abordaremos as especificações de como o Dynamo lerá as classes C# mais adiante.
O Gerenciador de soluções fornece acesso a tudo no projeto.
Janela Saída: precisaremos dela mais tarde para ver se a compilação foi bem-sucedida.
A próxima etapa é compilar o projeto, mas antes de fazer isso, há algumas configurações que precisamos verificar. Primeiro, assegure-se de que Any CPU ou x64 esteja selecionado como o destino da plataforma e que Prefer 32-bit esteja desmarcado nas Propriedades do projeto.
Abrir as propriedades do projeto selecionando
Project > "ProjectName" PropertiesSelecionar a página
BuildSelecionar
Any CPUoux64no menu suspensoGarantir que
Prefer 32-bitestá desmarcado
Agora podemos compilar o projeto para criar um .dll. Para isso, selecione Build Solution no menu Build ou use o atalho CTRL+SHIFT+B.
Selecionar
Build > Build SolutionÉ possível determinar se o projeto foi compilado com êxito verificando a janela Saída
Se o projeto tiver sido compilado com êxito, haverá um .dll nomeado MyCustomNode na pasta do projeto bin. Para este exemplo, deixamos o caminho de arquivo do projeto como padrão do Visual Studio em c:\users\username\documents\visual studio 2015\Projects. Vamos dar uma olhada na estrutura de arquivos do projeto.
A pasta
bincontém o.dllcriado no Visual Studio.O arquivo de projeto do Visual Studio.
O arquivo de classe.
Como nossa configuração de solução foi definida como
Debug, o.dllserá criado embin\Debug.
Agora, podemos abrir o Dynamo e importar o .dll. Com o recurso Adicionar, navegue até a localização do projeto bin e selecione o .dll que deseja abrir.
Selecionar o botão Adicionar para importar um
.dllNavegar até a localização do projeto. Nosso projeto está localizado no caminho de arquivo padrão do Visual Studio:
C:\Users\username\Documents\Visual Studio 2015\Projects\MyCustomNodeSelecionar o
MyCustomNode.dlla ser importadoClicar em
Openpara carregar o.dll
Se uma categoria for criada na biblioteca chamada MyCustomNode, significa que o .dll foi importado com êxito. No entanto, o Dynamo criou dois nós do que queríamos ser um nó único. Na próxima seção, explicaremos por que isso acontece e como o Dynamo lê um .dll.
MyCustomNode na biblioteca do Dynamo. A categoria da biblioteca é determinada pelo nome
.dll.SampleFunctions.MultiplyByTwo na tela.
Quando o Dynamo carrega um .dll, ele expõe todos os métodos estáticos públicos como nós. Construtores, métodos e propriedades serão transformados em nós Criar, Ação e Consulta, respectivamente. No nosso exemplo de multiplicação, o método MultiplyByTwo() se torna num nó Ação no Dynamo. Isso ocorre porque o nó foi nomeado com base em seu método e classe.
A entrada é nomeada
inputNumbercom base no nome do parâmetro do método.A saída é nomeada
doublepor padrão porque esse é o tipo de dados que está sendo retornado.O nó é nomeado
SampleFunctions.MultiplyByTwoporque esses são os nomes de classe e método.
No exemplo acima, o nó adicional Criar SampleFunctions foi criado porque não fornecemos explicitamente um construtor e, portanto, um foi criado automaticamente. Podemos evitar isso criando um construtor privado vazio em nossa classe SampleFunctions.
O Dynamo importou nosso método como um nó Criar
O nó de multiplicação é muito simples e não é necessário fazer referências ao Dynamo. Se quisermos acessar qualquer funcionalidade do Dynamo para criar geometria, por exemplo, precisaremos fazer referência aos pacotes NuGet do Dynamo.
ZeroTouchLibrary – Pacote para a compilação de bibliotecas de nós sem toque para o Dynamo que contém as seguintes bibliotecas: DynamoUnits.dll, ProtoGeometry.dll
WpfUILibrary – Pacote para bibliotecas de nós de compilação do Dynamo com interface de usuário personalizada no WPF que contém as seguintes bibliotecas: DynamoCoreWpf.dll, CoreNodeModels.dll, CoreNodeModelWpf.dll
DynamoServices – Biblioteca do DynamoServices para o Dynamo
– Infraestrutura de teste da unidade e do sistema para o Dynamo que contém as seguintes bibliotecas: DSIronPython.dll, DynamoApplications.dll, DynamoCore.dll, DynamoInstallDetetive.dll, DynamoShapeManager.dll, DynamoUtilities.dll, ProtoCore.dll, VMDataBridge.dll
– Infraestrutura de teste da unidade e do sistema para o Dynamo que contém as seguintes bibliotecas: DynamoCoreTests.dll, SystemTestServices.dll, TestServices.dll
– Pacote para a compilação de nós principais do Dynamo que contém as seguintes bibliotecas: Analysis.dll, GeometryColor.dll, DSCoreNodes.dll
Para fazer referência a esses pacotes em um projeto do Visual Studio, faça o download do pacote NuGet nos links acima e faça referência manualmente aos .dlls ou use o Gerenciador de pacotes NuGet no Visual Studio. Primeiro, podemos analisar como instalá-los com o NuGet no Visual Studio.
Abra o Gerenciador de pacotes NuGet selecionando
Tools > NuGet Package Manager > Manage NuGet Packages for Solution...
Esse é o Gerenciador de pacotes NuGet. Essa janela mostra quais pacotes foram instalados para o projeto e permite que o usuário procure outros. Se uma nova versão do pacote DynamoServices for liberada, os pacotes poderão ser atualizados daqui ou revertidos para uma versão anterior.
Selecionar Procurar e pesquisar DynamoVisualProgramming para ativar os pacotes do Dynamo.
Pacotes do Dynamo. Selecionar um mostrará a versão atual e a descrição do que está dentro.
Selecionar a versão do pacote necessária e clicar em instalar. Isso instala um pacote para o projeto específico no qual você está trabalhando. Como estamos usando a versão estável mais recente do Dynamo, a versão 1.3, escolha a versão do pacote correspondente.
Para adicionar manualmente um pacote transferido por download do navegador, abra o Gerenciador de referências no Gerenciador de soluções e procure o pacote.
Clicar com o botão direito do mouse em
Referencese selecionarAdd Reference.Selecionar
Browsepara navegar para a localização do pacote.
Agora que o Visual Studio está configurado corretamente e adicionamos com êxito um .dll ao Dynamo, temos uma base sólida para os conceitos daqui para frente. Este é apenas o início, portanto, siga em frente para saber mais sobre como criar um nó personalizado.

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.
O Dynamo é baseado no padrão de arquitetura do software
namespace MyCustomNode
{
public class SampleFunctions
{
public static double MultiplyByTwo(double inputNumber)
{
return inputNumber * 2.0;
}
}
}namespace MyCustomNode
{
public class SampleFunctions
{
//The empty private constructor.
//This will be not imported into Dynamo.
private SampleFunctions() { }
//The public multiplication method.
//This will be imported into Dynamo.
public static double MultiplyByTwo(double inputNumber)
{
return inputNumber * 2.0;
}
}
}












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.
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.
Selecionar
File > New > ProjectSelecionar
Other Project Typespara ativar a opção SoluçãoSelecionar
Blank SolutionNomear a solução
CustomNodeModelSelecionar
Ok
Crie dois projetos de biblioteca de classes C# na solução: um para as funções e outro para implementar a interface NodeModel.
Clicar com o botão direito do mouse na Solução e selecionar
Add > New ProjectEscolher a biblioteca de classes
Nomeá-la
CustomNodeModelClicar em
OkRepita 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.
Adicionar outra classe clicando com o botão direito do mouse no projeto
CustomNodeModel, selecionandoAdd > New Item...e escolhendoClass.No projeto
CustomNodeModel, precisamos das classesGridNodeModel.cseGridNodeView.csNo projeto
CustomNodeModelFunction, precisamos de uma classeGridFunctions.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.
Clicar com o botão direito do mouse em um projeto e selecionar
Manage NuGet PackagesInstalar 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.
Selecionar pacotes do Dynamo NuGet
Definir
Copy Localcomo 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.
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.
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
Clicar com o botão direito do mouse em
CustomNodeModele selecionarAdd > ReferenceEscolher
Projects > SolutionMarcar
CustomNodeModelFunctionClicar 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
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>.
Clicar com o botão direito do mouse em
CustomNodeModele selecionarAdd > New ItemSelecionar
WPFNomear o controle de usuário
SliderClicar em
Add
Copie o seguinte código para Slider.xaml
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.
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.
Clicar com o botão direito do mouse em
CustomNodeModele selecionarAdd > New ItemSelecionar
WebSelecionar
JSON FileNomear o arquivo
pkg.jsonClicar em
Add
Copie o seguinte código para pkg.json
"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.

GeometryPrimitiveConverter.csA classe GeometryPrimitiveConverter na biblioteca de códigos do DynamoRevit fornece vários métodos para converter entre tipos geométricos do Revit e do Dynamo. Esses métodos são úteis ao trabalhar com geometria em scripts do Dynamo que interagem com modelos do Revit.
É possível agrupar os métodos em GeometryPrimitiveConverter.cs em quatro categorias principais:
Tipos do Proto para Revit: métodos que convertem tipos do Dynamo (Proto) em tipos do Revit.
Tipos do Revit para Proto: métodos que convertem tipos do Revit em tipos do Dynamo (Proto).
Graus e radianos: métodos que convertem entre graus e radianos.
X e UZ: métodos que lidam com a obtenção de vetores perpendiculares.
Cria uma BoundingBoxXYZ do Revit com base em um sistema de coordenadas do Dynamo e em dois pontos de definição (mínimo e máximo).
public static Autodesk.Revit.DB.BoundingBoxXYZ ToRevitBoundingBox( Autodesk.DesignScript.Geometry.CoordinateSystem cs, Autodesk.DesignScript.Geometry.Point minPoint, Autodesk.DesignScript.Geometry.Point maxPoint, bool convertUnits = true)
Converte uma BoundingBox do Dynamo em uma BoundingBoxXYZ do Revit.
O indicador convertUnits (true definido como padrão) determina se as coordenadas devem ser convertidas do sistema de unidades do Dynamo em unidades internas do Revit.
public static Autodesk.Revit.DB.BoundingBoxXYZ ToRevitType(this Autodesk.DesignScript.Geometry.BoundingBox bb, bool convertUnits = true)
Converte um ponto do Dynamo em um XYZ do Revit.
O indicador convertUnits (true definido como padrão) converte as coordenadas, se necessário.
public static Autodesk.Revit.DB.XYZ ToRevitType(this Autodesk.DesignScript.Geometry.Point pt, bool convertUnits = true)
Converte um vetor do Dynamo em um XYZ do Revit.
Observe que o indicador convertUnits tem como padrão false porque os vetores representam a direção e a magnitude, que normalmente não requerem conversão de unidade. A conversão pode afetar a direção e o comprimento do vetor.
public static Autodesk.Revit.DB.XYZ ToRevitType(this Vector vec, bool convertUnits = false)
Converte um ponto do Dynamo em um XYZ do Revit.
public static Autodesk.Revit.DB.XYZ ToXyz(this Autodesk.DesignScript.Geometry.Point pt, bool convertUnits = true)
Converte um vetor do Dynamo em um XYZ do Revit.
Observe que o indicador convertUnits tem como padrão false porque os vetores representam a direção e a magnitude, que normalmente não requerem conversão de unidade. A conversão pode afetar a direção e o comprimento do vetor.
public static Autodesk.Revit.DB.XYZ ToXyz(this Vector vec, bool convertUnits = false)
Converte um CoordinateSystem do Dynamo em uma transformação do Revit.
public static Autodesk.Revit.DB.Transform ToTransform(this CoordinateSystem cs, bool convertUnits = true)
Converte um plano do Dynamo em um plano do Revit.
public static Autodesk.Revit.DB.Plane ToPlane(this Autodesk.DesignScript.Geometry.Plane plane, bool convertUnits = true)
Converte coleções de objetos de ponto do Dynamo em coleções XYZ do Revit.
Retornar uma lista de XYZs. public static List<XYZ> ToXyzs(this List<Autodesk.DesignScript.Geometry.Point> list, bool convertUnits = true)
Retornar uma matriz de XYZs. public static XYZ[] ToXyzs(this Autodesk.DesignScript.Geometry.Point[] list, bool convertUnits = true)
Converte uma matriz de objetos de vetor do Dynamo em uma matriz de vetores XYZ do Revit.
public static XYZ[] ToXyzs(this Autodesk.DesignScript.Geometry.Vector[] list, bool convertUnits = false)
Converte uma matriz de valores duplos em DoubleArray do Revit.
public static DoubleArray ToDoubleArray(this double[] list)
Converte uma matriz bidimensional (double[][]), em que cada matriz interna representa um par de valores (U e V) em uma matriz de objetos UV do Revit.
internal static Autodesk.Revit.DB.UV[] ToUvs(this double[][] uvArr)
Converte uma matriz bidimensional (double[][]), em que cada matriz interna representa um par de valores (U e V) em uma matriz de objetos UV do Dynamo.
internal static Autodesk.DesignScript.Geometry.UV[] ToDSUvs(this double[][] uvArr)
Este exemplo mostra um método rápido e fácil de usar o método .ToXyz (ponto) para converter um Point.ByCoordinates do Dynamo em um XYZ do Revit.
Converte uma BoundingBoxXYZ do Revit em uma BoundingBox do Dynamo.
public static Autodesk.DesignScript.Geometry.BoundingBox ToProtoType(this Autodesk.Revit.DB.BoundingBoxXYZ xyz, bool convertUnits = true)
Converte um XYZ do Revit em um ponto do Dynamo.
public static Autodesk.DesignScript.Geometry.Point ToPoint(this XYZ xyz, bool convertUnits = true)
Converte um ponto do Revit em um ponto do Dynamo.
public static Autodesk.DesignScript.Geometry.Point ToProtoType(this Autodesk.Revit.DB.Point point, bool convertUnits = true)
Converte um XYZ do Revit em um vetor do Dynamo.
public static Vector ToVector(this XYZ xyz, bool convertUnits = false)
Converte um UV do Revit em um UV do Dynamo.
public static Autodesk.DesignScript.Geometry.UV ToProtoType(this Autodesk.Revit.DB.UV uv)
Converte um plano do Revit em um plano do Dynamo.
public static Autodesk.DesignScript.Geometry.Plane ToPlane(this Autodesk.Revit.DB.Plane plane, bool convertUnits = true)
Converte uma transformação do Revit em um CoordinateSystem do Dynamo.
public static CoordinateSystem ToCoordinateSystem(this Transform t, bool convertUnits = true)
Converte uma lista de pontos XYZ do Revit em uma lista de pontos do Dynamo.
public static List<Autodesk.DesignScript.Geometry.Point> ToPoints(this List<XYZ> list, bool convertUnits = true)
Este exemplo mostra um método rápido e fácil de usar o método .ToPoint (XYZ) para converter um XYZ do Revit em um ponto do Dynamo.
Converte graus em radianos.
public static double ToRadians(this double degrees) { return degrees * Math.PI / 180.0; }
Converte radianos em graus.
public static double ToDegrees(this double degrees) { return degrees * 180.0 / Math.PI; }
Este exemplo mostra um método rápido e fácil de usar o método .ToRadianos para converter de graus em radianos.
Esse método retorna um vetor XYZ perpendicular ao vetor XYZ fornecido.
public static XYZ GetPerpendicular(this XYZ xyz)
Esse método retorna um Vector do Dynamo perpendicular ao Vector do Dynamo fornecido.
public static Vector GetPerpendicular(this Vector vector)
Este exemplo mostra um método rápido e fácil de usar o método .GetPerpendicular para obter o vetor perpendicular a um vetor de entrada.
Com um entendimento de como criar um projeto Sem toque, podemos nos aprofundar nos detalhes específicos da criação de um nó ao navegar pelo exemplo ZeroTouchEssentials no Dynamo Github.
Muitos dos nós padrão do Dynamo são essencialmente nós Sem toque, como a maioria dos nós matemáticos, de cor e de data e hora acima.
Para iniciar, faça o download do projeto ZeroTouchEssentials aqui:
No Visual Studio, abra o arquivo de solução ZeroTouchEssentials.sln e compile a solução.
O arquivo
ZeroTouchEssentials.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) };
}
}
}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;
}
}
}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()
{
}
}
}<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>using System.Windows.Controls;
namespace CustomNodeModel.CustomNodeModel
{
/// <summary>
/// Interaction logic for Slider.xaml
/// </summary>
public partial class Slider : UserControl
{
public Slider()
{
InitializeComponent();
}
}
}{
"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"
]
}






Abra o Dynamo e importe o ZeroTouchEssentials.dll para obter os nós que faremos referência nos exemplos a seguir.
Os exemplos de código são extraídos e geralmente coincidem com ZeroTouchEssentials.cs. A documentação XML foi removida para mantê-los concisos, e cada exemplo de código criará o nó na imagem acima dele.
O Dynamo suporta a definição de valores padrão para portas de entrada em um nó. Esses valores padrão serão fornecidos ao nó se as portas não tiverem conexões. Os padrões são expressos usando o mecanismo C# de especificação de argumentos opcionais no Guia de programação C#. Os valores padrão são especificados da seguinte maneira:
Defina os parâmetros do método para um valor padrão: inputNumber = 2.0
O valor padrão será exibido quando você passar o cursor sobre a porta de entrada do nó
Retornar vários valores é um pouco mais complexo do que criar várias entradas e isso precisará ser feito usando um dicionário. As entradas do dicionário se tornam portas no lado de saída do nó. Várias portas de retorno são criadas da seguinte maneira:
Adicione using System.Collections.Generic; para usar Dictionary<>.
Adicione using Autodesk.DesignScript.Runtime; para usar o atributo MultiReturn. Isso faz referência ao “DynamoServices.dll” do pacote DynamoServices NuGet.
Adicione o atributo [MultiReturn(new[] { "string1", "string2", ... more strings here })] ao método. As sequências de caracteres se referem às chaves no dicionário e se tornarão os nomes das portas de saída.
Retorne um Dictionary<> da função com chaves que coincidem com os nomes de parâmetro no atributo: return new Dictionary<string, object>
Consulte este exemplo de código em ZeroTouchEssentials.cs
Um nó que retorna várias saídas.
Observe que agora há duas portas de saída nomeadas de acordo com as sequências que inserimos para as chaves do dicionário.
É recomendável adicionar documentação aos nós do Dynamo que descrevam a função, as entradas, as saídas, os identificadores de pesquisa do nó etc. Isso é feito por meio de identificadores de documentação XML. A documentação XML é criada da seguinte maneira:
Qualquer texto de comentário que é precedido por três barras inclinadas adiante é considerado como documentação
Por exemplo: /// Documentation text and XML goes here
Após as três barras, crie identificadores XML acima dos métodos que o Dynamo lerá ao importar o .dll
Por exemplo: /// <summary>...</summary>
Ative a documentação XML no Visual Studio selecionando Project > [Project] Properties > Build > Output e marcando Documentation file
O Visual Studio gerará um arquivo XML na localização especificada
Os tipos de identificadores são os seguintes:
/// <summary>...</summary> é a documentação principal do nó e será exibida como uma dica de ferramenta sobre o nó na barra lateral esquerda de pesquisa
/// <param name="inputName">...</param> criará a documentação para os parâmetros de entrada específicos
/// <returns>...</returns> criará a documentação para um parâmetro de saída
/// <returns name = "outputName">...</returns> criará a documentação para vários parâmetros de saída
/// <search>...</search> corresponderá o nó aos resultados da pesquisa com base em uma lista separada por vírgulas. Por exemplo, se criarmos um nó que subdivide uma malha, poderemos desejar adicionar identificadores como “malha”, “subdivisão” e “catmull-Clark”.
A seguir está um nó de exemplo com descrições de entrada e saída, bem como um resumo que será exibido na biblioteca.
Consulte este exemplo de código em ZeroTouchEssentials.cs
Observe que o código para esse nó de exemplo contém:
Um resumo dos nós
Uma descrição de entrada
Uma descrição de saída
As descrições dos nós descrevem brevemente a função e a saída de um nó. No Dynamo, elas aparecem em dois locais:
Na dica de ferramenta do nó
No navegador de documentação
Siga estas diretrizes para garantir a consistência e ajudar a economizar tempo ao escrever ou atualizar as descrições dos nós.
Visão geral
As descrições devem ter uma a duas frases. Se for necessário incluir mais informações, inclua-as no navegador de documentação na opção Em profundidade.
Maiúsculas e minúsculas da frase (coloque em maiúsculas a primeira palavra de uma frase e os nomes próprios). Sem ponto final.
A linguagem deve ser o mais clara e simples possível. Defina os acrônimos na primeira vez que forem mencionadas, a menos que sejam conhecidos até mesmo por usuários não especialistas.
Sempre priorize a clareza, mesmo que isso signifique desviar-se dessas diretrizes.
Diretrizes
Inicie a descrição com um verbo em terceira pessoa.
Exemplo: Determina se um objeto de geometria faz intersecção com outro
Não comece com um verbo no infinitivo nem com substantivos.
Exemplo: Determinar se um objeto de geometria faz intersecção com outro
Use “Retorna”, “Cria” ou outro verbo descritivo em vez de “Obtém”.
Exemplo: Retorna uma representação Nurbs de uma superfície
Não use “Obter” ou “Obtém”. É menos específico e tem várias possíveis traduções.
Exemplo: Obtém uma representação Nurbs da superfície
Ao se referir a entradas, use “fornecido(a)” ou “entrada” em vez de “especificado(a)” ou outros termos. Omita “fornecido(a)” ou “entrada” quando possível para simplificar a descrição e reduzir a contagem de palavras.
Exemplo: Exclui o arquivo fornecido
Exemplo: Projeta uma curva ao longo da direção de projeção fornecida na geometria base fornecida
Você pode usar “especificado(a)” quando não se referir diretamente a uma entrada.
Ao se referir a entradas, para garantir a consistência, não use “especificado(a)” ou qualquer outro termo, exceto “fornecido(a)” ou “entrada”. Não misture “fornecido(a)” e “entrada” na mesma descrição, a menos que seja necessário para clareza.
Exemplo: Exclui o arquivo especificado
Exemplo: Projeta uma curva de entrada ao longo de uma direção de projeção fornecida em uma geometria base especificada
Use “um” ou “uma” ao se referir pela primeira vez a uma entrada. Use “fornecido(a)” ou “a entrada” em vez de “um” ou “uma”, conforme necessário para maior clareza.
Exemplo: Faz varreduras em uma curva ao longo da curva do caminho
Não use “este(a)” ou “neste(a)”ao se referir a uma entrada pela primeira vez.
Exemplo: Faz varredura nesta curva ao longo da curva do caminho
Ao se referir pela primeira vez a uma saída ou outro substantivo que seja o alvo da operação do nó, use “um” ou “uma”. Use apenas “o(a)” ao combinar com “entrada” ou “fornecido(a)”.
Exemplo: Copia um arquivo
Exemplo: Copia o arquivo fornecido
Ao se referir pela primeira vez a uma saída ou outro substantivo que é o alvo da operação do nó, não use “o(a)” sozinho.
Exemplo: Copia o arquivo
Coloque a primeira palavra de uma frase em maiúsculas e os nomes próprios, como nomes e substantivos tradicionalmente em maiúsculas.
Exemplo: Retorna a intersecção de duas BoundingBoxes
Não coloque objetos e conceitos de geometria comuns em maiúsculas, a menos que seja necessário para maior clareza.
Exemplo: Dimensiona de forma não uniforme em torno do plano fornecido
Os avisos e erros dos nós alertam o usuário sobre uma problema com o gráfico. Eles notificam o usuário sobre problemas que interferem na operação normal do gráfico exibindo um ícone e um balão de texto expandido acima do nó. Os erros e os avisos dos nós podem variar em gravidade: alguns gráficos podem ser executados adequadamente com avisos, enquanto outros bloqueiam os resultados esperados. Em todos os casos, os erros e os avisos dos nós são ferramentas importantes para manter o usuário atualizado sobre problemas com seu gráfico.
Para obter diretrizes para garantir consistência e ajudar a economizar tempo ao escrever ou atualizar mensagens de aviso e erro dos nós, consulte a página wiki Padrão de conteúdo: avisos e erros dos nós.
O Dynamo não tem uma palavra-chave new, portanto, os objetos precisarão ser construídos usando métodos de construção estáticos. Os objetos são construídos da seguinte maneira:
Tornar o construtor interno internal ZeroTouchEssentials(), a menos que seja necessário de outra forma
Construir o objeto com um método estático como public static ZeroTouchEssentials ByTwoDoubles(a, b)
Observação: O Dynamo usa o prefixo “Por” para indicar que um método estático é um construtor e, embora seja opcional, usar “Por” ajudará a biblioteca a se ajustar melhor ao estilo existente do Dynamo.
Consulte este exemplo de código em ZeroTouchEssentials.cs
Após a importação do dll ZeroTouchEssentials, haverá um nó ZeroTouchEssentials na biblioteca. É possível criar esse objeto usando o nó ByTwoDoubles.
As bibliotecas do Dynamo podem usar tipos de geometria nativos do Dynamo como entradas e criar uma nova geometria como saídas. Os tipos de geometria são criados da seguinte maneira:
Referenciar “ProtoGeometry.dll” no projeto incluindo using Autodesk.DesignScript.Geometry; na parte superior do arquivo C# e adicionando o pacote NuGet da ZeroTouchLibrary ao projeto.
Importante: Gerencie os recursos de geometria que não são retornados das funções. Consulte a seção Dispor/usar declarações abaixo.
Observação: Os objetos de geometria do Dynamo são usados como qualquer outro objeto passado para funções.
Consulte este exemplo de código em ZeroTouchEssentials.cs
Um nó que obtém o comprimento de uma curva e o duplica.
Esse nó aceita um tipo de geometria de curva como uma entrada.
Os recursos de geometria que não são retornados de funções precisarão ser gerenciados manualmente, a não ser que você esteja usando o Dynamo versão 2.5 ou posterior. No Dynamo 2.5 e versões posteriores, os recursos de geometria são manipulados internamente pelo sistema. No entanto, talvez você ainda precise descartar a geometria manualmente se tiver um caso de uso complexo ou precisar reduzir a memória em um momento determinado. O mecanismo do Dynamo lidará com quaisquer recursos de geometria que são retornados de funções. Os recursos de geometria que não são retornados podem ser manipulados manualmente das seguintes maneiras:
Com uma declaração de uso:
A declaração de uso está documentada aqui
Consulte Melhorias na estabilidade da geometria do Dynamo para saber mais sobre os novos recursos de estabilidade introduzidos no Dynamo 2.5
Com chamadas Dispor manuais:
Ao publicar uma versão mais recente de uma biblioteca, os nomes de nós podem ser alterados. As alterações de nome podem ser especificadas em um arquivo de migrações para que os gráficos criados em versões anteriores de uma biblioteca continuem a funcionar corretamente quando uma atualização é feita. As migrações são implementadas da seguinte maneira:
Crie um arquivo .xml na mesma pasta que o .dll com o seguinte formato: “BaseDLLName”.Migrations.xml
Em .xml, crie um único elemento <migrations>...</migrations>
Dentro do elemento de migrações, crie os elementos <priorNameHint>...</priorNameHint> para cada alteração de nome
Para cada alteração de nome, forneça um elemento <oldName>...</oldName> e <newName>...</newName>
Clicar com o botão direito do mouse e selecionar
Add > New ItemEscolher
XML FilePara este projeto, vamos nomear o arquivo de migrações
ZeroTouchEssentials.Migrations.xml
Esse código de exemplo está informando ao Dynamo que qualquer nó denominado GetClosestPoint agora é nomeado ClosestPointTo.
Consulte este exemplo de código em ProtoGeometry.Migrations.xml
No momento, o recurso Sem toque não suporta o uso de elementos genéricos. Eles podem ser usados, mas não no código que é importado diretamente onde o tipo não está definido. Métodos, propriedades ou classes que são genéricos e não têm o conjunto de tipos não podem ser expostos.
No exemplo abaixo, um nó Sem toque do tipo T não será importado. Se o resto da biblioteca for importado para o Dynamo, haverá exceções de tipo ausentes.
O uso de um tipo genérico com o tipo definido neste exemplo será importado para o Dynamo.


using (Point p1 = Point.ByCoordinates(0, 0, 0))
{
using (Point p2 = Point.ByCoordinates(10, 10, 0))
{
return Line.ByStartPointEndPoint(p1, p2);
}
}Point p1 = Point.ByCoordinates(0, 0, 0);
Point p2 = Point.ByCoordinates(10, 10, 0);
Line l = Line.ByStartPointEndPoint(p1, p2);
p1.Dispose();
p2.Dispose();
return l;namespace ZeroTouchEssentials
{
public class ZeroTouchEssentials
{
// Set the method parameter to a default value
public static double MultiplyByTwo(double inputNumber = 2.0)
{
return inputNumber * 2.0;
}
}
}using System.Collections.Generic;
using Autodesk.DesignScript.Runtime;
namespace ZeroTouchEssentials
{
public class ZeroTouchEssentials
{
[MultiReturn(new[] { "add", "mult" })]
public static Dictionary<string, object> ReturnMultiExample(double a, double b)
{
return new Dictionary<string, object>
{ "add", (a + b) },
{ "mult", (a * b) }
};
}
}
}using Autodesk.DesignScript.Geometry;
namespace ZeroTouchEssentials
{
public class ZeroTouchEssentials
{
/// <summary>
/// This method demonstrates how to use a native geometry object from Dynamo
/// in a custom method
/// </summary>
/// <param name="curve">Input Curve. This can be of any type deriving from Curve, such as NurbsCurve, Arc, Circle, etc</param>
/// <returns>The twice the length of the Curve </returns>
/// <search>example,curve</search>
public static double DoubleLength(Curve curve)
{
return curve.Length * 2.0;
}
}
}namespace ZeroTouchEssentials
{
public class ZeroTouchEssentials
{
private double _a;
private double _b;
// Make the constructor internal
internal ZeroTouchEssentials(double a, double b)
{
_a = a;
_b = b;
}
// The static method that Dynamo will convert into a Create node
public static ZeroTouchEssentials ByTwoDoubles(double a, double b)
{
return new ZeroTouchEssentials(a, b);
}
}
}using Autodesk.DesignScript.Geometry;
namespace ZeroTouchEssentials
{
public class ZeroTouchEssentials
{
// "Autodesk.DesignScript.Geometry.Curve" is specifying the type of geometry input,
// just as you would specify a double, string, or integer
public static double DoubleLength(Autodesk.DesignScript.Geometry.Curve curve)
{
return curve.Length * 2.0;
}
}
}<?xml version="1.0"?>
<migrations>
<priorNameHint>
<oldName>Autodesk.DesignScript.Geometry.Geometry.GetClosestPoint</oldName>
<newName>Autodesk.DesignScript.Geometry.Geometry.ClosestPointTo</newName>
</priorNameHint>
</migrations>public class SomeGenericClass<T>
{
public SomeGenericClass()
{
Console.WriteLine(typeof(T).ToString());
}
}public class SomeWrapper
{
public object wrapped;
public SomeWrapper(SomeGenericClass<double> someConstrainedType)
{
Console.WriteLine(this.wrapped.GetType().ToString());
}
}# Load the Python Standard and DesignScript Libraries
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Revit API
from Autodesk.Revit.DB import *
# Revit Geometry Conversion Library
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
# Input: Dynamo Point
dyn_point = IN[0]
# Convert to Revit XYZ
revit_point = dyn_point.ToXyz()
# Output
OUT = revit_point
import sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Revit API
from Autodesk.Revit.DB import *
# Revit Geometry Conversion Library
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
# Input: Dynamo Point
dyn_point = IN[0]
# Convert to Revit XYZ
revit_point = dyn_point.ToPoint()
# Output
OUT = revit_pointimport sys
import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Revit API
from Autodesk.Revit.DB import *
# Revit Geometry Conversion Library
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
# Input: Measure Angle
degree_angle = IN[0]
# Convert to Radians
radian_angle = Revit.GeometryConversion.GeometryPrimitiveConverter.ToRadians(degree_angle)
# Output
OUT = radian_angleimport clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *
# Revit API
from Autodesk.Revit.DB import *
# Revit Geometry Conversion Library
import Revit
clr.ImportExtensions(Revit.GeometryConversion)
# Input Dynamo Vector
input_vector = IN[0]
# Get perpendicular vector using GetPerpendicular
perpendicular_vector = Revit.GeometryConversion.GeometryPrimitiveConverter.GetPerpendicular(input_vector)
# Output the perpendicular vector
OUT = perpendicular_vector
Use maiúsculas em Booleano. Use maiúsculas em True e False ao se referir à saída de Booleanos.
Exemplo: Retornará True se os dois valores forem diferentes
Exemplo: Converte uma sequência de caracteres em todos os caracteres maiúsculos ou minúsculos com base em um parâmetro Booleano
Não coloque Booleano em minúsculas. Não coloque True e False em minúsculas ao se referir à saída de Booleanos.
Exemplo: Retornará true se os dois valores forem diferentes
Exemplo: Converte uma sequência de caracteres em todos os caracteres maiúsculos ou todos os caracteres minúsculos com base em um parâmetro Booleano







Esta seção contém informações sobre problemas que podem ocorrer durante a migração dos gráficos, dos pacotes e das bibliotecas para o Dynamo 3.x.
O Dynamo 3.0 é uma versão principal e algumas APIs foram alteradas ou removidas. A maior alteração que provavelmente afetará você como desenvolvedor ou usuário do Dynamo 3.x é a mudança para .NET8.
Dotnet/.NET é o tempo de execução que alimenta a linguagem C# na qual o Dynamo está escrito. Atualizamos para uma versão moderna deste tempo de execução junto com o resto do ecossistema da Autodesk.
Você pode ler mais em nossa postagem de blog.
Como o Dynamo 3.x agora é executado no tempo de execução do .NET8, não é garantido que os pacotes que foram criados para o Dynamo 2.x (usando o .NET48) funcionem no Dynamo 3.x. Quando você tentar fazer download de um pacote no Dynamo 3.x que foi publicado de uma versão do Dynamo inferior a 3.0, receberá um aviso de que o pacote é de uma versão anterior do Dynamo.
Isso não significa que o pacote não funcionará É simplesmente um aviso de que podem ocorrer problemas de compatibilidade e, em geral, é uma boa ideia verificar se há uma versão mais recente que tenha sido criada especificamente para o Dynamo 3.x.
Você também pode observar esse tipo de aviso nos arquivos de registro do Dynamo no momento da carga do pacote. Se tudo estiver funcionando corretamente, será possível ignorá-lo.
É muito improvável que um pacote criado para o Dynamo 3.x (usando .Net8) funcione no Dynamo 2.x. Você também verá um aviso ao fazer o download de pacotes criados para versões mais recentes do Dynamo enquanto usa uma versão mais antiga.
As extensões são uma poderosa ferramenta de desenvolvimento no ecossistema do Dynamo. Elas permitem que os desenvolvedores direcionem a funcionalidade personalizada com base nas interações e lógica do Dynamo. As extensões podem ser divididas em duas categorias principais, extensões e extensões de vista. Como a nomenclatura indica, a estrutura de extensão da vista permite estender a interface do usuário do Dynamo registrando itens de menu personalizados. As extensões regulares operam de forma muito semelhante, exceto a interface do usuário. Por exemplo, podemos compilar uma extensão que registra informações específicas no console do Dynamo. Esse cenário não requer uma interface do usuário personalizada e, portanto, também pode ser realizado usando uma extensão.
Seguindo o exemplo SampleViewExtension do repositório Github do DynamoSamples, vamos percorrer as etapas necessárias para criar uma janela simples sem janela restrita que exibe os nós ativos no gráfico em tempo real. Uma extensão de vista requer que criemos uma interface do usuário para a janela e vinculemos valores a um modelo de vista.
A janela de extensão da vista foi desenvolvida seguindo o exemplo SampleViewExtension no repositório Github.
Embora possamos compilar o exemplo desde o início, também é possível fazer o download e criar o repositório DynamoSamples para servir como referência.
Repositório DynamoSamples:
Este percurso virtual fará referência específica ao projeto denominado SampleViewExtension encontrado em
DynamoSamples/src/.
Uma extensão de vista tem três partes essenciais:
Uma montagem contendo uma classe que implementa IViewExtension, bem como uma classe que cria um modelo de vista
Um arquivo .xml que informa ao Dynamo onde ele deve procurar por essa montagem no tempo de execução e o tipo de extensão
Um arquivo .xaml que vincula os dados à exibição gráfica e determina a aparência da janela
1. Criar a estrutura do projeto
Comece criando um novo projeto Class Library chamado SampleViewExtension.
Criar um novo projeto selecionando
File > New > ProjectSelecionar
Class LibraryNomear o projeto
SampleViewExtension
Neste projeto, precisaremos de duas classes. Uma classe implementará IViewExtension e a outra que implementará NotificationObject. IViewExtension conterá todas as informações sobre como nossa extensão será implantada, carregada, referenciada e eliminada. NotificationObject fornecerá notificações de alterações no Dynamo e IDisposable quando ocorrer uma alteração, a contagem será atualizada de acordo.
Um arquivo de classe denominado
SampleViewExtension.csque implementaráIViewExtensionUm arquivo de classe denominado
SampleWindowViewMode.csque implementaráNotificationObject
Para usar o IViewExtension, precisaremos do pacote WpfUILibrary NuGet. A instalação desse pacote instalará automaticamente os pacotes Core, Services e ZeroTouchLibrary.
Selecionar a biblioteca WpfUIL
Selecionar
Installpara instalar todos os pacotes dependentes
2. Implementar a classe IViewExtension
Na classe IViewExtension, vamos determinar o que acontece quando o Dynamo é iniciado, quando a extensão é carregada e quando o Dynamo é fechado. No arquivo de classe SampleViewExtension.cs, adicione o seguinte código:
A classe SampleViewExtension cria um item de menu clicável para abrir a janela e conecta-a ao modelo de vista e à janela.
public class SampleViewExtension : IViewExtension SampleViewExtension herda da interface do IViewExtension e fornece tudo o que precisamos para criar o item de menu.
sampleMenuItem = new MenuItem { Header = "Show View Extension Sample Window" }; cria um MenuItem e o adiciona ao menu View.
O item de menu
sampleMenuItem.Click += (sender, args) aciona um evento que abrirá uma nova janela quando o item de menu for clicado
MainGrid = { DataContext = viewModel } define o contexto de dados para a grade principal na janela, referindo-se a Main Grid no arquivo .xaml que criaremos
3. Implementar o modelo de vista
Agora que estabelecemos alguns dos parâmetros básicos da janela, adicionaremos a lógica para responder a vários eventos relacionados ao Dynamo e instruiremos a interface do usuário a atualizar com base nesses eventos. Copie o seguinte código para o arquivo de classe SampleWindowViewModel.cs:
Essa implementação da classe de modelo de vista ouve o CurrentWorkspaceModel e aciona um evento quando um nó é adicionado ou removido do espaço de trabalho. Isso gera uma alteração de propriedade que notifica a interface do usuário ou elementos vinculados que os dados foram alterados e precisam ser atualizados. O getter ActiveNodeTypes é chamado, o que chama internamente uma função getNodeTypes() de ajuda adicional. Essa função interage em todos os nós ativos na tela, preenche uma sequência de caracteres contendo os nomes desses nós e retorna essa sequência para nossa associação no arquivo .xaml para ser exibido em nossa janela pop-out.
Com a lógica principal da extensão definida, agora vamos especificar os detalhes de aparência da janela com um arquivo .xaml. Tudo que precisamos é uma janela simples que exiba a sequência de caracteres usando a associação de propriedade ActiveNodeTypes noTextBlock Text.
Clicar com o botão direito do mouse no projeto e selecionar
Add > New Item...Selecionar o modelo Controle de usuário que vamos alterar para criar uma janela
Nomear o novo arquivo
SampleWindow.xaml
No código da janela .xaml, precisaremos vincular SelectedNodesText a um bloco de texto. Adicione o seguinte código a SampleWindow.xaml:
Text="{Binding ActiveNodeTypes}" vincula o valor da propriedade de ActiveNodeTypes em SampleWindowViewModel.cs ao valor TextBlock Text na janela.
Agora, inicializaremos a janela de amostra no arquivo de backup .xaml C# SampleWindow.xaml.cs. Adicione o seguinte código a SampleWindow.xaml:
A extensão da vista agora está pronta para ser criada e adicionada ao Dynamo. O Dynamo requer um arquivo xml para registrar nossa saída .dll como uma extensão.
Clicar com o botão direito do mouse no projeto e selecionar
Add > New Item...Selecionar o arquivo XML
Nomear o arquivo
SampleViewExtension_ViewExtensionDefinition.xml
O nome do arquivo segue a norma do Dynamo para fazer referência a uma montagem de extensão como esta: "extensionName"_ViewExtensionDefinition.xml
No arquivo xml, adicione o seguinte código para informar ao Dynamo onde procurar a montagem de extensão:
Neste exemplo, compilamos a montagem na pasta de projeto padrão do Visual Studio. Substitua o destino <AssemblyPath>...</AssemblyPath> pela localização da montagem.
A última etapa é copiar o arquivo SampleViewExtension_ViewExtensionDefinition.xml para a pasta de extensões de vista do Dynamo localizada no diretório de instalação C:\Program Files\Dynamo\Dynamo Core\1.3\viewExtensions do Dynamo Core. É importante observar que há pastas separadas para extensions e viewExtensions. Colocar o arquivo xml na pasta incorreta pode causar falha ao carregar corretamente no tempo de execução.
O arquivo
.xmlque copiamos para a pasta de extensões de vista do Dynamo
Esta é uma introdução básica às extensões da vista. Para um estudo de caso mais sofisticado, consulte o pacote DynaShape, um projeto de código aberto no Github. O pacote usa uma extensão de vista que permite a edição ao vivo na vista do modelo do Dynamo.
É possível fazer o download de um instalador de pacote para o DynamoShape do Fórum do Dynamo:
O código-fonte pode ser clonado do Github:
O Dynamo 2.0 é uma versão principal e algumas APIs foram alteradas ou removidas. Uma das maiores alterações que afetarão os autores de nó e pacote é a nossa mudança para um formato de arquivo JSON.
Em geral, os autores do nó Sem toque não terão muito trabalho a fazer para que os pacotes sejam executados na versão 2.0.
Os nós da interface do usuário e os nós que derivam diretamente do NodeModel exigirão mais trabalho para serem executados na versão 2.x.
Os autores da extensão também podem ter algumas alterações potenciais a serem feitas, dependendo de quanto das APIs principais do Dynamo eles usam em suas extensões.
Selecionar Ok
Owner = p.DynamoWindowwindow.Show(); exibe a janela onde as propriedades adicionais da janela foram definidas
Selecionar Add
Selecionar Add









using System;
using System.Windows;
using System.Windows.Controls;
using Dynamo.Wpf.Extensions;
namespace SampleViewExtension
{
public class SampleViewExtension : IViewExtension
{
private MenuItem sampleMenuItem;
public void Dispose()
{
}
public void Startup(ViewStartupParams p)
{
}
public void Loaded(ViewLoadedParams p)
{
// Save a reference to your loaded parameters.
// You'll need these later when you want to use
// the supplied workspaces
sampleMenuItem = new MenuItem {Header = "Show View Extension Sample Window"};
sampleMenuItem.Click += (sender, args) =>
{
var viewModel = new SampleWindowViewModel(p);
var window = new SampleWindow
{
// Set the data context for the main grid in the window.
MainGrid = { DataContext = viewModel },
// Set the owner of the window to the Dynamo window.
Owner = p.DynamoWindow
};
window.Left = window.Owner.Left + 400;
window.Top = window.Owner.Top + 200;
// Show a modeless window.
window.Show();
};
p.AddExtensionMenuItem(sampleMenuItem);
}
public void Shutdown()
{
}
public string UniqueId
{
get
{
return Guid.NewGuid().ToString();
}
}
public string Name
{
get
{
return "Sample View Extension";
}
}
}
}using System;
using Dynamo.Core;
using Dynamo.Extensions;
using Dynamo.Graph.Nodes;
namespace SampleViewExtension
{
public class SampleWindowViewModel : NotificationObject, IDisposable
{
private string activeNodeTypes;
private ReadyParams readyParams;
// Displays active nodes in the workspace
public string ActiveNodeTypes
{
get
{
activeNodeTypes = getNodeTypes();
return activeNodeTypes;
}
}
// Helper function that builds string of active nodes
public string getNodeTypes()
{
string output = "Active nodes:\n";
foreach (NodeModel node in readyParams.CurrentWorkspaceModel.Nodes)
{
string nickName = node.Name;
output += nickName + "\n";
}
return output;
}
public SampleWindowViewModel(ReadyParams p)
{
readyParams = p;
p.CurrentWorkspaceModel.NodeAdded += CurrentWorkspaceModel_NodesChanged;
p.CurrentWorkspaceModel.NodeRemoved += CurrentWorkspaceModel_NodesChanged;
}
private void CurrentWorkspaceModel_NodesChanged(NodeModel obj)
{
RaisePropertyChanged("ActiveNodeTypes");
}
public void Dispose()
{
readyParams.CurrentWorkspaceModel.NodeAdded -= CurrentWorkspaceModel_NodesChanged;
readyParams.CurrentWorkspaceModel.NodeRemoved -= CurrentWorkspaceModel_NodesChanged;
}
}
}<Window x:Class="SampleViewExtension.SampleWindow"
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:SampleViewExtension"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Width="500" Height="100">
<Grid Name="MainGrid"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<TextBlock HorizontalAlignment="Stretch" Text="{Binding ActiveNodeTypes}" FontFamily="Arial" Padding="10" FontWeight="Medium" FontSize="18" Background="#2d2d2d" Foreground="White"/>
</Grid>
</Window>using System.Windows;
namespace SampleViewExtension
{
/// <summary>
/// Interaction logic for SampleWindow.xaml
/// </summary>
public partial class SampleWindow : Window
{
public SampleWindow()
{
InitializeComponent();
}
}
}<ViewExtensionDefinition>
<AssemblyPath>C:\Users\username\Documents\Visual Studio 2015\Projects\SampleViewExtension\SampleViewExtension\bin\Debug\SampleViewExtension.dll</AssemblyPath>
<TypeName>SampleViewExtension.SampleViewExtension</TypeName>
</ViewExtensionDefinition>Não agrupe o Dynamo ou o Dynamo Revit .dlls com o pacote. Esses dlls já serão carregados pelo Dynamo. Se você agrupar uma versão diferente da que o usuário carregou _(ou seja, você distribui o dynamo core 1.3, mas o usuário está executando o pacote no dynamo 2.0) _, ocorrerão erros misteriosos de tempo de execução. Isso inclui dlls como DynamoCore.dll, DynamoServices.dll, DSCodeNodes.dll, ProtoGeometry.dll
Não agrupe nem distribua o newtonsoft.json.net com o pacote se você puder evitá-lo. Esse dll também será carregado pelo Dynamo 2.x. O mesmo problema que acima pode ocorrer.
Não agrupe nem distribua o CEFSharp com o pacote se você puder evitá-lo. Esse dll também será carregado pelo Dynamo 2.x. O mesmo problema que acima pode ocorrer.
Em geral, evite compartilhar dependências com o Dynamo ou o Revit se precisar controlar a versão dessa dependência.
Durante a abertura de um gráfico, alguns nós têm várias portas com o mesmo nome, mas o gráfico parecia correto ao salvar. Esse problema pode ter algumas causas.
A causa raiz comum é porque o nó foi criado usando um construtor que recriou as portas. Em vez disso, o construtor que carregou as portas deveria ter sido usado. Esses construtores são geralmente marcados [JsonConstructor]veja exemplos abaixo
Isso pode ocorrer porque:
Não havia nenhum [JsonConstructor] correspondente ou ele não foi passado de Inports e Outports do .dyn JSON.
Havia duas versões do JSON.net carregadas no mesmo processo ao mesmo tempo, causando falha de tempo de execução .net, de modo que o atributo [JsonConstructor] não podia ser usado corretamente para marcar o construtor.
O DynamoServices.dll com uma versão diferente da versão atual do Dynamo foi fornecido com o pacote e está causando a falha do tempo de execução .net ao identificar o atributo [MultiReturn]; portanto, os nós Sem toque marcados com vários atributos não terão sido aplicados. Você pode descobrir que um nó retorna uma única saída de dicionário em vez de várias portas.
Os nós estão completamente ausentes ao carregar o gráfico com alguns erros no console.
Isso pode ocorrer se a desserialização falhar por algum motivo. É uma boa prática serializar somente as propriedades que você precisa. Podemos usar [JsonIgnore] em propriedades complexas que não precisam ser carregadas ou salvas para serem ignoradas. Propriedades como function pointer, delegate, action, ou event etc. Elas não devem ser serializadas, pois normalmente falharão ao desserializar e causarão um erro de tempo de execução.
Problemas conhecidos:
Um nome de nó personalizado coincidente e um nome de categoria no mesmo nível no librarie.js causa um comportamento inesperado. QNTM-3653 – evite usar os mesmos nomes para a categoria e os nós.
Os comentários serão transformados em comentários de bloco ao invés de comentários de linha.
Nomes de tipo curto serão substituídos por nomes completos. Por exemplo, se você não especificou um tipo ao carregar o nó personalizado novamente, verá var[]..[] – pois esse é o tipo padrão.
No Dynamo 2.0, os tipos Lista e Dicionário foram divididos e a sintaxe para a criação de listas e dicionários foi alterada. As listas são inicializadas usando [], enquanto os dicionários usam {}.
Se você estava usando o atributo DefaultArgument anteriormente para marcar parâmetros nos nós sem toque e usou a sintaxe da lista para padronizar para uma lista específica como someFunc([DefaultArgument("{0,1,2}")]), isso não será mais válido e será necessário modificar o fragmento DesignScript para usar a nova sintaxe de inicialização das listas.
Como observado acima, não distribua os dlls do Dynamo com os pacotes. (DynamoCore, DynamoServices etc.)
Os nós do modelo de nós são os que requerem mais trabalho para serem atualizados para o Dynamo 2.x. Em um nível alto, será necessário implementar construtores que serão usados somente para carregar os nós do json, além dos construtores nodeModel normais que são usados para instanciar novas instâncias dos tipos de nó. Para diferenciar entre esses, marque os construtores de tempo de carga com [JsonConstructor], que é um atributo de newtonsoft.Json.net.
Os nomes dos parâmetros no construtor devem normalmente coincidir com os nomes das propriedades JSON – embora esse mapeamento se torne mais complicado se você substituir os nomes que são serializados usando os atributos [JsonProperty]. Consulte a documentação do Json.net para obter mais informações.
A alteração mais comum necessária para atualizar nós derivados da classe base NodeModel (ou outras classes base do núcleo do Dynamo, ou seja, DSDropDownBase) é a necessidade de adicionar um construtor JSON à classe.
O construtor original sem parâmetros ainda lidará com a inicialização de um novo nó que é criado no Dynamo (por exemplo, através da biblioteca). O construtor JSON é necessário para inicializar um nó que é desserializado (carregado) de um arquivo .dyn ou .dyf salvo.
O construtor JSON difere do construtor base no fato de ter parâmetros PortModel para inPorts e outPorts, que são fornecidos pela lógica de carregamento JSON. A chamada para registrar as portas para o nó não é necessária aqui, pois os dados existem no arquivo .dyn. Um exemplo de construtor JSON se parece com isto:
using Newtonsoft.Json; //New dependency for Json
………
[JsonConstructor] //Attribute required to identity the Json constructor
//Minimum constructor implementation. Note that the base method invocation must also be present.
FooNode(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(inPorts, outPorts) { }
Esta sintaxe :base(Inports,outPorts){} chama o construtor base nodeModel e passa as portas desserializadas para ele.
Qualquer lógica especial que existisse no construtor de classe que envolva a inicialização de dados específicos que são serializados no arquivo .dyn (por exemplo, definir o registro de porta, estratégia de amarra, etc) não precisa ser repetida nesse construtor, pois esses valores podem ser lidos do JSON.
Essa é a principal diferença entre o construtor JSON e os construtores não JSON para os nodeModels. Os construtores JSON são chamados ao carregar de um arquivo e são passados os dados carregados. No entanto, outra lógica do usuário deve ser duplicada no construtor JSON (por exemplo, inicializando manipuladores de eventos para o nó ou anexando).
Exemplos podem ser encontrados aqui no repositório do DynamoSamples -> ButtonCustomNodeModel, DropDown ou SliderCustomNodeModel
Anteriormente, um desenvolvedor podia serializar e desserializar dados de modelo específicos para o documento xml usando os métodos SerializeCore e DeserializeCore. Esses métodos ainda existem na API, mas serão obsoletos em uma versão futura do Dynamo (um exemplo pode ser encontrado aqui). Com a implementação do JSON.NET, agora as propriedades public na classe derivada NodeModel podem ser serializadas diretamente para o arquivo .dyn. O JSON.Net fornece vários atributos para controlar como a propriedade é serializada.
Esse exemplo que especifica um PropertyName é encontrado aqui no repositório do Dynamo.
[JsonProperty(PropertyName = "InputValue")]
public DSColor DsColor {...
Observação
Se você criar sua própria classe de conversor JSON.net, o Dynamo não terá um mecanismo que permita injetá-la nos métodos de carregamento e salvamento e, portanto, mesmo que você marque a classe com o atributo [JsonConverter], ela poderá não ser usada. Em vez disso, você poderá chamar o conversor diretamente no configurador ou getter. //TODO precisa de confirmação dessa limitação. Qualquer evidência é bem-vinda.
Um exemplo que especifica um método de serialização para converter a propriedade em uma sequência de caracteres é encontrado aqui no repositório do Dynamo.
[JsonProperty("MeasurementType"), JsonConverter(typeof(StringEnumConverter))]
public ConversionMetricUnit SelectedMetricConversion{...
As propriedades public que não são destinadas à serialização precisam ter o atributo [JsonIgnore] adicionado. Quando os nós são salvos no arquivo .dyn, isso garante que esses dados sejam ignorados pelo mecanismo de serialização e não causará consequências inesperadas quando o gráfico for aberto novamente. Um exemplo disso pode ser encontrado aqui no repositório do Dynamo.
Como mencionado acima, os métodos SerializeCore e DeserializeCore foram usados no passado para salvar e carregar nós no arquivo xml .dyn. Além disso, eles também foram usados para salvar e carregar o estado do nó para desfazer/refazer e ainda são. Se você desejar implementar a funcionalidade desfazer/refazer complexa para o nó da interface do usuário nodeModel, será necessário implementar esses métodos e serializar no objeto de documento XML fornecido como um parâmetro para esses métodos. Esse deve ser um caso de uso raro, exceto para nós de interface do usuário complexos.
Uma ocorrência comum nos nós nodeModel afetados pelas alterações da API 2.0 é o registro de porta no construtor do nó. Observando exemplos no repositório do Dynamo ou DynamoSamples, você terá encontrado o uso dos métodos InPortData.Add() ou OutPortData.Add(). Anteriormente, na API do Dynamo, as propriedades InPortData e OutPortData públicas eram marcadas como obsoletas. Na versão 2.0, essas propriedades foram removidas. Os desenvolvedores agora devem usar os métodos InPorts.Add() e OutPorts.Add(). Além disso, esses dois métodos Add() têm assinaturas ligeiramente diferentes:
InPortData.Add(new PortData("Port Name", "Port Description")); //Old version valid in 1.3 but now deprecated
x
InPorts.Add(new PortModel(PortType.Input, this, new PortData("Port Name", "Port Description"))); //Recommended 2.0
Exemplos de código convertido podem ser encontrados aqui no repositório do Dynamo -> DynamoConvert.cs ou FileSystem.cs
O outro caso de uso comum afetado pelas alterações da API 2.0 se relaciona aos métodos comumente usados no método BuildAst() para determinar o comportamento do nó com base na presença ou ausência de conectores de porta. Anteriormente, HasConnectedInput(index) era usado para validar um estado de porta conectada. Os desenvolvedores agora devem usar a propriedade InPorts[0].IsConnected para verificar o estado de conexão da porta. Um exemplo desse ícone pode ser encontrado em ColorRange.cs no repositório do Dynamo.
Vamos passar pela atualização de um nó de interface do usuário 1.3 para o Dynamo 2.x.
Tudo o que precisamos fazer para esta classe nodeModel para que ela seja carregada e salva corretamente na versão 2.0 é adicionar um jsonConstructor para lidar com o carregamento das portas. Simplesmente passamos as portas no construtor base e essa implementação fica vazia.
Observação: Não chame RegisterPorts() ou alguma variação disso no JsonConstructor. Isso usará os atributos de parâmetro de entrada e saída na classe de nó para construir novas portas. Não queremos isso, pois queremos usar as portas carregadas que são passadas para o construtor.
Este exemplo adiciona o construtor JSON de carga mínima possível. Mas e se precisarmos fazer uma lógica de construção mais complexa, como configurar alguns ouvintes para manipulação de eventos dentro do construtor? A próxima amostra obtida do
Repositório do DynamoSamples está vinculada acima na JsonConstructors Section deste documento.
Aqui está um construtor mais complexo para um nó de interface do usuário:
Quando adicionamos um construtor JSON para carregar esse nó de um arquivo, precisamos recriar parte dessa lógica, mas observe que não incluímos o código que cria portas, que define amarra ou que define os valores padrão para propriedades que podemos carregar do arquivo.
Observe que outras propriedades públicas que foram serializadas no JSON como ButtonText e WindowText não serão adicionadas como parâmetros explícitos ao construtor – elas são definidas automaticamente pelo JSON.net usando os definidores para essas propriedades.
A obtenção de um layout desejado para o pacote depende dos tipos de nós que você incluirá no pacote. Os nós derivados do modelo de nó, os nós ZeroTouch e os nós personalizados têm um processo ligeiramente diferente para definir a categorização. É possível misturar e combinar esses tipos de nó dentro do mesmo pacote, mas isso exigirá uma combinação das estratégias descritas abaixo.
Por padrão, as bibliotecas NodeModel são organizadas com base na estrutura de classes.
O nó ficará localizado em Complementos em:
Também é possível substituir a categoria usando o atributo NodeCategory na classe ou no construtor, como mostrado abaixo.
O nó agora ficará localizado em Complementos em:
As bibliotecas ZeroTouch também são organizadas com base na estrutura de classes por padrão.
O nó ficará localizado em Complementos em:
Também é possível substituir a localização da estrutura da classe usando um arquivo XML de personalização do Dynamo.
O arquivo XML deve ser nomeado adequadamente e ser incluído na pasta extra do pacote
PackageName_DynamoCustomization.xml
Os nós personalizados são organizados com base no Category Name especificado durante a criação dos nós (usando a caixa de diálogo Novo nó personalizado).
AVISO
O uso da notação de ponto em nomes de nós ou categorias resultará em subcategorias aninhadas adicionais. O . funcionará como um delimitador para determinar a hierarquia adicional. Esse é um novo comportamento na biblioteca para o Dynamo 2.0.
O nome da categoria pode ser atualizado posteriormente no arquivo .dyf (XML ou JSON)
Quando o autor de um pacote decide renomear um nó existente anterior em uma nova versão, ele deve fornecer um meio para migrar gráficos que contêm nós com os nomes antigos. Isso pode ser feito das seguintes maneiras:
Os nós ZeroTouch usam um arquivo Namespace.Migrations.XML localizado na pasta bin dos pacotes, como:
MyZeroTouchLib.MyNodes.SayHello para MyZeroTouchLib.MyNodes.SayHelloRENAMED
Os nós derivados do NodeModel usam o atributo AlsoKnownAs na classe, como:
SampleLibraryUI.Examples.DropDownExample para SampleLibraryUI.Examples.DropDownExampleRENAMED
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) };
}
}
}[JsonConstructor]
protected GridNodeModel(IEnumerable<PortModel> Inports, IEnumerable<PortModel> Outports ) :
base(Inports,Outports)
{
}[InPortNames("xCount", "yCount")]
[InPortTypes("double", "double")] public ButtonCustomNodeModel()
{
// When you create a UI node, you need to do the
// work of setting up the ports yourself. To do this,
// you can populate the InPorts and the OutPorts
// collections with PortData objects describing your ports.
InPorts.Add(new PortModel(PortType.Input, this, new PortData("inputString", "a string value displayed on our button")));
// Nodes can have an arbitrary number of inputs and outputs.
// If you want more ports, just create more PortData objects.
OutPorts.Add(new PortModel(PortType.Output, this, new PortData("button value", "returns the string value displayed on our button")));
OutPorts.Add(new PortModel(PortType.Output, this, new PortData("window value", "returns the string value displayed in our window when button is pressed")));
// This call is required to ensure that your ports are
// properly created.
RegisterAllPorts();
// Listen for input port disconnection to trigger button UI update
this.PortDisconnected += ButtonCustomNodeModel_PortDisconnected;
// The arugment lacing is the way in which Dynamo handles
// inputs of lists. If you don't want your node to
// support argument lacing, you can set this to LacingStrategy.Disabled.
ArgumentLacing = LacingStrategy.Disabled;
// We create a DelegateCommand object which will be
// bound to our button in our custom UI. Clicking the button
// will call the ShowMessage method.
ButtonCommand = new DelegateCommand(ShowMessage, CanShowMessage);
// Setting our property here will trigger a
// property change notification and the UI
// will be updated to reflect the new value.
ButtonText = defaultButtonText;
WindowText = defaultWindowText;
} // This constructor is called when opening a Json graph.
[JsonConstructor]
ButtonCustomNodeModel(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(inPorts, outPorts)
{
this.PortDisconnected += ButtonCustomNodeModel_PortDisconnected;
ButtonCommand = new DelegateCommand(ShowMessage, CanShowMessage);
}namespace SampleLibraryUI.Examples// Class Attribute
[NodeName("MyNodeModel")]
public class MyNewNodeModel : NodeModel
// or
// Constructor
public ButtonCustomNodeModel()
{
this.Name = "MyNodeModel";
}
SampleLibraryUI/Examples/MyNodeModel// Class Attribute
[NodeCategory("NewSampleLibraryUI.Examples")]
// or
// Constructor
public ButtonCustomNodeModel()
{
this.Category = "NewSampleLibraryUI.Examples";
}NewSampleLibraryUI/Examples/MyNodeModel
namespace MyZTLibrarypublic class Utilities
{
public double doubleValue(double num)
{
return num * 2;
}
}MyZTLibrary/Utilities/doubleValue<?xml version="1.0"?>
<doc>
<assembly>
<name>MeshToolkit</name>
</assembly>
<namespaces>
<!--Remap Namespaces-->
<namespace name="Autodesk.Dynamo.MeshToolkit">
<category>MeshToolkit</category>
</namespace>
<namespace name="Autodesk.Dynamo.MeshToolkit.Display">
<category>Display</category>
</namespace>
</namespaces>
<classes>
<!--Remap Class Names-->
<class name="Autodesk.Dynamo.MeshToolkit.Display.MeshDisplay" shortname="MeshDisplay"/>
<class name="Autodesk.Dynamo.MeshToolkit.Mesh" shortname="Mesh"/>
</classes>
</doc>
{
"Uuid": "85066088-1616-40b1-96e1-c33e685c6948",
"IsCustomNode": true,
"Category": "MyCustomNodes.Utilities.Actions",
"Description": "This is an example custom nodes.",
"Name": "doubleValue",
"ElementResolver": {
"ResolutionMap": {}
},...<Workspace Version="1.3.0.0000" X="100" Y="100" zoom="1.0000000" Description="This is an example custom nodes." Category="MyCustomNodes.Utilities.Actions" Name="doubleValue" ID="85066088-1616-40b1-96e1-c33e685c6948"><?xml version="1.0"?>
<migrations>
<priorNameHint>
<oldName>MyZeroTouchLib.MyNodes.SayHello</oldName>
<newName>MyZeroTouchLib.MyNodes.SayHelloRENAMED</newName>
</priorNameHint>
</migrations>namespace SampleLibraryUI.Examples
{
[NodeName("Drop Down Example")]
[NodeDescription("An example drop down node.")]
[IsDesignScriptCompatible]
[AlsoKnownAs("SampleLibraryUI.Examples.DropDownExample")]
public class DropDownExampleRENAMED : DSDropDownBase
{
...
}
{
Com um conhecimento básico do nó Sem toque já estabelecido, esta seção se aprofunda nas vantagens de personalizar os nós do Dynamo para aprimorar a funcionalidade e a experiência do usuário. Ao adicionar recursos como mensagens de aviso, mensagens informativas e ícones personalizados, é possível criar nós mais intuitivos, informativos e visualmente envolventes. Além de ajudar os usuários a entender possíveis problemas ou otimizar seus fluxos de trabalho, essas personalizações também fazem com que seus nós se destaquem como ferramentas profissionais e fáceis de usar.
Personalizar nós é uma excelente maneira de garantir que suas soluções sejam claras, confiáveis e adaptadas para atender às necessidades específicas do projeto.
No Dynamo, o método OnLogWarningMessage fornece uma maneira de registrar mensagens de aviso diretamente no console do Dynamo. Esse é um recurso poderoso, especialmente para os nós Sem toque, pois permite que os desenvolvedores alertem os usuários quando há problemas com entradas ou parâmetros que podem levar a um comportamento inesperado. Este guia ensinará como implementar OnLogWarningMessage em qualquer nó Sem Toque.
OnLogWarningMessageOnLogWarningMessage faz parte do namespace DynamoServices, por isso, comece adicionando-o ao arquivo do projeto.
Antes de adicionar uma mensagem de aviso, considere a lógica no método:
Quais condições podem causar resultados incorretos ou inesperados?
Há valores ou parâmetros de entrada específicos que o método requer para funcionar corretamente?
Exemplos de condições a serem verificadas:
Valores fora do intervalo (por exemplo, if (inputValue < 0)).
Coleções nulas ou vazias (por exemplo, if (list == null || list.Count == 0)).
O tipo de dados não coincide (por exemplo, se um tipo de arquivo não for suportado).
OnLogWarningMessage para registrar o avisoColoque chamadas OnLogWarningMessage onde são detectadas as condições que podem causar problemas. Quando a condição for atendida, registre uma mensagem de aviso que forneça orientação clara ao usuário.
OnLogWarningMessageOnLogWarningMessagePara demonstrar OnLogWarningMessage na prática, aqui estão diferentes cenários que podem ser encontrados ao criar um nó Sem Toque.
Neste exemplo, vamos nos basear no nó personalizado criado no “Estudo de caso do nó Sem toque – Nó de grade” anterior; um método denominado RectangularGrid que gera uma grade de retângulos com base em entradas xCount e yCount. Vamos percorrer o processo de teste Se uma entrada é inválida e, em seguida, usar OnLogWarningMessage para registrar um aviso e parar o processamento.
Usar OnLogWarningMessage para validação de entrada
Quando gerar uma grade com base em xCount e yCount. Recomenda-se garantir que os dois valores sejam inteiros positivos antes de continuar.
Neste exemplo:
Condição: se xCount ou yCount for menor ou igual a zero.
Mensagem: "Grid count values must be positive integers."
O aviso será mostrado no Dynamo se um usuário inserir valores zero ou negativos, ajudando-os a entender a entrada esperada.
Agora que sabemos como é, podemos implementá-lo no nó de exemplo Grades:
Exemplo 2: verificar coleções nulas ou vazias
Se o método exigir uma lista de pontos, mas um usuário passar uma lista vazia ou nula, será possível usar OnLogWarningMessage para informá-lo sobre o problema.
Neste exemplo:
Condição: se a lista points for nula ou contiver menos de três pontos.
Mensagem: "Point list cannot be null or have fewer than three points."
Avisa aos usuários que eles precisam passar por uma lista válida com pelo menos três pontos para formar um polígono.
Exemplo 3: verificar a compatibilidade de tipo de arquivo
Para um nó que processa caminhos de arquivo, pode ser necessário garantir que apenas determinados tipos de arquivo sejam permitidos. Se um tipo de arquivo sem suporte for detectado, registre um aviso.
Neste exemplo:
Condição: se o caminho do arquivo não terminar com “.csv”.
Mensagem: "Only CSV files are supported."
Avisa os usuários para garantir que estão transmitindo um arquivo CSV, ajudando a evitar problemas relacionados a formatos de arquivo incompatíveis.
OnLogInfoMessageNo Dynamo, o OnLogInfoMessage do namespace DynamoServices permite que os desenvolvedores registrem mensagens informativas diretamente no console do Dynamo. Isso é útil para confirmar operações bem-sucedidas, comunicar o progresso ou fornecer informações adicionais sobre as ações do nó. Este guia ensinará como adicionar OnLogInfoMessage em qualquer nó Sem Toque para aprimorar o feedback e a experiência do usuário.
OnLogInfoMessageOnLogInfoMessage faz parte do namespace DynamoServices, por isso, comece adicionando-o ao arquivo do projeto.
Antes de adicionar uma mensagem de informação, pense no propósito do método:
Quais informações seriam úteis para confirmar após a conclusão de uma ação?
Existem etapas ou marcos importantes no método que os usuários talvez queiram conhecer?
Exemplos de confirmações úteis:
Mensagens de conclusão (por exemplo, quando uma grade ou um modelo é totalmente criado).
Detalhes dos dados processados (por exemplo, “10 itens processados com êxito”).
Resumos de execução (por exemplo, parâmetros usados no processo).
OnLogInfoMessage para registrar mensagens informativasColoque chamadas OnLogInfoMessage em pontos significativos em seu método. Quando ocorrer uma etapa ou conclusão importante, registre uma mensagem informativa para atualizar o usuário sobre o que aconteceu.
OnLogInfoMessageOnLogInfoMessageVeja diferentes cenários para demonstrar usando OnLogInfoMessage nos nós Sem Toque.
Neste exemplo, vamos nos basear no nó personalizado criado no “Estudo de caso do nó Sem toque – Nó de grade” anterior; um método denominado RectangularGrid que gera uma grade de retângulos com base em entradas xCount e yCount. Vamos percorrer o teste Se uma entrada é inválida e, em seguida, usar OnLogInfoMessage para fornecer informações após o nó ter concluído sua execução.
Usar OnLogInfoMessage para validação de entrada
Quando gerar uma grade com base em xCount e yCount. Depois de gerar a grade, recomenda-se confirmar sua criação registrando uma mensagem informativa com as dimensões da grade.
Neste exemplo:
Condição: o processo de criação da grade foi concluído.
Mensagem: "Successfully created a grid with dimensions {xCount}x{yCount}."
Essa mensagem informará aos usuários que a grade foi criada conforme especificado, ajudando-os a confirmar que o nó funcionou conforme o esperado.
Agora que sabemos como é, podemos implementá-lo no nó de exemplo Grades:
Se estiver criando um nó que processa uma lista de pontos, talvez seja necessário registrar quantos pontos foram processados com êxito. Isso pode ser útil para grandes conjuntos de dados.
Neste exemplo:
Condição: após a conclusão do loop, mostrando a contagem de itens processados.
Mensagem: "6 points were processed successfully."
Essa mensagem ajudará os usuários a entender o resultado do processamento e confirmar que todos os pontos foram processados.
Em alguns casos, é útil confirmar os parâmetros de entrada de um nó usado para concluir uma ação. Por exemplo, se o nó exportar dados para um arquivo, o registro do nome e do caminho do arquivo poderá tranquilizar os usuários de que o arquivo correto foi usado.
Neste exemplo:
Condição: o processo de exportação é concluído com êxito.
Mensagem: "Data exported successfully to {filePath}."
Essa mensagem confirma aos usuários que a exportação funcionou e mostra o caminho exato do arquivo, ajudando a evitar confusão sobre a localização dos arquivos.
Historicamente, houve limitações no Dynamo de como os autores de pacotes poderiam fornecer documentação para seus nós. Os autores dos nós personalizados foram restritos a permitir apenas uma breve descrição que é exibida na dica de ferramenta do nó ou a enviar seu pacote com gráficos de amostra muito anotados.
O Dynamo agora oferece um sistema melhorado para os autores de pacotes a fim de fornecer uma documentação melhor e mais explicativa para seus nós personalizados. Essa nova abordagem usa a linguagem Markdown fácil de usar para criação de texto e a extensão de vista do Navegador de documentação para exibir o Markdown no Dynamo. O uso de Markdown oferece aos autores de pacotes uma ampla gama de novas possibilidades ao documentar seus nós personalizados.
Markdown é uma linguagem de marcação leve que você pode usar para formatar documentos de texto sem formatação. Desde que o Markdown foi criado em 2004, sua popularidade só aumentou e agora é uma das linguagens de marcação mais usadas no mundo.
É fácil começar a fazer arquivos Markdown – tudo o que você precisa é de um editor de texto simples, como o Bloco de notas, e você está pronto para começar. No entanto, há maneiras mais fáceis de escrever com Markdown do que usando o Bloco de notas. Existem vários editores on-line, como o , que permitem que você veja suas alterações em tempo real à medida que as faz. Outra forma muito usada de editar arquivos Markdown é usando um editor de código como o .
O Markdown é muito flexível e deve fornecer funcionalidade suficiente para criar facilmente uma boa documentação – isso inclui; adicionar arquivos de mídia como imagens ou vídeos, criar tabelas com diferentes formas de conteúdo e, claro, recursos de formatação de texto simples, como deixar o texto em negrito ou itálico. Tudo isso e muito mais é possível ao escrever documentos com Markdown. Para obter mais informações, veja este guia que explica a .
É fácil adicionar documentação aos nós. É possível adicionar documentação a todos os tipos de nós personalizados, incluindo:
Nós de Dynamo prontos para uso
Nós personalizados (.dyf) – Coleções de nós prontos para uso e/ou outros nós de pacote.
Nós de pacote C# personalizados (também conhecidos como Zerotouch. Esses nós personalizados se parecem com os nós prontos para uso)
Nós NodeModel (nós que contêm recursos especiais da interface do usuário, como menus suspensos ou botões de seleção)
Siga estas etapas para exibir os arquivos Markdown no Dynamo.
O Dynamo usa a extensão de vista do Navegador de documentação para exibir a documentação dos nós. Para abrir uma documentação de nós, clique com o botão direito do mouse no nó e selecione ajuda. Isso abrirá o Navegador de documentação e exibirá o Markdown associado a esse nó, se algum for fornecido.
A documentação exibida no Navegador de documentação é composta de duas partes. A primeira é a seção Node Info, que é gerada automaticamente com base nas informações extraídas do nó, como as entradas/saídas, a categoria do nó, o nome/namespace do nó e a breve descrição dos nós. A segunda parte mostra a documentação de nós personalizados, que é o arquivo Markdown fornecido para documentar o nó.
Para adicionar arquivos de documentação aos nós no Dynamo, crie uma nova pasta no diretório de pacotes chamado /doc. Quando o pacote for carregado, o Dynamo verificará esse diretório e obterá todos os arquivos Markdown de documentação nele.
Para garantir que o Dynamo saiba qual arquivo abrir quando um nó específico for solicitado, a nomenclatura do arquivo Markdown precisará estar em um formato específico. O arquivo Markdown deve ser nomeado de acordo com o nó que o namespace documenta. Se você não tiver certeza do namespace do nó, examine a seção Node Info quando pressionar Help no nó e, no nome do nó, você verá o namespace completo do nó selecionado.
Esse namespace deve ser o nome do arquivo Markdown desse nó específico. Por exemplo, o namespace de CustomNodeExample das imagens acima, é TestPackage.TestCategory.CustomNodeExample, portanto, o arquivo Markdown para esse nó deve ser nomeado TestPackage.TestCategory.CustomNodeExample.md
Em casos especiais em que você tem sobrecargas de nós (nós com o mesmo nome, mas entradas diferentes), será necessário adicionar os nomes de entrada em () após o namespace do nó. Por exemplo, o nó integrado Geometry.Translate apresenta várias sobrecargas. Nesse caso, nomearíamos os arquivos Markdown dos nós abaixo da seguinte maneira: Autodesk.DesignScript.Geometry.Geometry.Translate(geometry,direction).md Autodesk.DesignScript.Geometry.Geometry.Translate(geometry,direction,distance).md
Para facilitar a modificação de arquivos de documentação, o Navegador de documentação implementa um Inspetor de arquivos no arquivo de documentação aberto. Isso permite fazer alterações no arquivo Markdown e ver as alterações no Dynamo instantaneamente.
A adição de novos arquivos de documentação também pode ser feita enquanto o Dynamo está aberto. Basta adicionar um novo arquivo Markdown à pasta /doc, com um nome que corresponda ao nó que ele documenta.
Os ícones personalizados para nós Sem toque no Dynamo tornam os nós visualmente distintos e mais fáceis de reconhecer na biblioteca. Ao adicionar ícones personalizados, é possível fazer com que seus nós se destaquem dos demais, permitindo que os usuários os identifiquem rapidamente em uma lista.
Este guia mostrará como adicionar ícones aos nós Sem Toque.
Para começar, crie um projeto de biblioteca de classes do Visual Studio (.NET Framework) para os nós Sem Toque. Se ainda não tiver um projeto, consulte a seção Introdução para obter instruções passo a passo sobre como criar um.
Certifique-se de ter pelo menos um nó Sem toque funcional, pois os ícones só podem ser adicionados aos nós existentes. Para obter orientação, consulte o Estudo de caso do nó Sem toque - Nó de grade.
Para criar ícones personalizados:
Criar os ícones: use um editor de imagem para criar ícones simples e visualmente claros para os nós.
Especificações das imagens:
Ícone pequeno: 32 x 32 pixels (usado na barra lateral da Biblioteca e no próprio nó).
Ícone grande: 128 x 128 pixels (usado nas propriedades do nó ao passar o cursor sobre o nó na biblioteca).
Exemplo: se o projeto for ZeroTouchNodeIcons, a classe for Grids e o método for RectangularGrid, os arquivos deverão ser nomeados:
ZeroTouchNodeIcons.Grids.RectangularGrid.Small.png
ZeroTouchNodeIcons.Grids.RectangularGrid.Large.png
Dica: Mantenha um tema de design consistente em todos os ícones para obter uma aparência profissional.
Para incorporar os ícones no .dll, crie um arquivo de recursos:
Adicionar um novo arquivo de recursos:
Clique com o botão direito do mouse no projeto no Gerenciador de soluções.
Acesse Adicionar > Novo item e selecione Arquivo de recursos.
Nomeie o arquivo <ProjectName>Images.resx. Por exemplo, ZeroTouchNodeIconsImages.resx.
Desmarque a propriedade Ferramenta personalizada:
Selecione o arquivo de recursos no Gerenciador de soluções.
No painel Propriedades, limpe o campo Custom Tool removendo o valor ResXFileCodeGenerator.
OBSERVAÇÃO: Não limpar o campo “Ferramenta personalizada” fará com que o Visual Studio converta os pontos em sublinhados nos nomes de recurso. Verifique antes de construir se os nomes dos recursos têm pontos separando os nomes de classe em vez de sublinhados.
Clique duas vezes no arquivo de recursos criado:
Adicione uma imagem de cada vez usando o botão “+”
Defina o tipo de recurso como Arquivo
Navegue até a localização do arquivo de imagens e inclua os ícones dos nós Large e Small.
OBSERVAÇÃO: Não é necessário organizar as imagens em uma pasta Recursos, nem nas subpastas Grandes e Pequenos, mas é uma boa prática para manter os recursos bem organizados.
Se o projeto ainda não estiver no estilo SDK (necessário para incorporar recursos), converta-o:
Instale a extensão .NET Upgrade Assistant no menu Extensões > Gerenciar extensões do Visual Studio.
Clique com o botão direito do mouse no projeto no Gerenciador de soluções e selecione Atualizar > Converter projeto em estilo SDK.
Aguarde a conclusão da conversão.
Descarregue o projeto:
Clique com o botão direito do mouse no projeto no Gerenciador de soluções e selecione Descarregar projeto.
Edite o arquivo .csproj:
Adicione o seguinte elemento <Target> entre </ItemGroup> e </Project>:
Substitua todas as instâncias de ZeroTouchNodeIcons pelo nome do projeto.
Recarregue o projeto:
Clique com o botão direito do mouse no projeto descarregado e selecione Recarregar projeto.
Construir o projeto:
Depois de adicionar o script After-Build, construa o projeto no Visual Studio.
Verifique os arquivos de saída:
Verifique se o .dll e o .customization.dll estão na pasta bin.
Adicione o .dll ao Dynamo:
Os nós personalizados agora devem aparecer com seus respectivos ícones.
Nós NodeModel com interface do usuário personalizada (nós que contêm recursos exclusivos da interface do usuário, como gráficos no nó)
Convenção de nomenclatura:
Os nomes de arquivo devem coincidir com o formato abaixo para associá-los ao nó correto:
<ProjectName>.<ClassName>.<MethodName>.Small.png (para o ícone pequeno).
<ProjectName>.<ClassName>.<MethodName>.Large.png (para o ícone grande).
Defina “Ação de construção” como “Nenhuma”
Esse recurso será criado um pouco mais à frente, por isso, não precisamos criá-lo automaticamente.
No Dynamo, use o botão Importar biblioteca para importar o .dll para o Dynamo.

























using DynamoServices;LogWarningMessageEvents.OnLogWarningMessage("Your warning message here.");public static List<Rectangle> CreateGrid(int xCount, int yCount)
{
// Check if xCount and yCount are positive
if (xCount <= 0 || yCount <= 0)
{
LogWarningMessageEvents.OnLogWarningMessage("Grid count values must be positive integers.");
return new List<Rectangle>(); // Return an empty list if inputs are invalid
}
// Proceed with grid creation...
}using Autodesk.DesignScript.Geometry;
using DynamoServices;
namespace CustomNodes
{
public class Grids
{
// The empty private constructor.
// This will not be imported into Dynamo.
private Grids() { }
/// <summary>
/// This method creates a rectangular grid from an X and Y count.
/// </summary>
/// <param name="xCount">Number of grid cells in the X direction</param>
/// <param name="yCount">Number of grid cells in the Y direction</param>
/// <returns>A list of rectangles</returns>
/// <search>grid, rectangle</search>
public static List<Rectangle> RectangularGrid(int xCount = 10, int yCount = 10)
{
// Check for valid input values
if (xCount <= 0 || yCount <= 0)
{
// Log a warning message if the input values are invalid
LogWarningMessageEvents.OnLogWarningMessage("Grid count values must be positive integers.");
return new List<Rectangle>(); // Return an empty list if inputs are invalid
}
double x = 0;
double y = 0;
var pList = new List<Rectangle>();
for (int i = 0; i < xCount; i++)
{
y++;
x = 0;
for (int j = 0; j < yCount; j++)
{
x++;
Point pt = Point.ByCoordinates(x, y);
Vector vec = Vector.ZAxis();
Plane bP = Plane.ByOriginNormal(pt, vec);
Rectangle rect = Rectangle.ByWidthLength(bP, 1, 1);
pList.Add(rect);
Point cPt = rect.Center();
}
}
return pList;
}
}
}public static Polygon CreatePolygonFromPoints(List<Point> points)
{
if (points == null || points.Count < 3)
{
LogWarningMessageEvents.OnLogWarningMessage("Point list cannot be null or have fewer than three points.");
return null; // Return null if the input list is invalid
}
// Proceed with polygon creation...
}public static void ProcessFile(string filePath)
{
if (!filePath.EndsWith(".csv"))
{
LogWarningMessageEvents.OnLogWarningMessage("Only CSV files are supported.");
return;
}
// Proceed with file processing...
}LogWarningMessageEvents.OnLogInfoMessage("Your info message here.");public static List<Rectangle> CreateGrid(int xCount, int yCount)
{
var pList = new List<Rectangle>();
// Grid creation code here...
// Confirm successful grid creation
LogWarningMessageEvents.OnLogInfoMessage($"Successfully created a grid with dimensions {xCount}x{yCount}.");
return pList;
}using Autodesk.DesignScript.Geometry;
using DynamoServices;
namespace CustomNodes
{
public class Grids
{
// The empty private constructor.
// This will not be imported into Dynamo.
private Grids() { }
/// <summary>
/// This method creates a rectangular grid from an X and Y count.
/// </summary>
/// <param name="xCount">Number of grid cells in the X direction</param>
/// <param name="yCount">Number of grid cells in the Y direction</param>
/// <returns>A list of rectangles</returns>
/// <search>grid, rectangle</search>
public static List<Rectangle> RectangularGrid(int xCount = 10, int yCount = 10)
{
double x = 0;
double y = 0;
var pList = new List<Rectangle>();
for (int i = 0; i < xCount; i++)
{
y++;
x = 0;
for (int j = 0; j < yCount; j++)
{
x++;
Point pt = Point.ByCoordinates(x, y);
Vector vec = Vector.ZAxis();
Plane bP = Plane.ByOriginNormal(pt, vec);
Rectangle rect = Rectangle.ByWidthLength(bP, 1, 1);
pList.Add(rect);
Point cPt = rect.Center();
}
}
// Log an info message indicating the grid was successfully created
LogWarningMessageEvents.OnLogInfoMessage($"Successfully created a grid with dimensions {xCount}x{yCount}.");
return pList;
}
}
}public static List<Point> ProcessPoints(List<Point> points)
{
var processedPoints = new List<Point>();
foreach (var point in points)
{
// Process each point...
processedPoints.Add(point);
}
// Log info about the count of processed points
LogWarningMessageEvents.OnLogInfoMessage($"{processedPoints.Count} points were processed successfully.");
return processedPoints;
}public static void ExportData(string filePath, List<string> data)
{
// Code to write data to the specified file path...
// Log the file path used for export
LogWarningMessageEvents.OnLogInfoMessage($"Data exported successfully to {filePath}.");
}<Target Name="CreateNodeIcons" AfterTargets="PostBuildEvent">
<!-- Get System.Drawing.dll -->
<GetReferenceAssemblyPaths TargetFrameworkMoniker=".NETFramework, Version=v4.8">
<Output TaskParameter="FullFrameworkReferenceAssemblyPaths" PropertyName="FrameworkAssembliesPath" />
</GetReferenceAssemblyPaths>
<!-- Get assembly -->
<GetAssemblyIdentity AssemblyFiles="$(OutDir)$(TargetName).dll">
<Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
</GetAssemblyIdentity>
<!-- Generate customization dll -->
<GenerateResource SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)" UseSourcePath="true" Sources="$(ProjectDir)ZeroTouchNodeIconsImages.resx" OutputResources="$(ProjectDir)ZeroTouchNodeIconsImages.resources" References="$(FrameworkAssembliesPath)System.Drawing.dll" />
<AL SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)" TargetType="library" EmbedResources="$(ProjectDir)ZeroTouchNodeIconsImages.resources" OutputAssembly="$(OutDir)ZeroTouchNodeIcons.customization.dll" Version="%(AssemblyInfo.Version)" />
</Target>


Esta é a documentação de integração para a linguagem de programação visual do Dynamo.
Este guia discutirá vários aspectos sobre como hospedar o Dynamo no aplicativo para permitir que os usuários interajam com o aplicativo usando a programação visual.
Conteúdo:
Esta introdução: visão geral de alto nível do que este guia inclui e o que é o Dynamo.
Ponto de entrada personalizado do Dynamo: como criar um DynamoModel e por onde começar.
: usar o mecanismo de rastreamento do Dynamo para vincular os nós no gráfico a seus resultados no hospedeiro.
: como implementar nós que permitem aos usuários selecionar objetos ou dados do hospedeiro e passá-los como entradas para o gráfico do Dynamo.
: o que é a Biblioteca padrão do Dynamo e como usar o mecanismo subjacente para enviar pacotes com a integração.
Um pouco de dicção:
Usaremos os termos script, gráfico e programa do Dynamo de forma intercambiável nestes documentos para nos referirmos ao código que os usuários criam no Dynamo.
O DynamoModel é o ponto de entrada para um aplicativo que hospeda o Dynamo. Ele representa um aplicativo do Dynamo. O modelo é o objeto raiz de nível superior que contém referências a outras estruturas de dados e objetos importantes que compõem o aplicativo Dynamo e a máquina virtual do DesignScript.
Um objeto de configuração é usado para definir parâmetros comuns no DynamoModel quando ele é construído.
Os exemplos neste documento foram retirados da implementação do DynamoRevit, que é uma integração na qual o Revit hospeda um DynamoModel como um complemento (arquitetura de plug-in para Revit). Quando esse complemento é carregado, ele inicia um DynamoModel e, em seguida, o exibe para o usuário com um DynamoView e DynamoViewModel.
O Dynamo é um projeto .net em c#. Para usá-lo em seu aplicativo, você precisa ser capaz de hospedar e executar código .net.
O DynamoCore é um mecanismo de computação de plataforma cruzada e uma coleção de modelos principais, que podem ser criados com .net ou mono (no futuro .net core). Mas o DynamoCoreWPF contém os componentes de interface do usuário do Dynamo somente para Windows e não será compilado em outras plataformas.
Para inicializar o DynamoModel, os integradores precisarão executar estas etapas em algum lugar no código do hospedeiro.
No momento, a lista no D4R inclui apenas Revit\SDA\bin\ICSharpCode.AvalonEdit.dll. Isso é feito para evitar conflitos de versões de bibliotecas entre o Dynamo e o Revit. Por exemplo: quando ocorrem conflitos em AvalonEdit, a função do bloco de código pode ser totalmente interrompida. O problema é reportado no Dynamo 1.1.x em e também é reproduzível manualmente. Se os integradores encontrarem conflitos de bibliotecas entre a função do hospedeiro e o Dynamo, recomenda-se fazer isso como primeiro passo. Às vezes, isso é necessário para impedir que outro plug-in ou o próprio aplicativo hospedeiro carregue uma versão incompatível de uma dependência compartilhada. Uma solução melhor é resolver o conflito de versões alinhando a versão ou usar um redirecionamento de vinculação .net no app.config do hospedeiro, se possível.
A ASM é a biblioteca de geometria ADSK com base na qual o Dynamo foi construído.
O LibG é um wrapper .Net fácil de usar em torno do kernel de geometria ASM. O libG compartilha seu esquema de versões com a biblioteca ASM; ele usa o mesmo número de versão principal e secundária da ASM para indicar que é o wrapper correspondente de uma versão específica da ASM. Quando é fornecida uma versão da ASM, a versão do libG correspondente deve ser a mesma. O LibG, na maioria dos casos, deve funcionar com todas as versões da ASM de uma determinada versão principal. Por exemplo, o LibG 223 deve ser capaz de carregar qualquer versão da ASM 223.
O Dynamo Sandbox foi desenvolvido para funcionar com diversas versões da ASM. Para isso, diversas versões do libG são agrupadas e enviadas com o núcleo. Há uma funcionalidade integrada no Dynamo Shape Manager para procurar produtos da Autodesk que são fornecidos com a ASM, para que o Dynamo possa carregar a ASM desses produtos e fazer com que os nós de geometria funcionem sem serem carregados explicitamente em um aplicativo hospedeiro. A lista de produtos existente hoje é:
O Dynamo pesquisará no registro do Windows e descobrirá se os produtos da Autodesk nessa lista estão instalados no computador do usuário. Se algum deles estiver instalado, ele pesquisará por binários da ASM, obterá a versão e procurará uma versão do libG correspondente no Dynamo.
Dada a versão da ASM, a seguinte API do ShapeManager escolherá a localização do pré-carregador libG correspondente para carregar. Se houver uma correspondência exata da versão, ela será usada; caso contrário, o libG com a versão mais próxima abaixo, mas com a mesma versão principal, será carregada.
Por exemplo: se o Dynamo estiver integrado com uma compilação de desenvolvimento do Revit, em que há uma compilação da ASM 225.3.0 mais recente, o Dynamo tentará usar o libG 225.3.0, se existir; caso contrário, ele tentará usar a versão principal mais próxima, menor que sua primeira escolha, ou seja, 225.0.0.
public static string GetLibGPreloaderLocation(Version asmVersion, string dynRootFolder)
O Revit é a primeira entrada na lista de pesquisa de produtos da ASM, o que significa que, por padrão, o DynamoSandbox.exe tentará carregar a ASM do Revit primeiro. Ainda queremos garantir que a sessão de trabalho integrada do D4R carregue a ASM do hospedeiro atual do Revit: por exemplo, se o usuário tiver o R2018 e o R2020 no computador, ao iniciar o D4R do R2020, o D4R deverá usar a ASM 225 do R2020 em vez da ASM 223 do R2018. Os integradores precisarão implementar chamadas similares às seguintes para forçar o carregamento de sua versão especificada.
Recentemente, adicionamos a capacidade de o DynamoSandbox.exe e o DynamoCLI.exe carregarem uma versão da ASM específica. Para ignorar o comportamento normal de pesquisa do registro, é possível usar o indicador --GeometryPath para forçar o Dynamo a carregar a ASM de um caminho específico.
DynamoSandbox.exe --GeometryPath "somePath/To/ASMDirectory"
O StartupConfiguration é usado para ser passado como um parâmetro para inicializar o DynamoModel, o que indica que ele contém quase todas as definições de como você gostaria de personalizar suas configurações de sessão do Dynamo. Dependendo de como as propriedades a seguir são definidas, a integração do Dynamo pode variar entre diferentes integradores. Por exemplo, diferentes integradores podem definir diferentes caminhos de modelo Python ou formatos de números exibidos.
Consiste no seguinte:
DynamoCorePath // Onde os binários de carregamento do DynamoCore estão localizados
DynamoHostPath // Onde os binários de integração do Dynamo estão localizados
GeometryFactoryPath // Onde os binários libG carregados estão localizados
PathResolver // Objeto que ajuda a resolver vários arquivos
O caminho de configuração de preferência padrão é gerenciado por PathManager.PreferenceFilePath, por exemplo, "AppData\\Roaming\\Dynamo\\Dynamo Revit\\2.5\\DynamoSettings.xml". Os integradores podem decidir se desejam também enviar um arquivo de configuração de preferência personalizado para uma localização que precisa ser alinhada com o gerenciador de caminho. A seguir, estão as propriedades de configuração de preferência que são serializadas:
IsFirstRun // Indica se é a primeira vez que esta versão do Dynamo é executada, por exemplo, usado para determinar se é necessário exibir a mensagem de aceitação/exclusão do GA. Também usado para determinar se é necessário migrar a configuração de preferência do Dynamo legado ao iniciar uma nova versão do Dynamo, para que os usuários tenham uma experiência consistente
IsUsageReportingApproved // Indica se o relatório de uso foi aprovado ou não
IsAnalyticsReportingApproved // Indica se o relatório analítico foi aprovado ou não
LibraryWidth // A largura do painel esquerdo da biblioteca do Dynamo.
Um exemplo de configurações de preferência serializadas:
Extensions // Uma lista de extensões que implementam a IExtension. Se for nulo, o Dynamo carregará as extensões do caminho padrão (pasta extensions na pasta Dynamo)
IsHeadless // Indica se o Dynamo é iniciado sem a interface do usuário. Afeta o Analytics.
UpdateManager // Implementação do UpdateManager do integrador. Veja a descrição acima
ProcessMode // Equivalente a TaskProcessMode. Síncrono se estiver em modo de teste; caso contrário, Assíncrono. Isso controla o comportamento do agendador. Os ambientes de thread único também podem definir isso como síncrono.
Use o StartConfiguration de destino para iniciar o DynamoModel
Depois que o StartConfig for passado para iniciar o DynamoModel, o DynamoCore supervisionará as especificações reais para garantir que a sessão do Dynamo seja inicializada corretamente com os detalhes especificados. Deve haver algumas etapas de configuração que os integradores individuais precisarão executar após a inicialização do DynamoModel. Por exemplo, no D4R, os eventos são inscritos para monitorar transações do hospedeiro do Revit ou atualizações de documentos, personalização do nó Python etc.
Para inicializar o DynamoViewModel e o DynamoView, primeiro é preciso construir um DynamoViewModel, o que pode ser feito usando o método estático DynamoViewModel.Start. Veja abaixo:
O DynamoViewModel.StartConfiguration tem muito menos opções do que a configuração do modelo. Esses nós são, em sua maioria, autoexplicativos. O CommandFilePath pode ser ignorado, a menos que você esteja escrevendo um caso de teste.
O parâmetro Watch3DViewModel controla como a visualização do plano de fundo e os nós watch3d exibem a geometria 3D. Será possível usar sua própria implementação se implementar as interfaces necessárias.
Para construir o DynamoView, basta o DynamoViewModel. A Vista é um controle de janela e pode ser exibida usando o WPF.
O DynamoSandbox.exe é um ambiente de desenvolvimento para testar, usar e experimentar o DynamoCore. É um ótimo exemplo para verificar como os componentes DynamoCore e DynamoCoreWPF são carregados e configurados. É possível ver alguns dos pontos de entrada .
O rastreamento é um mecanismo no Dynamo Core, que é capaz de serializar dados no arquivo .dyn (arquivo do Dynamo). Fundamentalmente, esses dados são vinculados aos locais de chamada dos nós dentro do gráfico do Dynamo.
Quando um gráfico do Dynamo é aberto do disco, os dados de rastreamento salvos nele são reassociados aos nós do gráfico.
Mecanismo de rastreamento:
Implementa a vinculação de elementos no Dynamo
É possível usar o mecanismo de rastreamento para garantir que os objetos sejam vinculados novamente à geometria que eles criaram
O mecanismo de rastreamento e o local de chamada fornecem um GUID persistente que o implementador de nós pode usar para revincular
Os dados de rastreamento são serializados no arquivo .dyn dentro de uma propriedade chamada Bindings. Essa é uma matriz de callsites-ids -> dados. Um local de chamada é a localização/instância específica de onde um nó é chamado na máquina virtual do DesignScript. Vale a pena mencionar que os nós em um gráfico do Dynamo podem ser chamados várias vezes e, portanto, vários locais de chamada podem ser criados para uma única instância de nó.
NÃO é recomendável depender do formato dos dados serializados codificados em base64.
Há muitos motivos pelos quais alguém gostaria de salvar dados arbitrários como resultado da execução de uma função, mas neste caso o rastreamento foi desenvolvido para resolver um problema específico que os usuários encontram com frequência ao criar e iterar em programas de software que criam elementos em aplicativos hospedeiros.
O problema é aquele que chamamos de Element Binding e a ideia é esta:
À medida que um usuário desenvolve e executa um gráfico do Dynamo, ele provavelmente gerará novos elementos no modelo do aplicativo hospedeiro. Para o nosso exemplo, digamos que o usuário tenha um pequeno programa que gera 100 portas em um modelo arquitetônico. O número e a localização dessas portas são controlados pelo programa.
A primeira vez que o usuário executa o programa, ele gera essas 100 portas.
Mais tarde, quando o usuário modificar uma entrada em seu programa e executá-la novamente, seu programa (sem vinculação de elementos) criará 100 novas portas. As portas antigas ainda existirão no modelo junto com as novas.
Como o Dynamo é um ambiente de programação ativo e apresenta um modo de execução "Automatic", em que as alterações no gráfico acionam uma nova execução, isso pode rapidamente sobrecarregar um modelo com os resultados de muitas execuções do programa.
Descobrimos que isso geralmente não é o que os usuários esperam. Em vez disso, com a vinculação de elementos ativada, os resultados anteriores da execução de um gráfico são limpos e excluídos ou modificados. Qual deles (excluir ou modificar) depende da flexibilidade da API do hospedeiro. Com a vinculação de elementos ativada, após a segunda, terceira ou 50ª execução do programa do Dynamo do usuário, haverá apenas 100 portas no modelo.
Isso requer mais do que apenas ser capaz de serializar dados no arquivo .dyn, e, como você verá abaixo, há mecanismos no DynamoRevit criados sobre o rastreamento para dar suporte a esses fluxos de trabalho de revinculação.
Este é o momento apropriado para mencionar o outro caso de uso importante da vinculação de elementos para hospedeiros como o Revit. Como os elementos que foram criados quando a vinculação de elementos foi ativada tentarão manter as IDs dos elementos existentes (modificar elementos existentes), a lógica que foi criada sobre esses elementos no aplicativo hospedeiro continuará existindo após a execução de um programa do Dynamo. Por exemplo:
Vamos voltar ao nosso exemplo de modelo arquitetônico.
Vamos primeiro executar um exemplo com a vinculação de elementos desativada. Desta vez, o usuário tem um programa que gera algumas paredes arquitetônicas.
Ele executa o programa, que gera algumas paredes no aplicativo hospedeiro. Em seguida, ele sai do gráfico do Dynamo e usa as ferramentas normais do Revit para colocar algumas janelas nessas paredes. As janelas são vinculadas a essas paredes específicas como parte do modelo Revit.
O usuário inicia o Dynamo novamente e executa o gráfico novamente. Agora, como no nosso último exemplo, ele tem dois conjuntos de paredes. O primeiro conjunto tem janelas adicionadas, mas as novas paredes não.
Se a vinculação de elementos tiver sido ativada, será possível manter o trabalho existente que foi feito manualmente no aplicativo hospedeiro sem o Dynamo. Por exemplo, se a vinculação estivesse ativada quando o usuário executasse o programa pela segunda vez, as paredes seriam modificadas, não excluídas, e as alterações posteriores feitas no aplicativo hospedeiro persistiriam. O modelo conteria paredes com janelas, em vez de dois conjuntos de paredes em vários estados.
O rastreamento é um mecanismo no Dynamo Core. Ele usa uma variável estática de locais de chamada para os dados para mapear os dados para o local de chamada de uma função no gráfico, conforme descrito acima.
Ele também permite serializar dados arbitrários no arquivo .dyn ao gravar nós do Dynamo sem toque. Isso geralmente não é aconselhável, pois significa que o código sem toque potencialmente transferível agora depende do Dynamo Core.
Não confie no formato serializado dos dados no arquivo .dyn. Em vez disso, use o atributo [Serializable] e a interface
O ElementBinding, por outro lado, é construído com base nas APIs de rastreamento e é implementado na integração do Dynamo (DynamoRevit, Dynamo4Civil etc.)
Algumas das APIs de rastreamento de baixo nível que vale a pena conhecer são:
É possível vê-las em uso no exemplo abaixo
Para interagir com os dados de rastreamento que o Dynamo carregou de um arquivo existente ou está gerando, veja:
Um exemplo de nó do Dynamo que usa rastreamento diretamente é fornecido aqui no
O resumo da classe explica a essência do que é o rastreamento:
Esse exemplo usa as APIs de rastreamento no DynamoCore diretamente para armazenar alguns dados sempre que um nó específico é executado. Nesse caso, um dicionário desempenha o papel do modelo do aplicativo hospedeiro, como o banco de dados de modelos do Revit.
A configuração bruta é:
Uma classe utilitária estática TraceExampleWrapper é importada como um nó no Dynamo. Ela contém um único método ByString que cria TraceExampleItem. Esses são objetos .net regulares que contêm uma propriedade description.
Cada TraceExampleItem é serializado em um rastreamento representado como um TraceableId. Essa é apenas uma classe que contém um IntId que é marcado como [Serializeable] para que possa ser serializado com o formatador SOAP. Consulte
Também é preciso implementar a interface ISerializable definida
Essa classe é criada para cada TraceExampleItem que desejamos salvar no rastreamento, serializada, codificada em base64 e salva no disco quando o gráfico é salvo para que as vinculações possam ser reassociadas, mesmo mais tarde, quando o gráfico for aberto novamente sobre um dicionário de elementos existente. Isso não funcionará bem no caso deste exemplo, pois o dicionário não é realmente persistente como um documento do Revit.
Finalmente, a última parte da equação é o TraceableObjectManager, que é semelhante ao ElementBinder no DynamoRevit. Ele gerencia o relacionamento entre os objetos presentes no modelo de documento do hospedeiro e os dados que armazenamos no rastreamento do Dynamo.
Quando um usuário executa um gráfico contendo o nó TraceExampleWrapper.ByString pela primeira vez, um novo TraceableId é criado com uma nova ID, o TraceExampleItem é armazenado no dicionário mapeado para essa nova ID e o TraceableID é armazenado no rastreamento.
Na próxima execução do gráfico, procuramos no rastreamento, encontramos a ID que armazenamos lá, encontramos o objeto mapeado para essa ID e retornamos esse objeto. Em vez de criar um objeto novo, modificamos o existente.
O fluxo de duas execuções consecutivas do gráfico que cria um único TraceExampleItem é assim:
A mesma ideia é ilustrada no próximo exemplo com um caso de uso de nó DynamoRevit mais realista.
–
Em versões recentes do Dynamo, o uso do TLS (Thread Local Storage) foi substituído pelo uso do membro estático.
Vamos analisar rapidamente como fica um nó que usa a vinculação de elementos quando implementado no DynamoRevit. Isso é análogo ao tipo de nó usado acima nos exemplos de criação de paredes fornecidos.
O código acima ilustra um construtor de exemplo para um elemento de parede. Esse construtor seria chamado de um nó no Dynamo como: Wall.byParams
Fases importantes da execução do construtor em relação à vinculação de elementos:
Use o elementBinder para verificar se há algum objeto criado anteriormente que foi vinculado a este local de chamada em uma execução anterior. ElementBinder.GetElementFromTrace<Autodesk.Revit.DB.Wall>
Em caso afirmativo, tente modificar essa parede em vez de criar uma nova.
Caso contrário, crie uma nova parede.
Exclua o elemento antigo que acabamos de recuperar do rastreamento e adicione o novo para que possamos procurá-lo no futuro:
Atualmente, cada objeto de rastreamento serializado é serializado usando a formatação xml SOAP, que é bastante detalhada e duplica muitas informações. Em seguida, os dados são codificados em base64 duas vezes. Isso não é eficiente em termos de serialização ou desserialização. Isso poderá ser melhorado no futuro se o formato interno não for construído em cima dele. Novamente, repetimos, não confie no formato dos dados serializados, quando inativos.
Há casos de uso em que a vinculação de elementos não é desejada. E se alguém for um usuário avançado do Dynamo desenvolvendo um programa que deve ser executado diversas vezes para gerar agrupamentos aleatórios de elementos? A intenção do programa é criar elementos adicionais cada vez que o programa for executado. Esse caso de uso não é facilmente alcançável sem soluções alternativas para impedir que a vinculação de elementos funcione. É possível desativar o elementBinding no nível de integração, mas provavelmente essa deve ser uma funcionalidade central do Dynamo. Não está claro qual o nível de granularidade necessário para essa funcionalidade: Nível do nó? Nível do local de chamada? Sessão inteira do Dynamo? Espaço de trabalho? etc.
Em geral, esses nós permitem que o usuário descreva de alguma forma um subconjunto do documento ativo do Revit que deseja referenciar. Há várias formas pelas quais o usuário pode referenciar um elemento do Revit (descrito abaixo). A saída resultante do nó pode ser um wrapper de elemento do Revit (wrapper do DynamoRevit) ou alguma geometria do Dynamo (convertida da geometria do Revit). A diferença entre esses tipos de saída será útil para considerar no contexto de outras integrações de hospedeiro.
Em um nível superior, uma boa maneira de conceituar esses nós é como uma função que aceita uma ID de elemento e que retorna um ponteiro para esse elemento ou alguma geometria que representa esse elemento.
Há vários nós Selection no DynamoRevit. Podemos dividi-los em pelo menos dois grupos:
Seleção da interface do usuário:
Exemplo de nós DynamoRevit nesta categoria são SelectModelElement, SelectElementFace
Esses nós permitem que o usuário alterne para o contexto da interface do usuário do Revit e selecione um elemento ou conjunto de elementos, as IDs desses elementos são capturadas e é executada alguma função de conversão: um wrapper é criado ou a geometria é extraída e convertida do elemento. A conversão executada depende do tipo de nó que o usuário escolhe.
Consulta de documento:
Os nós de exemplo nessa categoria são AllElementsOfClass
O usuário seleciona uma parede do Revit com SelectModelElement. Um wrapper de parede do Dynamo é retornado ao gráfico (visível na bolha de visualização do nó)
O usuário coloca o nó Element.Geometry e anexa a saída do SelectModelElement a esse novo nó. A geometria da parede envolvida é extraída e convertida em geometria do Dynamo usando a API libG.
Os fluxos de trabalho no D4C são muito semelhantes à descrição acima para o Revit. Veja dois conjuntos típicos de nós de seleção no D4C:
Por causa do atualizador de modificação de documentos que os nós de seleção no DynamoRevit implementam, os loops infinitos são fáceis de construir: imagine um nó monitorando o documento para todos os elementos e, em seguida, criando novos elementos em algum lugar a jusante desse nó. Este programa, quando executado, ativará um loop. O DynamoRevit tenta capturar esses casos de várias formas usando IDs de transação e, para isso, evita modificar o documento quando as entradas para os construtores de elementos não foram alteradas.
Isso precisará ser considerado se a execução automática do gráfico for iniciada quando um elemento selecionado for modificado no aplicativo hospedeiro.
Os nós de seleção no DynamoRevit são implementados no projeto RevitUINodes.dll que faz referência ao WPF. Isso pode não ser um problema, mas vale a pena estar ciente disso, dependendo da plataforma de destino.
Os nós de seleção são implementados herdando os tipos de SelectionBase genéricos: SelectionBase<TSelection, TResult> e um conjunto mínimo de membros:
Implementação de um método BuildOutputAST. Esse método precisa retornar um AST, que será executado em algum momento no futuro, quando o nó for executado. No caso de nós de seleção, ele deve retornar elementos ou geometria das IDs de elementos.
A implementação do BuildOutputAST é uma das partes mais difíceis da implementação de nós NodeModel/da interface do usuário. É melhor colocar o máximo de lógica possível em uma função c# e simplesmente incorporar um nó de chamada de função AST no AST. Observe que aqui, o node é um nó AST na árvore de sintaxe abstrata, não um nó no gráfico do Dynamo.
Serialização
Como esses são tipos derivados explícitos do NodeModel (não do ZeroTouch), eles também exigem a implementação de um [JsonConstructor] que será usado durante a desserialização do nó em um arquivo .dyn.
As referências de elementos do hospedeiro devem ser salvas no arquivo .dyn para que, quando um usuário abrir um gráfico contendo esse nó, sua seleção ainda esteja definida. Os nós NodeModel no Dynamo usam json.net para serializar. Todas as propriedades públicas serão serializadas automaticamente usando Json.net. Use o atributo [JsonIgnore] para serializar apenas o que for necessário.
Os nós de consulta de documento são um pouco mais simples, pois não precisam armazenar uma referência a nenhuma ID de elemento. Veja a seguir as implementações da classe
O mecanismo de Pacotes Integrados é um esforço para agrupar mais conteúdo de nós com o Dynamo Core sem expandir o núcleo em si, aproveitando a funcionalidade de carregamento de pacotes do Dynamo implementada pela extensão PackageLoader e PackageManager.
Neste documento, usaremos alternadamente os termos Pacotes integrados, Pacotes integrados do Dynamo e pacotes integrados para significar a mesma coisa.
O pacote deve ter pontos de entrada binários assinados ou não será carregado.
Todo o esforço deve ser feito para evitar alterações de quebra nesses pacotes. Isso significa que o conteúdo do pacote deve ter testes automatizados.
Versão semântica: provavelmente é uma boa ideia controlar a versão do pacote usando um esquema de versão semântica e comunicá-lo aos usuários na descrição do pacote ou na documentação.
Testes automatizados. Veja acima, se um pacote for incluído usando o mecanismo de Pacote integrado, para um usuário, ele parecerá fazer parte do produto e deverá ser testado como um produto.
Basicamente, você deve ter controle total sobre o pacote, a capacidade de corrigi-lo, mantê-lo atualizado e testá-lo em relação às últimas alterações no Dynamo e em seu produto. Você também precisa ser capaz de assiná-lo.
Nossa intenção é que o Built-In Packages seja um recurso central, um conjunto de pacotes aos quais todos os usuários tenham acesso, mesmo que não tenham acesso ao gerenciador de pacotes. Atualmente, o mecanismo subjacente para suportar esse recurso é uma localização de carregamento padrão adicional para pacotes diretamente no diretório do Dynamo Core, em relação ao DynamoCore.dll.
Com algumas restrições, essa localização poderá ser usada por clientes e integradores do ADSK Dynamo para distribuir seus pacotes específicos de integração (por exemplo, a integração do FormIt no Dynamo requer um pacote personalizado do FormIt no Dynamo).
Como o mecanismo de carregamento subjacente é o mesmo para pacotes de núcleo e específicos do hospedeiro, será necessário garantir que os pacotes distribuídos dessa maneira não causem confusão ao usuário sobre pacotes principais Built-In Packages versus pacotes específicos de integração que estão disponíveis apenas em um único produto hospedeiro. Recomendamos que, para evitar que o usuário se confunda, os pacotes específicos do hospedeiro sejam introduzidos na discussão com as equipes do Dynamo.
Como os pacotes incluídos no Built-In Packages estarão disponíveis para mais clientes e as garantias que damos sobre eles serão mais rigorosas (veja acima), eles devem ser localizados.
Para pacotes ADSK internos destinados à inclusão de Built-In Packages, as limitações atuais de não poder publicar conteúdo localizado no gerenciador de pacotes não são bloqueadoras, pois os pacotes não precisam necessariamente ser publicados no gerenciador de pacotes.
Usando uma solução alternativa, é possível criar manualmente (e até publicar) pacotes com subdiretórios de cultura na pasta /bin de um pacote.
Primeiro, crie manualmente os subdiretórios específicos da cultura que você precisa na pasta /bin dos pacotes.
Se, por algum motivo, o pacote também precisar ser publicado no gerenciador de pacotes, será necessário primeiro publicar uma versão do pacote que não tenha esses subdiretórios de cultura. Depois, publicar uma nova versão do pacote usando o DynamoUI publish package version. O carregamento da nova versão no Dynamo não deve excluir as pastas e os arquivos em /bin, que você adicionou manualmente usando o explorador de arquivos do Windows. O processo de carregamento de pacotes no Dynamo será atualizado para lidar com os requisitos de arquivos localizados no futuro.
Esses subdiretórios de cultura serão carregados sem problemas pelo tempo de execução .net se estiverem localizados no mesmo diretório que os binários do nó/extensão.
Para obter mais informações sobre as montagens de recursos e os arquivos .resx, consulte: .
Você provavelmente estará criando os arquivos .resx e compilando-os com o Visual Studio. Para uma determinada montagem xyz.dll (os recursos resultantes serão compilados em uma nova montagem xyz.resources.dll). Conforme descrito acima, a localização e o nome dessa montagem são importantes.
O xyz.resources.dll gerado deve estar localizado como segue: package\bin\culture\xyz.resources.dll.
Para acessar as sequências de caracteres localizadas no pacote, é possível usar o ResourceManager, mas ainda mais simples: você deve conseguir consultar o Properties.Resources.YourLocalizedResourceName de dentro da montagem para a qual você adicionou um arquivo .resx. Por exemplo, consulte:
para obter um exemplo de mensagem de erro localizada
ou para obter um exemplo de uma sequência de caracteres de atributo NodeDescription específica do Dynamo localizada.
ou para obter outro exemplo.
Normalmente, quando o Dynamo carrega nós de um pacote, ele os coloca na seção Addons na biblioteca de nós. Para integrar melhor os nós de pacotes integrados com outros conteúdos integrados, adicionamos a capacidade de os autores de pacotes integrados fornecerem um arquivo layout specification parcial para ajudar a colocar os novos nós na categoria de nível superior correta na seção da biblioteca default.
Por exemplo, o seguinte arquivo json de especificação de layout, se encontrado no caminho package/extra/layoutspecs.json, colocará os nós especificados por path na categoria Revit na seção default, que é a principal seção de nós integrados.
Observe que os nós importados de um pacote interno terão o prefixo bltinpkg://, quando forem considerados para correspondência com um caminho incluído na especificação de layout.
As modificações complexas de layout não foram bem testadas ou não são suportadas. A intenção para o carregamento dessa especificação de layout em especial é mover um namespace de pacote inteiro sob uma categoria de hospedeiro específica como Revit ou Formit.
PreloadLibraryPaths // Onde estão localizados os nós binários pré-carregados, por exemplo, DSOffice.dll
AdditionalNodeDirectories // Onde os binários dos nós adicionais estão localizados
AdditionalResolutionPaths // Caminhos de resolução de montagem adicionais para outras dependências que podem ser necessárias durante o carregamento de bibliotecas
UserDataRootFolder // Pasta de dados do usuário, por exemplo, "AppData\Roaming\Dynamo\Dynamo Revit"
CommonDataRootFolder // Pasta padrão para salvar definições personalizadas, amostras etc.
Context // Nome do hospedeiro do integrador + versão (Revit<BuildNum>)
SchedulerThread // Thread do programador do integrador implementando o ISchedulerThread. Para a maioria dos integradores, esse é o thread da interface principal ou qualquer thread de onde eles podem acessar sua API.
StartInTestMode // Se a sessão atual é uma sessão de automação de teste (modifica vários comportamentos do Dynamo), não use, a menos que esteja escrevendo testes.
AuthProvider // Implementação do integrador do IAuthProvider, por exemplo, a implementação do RevitOxygenProvider está no Greg.dll, usado para integração de carregamento do packageManager.
ConsoleHeight // A altura da tela do console
ShowPreviewBubbles // Indica se as bolhas de visualização devem ser exibidas
ShowConnector // Indica se os conectores são exibidos
ConnectorType // Indica o tipo de conector: Bezier ou Polilinha
BackgroundPreviews // Indica o estado ativo da visualização do plano de fundo especificada
RenderPrecision // O nível de precisão de renderização; menor gera malhas com menos triângulos. Maior gerará uma geometria mais suave na visualização do plano de fundo. 128 é um bom número rápido para a geometria de visualização.
ShowEdges // Indica se as arestas de sólido e superfície serão renderizadas
ShowDetailedLayout // NÃO USADO
WindowX, WindowY // Última coordenada X, Y da janela do Dynamo
WindowW, WindowH // Última largura, altura da janela do Dynamo
UseHardwareAcceleration // O Dynamo deve usar a aceleração por hardware, se for compatível
NumberFormat // A precisão decimal usada para exibir os números em toString() da bolha de visualização.
MaxNumRecentFiles // O número máximo de caminhos de arquivo recentes a serem salvos
RecentFiles // Uma lista de caminhos de arquivos abertos recentemente. Tocar aqui afetará diretamente a lista de arquivos recentes na página inicial do Dynamo
BackupFiles // Uma lista de caminhos de arquivo de backup
CustomPackageFolders // Uma lista de pastas contendo binários sem toque e caminhos de diretório que serão verificados em busca de pacotes e nós personalizados.
PackageDirectoriesToUninstall // Uma lista de pacotes usados pelo Gerenciador de pacotes para determinar quais pacotes estão marcados para exclusão. Esses caminhos serão excluídos, se possível, durante a inicialização do Dynamo.
PythonTemplateFilePath // Caminho para o arquivo Python (.py) para ser usado como modelo inicial ao criar um novo nó PythonScript. Pode ser usado para configurar um modelo Python personalizado para a integração.
BackupInterval // Indica em quanto tempo (em milissegundos) o gráfico será salvo automaticamente
BackupFilesCount // Indica quantos backups serão feitos
PackageDownloadTouAccepted // Indica se o usuário aceitou os termos de uso para fazer o download dos pacotes do gerenciador de pacotes
OpenFileInManualExecutionMode // Indica o estado padrão da caixa de seleção “Abrir no modo manual” na OpenFileDialog
NamespacesToExcludeFromLibrary // Indica quais namespaces (se houver) não devem ser exibidos na biblioteca de nós do Dynamo. Formato da sequência de caracteres: “[nome da biblioteca]:[namespace totalmente qualificado]”
Local de chamada
O executável contém vários locais de chamada. Esses ocais de chamada são usados para despachar a execução para os vários lugares de onde eles precisam ser despachados:
Biblioteca em C#
Método integrado
Função DesignScript
Nó personalizado (função DS)
TraceSerializer
Serializa classes marcadas com ISerializable e [Serializable] no rastreamento.
Lida com a serialização e a desserialização dos dados no rastreamento.
O TraceBinder controla a vinculação de dados desserializados a um tipo de tempo de execução (cria a instância de classe real).
AllElementsOfCategoryEsses nós permitem que o usuário consulte todo o documento em busca de um subconjunto de elementos. Esses nós normalmente retornam wrappers que apontam para os elementos subjacentes do Revit. Esses wrappers são essenciais para a experiência do DynamoRevit, permitindo funcionalidades mais avançadas, como vinculação de elementos, e permitindo que os integradores do Dynamo selecionem quais APIs de hospedeiro serão expostas como nós para os usuários.
O usuário alterna o gráfico para o modo de execução automática.
O usuário modifica a parede original no Revit.
O gráfico é executado novamente de forma automática quando o documento do Revit gera um evento sinalizando que alguns elementos foram atualizados. O nó de seleção observa esse evento e vê que a ID do elemento selecionado foi modificada.
ElementQueryBaseAlto nível de polimento: ícones, documentação de nós, conteúdo localizado.
Não envie pacotes que você ou sua equipe não possam manter.
Não envie pacotes de terceiros dessa forma (consulte acima).










private static readonly List<string> ProductsWithASM = new List<string>()
{ "Revit", "Civil", "Robot Structural Analysis", "FormIt" }; internal static Version PreloadAsmFromRevit()
{
var asmLocation = AppDomain.CurrentDomain.BaseDirectory;
Version libGVersion = findRevitASMVersion(asmLocation);
var dynCorePath = DynamoRevitApp.DynamoCorePath;
var preloaderLocation = DynamoShapeManager.Utilities.GetLibGPreloaderLocation(libGVersion, dynCorePath);
Version preLoadLibGVersion = PreloadLibGVersion(preloaderLocation);
DynamoShapeManager.Utilities.PreloadAsmFromPath(preloaderLocation, asmLocation);
return preLoadLibGVersion;
} <PreferenceSettings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<IsFirstRun>false</IsFirstRun>
<IsUsageReportingApproved>false</IsUsageReportingApproved>
<IsAnalyticsReportingApproved>false</IsAnalyticsReportingApproved>
<LibraryWidth>204</LibraryWidth>
<ConsoleHeight>0</ConsoleHeight>
<ShowPreviewBubbles>true</ShowPreviewBubbles>
<ShowConnector>true</ShowConnector>
<ConnectorType>BEZIER</ConnectorType>
<BackgroundPreviews>
<BackgroundPreviewActiveState>
<Name>IsBackgroundPreviewActive</Name>
<IsActive>true</IsActive>
</BackgroundPreviewActiveState>
<BackgroundPreviewActiveState>
<Name>IsRevitBackgroundPreviewActive</Name>
<IsActive>true</IsActive>
</BackgroundPreviewActiveState>
</BackgroundPreviews>
<IsBackgroundGridVisible>true</IsBackgroundGridVisible>
<RenderPrecision>128</RenderPrecision>
<ShowEdges>false</ShowEdges>
<ShowDetailedLayout>true</ShowDetailedLayout>
<WindowX>553</WindowX>
<WindowY>199</WindowY>
<WindowW>800</WindowW>
<WindowH>676</WindowH>
<UseHardwareAcceleration>true</UseHardwareAcceleration>
<NumberFormat>f3</NumberFormat>
<MaxNumRecentFiles>10</MaxNumRecentFiles>
<RecentFiles>
<string></string>
</RecentFiles>
<BackupFiles>
<string>..AppData\Roaming\Dynamo\Dynamo Revit\backup\backup.DYN</string>
</BackupFiles>
<CustomPackageFolders>
<string>..AppData\Roaming\Dynamo\Dynamo Revit\2.5</string>
</CustomPackageFolders>
<PackageDirectoriesToUninstall />
<PythonTemplateFilePath />
<BackupInterval>60000</BackupInterval>
<BackupFilesCount>1</BackupFilesCount>
<PackageDownloadTouAccepted>true</PackageDownloadTouAccepted>
<OpenFileInManualExecutionMode>false</OpenFileInManualExecutionMode>
<NamespacesToExcludeFromLibrary>
<string>ProtoGeometry.dll:Autodesk.DesignScript.Geometry.TSpline</string>
</NamespacesToExcludeFromLibrary>
</PreferenceSettings>
viewModel = DynamoViewModel.Start(
new DynamoViewModel.StartConfiguration()
{
CommandFilePath = commandFilePath,
DynamoModel = model,
Watch3DViewModel =
HelixWatch3DViewModel.TryCreateHelixWatch3DViewModel(
null,
new Watch3DViewModelStartupParams(model),
model.Logger),
ShowLogin = true
});
var view = new DynamoView(viewModel);
"Bindings": [
{
"NodeId": "1e83cc25-7de6-4a7c-a702-600b79aa194d",
"Binding": {
"WrapperObject_InClassDecl-1_InFunctionScope-1_Instance0_1e83cc25-7de6-4a7c-a702-600b79aa194d": "Base64 Encoded Data"
}
},
{
"NodeId": "c69c7bec-d54b-4ead-aea8-a3f45bea9ab2",
"Binding": {
"WrapperObject_InClassDecl-1_InFunctionScope-1_Instance0_c69c7bec-d54b-4ead-aea8-a3f45bea9ab2": "Base64 Encoded Data"
}
}
],
public static ISerializable GetTraceData(string key)
///Returns the data that is bound to a particular key
public static void SetTraceData(string key, ISerializable value)
///Set the data bound to a particular key public IDictionary<Guid, List<CallSite.RawTraceData>>
GetTraceDataForNodes(IEnumerable<Guid> nodeGuids, Executable executable) /*
* After a graph update, Dynamo typically disposes of all
* objects created during the graph update. But what if there are
* objects which are expensive to re-create, or which have other
* associations in a host application? You wouldn't want those those objects
* re-created on every graph update. For example, you might
* have an external database whose records contain data which needs
* to be re-applied to an object when it is created in Dynamo.
* In this example, we use a wrapper class, TraceExampleWrapper, to create
* TraceExampleItem objects which are stored in a static dictionary
* (they could be stored in a database as well). On subsequent graph updates,
* the objects will be retrieved from the data store using a trace id stored
* in the trace cache.
*/ [IsVisibleInDynamoLibrary(false)]
[Serializable]
public class TraceableId : ISerializable
{
} private void InitWall(Curve curve, Autodesk.Revit.DB.WallType wallType, Autodesk.Revit.DB.Level baseLevel, double height, double offset, bool flip, bool isStructural)
{
// This creates a new wall and deletes the old one
TransactionManager.Instance.EnsureInTransaction(Document);
//Phase 1 - Check to see if the object exists and should be rebound
var wallElem =
ElementBinder.GetElementFromTrace<Autodesk.Revit.DB.Wall>(Document);
bool successfullyUsedExistingWall = false;
//There was a modelcurve, try and set sketch plane
// if you can't, rebuild
if (wallElem != null && wallElem.Location is Autodesk.Revit.DB.LocationCurve)
{
var wallLocation = wallElem.Location as Autodesk.Revit.DB.LocationCurve;
<SNIP>
if(!CurveUtils.CurvesAreSimilar(wallLocation.Curve, curve))
wallLocation.Curve = curve;
<SNIP>
}
var wall = successfullyUsedExistingWall ? wallElem :
Autodesk.Revit.DB.Wall.Create(Document, curve, wallType.Id, baseLevel.Id, height, offset, flip, isStructural);
InternalSetWall(wall);
TransactionManager.Instance.TransactionTaskDone();
// delete the element stored in trace and add this new one
ElementBinder.CleanupAndSetElementForTrace(Document, InternalWall);
} if(!CurveUtils.CurvesAreSimilar(wallLocation.Curve, curve))
wallLocation.Curve = curve; var wall = successfullyUsedExistingWall ? wallElem :
Autodesk.Revit.DB.Wall.Create(Document, curve, wallType.Id, baseLevel.Id, height, offset, flip, isStructural);
ElementBinder.CleanupAndSetElementForTrace(Document, InternalWall);{
"sections": [
{
"text": "default",
"iconUrl": "",
"elementType": "section",
"showHeader": false,
"include": [ ],
"childElements": [
{
"text": "Revit",
"iconUrl": "",
"elementType": "category",
"include": [],
"childElements": [
{
"text": "some sub group name",
"iconUrl": "",
"elementType": "group",
"include": [
{
"path": "bltinpkg://namespace.namespace",
"inclusive": false
}
],
"childElements": []
}
]
}
]
}
]
}