arrow-left
All pages
gitbookPowered by GitBook
1 of 18

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Interface de linha de comando do Dynamo

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

hashtag
Por quê

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

hashtag
O quê

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.

hashtag
Observações importantes

  • 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

hashtag
Como

-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

“C:path\to\arquivo.dyn”
  • 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 aquiarrow-up-right

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

    Publicar um pacote

    hashtag
    Publicar um pacote

    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 Manualarrow-up-right tem um guia geral sobre os pacotes.

    hashtag
    O que é um Gerenciador de 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.

    1. Procurar pacotes on-line: Packages > Search for a Package...

    2. Visualizar/editar pacotes instalados: Packages > Manage Packages...

    3. Publicar um novo pacote: Packages > Publish New Package...

    hashtag
    Publicar um pacote

    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.

    1. Selecionar Add file... para procurar arquivos para adicionar ao pacote

    2. Selecionar os dois arquivos .dll no estudo de caso NodeModel

    3. Selecionar 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.

    1. Fornecer as informações necessárias para o nome, a descrição e a versão.

    2. Publicar clicando em “Publicar localmente” e selecionar a pasta de pacotes do Dynamo: AppData\Roaming\Dynamo\Dynamo Core\1.3\packages para 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.

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

    1. Para ver como o Dynamo formatou o pacote, clicar nos três pontos verticais à direita de “CustomNodeModel” e escolher “Mostrar diretório raiz”

    2. Selecionar Publish e, em seguida, Publish Online na janela “Publicar um pacote do Dynamo”.

    3. Para excluir um pacote, selecionar Delete.

    hashtag
    Como atualizar um pacote?

    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.

    1. Selecionar Publish Version para atualizar um pacote existente com novos arquivos no diretório raiz e, em seguida, escolher se ele deve ser publicado localmente ou on-line.

    hashtag
    Cliente Web do Gerenciador de pacotes

    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:

    1. Em Meus pacotes, selecione o pacote e clique em Editar detalhes do pacote.

    2. Adicione ou modifique os links do Site e do Repositório usando os respectivos campos.

    3. 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:

    1. Clique na versão do pacote que você deseja atualizar.

    2. A lista Depende será preenchida automaticamente com os pacotes dos quais o pacote depende.

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

    Compilar um pacote do Visual Studio

    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.

    hashtag
    Como compilar diretamente na pasta de pacotes

    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.

    hashtag
    Copiar arquivos de pacote com o método AfterBuild

    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:

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

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

    1. A nova pasta de pacotes que o destino AfterBuild criou

    2. A pasta src existente com o projeto

    3. As pastas dyf e extra criadas 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.

    Estudo de caso sem toque – Nó de grade

    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.

    hashtag
    Nó de grade retangular personalizado

    Clique em Salvar alterações para aplicar as atualizações.
    https://dynamopackages.com/arrow-up-right
    https://dynamobim.org/discover-the-new-dynamo-package-management-experience/arrow-up-right
    https://dynamopackages.com/arrow-up-right
    Procurar pacotes
    Publicar um pacote
    Configurações do pacote
    Pacote na biblioteca do Dynamo
    Publicar um pacote no Gerenciador de pacotes
    Publicar uma versão do pacote
    Cliente Web do gerenciador de pacotes
    Nova interface do usuário para atualizar os detalhes do pacote para pacotes publicados
    Editar informações de compatibilidade para pacotes publicados – Etapa 1
    Qual opção escolher para o fluxo de trabalho “Editar informações de compatibilidade”
    Editar opções de informações de compatibilidade
    Editar informações de compatibilidade – Etapa 2
    Copiar manualmente o arquivo pkg.json.
    Atomarrow-up-right
    Mover os arquivos de projeto
    Colocar o destino AfterBuild
    Copiar arquivos
    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" />
    Para começar a compilar o nó de grade, crie um novo projeto de biblioteca de classes do Visual Studio. Consulte a página Introdução para obter uma visão geral detalhada de como configurar um projeto.
    Criar um novo projeto no Visual Studio
    Configurar um novo projeto no Visual Studio
    1. Escolher Class Library para o tipo de projeto

    2. Nomear 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;.

    Pacote ZeroTouchLibrary
    1. Procure o pacote ZeroTouchLibrary

    2. Usaremos esse nó na compilação atual do Dynamo Studio, que é 1.3. Selecione a versão do pacote que corresponde a isso.

    3. 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 ZeroTouchLibrary System.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.

    Compilar um DLL
    1. 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.

    Nós personalizados no Dynamo
    1. O nó personalizado RectangularGrids na Biblioteca do Dynamo

    2. O nó personalizado na tela

    3. O botão Adicionar para adicionar o .dll ao Dynamo

    hashtag
    Modificações de nós personalizados

    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.

    Dica de ferramenta de entrada
    1. Um valor de entrada padrão

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

    Ativar a documentação XML
    1. 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.

    Gráfico de grade retangular
    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;
            }
        }
    }

    Executar scripts Python em nós Sem toque (C#)

    hashtag
    Executar scripts Python em nós sem toque (C#)

    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

    Um nó Sem toque que executará uma sequência de caracteres de script Python

    hashtag
    Mecanismo 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 .

    hashtag
    Várias saídas

    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.

    Usar tipos COM (interoperabilidade) em pacotes do Dynamo

    hashtag
    Algumas informações gerais sobre tipos de interoperabilidade

    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:

    Extensões como pacotes

    hashtag
    Extensões como pacotes

    hashtag
    Visão geral

    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)

    seção Python do manualarrow-up-right
    Esse nó está nos permitindo retornar o volume do cuboide e seu centroide.

    https://learn.microsoft.com/pt-br/dotnet/framework/interop/type-equivalence-and-embedded-interop-typesarrow-up-right

    hashtag
    Como o Dynamo gerencia a equivalência de tipos

    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 IsEquivalentToarrow-up-right

    hashtag
    Como evitar conflitos entre tipos de interoperabilidade integrados

    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 aquiarrow-up-right) 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 aquiarrow-up-right).

    Você pode seguir este exemplo:

    https://learn.microsoft.com/pt-br/windows/win32/com/the-component-object-modelarrow-up-right
    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*/)
                {}
            }
        }
    }

    hashtag
    Estrutura do pacote

    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:

    hashtag
    Carregar

    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.

    Publicar um pacote

    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.

    hashtag
    Extrair

    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.

    Procurar pacotes

    Desenvolvimento do Dynamo

    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

    Três ambientes de desenvolvimento: Visual Studio, Editor do Python e DesignScript com Blocos de código

    hashtag
    Quais são as minhas opções?

    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.

    hashtag
    Para o Dynamo

    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

    hashtag
    No Dynamo

    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

    hashtag
    Quais são as vantagens/desvantagens de cada um?

    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

    hashtag
    Entender o controle de versão do Dynamo e as alterações da API (1.x → 2.x)

    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:

    hashtag
    Permissão para distribuir binários em um pacote

    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.

    hashtag
    Considerações sobre o desempenho da interface do usuário do Dynamo

    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.

    Guia de Introdução

    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.

    hashtag
    Criar um projeto do Visual Studio

    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 Manualarrow-up-right

  • importar bibliotecas Sem toquearrow-up-right
    Estratégias de script
    Manualarrow-up-right
    exemplo A-Forge
    Wiki do Dynamo Githubarrow-up-right
    construtor JSONarrow-up-right
    http://dynamods.github.io/DynamoAPIarrow-up-right
    Página Wiki de Considerações de desempenho do Dynamoarrow-up-right
    Interface do Visual Studio
    Desenvolvimento no espaço de trabalho do Dynamo com o nó Python
    Bloco de código, script Python e nó personalizado
    Nós Sem toque
    Nós derivados do NodeModel
    A API do Dynamo altera o documento
    Documentação da API
    Manualarrow-up-right
    .dll
    .
    Criar um novo projeto no Visual Studio
    Configurar um novo projeto no Visual Studio

    Janela Novo projeto no Visual Studio

    1. Começar abrindo o Visual Studio e criando um novo projeto: File > New > Project

    2. Selecionar o modelo de projeto Class Library

    3. Nomear o projeto (nomeamos o projeto MyCustomNode)

    4. Definir o caminho do arquivo para o projeto. Para este exemplo, vamos deixá-lo na localização padrão

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

    Usar o Gerenciador de soluções
    1. Abrir o Gerenciador de soluções e as janelas Saída em View.

    2. Renomear o arquivo Class1.cs SampleFunctions.cs no Gerenciador de soluções à direita.

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

    4. O Gerenciador de soluções fornece acesso a tudo no projeto.

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

    Configurações de compilação do Visual Studio
    1. Abrir as propriedades do projeto selecionando Project > "ProjectName" Properties

    2. Selecionar a página Build

    3. Selecionar Any CPU ou x64 no menu suspenso

    4. Garantir que Prefer 32-bit está 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.

    Compilar uma solução
    1. Selecionar Build > Build Solution

    2. É 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.

    Estrutura de arquivos do projeto
    1. A pasta bin contém o .dll criado no Visual Studio.

    2. O arquivo de projeto do Visual Studio.

    3. O arquivo de classe.

    4. Como nossa configuração de solução foi definida como Debug, o .dll será criado em bin\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.

    Abrir o arquivo dll do projeto
    1. Selecionar o botão Adicionar para importar um .dll

    2. Navegar 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\MyCustomNode

    3. Selecionar o MyCustomNode.dll a ser importado

    4. Clicar em Open para 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.

    Nós personalizados
    1. MyCustomNode na biblioteca do Dynamo. A categoria da biblioteca é determinada pelo nome .dll.

    2. SampleFunctions.MultiplyByTwo na tela.

    hashtag
    Como o Dynamo lê as classes e os métodos

    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.

    Nó SampleFunction.MultiplyByTwo em um gráfico
    1. A entrada é nomeada inputNumber com base no nome do parâmetro do método.

    2. A saída é nomeada double por padrão porque esse é o tipo de dados que está sendo retornado.

    3. O nó é nomeado SampleFunctions.MultiplyByTwo porque 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.

    Método importado como um nó de criação
    1. O Dynamo importou nosso método como um nó Criar

    hashtag
    Adicionar referências do pacote NuGet do Dynamo

    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.

    • ZeroTouchLibraryarrow-up-right – 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

    • WpfUILibraryarrow-up-right – 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

    • DynamoServicesarrow-up-right – 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.

    Abrir o gerenciador de pacotes NuGet
    1. 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.

    Gerenciador de pacotes NuGet
    1. Selecionar Procurar e pesquisar DynamoVisualProgramming para ativar os pacotes do Dynamo.

    2. Pacotes do Dynamo. Selecionar um mostrará a versão atual e a descrição do que está dentro.

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

    Gerenciador de referências
    1. Clicar com o botão direito do mouse em References e selecionar Add Reference.

    2. Selecionar Browse para 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.

    Visual Studio

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

    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.

    hashtag
    Padrão “Model-View-Viewmodel”

    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;
            }
        }
    }
    Corearrow-up-right
    Testsarrow-up-right
    DynamoCoreNodesarrow-up-right
    (MVVM) para manter a interface do usuário separada do back-end. Ao criar nós Sem toque, o Dynamo faz a associação de dados entre os dados de um nó e sua interface de usuário. Para criar uma interface de usuário personalizada, é preciso adicionar a lógica de vinculação de dados.

    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.

    hashtag
    Como implementar o NodeModel

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

    1. Criar a estrutura do projeto:

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

    1. Selecionar File > New > Project

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

    3. Selecionar Blank Solution

    4. Nomear a solução CustomNodeModel

    5. Selecionar Ok

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

    Adicionar uma nova biblioteca de classes
    1. Clicar com o botão direito do mouse na Solução e selecionar Add > New Project

    2. Escolher a biblioteca de classes

    3. Nomeá-la CustomNodeModel

    4. Clicar em Ok

    5. Repita o processo para adicionar outro projeto nomeado CustomNodeModelFunctions

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

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

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

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

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

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

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

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

    Desativar a cópia do pacote local
    1. Selecionar pacotes do Dynamo NuGet

    2. Definir Copy Local como false

    2. Herdar a classe NodeModel

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

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

    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.

    Adicionar uma referência

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

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

    2. Escolher Projects > Solution

    3. Marcar CustomNodeModelFunction

    4. Clicar em Ok

    4. Personalizar a vista

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

    Copie o seguinte código para GridNodeView.cs

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

    Adicionar um novo controle deslizante
    1. Clicar com o botão direito do mouse em CustomNodeModel e selecionar Add > New Item

    2. Selecionar WPF

    3. Nomear o controle de usuário Slider

    4. Clicar em Add

    Copie o seguinte código para Slider.xaml

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

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

    2. Selecionar Web

    3. Selecionar JSON File

    4. Nomear o arquivo pkg.json

    5. Clicar em Add

    • Copie o seguinte código para pkg.json

    • "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.

    Gráfico de grade retangular
    model-view-viewmodelarrow-up-right

    Desenvolvimento do Dynamo para Revit

    hashtag
    Usar métodos em GeometryPrimitiveConverter.cs

    A classe GeometryPrimitiveConverterarrow-up-right 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.

    hashtag
    Categorias de métodos

    É possível agrupar os métodos em GeometryPrimitiveConverter.cs em quatro categorias principais:

    1. Tipos do Proto para Revit: métodos que convertem tipos do Dynamo (Proto) em tipos do Revit.

    2. Tipos do Revit para Proto: métodos que convertem tipos do Revit em tipos do Dynamo (Proto).

    3. Graus e radianos: métodos que convertem entre graus e radianos.

    4. X e UZ: métodos que lidam com a obtenção de vetores perpendiculares.

    hashtag
    Tipos do Proto para Revit

    hashtag
    ToRevitBoundingBox

    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)

    hashtag
    ToRevitType (BoundingBox)

    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)

    hashtag
    ToRevitType (ponto)

    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)

    hashtag
    ToRevitType (vetor)

    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)

    hashtag
    ToXyz (ponto)

    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)

    hashtag
    ToXyz (vetor)

    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)

    hashtag
    ToTransform

    Converte um CoordinateSystem do Dynamo em uma transformação do Revit.

    public static Autodesk.Revit.DB.Transform ToTransform(this CoordinateSystem cs, bool convertUnits = true)

    hashtag
    ToPlane

    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)

    hashtag
    ToXyzs (pontos)

    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)

    hashtag
    ToXyzs (vetores)

    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)

    hashtag
    ToDoubleArray

    Converte uma matriz de valores duplos em DoubleArray do Revit.

    public static DoubleArray ToDoubleArray(this double[] list)

    hashtag
    ToUvs

    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)

    hashtag
    ToDSUvs

    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)

    hashtag
    Exemplo de uso de tipos do Proto para Revit

    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.

    hashtag
    Tipos do Revit para Proto

    hashtag
    ToProtoType (BoundingBox)

    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)

    hashtag
    ToPoint (XYZ)

    Converte um XYZ do Revit em um ponto do Dynamo.

    public static Autodesk.DesignScript.Geometry.Point ToPoint(this XYZ xyz, bool convertUnits = true)

    hashtag
    ToProtoType (ponto)

    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)

    hashtag
    ToVector (XYZ)

    Converte um XYZ do Revit em um vetor do Dynamo.

    public static Vector ToVector(this XYZ xyz, bool convertUnits = false)

    hashtag
    ToProtoType (UV)

    Converte um UV do Revit em um UV do Dynamo.

    public static Autodesk.DesignScript.Geometry.UV ToProtoType(this Autodesk.Revit.DB.UV uv)

    hashtag
    ToPlane (Plano do Revit)

    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)

    hashtag
    ToCoordinateSystem

    Converte uma transformação do Revit em um CoordinateSystem do Dynamo.

    public static CoordinateSystem ToCoordinateSystem(this Transform t, bool convertUnits = true)

    hashtag
    ToPoints

    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)

    hashtag
    Exemplo de uso dos tipos do Revit para Proto

    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.

    hashtag
    Graus e radianos

    hashtag
    ToRadians

    Converte graus em radianos.

    public static double ToRadians(this double degrees) { return degrees * Math.PI / 180.0; }

    hashtag
    ToDegrees

    Converte radianos em graus.

    public static double ToDegrees(this double degrees) { return degrees * 180.0 / Math.PI; }

    hashtag
    Exemplo de uso de graus e radianos

    Este exemplo mostra um método rápido e fácil de usar o método .ToRadianos para converter de graus em radianos.

    hashtag
    X e UZ

    hashtag
    GetPerpendicular (XYZ)

    Esse método retorna um vetor XYZ perpendicular ao vetor XYZ fornecido.

    public static XYZ GetPerpendicular(this XYZ xyz)

    hashtag
    GetPerpendicular (vetor)

    Esse método retorna um Vector do Dynamo perpendicular ao Vector do Dynamo fornecido.

    public static Vector GetPerpendicular(this Vector vector)

    hashtag
    Exemplo de uso de X e UZ

    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.

    Aprofundar o conhecimento sobre o nó Sem toque

    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"
      ]
    }
    contém todos os métodos que iremos importar para o Dynamo.

    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.csarrow-up-right. A documentação XML foi removida para mantê-los concisos, e cada exemplo de código criará o nó na imagem acima dele.

    hashtag
    Valores de entrada padrão

    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#arrow-up-right. 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

    Valor padrão
    1. O valor padrão será exibido quando você passar o cursor sobre a porta de entrada do nó

    hashtag
    Retornar vários valores

    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.csarrow-up-right

    Um nó que retorna várias saídas.

    Várias saídas
    1. Observe que agora há duas portas de saída nomeadas de acordo com as sequências que inserimos para as chaves do dicionário.

    hashtag
    Documentação, dicas de ferramentas e pesquisa

    É 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

    Gerar um arquivo XML
    1. 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.csarrow-up-right

    Observe que o código para esse nó de exemplo contém:

    1. Um resumo dos nós

    2. Uma descrição de entrada

    3. Uma descrição de saída

    hashtag
    Práticas recomendadas para as descrições dos nós do Dynamo

    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

    Descrição do nó

    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

    O que fazer
    O que não fazer

    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

    hashtag
    Avisos e erros dos nós do Dynamo

    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ósarrow-up-right.

    hashtag
    Objetos

    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.csarrow-up-right

    Após a importação do dll ZeroTouchEssentials, haverá um nó ZeroTouchEssentials na biblioteca. É possível criar esse objeto usando o nó ByTwoDoubles.

    Nó ByTwoDoubles

    hashtag
    Usar tipos de geometria do Dynamo

    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.csarrow-up-right

    Um nó que obtém o comprimento de uma curva e o duplica.

    Entrada de curva
    1. Esse nó aceita um tipo de geometria de curva como uma entrada.

    hashtag
    Dispor/usar declarações

    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 aquiarrow-up-right

      Consulte Melhorias na estabilidade da geometria do Dynamoarrow-up-right para saber mais sobre os novos recursos de estabilidade introduzidos no Dynamo 2.5

    • Com chamadas Dispor manuais:

    hashtag
    Migrações

    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>

    Arquivo de migração
    1. Clicar com o botão direito do mouse e selecionar Add > New Item

    2. Escolher XML File

    3. Para 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.xmlarrow-up-right

    hashtag
    Elementos genéricos

    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.

    https://github.com/DynamoDS/ZeroTouchEssentialsarrow-up-right
    Nós Sem toque
    ZeroTouchEssentials no Visual Studio
    Converter um Point.ByCoordinates do Dynamo em um XYZ do Revit
    Converter um XYZ do Revit em um Point.ByCoordinates do Dynamo
    Graus em radianos
    Obter vetor perpendicular
    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_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: Measure Angle
    degree_angle = IN[0]
    
    # Convert to Radians
    radian_angle = Revit.GeometryConversion.GeometryPrimitiveConverter.ToRadians(degree_angle)
    
    # Output
    OUT = radian_angle
    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 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
    
    Exemplo: Grava o conteúdo do texto em um arquivo
    especificado
    pelo caminho fornecido

    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

    Atualizar os pacotes e as bibliotecas do Dynamo para Dynamo 3.x

    hashtag
    Introdução

    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 blogarrow-up-right.


    hashtag
    Compatibilidade dos pacotes

    hashtag
    Usar pacotes do Dynamo 2.x no Dynamo 3.x

    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.

    hashtag
    Usar pacotes do Dynamo 3.x no Dynamo 2.x

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

    Extensões

    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.

    hashtag
    Estudo de caso de 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.

    1. 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/.

    hashtag
    Como implementar uma extensão de vista

    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.

    1. Criar um novo projeto selecionando File > New > Project

    2. Selecionar Class Library

    3. Nomear 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.

    1. Um arquivo de classe denominado SampleViewExtension.cs que implementará IViewExtension

    2. Um arquivo de classe denominado SampleWindowViewMode.cs que implementará NotificationObject

    Para usar o IViewExtension, precisaremos do pacote WpfUILibrary NuGet. A instalação desse pacote instalará automaticamente os pacotes Core, Services e ZeroTouchLibrary.

    1. Selecionar a biblioteca WpfUIL

    2. Selecionar Install para 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.

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

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

    2. Selecionar o modelo Controle de usuário que vamos alterar para criar uma janela

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

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

    2. Selecionar o arquivo XML

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

    1. O arquivo .xml que 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:

    Atualizar os pacotes e as bibliotecas do Dynamo para Dynamo 2.x

    hashtag
    Introdução:

    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.DynamoWindow
    define o proprietário da janela pop-out como Dynamo. Isso significa que a nova janela depende do Dynamo, portanto, ações como minimizar, maximizar e restaurar o Dynamo farão com que a nova janela siga esse mesmo comportamento
  • window.Show(); exibe a janela onde as propriedades adicionais da janela foram definidas

  • Selecionar Add

    Selecionar Add

    https://github.com/DynamoDS/DynamoSamplesarrow-up-right
    https://forum.dynamobim.com/t/dynashape-published/11666arrow-up-right
    https://github.com/LongNguyenP/DynaShapearrow-up-right
    Janela de extensão da vista
    Criar uma nova biblioteca de classes
    Configurar um novo projeto
    Visualizar os arquivos de classe de extensão
    Visualizar os pacotes de extensão
    O item de menu
    Adicionar uma janela
    Adicionar um novo XML
    Arquivo XML copiado para a pasta Extensões
    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>

    hashtag
    Regras gerais de empacotamento:

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

    hashtag
    Problemas comuns:

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

    JSON quebrado

    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.

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

    hashtag
    Atualização em profundidade:

    hashtag
    Nós personalizados 1.3 -> 2.0

    Organizar nós personalizados no arquivo librarie.jsarrow-up-right

    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-3653arrow-up-right – 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.

    hashtag
    Nós Sem toque 1.3 -> 2.0

    • 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.)

    hashtag
    Nós do modelo de nós 1.3 -> 2.0

    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.arrow-up-right

    hashtag
    Construtores JSON

    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 -> ButtonCustomNodeModelarrow-up-right, DropDownarrow-up-right ou SliderCustomNodeModelarrow-up-right

    hashtag
    Propriedades públicas e serialização

    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 aquiarrow-up-right). 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 aquiarrow-up-right no repositório do Dynamo.

    [JsonProperty(PropertyName = "InputValue")]

    public DSColor DsColor {...

    hashtag
    Conversores:

    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 aquiarrow-up-right no repositório do Dynamo.

    [JsonProperty("MeasurementType"), JsonConverter(typeof(StringEnumConverter))]

    public ConversionMetricUnit SelectedMetricConversion{...

    hashtag
    Ignorar as propriedades

    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 aquiarrow-up-right no repositório do Dynamo.


    hashtag
    Desfazer/Refazer

    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.

    hashtag
    APIs de porta de entrada e saída

    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.csarrow-up-right ou FileSystem.csarrow-up-right

    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.csarrow-up-right no repositório do Dynamo.

    hashtag
    Exemplos:

    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 DynamoSamplesarrow-up-right 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.

    Definir a organização de pacotes personalizados no Dynamo 2.0 e superior

    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.

    hashtag
    NodeModel

    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:

    hashtag
    ZeroTouch

    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

    hashtag
    CustomNodes

    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)

    hashtag
    Estratégias de migração de nós do pacote

    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
    Propriedades do nó personalizado
    namespace MyZTLibrary
    public 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
        {
            ...
        }
    {

    Personalização avançada de nós do Dynamo

    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.

    hashtag
    Gerar mensagens de aviso personalizadas usando OnLogWarningMessage

    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.

    hashtag
    Etapas de implementação de OnLogWarningMessage

    hashtag
    Etapa 1: Importar o namespace necessário

    OnLogWarningMessage faz parte do namespace DynamoServices, por isso, comece adicionando-o ao arquivo do projeto.

    hashtag
    Etapa 2: Identificar quando registrar avisos

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

    hashtag
    Etapa 3: Usar o OnLogWarningMessage para registrar o aviso

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

    hashtag
    Sintaxe para OnLogWarningMessage

    hashtag
    Exemplo de implementações de OnLogWarningMessage

    Para demonstrar OnLogWarningMessage na prática, aqui estão diferentes cenários que podem ser encontrados ao criar um nó Sem Toque.

    hashtag
    Exemplo 1: Validar entradas numéricas

    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.

    hashtag
    Adicionar mensagens informativas com OnLogInfoMessage

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

    hashtag
    Etapas de implementação de OnLogInfoMessage

    hashtag
    Etapa 1: Importar o namespace necessário

    OnLogInfoMessage faz parte do namespace DynamoServices, por isso, comece adicionando-o ao arquivo do projeto.

    hashtag
    Etapa 2: Identificar quando registrar as informações

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

    hashtag
    Etapa3: Usar OnLogInfoMessage para registrar mensagens informativas

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

    hashtag
    Sintaxe para OnLogInfoMessage

    hashtag
    Exemplo de implementações de OnLogInfoMessage

    Veja diferentes cenários para demonstrar usando OnLogInfoMessage nos nós Sem Toque.

    hashtag
    Exemplo 1: Validar entradas numéricas

    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:

    hashtag
    Exemplo 2: Fornecer informações de contagem de dados

    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.

    hashtag
    Exemplo 3: Resumir os parâmetros usados

    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.

    hashtag
    Criar e adicionar documentação personalizada a nós

    hashtag
    Documentação personalizada dos nós

    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.

    hashtag
    Um novo modo

    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.

    hashtag
    O que é o Markdown?

    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.

    hashtag
    Guia de Introdução ao Markdown

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

    hashtag
    O que o Markdown pode fazer?

    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 .

    hashtag
    Adicionar documentação estendida aos nós

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

    hashtag
    Abrir arquivos de documentação 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ó.

    hashtag
    Pasta doc do pacote

    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.

    hashtag
    Nomenclatura dos arquivos Markdown

    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

    hashtag
    Modificar arquivos Markdown enquanto abertos no Dynamo

    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.

    hashtag
    Adicionar ícones personalizados a nós Sem toque

    hashtag
    Visão geral

    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.

    hashtag
    Etapas para adicionar ícones de nós personalizados

    hashtag
    Etapa 1: Configurar o projeto

    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.

    hashtag
    Etapa 2: Criar as imagens dos ícones

    Para criar ícones personalizados:

    1. Criar os ícones: use um editor de imagem para criar ícones simples e visualmente claros para os nós.

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

    hashtag
    Etapa 3: Adicionar um arquivo de recursos ao projeto

    Para incorporar os ícones no .dll, crie um arquivo de recursos:

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

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

    hashtag
    Etapa 4: Adicionar as imagens como recursos

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

    hashtag
    Etapa 5: Converter o projeto no estilo SDK (para projetos herdados)

    Se o projeto ainda não estiver no estilo SDK (necessário para incorporar recursos), converta-o:

    1. Instale a extensão .NET Upgrade Assistant no menu Extensões > Gerenciar extensões do Visual Studio.

    1. Clique com o botão direito do mouse no projeto no Gerenciador de soluções e selecione Atualizar > Converter projeto em estilo SDK.

    1. Aguarde a conclusão da conversão.

    hashtag
    Etapa 6: Adicionar um script After-Build para incorporar recursos

    1. Descarregue o projeto:

      • Clique com o botão direito do mouse no projeto no Gerenciador de soluções e selecione Descarregar projeto.

    1. Edite o arquivo .csproj:

      • Adicione o seguinte elemento <Target> entre </ItemGroup> e </Project>:

    1. Substitua todas as instâncias de ZeroTouchNodeIcons pelo nome do projeto.

    2. Recarregue o projeto:

      • Clique com o botão direito do mouse no projeto descarregado e selecione Recarregar projeto.

    hashtag
    Etapa 7: Construir e carregar o .dll no Dynamo

    1. Construir o projeto:

      • Depois de adicionar o script After-Build, construa o projeto no Visual Studio.

    1. Verifique os arquivos de saída:

      • Verifique se o .dll e o .customization.dll estão na pasta bin.

    2. Adicione o .dll ao Dynamo:

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

  • Dillingerarrow-up-right
    Visual Studio Codearrow-up-right
    sintaxe básica do Markdownarrow-up-right
    Exemplo 1 de OnLogWarningMessage
    Exemplo 2 de OnLogWarningMessage
    Exemplo 3 de OnLogWarningMessage
    Exemplo 1 de OnLogInfoMessage
    Exemplo 2 de OnLogInfoMessage
    Exemplo 3 de OnLogInfoMessage
    Descrição da dica de ferramenta do nó
    Navegação de documentação
    Documentação personalizada do nó
    Nós de sobrecarga
    Recarga dinâmica
    Criar um projeto do Visual Studio
    Configurar um novo projeto no Visual Studio
    Adicionar um novo item
    Adicionar um arquivo de recursos
    Limpar a propriedade Ferramenta personalizada
    Adicionar recursos...
    Gerenciar extensões
    Instalar o Assistente de atualização do .NET
    Atualizar o projeto
    Converter em estilo SDK
    Atualização concluída
    Descarregar o projeto
    Adicionar o código After-Build
    Recarregar o projeto
    Construir a solução
    Botão Importar biblioteca
    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>

    Integração do Dynamo

    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.

    hashtag
    Ponto de entrada personalizado do Dynamo

    hashtag
    Revit do Dynamo como exemplo

    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.

    hashtag
    Etapas para personalizar o ponto de entrada do Dynamo

    Para inicializar o DynamoModel, os integradores precisarão executar estas etapas em algum lugar no código do hospedeiro.

    hashtag
    Pré-carregar as DLLs do Dynamo compartilhadas 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.

    hashtag
    Carregar o ASM

    hashtag
    O que são a ASM e o LibG

    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.

    hashtag
    Dynamo Sandbox carregando a ASM

    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)

    hashtag
    Integração em processo do Dynamo carregando a ASM do hospedeiro

    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.

    hashtag
    O Dynamo carregando a ASM de um caminho personalizado

    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"

    hashtag
    Criar um StartConfiguration

    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

    hashtag
    Preferências

    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.

    hashtag
    Vamos já à parte de “programação visual”

    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.

    hashtag
    Exemplo do DynamoSandbox.exe:

    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 .

    hashtag
    Vinculação e rastreamento de elementos

    hashtag
    Visão geral

    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.

    hashtag
    Glossário:

    • 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

    hashtag
    Como é?


    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.

    hashtag
    Que problema estamos tentando resolver.


    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.


    hashtag
    Vinculação de elementos em comparação com rastreamento


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

    hashtag
    APIs de rastreamento

    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:

    hashtag
    Exemplo de rastreamento simples de um nó


    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.

    hashtag
    Diagrama de rastreamento

    –

    hashtag
    OBSERVAÇÃO:

    Em versões recentes do Dynamo, o uso do TLS (Thread Local Storage) foi substituído pelo uso do membro estático.

    hashtag
    Exemplo de implementação da vinculação de elementos


    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:

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

    2. Em caso afirmativo, tente modificar essa parede em vez de criar uma nova.

    1. Caso contrário, crie uma nova parede.

    1. Exclua o elemento antigo que acabamos de recuperar do rastreamento e adicione o novo para que possamos procurá-lo no futuro:

    hashtag
    Discussão

    hashtag
    Eficiência

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

    hashtag
    O ElementBinding deve estar ativado por padrão?

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

    hashtag
    Nós de seleção do Revit do Dynamo (o que são?)

    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:

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

    2. Consulta de documento:

      Os nós de exemplo nessa categoria são AllElementsOfClass

    hashtag
    Fluxos de trabalho do usuário do Revit do Dynamo:

    hashtag
    Casos de exemplo

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

    hashtag
    Fluxos de trabalho do usuário do DynamoCivil:

    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:

    hashtag
    Problemas:

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

    hashtag
    Diagramas de fluxo de dados

    hashtag
    Implementação técnica: (consulte os diagramas acima):

    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

    hashtag
    Referências:

    hashtag
    Classes base do DynamoCore:

    hashtag
    DynamoRevit:

    hashtag
    Visão geral dos pacotes integrados do Dynamo

    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.

    hashtag
    Devo enviar um pacote como um Pacote integrado?

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

    hashtag
    Pacotes integrados versus pacotes específicos de integração de hospedeiro

    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.

    hashtag
    Localização dos pacotes

    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.

    hashtag
    Layout da biblioteca de nós

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

  • ,
    AllElementsOfCategory

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

  • ElementQueryBase
    e da classe derivada. Quando executados, esses nós fazem uma chamada para a API do Revit e consultam o documento subjacente em busca de elementos, além de realizar a conversão mencionada anteriormente para a geometria ou os wrappers de elementos do Revit.
  • Alto 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).

  • Vinculação e rastreamento de elementos
    Nós de seleção do Revit do Dynamo
    Visão geral dos pacotes integrados do Dynamo
    https://github.com/DynamoDS/DynamoRevit/blob/master/src/DynamoRevit/DynamoRevit.cs#L534arrow-up-right
    https://github.com/DynamoDS/Dynamo/issues/7130arrow-up-right
    aquiarrow-up-right
    GetTraceDataForNodesarrow-up-right
    RuntimeTrace.csarrow-up-right
    repositório do DynamoSamplesarrow-up-right
    aqui para obter mais informações sobre o atributo serializávelarrow-up-right
    aquiarrow-up-right
    https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodesUI/Selection.cs#L280arrow-up-right
    https://github.com/DynamoDS/Dynamo/blob/ec10f936824152e7dd7d6d019efdcda0d78a5264/src/Libraries/CoreNodeModels/Selection.csarrow-up-right
    Estudo de caso do NodeModel – Interface do usuário personalizadaarrow-up-right
    Atualizar os pacotes e as bibliotecas do Dynamo para Dynamo 2.xarrow-up-right
    Atualizar os pacotes e as bibliotecas do Dynamo para Dynamo 3.xarrow-up-right
    https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodesUI/Selection.csarrow-up-right
    https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodesUI/Elements.csarrow-up-right
    https://docs.microsoft.com/pt-br/dotnet/framework/resources/creating-resource-files-for-desktop-appsarrow-up-right
    https://github.com/DynamoDS/Dynamo/blob/master/src/Libraries/CoreNodes/List.cs#L457arrow-up-right
    https://github.com/DynamoDS/Dynamo/blob/master/src/Libraries/CoreNodeModels/ColorRange.cs#L19arrow-up-right
    https://github.com/DynamoDS/DynamoSamples/blob/master/src/SampleLibraryUI/Examples/LocalizedCustomNodeModel.csarrow-up-right
    Criar paredes
    Primeira chamada
    Segunda chamada
    Nós de seleção do Revit
    Nós de seleção do Civil 3D
    Fluxo de seleção
    Fluxo de seleção2
    Fluxo de seleção2
    Etapas de rastreamento
    Fluxo de rastreamento
    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": []
                }
              ]
            }
          ]
        }
      ]
    }