All pages
Powered by GitBook
1 of 18

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Opracowywanie rozwiązań dla dodatku Dynamo

Platformę Dynamo zaprojektowano tak, aby umożliwić współtworzenie wszystkim użytkownikom, niezależnie od poziomu doświadczenia. Dostępnych jest kilka opcji programowania odpowiednich do różnych rodzajów i poziomów umiejętności, z których każda ma zalety i wady w zależności od zamierzonego celu. Poniżej omówimy te różne opcje i sposób wyboru między nimi.

Trzy środowiska programistyczne

Trzy środowiska programistyczne: program Visual Studio, Edytor języka Python i język Code Block DesignScript

Jakie mam opcje?

Opcje programowania rozwiązań dla dodatku Dynamo należą przede wszystkim do dwóch kategorii: dla dodatku Dynamo i w dodatku Dynamo. Te dwie kategorie należy rozumieć tak: „w” dodatku Dynamo oznacza zawartość tworzoną za pomocą środowiska IDE dodatku Dynamo, która ma być używana w dodatku Dynamo; natomiast „dla” dodatku Dynamo oznacza tworzenie za pomocą narzędzi zewnętrznych zawartości, która ma być importowana do dodatku Dynamo w celu jej używania. W tym podręczniku skoncentrowano się na programowaniu dla dodatku Dynamo, ale poniżej opisano zasoby dotyczące wszystkich procesów.

Dla dodatku Dynamo

Te węzły umożliwiają najwyższy stopień dostosowania. Wiele pakietów jest kompilowanych za pomocą tej metody i jest ona niezbędna do współtworzenia źródła dodatku Dynamo. Proces ich kompilowania zostanie omówiony w tym podręczniku.

  • Węzły Zero-Touch

  • Węzły pochodne od klasy NodeModel

  • Rozszerzenia

Przewodnik Primer zawiera podręcznik dotyczący importowania bibliotek Zero-Touch.

W poniższym omówieniu jako środowisko programistyczne dla węzłów Zero-Touch i NodeModel jest używany program Visual Studio.

Interfejs programu Visual Studio

Interfejs programu Visual Studio z projektem, który będziemy opracowywać

W dodatku Dynamo

Mimo że te procesy istnieją w obszarze roboczym programowania wizualnego i są stosunkowo proste, wszystkie umożliwiają dostosowanie dodatku Dynamo. W przewodniku Primer opisano je szczegółowo i podano wskazówki dotyczące skryptów oraz wzorce postępowania — w rozdziale Strategie dotyczące skryptów.

  • Węzły z bokami kodu, Code Block, uwidaczniają kod DesignScript w środowisku programowania wizualnego, umożliwiając używanie elastycznych procesów roboczych węzłów i skryptów tekstowych. Funkcję w węźle Code Block może wywołać dowolny element w obszarze roboczym.

    Pobierz przykład węzła Code Block (kliknij prawym przyciskiem myszy i zapisz jako) lub zobacz szczegółowe omówienie w przewodniku Primer.

  • Węzły niestandardowe są kontenerami dla kolekcji węzłów, a nawet całych wykresów. Są one skutecznym sposobem gromadzenia często używanych procedur i udostępniania ich społeczności.

    Pobierz przykład węzła niestandardowego (kliknij prawym przyciskiem myszy i zapisz jako) lub zobacz szczegółowe omówienie w przewodniku Primer.

  • Węzły w języku Python są interfejsem skryptowym w obszarze roboczym programowania wizualnego, podobnie jak węzły Code Block. W bibliotekach Autodesk.DesignScript używa się zapisu kropkowego podobnego do tego używanego w języku DesignScript.

    Pobierz przykład węzła w języku Python (kliknij prawym przyciskiem myszy i zapisz jako) lub zobacz szczegółowe omówienie w przewodniku Primer

Programowanie w obszarze roboczym dodatku Dynamo to wydajne rozwiązanie umożliwiające natychmiastowe uzyskanie informacji zwrotnych.

Programowanie w obszarze roboczym dodatku Dynamo za pomocą węzła w języku Python

Programowanie w obszarze roboczym dodatku Dynamo za pomocą węzła w języku Python

Jakie są zalety/wady poszczególnych opcji?

Opcje programowania dla dodatku Dynamo zaprojektowano z uwzględnieniem złożoności wymagań dotyczących dostosowywania. Niezależnie od tego, czy celem jest napisanie skryptu cyklicznego w języku Python, czy opracowanie całkowicie niestandardowego interfejsu użytkownika węzła, dostępne są opcje implementowania kodu obejmujące tylko czynności niezbędne do przygotowania działającego rozwiązania.

Węzły Code Block, węzeł w języku Python i węzły niestandardowe w dodatku Dynamo

Są to proste opcje pisania kodu w środowisku programowania wizualnego dodatku Dynamo. Obszar roboczy programowania wizualnego dodatku Dynamo zapewnia dostęp do języka Python i języka DesignScript oraz możliwość umieszczania wielu węzłów wewnątrz węzła niestandardowego.

Węzeł Code Block, skrypt w języku Python i węzeł niestandardowy

Te metody zapewniają następujące możliwości:

  • Rozpoczęcie pisania w języku Python lub DesignScript przy niewielkiej konfiguracji lub w ogóle bez niej.

  • Importowanie bibliotek języka Python do dodatku Dynamo.

  • Udostępnianie społeczności węzłów Code Block, węzłów w języku Python i węzłów niestandardowych dodatku Dynamo w ramach pakietu.

Węzły Zero-Touch

Zero-Touch to prosta metoda importowania bibliotek C# przez wskazanie i kliknięcie. Dodatek Dynamo odczyta publiczne metody z pliku .dll i przekonwertuje je na węzły Dynamo. Za pomocą metody Zero-Touch można tworzyć własne pakiety i węzły niestandardowe.

Węzły Zero-Touch

Co można zrobić za pomocą tej metody:

  • Importowanie biblioteki, która nie została opracowana dla dodatku Dynamo, i automatyczne tworzenie pakietu nowych węzłów, jak w przykładzie A-Forge z przewodnika Primer

  • Pisanie metod w języku C# i łatwe używanie ich jako węzłów w dodatku Dynamo

  • Udostępnianie społeczności dodatku Dynamo biblioteki C# jako węzłów w pakiecie

Węzły pochodne od klasy NodeModel

Te węzły są osadzone nieco głębiej w strukturze dodatku Dynamo. Są one oparte na klasie NodeModel i napisane w języku C#. Mimo że ta metoda zapewnia największą elastyczność i największe możliwości, wymaga jednak wyraźnego zdefiniowania większości aspektów węzła i umieszczenia funkcji w osobnym zespole.

Węzły pochodne od klasy NodeModel

Co można zrobić za pomocą tej metody:

  • Tworzenie w pełni konfigurowalnego interfejsu użytkownika węzła z suwakami, obrazami, kolorem itp. (np. węzeł ColorRange)

  • Uzyskiwanie dostępu do informacji o tym, co się dzieje w obszarze rysunku dodatku Dynamo, i wpływanie na to

  • Dostosowywanie skratowania

  • Wczytywanie do dodatku Dynamo w postaci pakietu

Omówienie obsługi wersji dodatku Dynamo i zmian w interfejsie API (z wersji 1.x do wersji 2.x)

Ponieważ dodatek Dynamo jest regularnie aktualizowany, w części interfejsu API używanej przez pakiet mogą być wprowadzane zmiany. Śledzenie tych zmian jest ważne na potrzeby zapewnienia dalszego poprawnego działania istniejących pakietów.

Zmiany interfejsu API są śledzone na stronie wiki dodatku Dynamo w serwisie GitHub. Obejmuje to zmiany wprowadzone w pakiecie DynamoCore, bibliotekach i obszarach roboczych.

Dokument zmian w interfejsie API dodatku Dynamo

Przykładem nadchodzącej istotnej zmiany jest przejście z formatu pliku XML na format pliku JSON w wersji 2.0. Węzły pochodne od klasy NodeModel będą teraz wymagać konstruktora JSON. W przeciwnym razie nie będą otwierane w dodatku Dynamo 2.0.

Dokumentacja interfejsu API dodatku Dynamo obejmuje obecnie podstawowe funkcje: http://dynamods.github.io/DynamoAPI

Dokumentacja interfejsu API

Uprawnienia do dystrybucji plików binarnych w pakiecie

Należy nadzorować pliki .dll zawarte w pakiecie przekazywanym do Menedżera pakietów. Jeśli autor pakietu nie utworzył danego pliku .dll, musi mieć uprawnienia do jego udostępniania.

Jeśli pakiet zawiera pliki binarne, użytkownicy muszą być monitowani podczas pobierania z informacją o tym, że pakiet zawiera pliki binarne.

Zagadnienia dotyczące wydajności interfejsu użytkownika dodatku Dynamo

W chwili pisania tego tekstu dodatek Dynamo używa do renderowania interfejsu użytkownika głównie platformy WPF (Windows Presentation Foundation). Platforma WPF jest złożonym i zaawansowanym systemem opartym na XAML/powiązaniach. Ponieważ dodatek Dynamo ma złożony interfejs użytkownika, łatwo jest wytworzyć zawieszenia interfejsu użytkownika, przecieki pamięci lub zawinięcia wykonywania wykresu i aktualizacji interfejsu użytkownika w sposób, który obniża wydajność.

Zapoznaj się ze stroną wiki poświęconą zagadnieniom związanym z wydajnością dodatku Dynamo, która pomoże Ci uniknąć kilku typowych pułapek podczas wprowadzania zmian w kodzie dodatku Dynamo.

Pierwsze kroki

Przed rozpoczęciem prac nad rozwiązaniem należy opracować solidne podstawy dla nowego projektu. W społeczności programistów dodatku Dynamo dostępnych jest kilka szablonów projektów, które doskonale nadają się do rozpoczęcia pracy, ale jeszcze cenniejsza jest umiejętność rozpoczynania projektu od podstaw. Tworzenie projektu od podstaw pozwala lepiej zrozumieć proces opracowywania rozwiązania.

Visual Studio

Tworzenie projektu programu Visual Studio

Program Visual Studio to zaawansowane środowisko IDE, w którym można tworzyć projekty, dodawać odwołania, kompilować biblioteki .dlls i debugować. Podczas tworzenia nowego projektu program Visual Studio tworzy również rozwiązanie, czyli strukturę organizacyjną projektów. W jednym rozwiązaniu może istnieć wiele projektów i można je kompilować razem. Aby utworzyć węzeł ZeroTouch, należy rozpocząć nowy projekt programu Visual Studio, w którym zostanie napisana biblioteka klas języka C# i zostanie skompilowany plik .dll.

Tworzenie nowego projektu w programu Visual Studio
Konfigurowanie nowego projektu w programie Visual Studio

Okno nowego projektu w programie Visual Studio

  1. Zacznij od otwarcia programu Visual Studio i utworzenia nowego projektu: File > New > Project

  2. Wybierz szablon projektu Class Library

  3. Nadaj projektowi nazwę (w tym przypadku nazwaliśmy projekt MyCustomNode)

  4. Ustaw ścieżkę pliku dla projektu. W tym przykładzie pozostawimy go w położeniu domyślnym

  5. Wybierz przycisk Ok

Program Visual Studio automatycznie utworzy i otworzy plik w języku C#. Należy nadać mu odpowiednią nazwę, skonfigurować obszar roboczy i zastąpić kod domyślny tą metodą mnożenia.

 namespace MyCustomNode
 {
     public class SampleFunctions
     {
         public static double MultiplyByTwo(double inputNumber)
         {
             return inputNumber * 2.0;
         }
     }
 }
Korzystanie z Eksploratora rozwiązań
  1. Otwórz Eksplorator rozwiązań i okna danych wyjściowych z poziomu obszaru View.

  2. W Eksploratorze rozwiązań po prawej stronie zmień nazwę pliku Class1.cs na SampleFunctions.cs.

  3. Dodaj powyższy kod dla funkcji mnożenia. Szczegóły dotyczące tego, jak dodatek Dynamo będzie odczytywał klasy w języku C#, zostaną omówione później.

  4. Eksplorator rozwiązań: umożliwia dostęp do wszystkich elementów w projekcie.

  5. Okno danych wyjściowych: będzie potrzebne później, aby sprawdzić, czy kompilacja się powiodła.

Następnym krokiem jest skompilowanie projektu, ale wcześniej należy sprawdzić kilka ustawień. Najpierw upewnij się, że jako platformę docelową wybrano Any CPU lub x64 i że opcja Prefer 32-bit nie jest zaznaczona we właściwościach projektu.

Ustawienia kompilacji programu Visual Studio
  1. Otwórz właściwości projektu, wybierając opcję Project > "ProjectName" Properties

  2. Wybierz stronę Build

  3. Wybierz z menu rozwijanego opcję Any CPU lub x64

  4. Upewnij się, że opcja Prefer 32-bit nie jest zaznaczona

Teraz możemy skompilować projekt, aby utworzyć plik .dll. Aby to zrobić, wybierz opcję Build Solution z menu Build lub użyj skrótu CTRL+SHIFT+B.

Kompilowanie rozwiązania
  1. Wybierz opcję Build > Build Solution

  2. Aby ustalić, czy projekt został pomyślnie skompilowany, należy sprawdzić okno danych wyjściowych

Jeśli projekt został pomyślnie skompilowany, w folderze projektu bin będzie znajdować się plik .dll o nazwie MyCustomNode. W tym przykładzie pozostawiliśmy ścieżkę pliku projektu jako domyślną w programie Visual Studio: c:\users\username\documents\visual studio 2015\Projects. Przyjrzyjmy się strukturze plików projektu.

Struktura plików projektu
  1. Folder bin zawiera plik .dll skompilowany w programie Visual Studio.

  2. Plik projektu programu Visual Studio.

  3. Plik klasy.

  4. Ponieważ jako konfigurację rozwiązania ustawiono Debug, plik .dll zostanie utworzony w folderze bin\Debug.

Teraz możemy otworzyć dodatek Dynamo i zaimportować plik .dll. Za pomocą funkcji dodawania przejdź do położenia projektu bin i wybierz plik .dll, który chcesz otworzyć.

Otwieranie pliku dll projektu
  1. Wybierz przycisk Add (Dodaj), aby zaimportować plik .dll

  2. Przejdź do położenia projektu. Projekt znajduje się w domyślnej ścieżce pliku programu Visual Studio: C:\Users\username\Documents\Visual Studio 2015\Projects\MyCustomNode

  3. Wybierz plik MyCustomNode.dll do zaimportowania

  4. Kliknij przycisk Open, aby wczytać plik .dll

Jeśli w bibliotece o nazwie MyCustomNode została utworzona kategoria, plik .dll został zaimportowany pomyślnie. Dodatek Dynamo utworzył jednak dwa węzły z tego, co powinno być jednym węzłem. W następnej sekcji wyjaśnimy, dlaczego tak się dzieje i jak dodatek Dynamo odczytuje plik .dll.

Węzły niestandardowe
  1. Węzeł MyCustomNode w bibliotece dodatku Dynamo. Kategoria biblioteki jest określana przez nazwę pliku .dll.

  2. Węzeł SampleFunctions.MultiplyByTwo w obszarze rysunku.

Jak dodatek Dynamo odczytuje klasy i metody

Gdy dodatek Dynamo wczytuje plik .dll, wszystkie publiczne metody statyczne zostają uwidocznione jako węzły. Konstruktory, metody i właściwości zostają przekształcone w węzły odpowiednio Create (tworzenia), Action (operacji) i Query (zapytań). W tym przykładzie z mnożeniem metoda MultiplyByTwo() staje się węzłem operacji w dodatku Dynamo. Dzieje się tak, ponieważ węzeł został nazwany na podstawie metody i klasy.

Węzeł SampleFunction.MultiplyByTwo na wykresie
  1. Nazwa danych wejściowych to inputNumber na podstawie nazwy parametru metody.

  2. Nazwa danych wyjściowych to domyślnie double, ponieważ jest to zwracany typ danych.

  3. Węzeł ma nazwę SampleFunctions.MultiplyByTwo, ponieważ takie są nazwy klasy i metody.

W powyższym przykładzie utworzono dodatkowy węzeł tworzenia, SampleFunctions: nie udostępniliśmy konstruktora bezpośrednio, więc został on utworzony automatycznie. Można tego uniknąć, tworząc pusty konstruktor prywatny w klasie SampleFunctions.

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;
        }
    }
}
Metoda zaimportowana jako węzeł tworzenia
  1. Dodatek Dynamo zaimportował metodę jako węzeł tworzenia

Dodawanie odwołań do pakietów NuGet dodatku Dynamo

Ten węzeł mnożenia jest bardzo prosty i nie są wymagane żadne odwołania do dodatku Dynamo. Aby uzyskać dostęp do dowolnej funkcji dodatku Dynamo na przykład w celu utworzenia geometrii, należy odwołać się do pakietów NuGet dodatku Dynamo.

  • ZeroTouchLibrary — pakiet umożliwiający kompilowanie bibliotek węzłów Zero-Touch dla dodatku Dynamo, który zawiera następujące biblioteki: DynamoUnits.dll, ProtoGeometry.dll

  • WpfUILibrary — pakiet umożliwiający kompilowanie bibliotek węzłów dla dodatku Dynamo z niestandardowym interfejsem użytkownika w pliku WPF, który zawiera następujące biblioteki: DynamoCoreWpf.dll, CoreNodeModels.dll, CoreNodeModelWpf.dll

  • DynamoServices — biblioteka DynamoServices dla dodatku Dynamo

  • Core — infrastruktura testów jednostkowych i systemowych dla dodatku Dynamo, która zawiera następujące biblioteki: DSIronPython.dll, DynamoApplications.dll, DynamoCore.dll, DynamoInstallDetective.dll, DynamoShapeManager.dll, DynamoUtilities.dll, ProtoCore.dll, VMDataBridge .dll

  • Tests — infrastruktura testów jednostkowych i systemowych dla dodatku Dynamo, która zawiera następujące biblioteki: DynamoCoreTests.dll, SystemTestServices.dll, TestServices.dll

  • DynamoCoreNodes — pakiet umożliwiający kompilowanie węzłów podstawowych dodatku Dynamo, który zawiera następujące biblioteki: Analysis.dll, GeometryColor.dll, DSCoreNodes.dll

Aby utworzyć odwołanie do tych pakietów w projekcie programu Visual Studio, należy pobrać pakiet z witryny NuGet za pomocą powyższych linków i ręcznie utworzyć odwołanie do plików .dll lub użyć Menedżera pakietów NuGet w programie Visual Studio. Najpierw omówimy sposób ich instalowania za pomocą menedżera NuGet w programie Visual Studio.

Otwieranie Menedżera pakietów NuGet
  1. Otwórz Menedżera pakietów NuGet, wybierając opcję Tools > NuGet Package Manager > Manage NuGet Packages for Solution...

To jest Menedżer pakietów NuGet. W tym oknie wyświetlane są pakiety zainstalowane dla projektu. Użytkownik może w nim też przeglądać inne pakiety. Jeśli zostanie wydana nowa wersja pakietu DynamoServices, w tym miejscu można zaktualizować pakiety lub przywrócić ich wcześniejszą wersję.

Menedżer pakietów NuGet
  1. Wybierz opcję przeglądania i wyszukaj dodatek DynamoVisualProgramming, aby wywołać pakiety dodatku Dynamo.

  2. Pakiety dodatku Dynamo. Wybranie jednego z nich spowoduje wyświetlenie bieżącej wersji i opisu zawartości.

  3. Wybierz potrzebną wersję pakietu i kliknij przycisk instalowania. Spowoduje to zainstalowanie pakietu dla określonego projektu, w którym pracujesz. Używasz najnowszej stabilnej wersji dodatku Dynamo w wersji 1.3, więc wybierz odpowiednią dla niej wersję pakietu.

Aby ręcznie dodać pakiet pobrany z przeglądarki, otwórz Menedżera odnośników w Eksploratorze rozwiązań i wyszukaj pakiet.

Menedżer odnośników
  1. Kliknij prawym przyciskiem myszy opcję References i wybierz polecenie Add Reference.

  2. Wybierz opcję Browse, aby przejść do lokalizacji pakietu.

Program Visual Studio jest teraz właściwie skonfigurowany i pomyślnie dodano plik .dll do dodatku Dynamo, więc mamy dobrze przygotowane środowisko do dalszej pracy. Jest to dopiero początek, dlatego postępuj zgodnie z instrukcjami, aby dowiedzieć się więcej na temat tworzenia węzła niestandardowego.

Aktualizowanie pakietów i bibliotek dodatku Dynamo dla dodatku Dynamo 3.x

Wprowadzenie

Ta sekcja zawiera informacje na temat problemów, które mogą wystąpić podczas migrowania wykresów, pakietów i bibliotek do dodatku Dynamo 3.x.

Dodatek Dynamo 3.0 jest wersją główną i niektóre interfejsy API zostały w nim zmienione lub usunięte. Największą zmianą, która może mieć konsekwencje dla programisty lub użytkownika dodatku Dynamo 3.x, jest przejście na platformę .NET8.

Dotnet/.NET to środowisko wykonawcze obsługujące język C#, w którym jest napisany dodatek Dynamo. Zaktualizowaliśmy środowisko wykonawcze do najnowszej wersji wraz z resztą ekosystemu firmy Autodesk.

Więcej informacji można znaleźć w tym wpisie w blogu.


Zgodność pakietów

Korzystanie z pakietów dodatku Dynamo 2.x w dodatku Dynamo 3.x

Ponieważ dodatek Dynamo 3.x działa teraz w środowisku wykonawczym .NET8, nie ma gwarancji, że pakiety utworzone dla dodatku Dynamo 2.x (przy użyciu platformy .NET48) będą działać w dodatku Dynamo 3.x. W przypadku próby pobrania w dodatku Dynamo 3.x pakietu opublikowanego w wersji Dynamo starszej niż 3.0 zostanie wyświetlone ostrzeżenie, że pakiet pochodzi ze starszej wersji dodatku Dynamo.

To nie oznacza, że pakiet nie będzie działał. Jest to po prostu ostrzeżenie, że mogą wystąpić problemy ze zgodnością, i że ogólnie warto sprawdzić, czy nie istnieje nowsza wersja, która została opracowana specjalnie dla dodatku Dynamo 3.x.

Ten typ ostrzeżenia może też pojawiać się w plikach dziennika dodatku Dynamo podczas wczytywania pakietu. Jeśli wszystko działa poprawnie, można zignorować to ostrzeżenie.

Korzystanie z pakietów dodatku Dynamo 3.x w dodatku Dynamo 2.x

Jest bardzo mało prawdopodobne, że pakiet utworzony dla dodatku Dynamo 3.x (przy użyciu platformy .Net8) będzie działał w dodatku Dynamo 2.x. Ponadto w przypadku pobierania w starszej wersji dodatku Dynamo pakietów przeznaczonych dla nowszych wersji również są wyświetlane ostrzeżenia.

Rozszerzenia jako pakiety

Rozszerzenia jako pakiety

Omówienie

Rozszerzenia dodatku Dynamo można wdrażać w Menedżerze pakietów, tak jak zwykłe biblioteki węzłów dodatku Dynamo. Jeśli zainstalowany pakiet zawiera rozszerzenie widoku, jest ono wczytywane podczas wykonywania wraz z wczytaniem dodatku Dynamo. Aby upewnić się, że rozszerzenie zostało poprawnie wczytane, można sprawdzić konsolę dodatku Dynamo.

Struktura pakietu

Struktura pakietu rozszerzenia jest taka sama jak zwykłego pakietu i zawiera:

Przy założeniu, że już skompilowano rozszerzenie, będzie istnieć (co najmniej) zespół .NET i plik manifestu. Zespół powinien zawierać klasę z zaimplementowanym interfejsem IViewExtension lub IExtension. Plik manifestu .XML informuje dodatek Dynamo, wystąpienie której klasy ma utworzyć w celu uruchomienia rozszerzenia. Aby Menedżer pakietów poprawnie zlokalizował rozszerzenie, plik manifestu powinien być w pełni zgodny z położeniem zespołu i nazewnictwem.

Umieść wszystkie pliki zespołu w folderze bin, a pliki manifestu w folderze extra. W tym folderze można również umieścić wszelkie dodatkowe zasoby.

Przykładowy plik manifestu .XML:

Przekazywanie

Po utworzeniu folderu zawierającego podkatalogi opisane powyżej wszystko jest gotowe do wysłania (przekazania) do Menedżera pakietów. Należy jednak pamiętać, że obecnie nie można publikować pakietów z trybu Dynamo Sandbox. Oznacza to, że należy używać dodatku Dynamo Revit. W dodatku Revit Dynamo przejdź do opcji Packages (Pakiety) => Publish New Package (Publikuj nowy pakiet). Spowoduje to wyświetlenie monitu o zalogowanie się na koncie Autodesk, z którym ma zostać skojarzony pakiet.

W tym momencie powinno być wyświetlone normalne okno publikowania pakietu, w którym należy wypełnić wszystkie wymagane pola dotyczące pakietu/rozszerzenia. Bardzo ważną dodatkową czynnością jest upewnienie się, że żaden plik zespołu nie jest oznaczony jako biblioteka węzłów. W tym celu kliknij prawym przyciskiem myszy zaimportowane pliki (folder pakietu utworzony powyżej). Zostanie wyświetlone menu kontekstowe, które umożliwia zaznaczenie (lub cofnięcie zaznaczenia) tej opcji. Żadne zespoły rozszerzenia nie powinny być zaznaczone.

Przed opublikowaniem publicznie należy zawsze opublikować lokalnie, aby upewnić się, że wszystko działa zgodnie z oczekiwaniami. Gdy to zostanie już sprawdzone, możesz wysłać pakiet w świat, wybierając opcję publikowania.

Ściąganie (pull)

Aby upewnić się, że pakiet został pomyślnie przekazany, potwierdź, że możesz wyszukać go na podstawie nazw i słów kluczowych określonych w kroku publikowania. Na koniec należy pamiętać, że do działania niektórych rozszerzeń wymagane jest ponowne uruchomienie dodatku Dynamo. Zazwyczaj te rozszerzenia wymagają określenia parametrów podczas uruchamiania dodatku Dynamo.

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>
Publikowanie pakietu
Wyszukiwanie pakietów

Używanie typów COM (międzyoperacyjnych) w pakietach dodatku Dynamo

Niektóre ogólne informacje o typach międzyoperacyjnych

Czym są typy COM? — https://learn.microsoft.com/pl-pl/windows/win32/com/the-component-object-model

Standardowym sposobem używania typów COM w języku C# jest odwoływanie się do podstawowych zespołów międzyoperacyjnych (w zasadzie dużej kolekcji interfejsów API) i dostarczanie ich z pakietem.

Alternatywą do tego jest osadzenie PIA (podstawowych zespołów międzyoperacyjnych) w zarządzanym zespole. Zasadniczo obejmuje to tylko te typy i składniki, które są rzeczywiście używane przez zarządzany zespół. Jednak to podejście wiąże się z pewnymi innymi problemami, takimi jak równoważność typów.

Ten wpis dość dobrze opisuje ten problem:

  • https://learn.microsoft.com/pl-pl/dotnet/framework/interop/type-equivalence-and-embedded-interop-types

Jak dodatek Dynamo zarządza równoważnością typów

Dodatek Dynamo deleguje równoważność typów do środowiska wykonawczego platformy .NET. Przykładem tego jest to, że 2 typy o tej samej nazwie i przestrzeni nazw pochodzące z różnych zespołów nie będą uznawane za równoważne, a dodatek Dynamo zwróci błąd podczas wczytywania zespołów powodujących konflikt. Jeśli chodzi o typy międzyoperacyjne, dodatek Dynamo sprawdzi, czy te typy międzyoperacyjne są równoważne, przy użyciu interfejsu API IsEquivalentTo

Jak uniknąć konfliktów między osadzonymi typami międzyoperacyjnymi

Niektóre pakiety są już utworzone z osadzonymi typami międzyoperacyjnymi (np. CivilConnection). Wczytanie 2 pakietów z osadzonymi zespołami międzyoperacyjnymi, które nie są uznawane za równoważne (różne wersje, jak zdefiniowano tutaj), spowoduje błąd package load error. Z tego powodu sugerujemy, aby autorzy pakietów używali dla typów międzyoperacyjnych powiązania dynamicznego (znanego również jako powiązanie późne) — rozwiązanie opisano również tutaj.

Można posłużyć się następującym przykładem:

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*/)
            {}
        }
    }
}

Kompilowanie pakietu z programu Visual Studio

Jeśli opracowujesz zespoły, które mają być publikowane jako pakiet dla dodatku Dynamo, projekt można skonfigurować tak, aby zgrupować wszystkie niezbędne zasoby i umieścić je w strukturze katalogów zgodnej z pakietem. Dzięki temu projekt zostanie szybko przetestowany jako pakiet i będzie mógł symulować środowisko użytkownika.

Jak kompilować bezpośrednio w folderze pakietu

Istnieją dwie metody kompilowania pakietu w programie Visual Studio:

  • Dodanie zdarzeń po kompilacji za pomocą okna dialogowego ustawień projektu, w których niezbędne pliki są kopiowane za pomocą polecenia xcopy lub skryptów w języku Python

  • Utworzenie zadań kopiowania plików i katalogów za pomocą obiektu docelowego kompilacji „AfterBuild” w pliku .csproj

Opcja „AfterBuild” jest metodą preferowaną w przypadku tych typów operacji (i to ją opisano w tym podręczniku), ponieważ nie jest oparta na kopiowaniu plików, które może nie być dostępne na komputerze kompilacji.

Kopiowanie plików pakietu metodą AfterBuild

Skonfiguruj strukturę katalogów w repozytorium, tak aby pliki źródłowe były oddzielone od plików pakietu. Używając analizy przypadku CustomNodeModel, umieść projekt programu Visual Studio i wszystkie skojarzone pliki w nowym folderze src. Wszystkie pakiety wygenerowane przez projekt będą zapisywane w tym folderze. Struktura folderów powinna teraz wyglądać tak:

CustomNodeModel
> src
  > CustomNodeModel
  > CustomNodeModelFunction
  > packages
  > CustomNodeModel.sln
Przenoszenie plików projektu
  1. Przenieś pliki projektu do nowego folderu src

Pliki źródłowe znajdują się już w oddzielnym folderze. Dodaj obiekt docelowy AfterBuild do pliku CustomNodeModel.csproj w programie Visual Studio. Powinno to spowodować skopiowanie potrzebnych plików do nowego folderu pakietu. Otwórz plik CustomNodeModel.csproj w edytorze tekstu (użyliśmy edytora Atom) i umieść obiekt docelowy kompilacji przed tagiem zamykającym </Project>. Ten obiekt docelowy AfterBuild spowoduje skopiowanie wszystkich plików .dll, .pbd, .xml i .config do nowego folderu bin oraz utworzenie folderów dyf i extra.

  <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>
Umieszczanie obiektu docelowego AfterBuild

Musimy upewnić się, że obiekt docelowy dodano do pliku CustomNodeModel.csproj (a nie innego pliku projektu) i że projekt nie ma żadnych istniejących ustawień po kompilacji (Post-Build).

  1. Umieść element AfterBuild przed tagiem zamykającym </Project>.

W sekcji <ItemGroup> zdefiniowano szereg zmiennych reprezentujących określone typy plików. Na przykład zmienna Dll reprezentuje wszystkie pliki w katalogu wyjściowym mające rozszerzenie .dll.

<ItemGroup>
  <Dlls Include="$(OutDir)*.dll" />
</ItemGroup>

Zadanie Copy polega na skopiowaniu wszystkich plików .dll do katalogu, a konkretnie do folderu kompilowanego pakietu.

<Copy SourceFiles="@(Dlls)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />

Pakiety dodatku Dynamo zazwyczaj zawierają foldery dyf i extra na węzły niestandardowe dodatku Dynamo i inne zasoby, takie jak obrazy. Aby utworzyć te foldery, należy użyć zadania MakeDir. To zadanie utworzy folder, jeśli on nie istnieje. Pliki można dodać do tego folderu ręcznie.

<MakeDir Directories="$(SolutionDir)..\packages\CustomNodeModel\extra" />

W przypadku kompilowania projektu folder projektu powinien teraz zawierać folder packages obok utworzonego wcześniej folderu src. W katalogu packages znajduje się folder zawierający wszystkie elementy potrzebne do utworzenia pakietu. Musimy również skopiować plik pkg.json do folderu pakietu, aby dodatek Dynamo wiedział, że ma wczytać pakiet.

Kopiowanie plików
  1. Nowy folder packages utworzony przez obiekt docelowy AfterBuild

  2. Istniejący folder src z projektem

  3. Foldery dyf i extra utworzone z obiektu docelowego AfterBuild

  4. Ręcznie skopiuj plik pkg.json.

Teraz można opublikować pakiet za pomocą Menedżera pakietów dodatku Dynamo lub bezpośrednio skopiować go do katalogu pakietu dodatku Dynamo: <user>\AppData\Roaming\Dynamo\1.3\packages.

Wykonywanie skryptów w języku Python w węzłach Zero-Touch (C#)

Wykonywanie skryptów w języku Python w węzłach Zero-Touch (C#)

Jeśli użytkownik potrafi pisać skrypty w języku Python i chce uzupełnić węzły standardowe dodatku w języku Python Dynamo o więcej funkcji, może utworzyć własny za pomocą funkcji Zero-Touch. Zacznijmy od prostego przykładu umożliwiającego przekazanie skryptu w języku Python jako ciągu do węzła Zero-Touch, w którym wykonywany jest skrypt i zwracany jest wynik. Ta analiza przypadku jest oparta na przewodnikach i przykładach z sekcji „Pierwsze kroki”. Użytkownicy dopiero zaczynający tworzenie węzłów Zero-Touch powinni się z nimi zapoznać.

Węzeł Zero-Touch wykonujący ciąg skryptu w języku Python

Węzeł Zero-Touch wykonujący ciąg skryptu w języku Python

Silnik języka Python

Ten węzeł bazuje na wystąpieniu silnika skryptów IronPython. Aby to obsłużyć, należy utworzyć odwołanie do kilku dodatkowych zespołów. Wykonaj poniższe czynności, aby skonfigurować szablon podstawowy w programie Visual Studio:

  • Tworzenie nowego projektu klasy programu Visual Studio

  • Dodaj odwołanie do pliku IronPython.dll znajdującego się tutaj: C:\Program Files (x86)\IronPython 2.7\IronPython.dll

  • Dodaj odwołanie do pliku Microsoft.Scripting.dll znajdującego się tutaj: C:\Program Files (x86)\IronPython 2.7\Platforms\Net40\Microsoft.Scripting.dll

  • Dołącz do tej klasy instrukcje IronPython.Hosting i Microsoft.Scripting.Hosting using

  • Dodaj pusty konstruktor prywatny, aby zapobiec dodaniu dodatkowego węzła do biblioteki Dynamo wraz z pakietem

  • Utwórz nową metodę, która przyjmuje pojedynczy ciąg jako parametr wejściowy

  • W ramach tej metody utworzymy wystąpienie nowego silnika języka Python i utworzymy pusty zakres skryptu. Ten zakres można sobie wyobrazić jako zmienne globalne w wystąpieniu interpretera języka Python

  • Następnie wywołaj operację Execute dla silnika, przekazując ciąg wejściowy i zakres jako parametry

  • Na koniec pobierz i zwróć wyniki skryptu, wywołując operację GetVariable dla zakresu i przekazując nazwę zmiennej ze skryptu w języku Python zawierającą wartość, którą próbujesz zwrócić. (Więcej informacji znajduje się w poniższym przykładzie)

Poniższy kod stanowi przykład kroku opisanego powyżej. Skompilowanie rozwiązania spowoduje utworzenie nowego pliku .dll znajdującego się w folderze bin projektu. Ten plik .dll można teraz zaimportować do dodatku Dynamo jako część pakietu lub przechodząc do polecenia File < Import Library...

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);
        }
    }
}

Skrypt w języku Python zwraca zmienną output, co oznacza, że w skrypcie w języku Python będzie potrzebna zmienna output. Użyj tego skryptu przykładowego, aby przetestować węzeł w dodatku Dynamo. Jeśli ten węzeł języka Python był kiedykolwiek używany w dodatku Dynamo, poniższe czynności powinny wyglądać znajomo. Aby uzyskać więcej informacji, zobacz sekcję dotyczącą języka Python w przewodniku.

import clr
clr.AddReference('ProtoGeometry')
from Autodesk.DesignScript.Geometry import *

cube = Cuboid.ByLengths(10,10,10);
volume = cube.Volume
output = str(volume)

Wiele pozycji danych wyjściowych

Jednym z ograniczeń standardowych węzłów języka Python jest to, że mają one tylko jeden port wyjściowy. Jeśli więc chcemy zwrócić wiele obiektów, musimy utworzyć listę i umieścić na niej poszczególne obiekty. Jeśli zmodyfikujemy powyższy przykład tak, aby zwracał słownik, możemy dodać dowolną liczbę portów wyjściowych. Więcej informacji na temat słowników znajduje się w temacie „Dalsze kroki z Zero-Touch” w sekcji dotyczącej zwracania wielu wartości.

Ten węzeł umożliwia zwrócenie zarówno objętości prostopadłościanu, jak i jego centroidy.

Ten węzeł umożliwia zwrócenie zarówno objętości prostopadłościanu, jak i jego centroidy.

Zmodyfikujmy poprzedni przykład, wykonując następujące czynności:

  • Dodaj odwołanie do pliku DynamoServices.dll z Menedżera pakietów NuGet

  • Oprócz poprzednich zespołów dołącz zespoły System.Collections.Generic i Autodesk.DesignScript.Runtime

  • Zmień typ zwracany w metodzie, aby zwracać słownik, który będzie zawierał dane wyjściowe

  • Każda pozycja wyjściowa musi zostać osobno pobrana z zakresu (dla większych zestawów danych wyjściowych rozważ skonfigurowanie prostej pętli)

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) }
            };
        }
    }
}

Do tego przykładowego skryptu w języku Python dodaliśmy również dodatkową zmienną wyjściową (output2). Należy pamiętać, że te zmienne mogą używać dowolnych konwencji nazewnictwa języka Python, dlatego określenia „output” (dane wyjściowe) użyto wyłącznie w celu zachowania przejrzystości w tym przykładzie.

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)

Publikowanie pakietu

Publikowanie pakietu

Pakiety to wygodny sposób przechowywania węzłów i udostępniania ich społeczności dodatku Dynamo. Pakiet może zawierać wszystko, od węzłów niestandardowych utworzonych w obszarze roboczym dodatku Dynamo po węzły pochodne od klasy NodeModel. Pakiety publikuje się i instaluje za pomocą Menedżera pakietów. Oprócz tej strony, także przewodnik Primer zawiera ogólne wskazówki dotyczące pakietów.

Czym jest Menedżer pakietów?

Menedżer pakietów dodatku Dynamo to rejestr oprogramowania (podobny do programu npm), do którego można uzyskać dostęp z poziomu dodatku Dynamo lub w przeglądarce internetowej. Menedżer pakietów umożliwia instalowanie, publikowanie, aktualizowanie i przeglądanie pakietów. Podobnie jak w przypadku programu npm, obsługuje on różne wersje pakietów. Pomaga również w zarządzaniu zależnościami projektu.

W przeglądarce wyszukaj pakiety i wyświetl statystyki: https://dynamopackages.com/

  • W dodatku Dynamo Menedżer pakietów umożliwia instalowanie, publikowanie i aktualizowanie pakietów.

Wyszukiwanie pakietów
  1. Wyszukaj pakiety online: Packages > Search for a Package...

  2. Wyświetl/edytuj zainstalowane pakiety: Packages > Manage Packages...

  3. Opublikuj nowy pakiet: Packages > Publish New Package...

Publikowanie pakietu

Pakiety publikuje się z poziomu Menedżera pakietów w dodatku Dynamo. Zalecanym procesem jest opublikowanie pakietu lokalnie, przetestowanie go, a następnie opublikowanie go online w celu udostępnienia go społeczności. Korzystając z analizy przypadku NodeModel, wykonamy czynności niezbędne do opublikowania węzła RectangularGrid jako pakietu lokalnie, a następnie w trybie online.

Uruchom dodatek Dynamo i wybierz opcję Packages > Publish New Package..., aby otworzyć okno Publish a Package.

Publikowanie pakietu
  1. Wybierz opcję Add file..., aby wyszukać pliki, które mają zostać dodane do pakietu

  2. Wybierz dwa pliki .dll z analizy przypadku NodeModel

  3. Wybierz przycisk Ok

Po dodaniu plików do zawartości pakietu nadaj pakietowi nazwę oraz dodaj do niego opis i wersję. Opublikowanie pakietu przy użyciu dodatku Dynamo powoduje automatyczne utworzenie pliku pkg.json.

Ustawienia pakietu

Pakiet gotowy do opublikowania.

  1. Podaj wymagane informacje dotyczące nazwy, opisu i wersji.

  2. Opublikuj, klikając opcję „Opublikuj lokalnie” i wybierając folder pakietu dodatku Dynamo: AppData\Roaming\Dynamo\Dynamo Core\1.3\packages, aby węzeł był dostępny w składniku Core. Dopóki pakiet nie będzie gotowy do udostępnienia, zawsze publikuj lokalnie.

Po opublikowaniu pakietu węzły będą dostępne w bibliotece dodatku Dynamo w kategorii CustomNodeModel.

Pakiet w bibliotece dodatku Dynamo
  1. Właśnie utworzony pakiet w bibliotece dodatku Dynamo

Gdy pakiet będzie gotowy do opublikowania w trybie online, otwórz Menedżera pakietów i wybierz opcję Publish, a następnie opcję Publish Online.

Publikowanie pakietu w Menedżerze pakietów
  1. Aby sprawdzić, jak dodatek Dynamo sformatował pakiet, kliknij pionowy trzykropek po prawej stronie pozycji „CustomNodeModel” i wybierz opcję „Pokaż katalog główny”.

  2. Wybierz opcję Publish, a następnie opcję Publish Online w oknie „Publikowanie pakietów Dynamo”.

  3. Aby usunąć pakiet, wybierz opcję Delete.

Jak mogę zaktualizować pakiet?

Aktualizowanie pakietu jest procesem podobnym do publikowania. Otwórz Menedżera pakietów i wybierz opcję Publish Version... dla pakietu wymagającego aktualizacji, a następnie wprowadź nowszą wersję.

Publikowanie wersji pakietu
  1. Wybierz opcję Publish Version, aby zaktualizować istniejący pakiet o nowe pliki w katalogu głównym, a następnie określ, czy ma on zostać opublikowany lokalnie, czy online.

Klient internetowy Menedżera pakietów

Klient internetowy Menadżera pakietów umożliwia użytkownikom wyszukiwanie i wyświetlanie danych pakietów, w tym przechowywania wersji, statystyk pobierania i innych istotnych informacji. Ponadto autorzy pakietów mogą się logować, aby aktualizować szczegóły pakietu, takie jak informacje o zgodności, bezpośrednio za pomocą klienta internetowego.

Aby uzyskać więcej informacji na temat tych funkcji, zobacz wpis w blogu tutaj: https://dynamobim.org/discover-the-new-dynamo-package-management-experience/.

Dostęp do klienta internetowego Menedżera pakietów można uzyskać za pomocą tego linku: https://dynamopackages.com/

Klient internetowy Menedżera pakietów

Aktualizowanie szczegółów pakietu

Autorzy mogą edytować opis pakietu, link do witryny internetowej i link do repozytorium, wykonując następujące kroki:

  1. W obszarze Moje pakiety wybierz pakiet i kliknij opcję Edytuj szczegóły pakietu.

  2. Dodaj lub zmodyfikuj łącza Witryna i Repozytorium przy użyciu odpowiednich pól.

  3. Zaktualizuj pole Opis pakietu zgodnie z potrzebami.

  4. Kliknij przycisk Zapisz zmiany, aby zastosować aktualizacje.

Uwaga: odświeżenie w celu uwzględnienia aktualizacji w Menedżerze pakietów w dodatku Dynamo może potrwać do 15 minut, ponieważ zastosowanie aktualizacji serwera może zająć trochę czasu. Podejmowane są działania mające na celu zmniejszenie tego opóźnienia.

Nowy interfejs użytkownika umożliwiający aktualizację szczegółów pakietów dla opublikowanych pakietów

Edytowanie informacji o zgodności dotyczących opublikowanych wersji pakietu

Informacje o zgodności można aktualizować wstecz dla opublikowanych wcześniej wersji pakietów. Wykonaj następujące czynności:

Edycja informacji o zgodności dotyczących opublikowanych pakietów — krok 1

Krok 1:

  1. Kliknij wersję pakietu, którą chcesz zaktualizować.

  2. Lista Zależy od zostanie automatycznie wypełniona pakietami, od których zależy pakiet.

  3. Kliknij ikonę ołówka obok pozycji Zgodność, aby otworzyć proces Edycja informacji o zgodności.

Krok 2:

Postępuj zgodnie z poniższym schematem blokowym i zapoznaj się z poniższą tabelą, aby zrozumieć, która opcja najlepiej pasuje do Twojego pakietu.

Którą opcję wybrać dla procesu „Edycja informacji o zgodności”

Przeanalizujmy kilka przykładów, aby omówić niektóre scenariusze:

Pakiet przykładowy nr 1 — Civil Connection: ten pakiet ma zależności interfejsu API dotyczące zarówno programu Revit, jak i programu Civil 3D. Ponadto nie zawiera kolekcji węzłów podstawowych (np. funkcji geometrii, funkcji matematycznych ani zarządzania listami). Tak więc w tym przypadku idealnym rozwiązaniem byłoby skorzystanie z opcji 1. Pakiet będzie wyświetlany jako zgodny w programach Revit i Civil 3D zgodnych z zakresem wersji i/lub listą poszczególnych wersji.

Pakiet przykładowy nr 2 — Rhythm: ten pakiet to kolekcja węzłów charakterystycznych dla programu Revit wraz z kolekcją węzłów podstawowych. W tym przypadku pakiet ma zależności od oprogramowania nadrzędnego. Ale zawiera również węzły podstawowe, które będą działać w dodatku Dynamo Core. Tak więc w tym przypadku idealnym rozwiązaniem byłaby opcja 2. Pakiet będzie wyświetlany jako zgodny w programie Revit i dodatku Dynamo Core (nazywanym również Dynamo Sandbox), które są zgodne z zakresem wersji i/lub listą poszczególnych wersji.

Pakiet przykładowy nr 3 — Mesh Toolkit: ten pakiet jest pakietem Dynamo Core stanowiącym kolekcję węzłów geometrii, która nie ma zależności od oprogramowania nadrzędnego. Tak więc w tym przypadku idealnym rozwiązaniem byłaby opcja 3. Pakiet będzie wyświetlany jako zgodny w dodatku Dynamo i wszystkich środowiskach nadrzędnych zgodnych z zakresem wersji i/lub listą poszczególnych wersji.

Opcje edycji informacji o zgodności

W zależności od wybranej opcji zostaną wyświetlone pola specyficzne dla dodatku Dynamo i/lub programu nadrzędnego, jak pokazano na poniższej ilustracji.

Edycja informacji o zgodności — krok 2

Analiza przypadku Zero-Touch — węzeł siatki

Mamy już działający projekt programu Visual Studio, więc teraz omówimy tworzenie węzła niestandardowego, który tworzy prostokątną siatkę komórek. Mimo że można ją utworzyć za pomocą kilku węzłów standardowych, jest to przydatne narzędzie, które można łatwo umieścić w węźle Zero-Touch. Inaczej niż w przypadku linii siatki komórki można skalować względem punktów środkowych, można sprawdzać ich wierzchołki narożnikowe i można wbudowywać je w powierzchnie.

W tym przykładzie omówiono kilka funkcji i pojęć, które należy uwzględnić podczas tworzenia węzła Zero-Touch. Po utworzeniu węzła niestandardowego i dodaniu go do dodatku Dynamo należy przejrzeć stronę „Dalsze kroki z Zero-Touch”, aby uzyskać więcej informacji na temat domyślnych wartości wejściowych, zwracania wielu wartości, dokumentacji, obiektów, używania typów geometrii dodatku Dynamo i migracji.

Węzeł niestandardowy siatki prostokątnej

Aby rozpocząć kompilowanie węzła siatki, utwórz nowy projekt biblioteki klas programu Visual Studio. Na stronie „Pierwsze kroki” można znaleźć szczegółowe omówienie sposobu konfigurowania projektu.

  1. Jako typ projektu wybierz Class Library

  2. Nadaj projektowi nazwę CustomNodes

Ponieważ będziemy tworzyć geometrię, musimy odwołać się do odpowiedniego pakietu NuGet. Zainstaluj pakiet ZeroTouchLibrary za pomocą Menedżera pakietów NuGet. Ten pakiet jest niezbędny dla instrukcji using Autodesk.DesignScript.Geometry;.

  1. Odszukaj pakiet ZeroTouchLibrary

  2. Użyjemy tego węzła w bieżącej kompilacji programu Dynamo Studio, czyli 1.3. Wybierz wersję pakietu zgodną z tą wersją.

  3. Zwróć uwagę, że zmieniliśmy również nazwę pliku klasy na Grids.cs

Następnie należy ustanowić przestrzeń nazw i klasę, w których będzie istnieć metoda RectangularGrid. Węzeł zostanie nazwany w dodatku Dynamo zgodnie z nazwami metody i klasy. Nie musimy tego jeszcze kopiować do programu Visual Studio.

Część Autodesk.DesignScript.Geometry; odwołuje się do pliku ProtoGeometry.dll w pakiecie ZeroTouchLibrary System.Collections.Generic, który jest niezbędny do tworzenia list

Teraz możemy dodać metodę rysowania prostokątów. Plik klasy powinien wyglądać następująco i można go skopiować do programu Visual Studio.

Jeśli projekt wygląda podobnie do tego, spróbuj skompilować plik .dll.

  1. Wybierz polecenie Build (Kompiluj) > Build Solution (Kompiluj rozwiązanie)

Sprawdź, czy w folderze bin projektu znajduje się plik .dll. Jeśli kompilacja się powiodła, można dodać plik .dll do dodatku Dynamo.

  1. Węzeł niestandardowy RectangularGrids w bibliotece Dynamo

  2. Węzeł niestandardowy w obszarze rysunku

  3. Przycisk Add (Dodaj) umożliwiający dodanie pliku .dll do dodatku Dynamo

Modyfikacje węzłów niestandardowych

W powyższym przykładzie utworzyliśmy dość prosty węzeł, który nie definiował wiele więcej oprócz metody RectangularGrids. Jednak może być konieczne utworzenie etykiet narzędzi dla portów wejściowych lub nadanie węzłowi podsumowania, jak w przypadku standardowych węzłów Dynamo. Dodanie tych elementów do węzłów niestandardowych ułatwia korzystanie z nich, zwłaszcza jeśli użytkownik chce wyszukiwać je w bibliotece.

  1. Domyślna wartość wejściowa

  2. Etykieta narzędzia dla danych wejściowych xCount

Węzeł RectangularGrid wymaga niektórych z tych podstawowych funkcji. W poniższym kodzie dodaliśmy opisy portów wejściowych i wyjściowych, podsumowanie oraz domyślne wartości wejściowe.

  • Nadaj wartości domyślne danym wejściowym, przypisując wartości parametrom metody: RectangularGrid(int xCount = 10, int yCount = 10)

  • Utwórz etykiety narzędzi dla portów wejściowych i wyjściowych, słowa kluczowe wyszukiwania i podsumowanie za pomocą dokumentacji XML poprzedzonej znakiem ///.

Aby dodać etykiety narzędzi, potrzebujemy pliku xml w katalogu projektu. Plik .xml może zostać automatycznie wygenerowany przez program Visual Studio.

  1. Włącz plik dokumentacji XML tutaj i określ ścieżkę pliku. Spowoduje to wygenerowanie pliku XML.

Gotowe! Utworzyliśmy nowy węzeł z kilkoma standardowymi elementami. W kolejnym rozdziale dotyczącym podstaw Zero-Touch podano więcej szczegółów na temat opracowywania węzłów Zero-Touch i problemów, o których należy pamiętać.

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;
        }
    }
}
Wykres siatki prostokątnej
Tworzenie nowego projektu w programu Visual Studio
Konfigurowanie nowego projektu w programie Visual Studio
Pakiet ZeroTouchLibrary
Kompilowanie biblioteki DLL
Węzły niestandardowe w dodatku Dynamo
Etykieta narzędzia dla portu wejściowego
Włączanie dokumentacji XML

Opracowywanie rozwiązań dla dodatku Dynamo dla programu Revit

Korzystanie z metod w pliku GeometryPrimitiveConverter.cs

Klasa GeometryPrimitiveConverter w bibliotece kodu dodatku DynamoRevit udostępnia różne metody konwersji typów geometrii między programem Revit i dodatkiem Dynamo. Te metody są przydatne podczas pracy z geometrią w skryptach dodatku Dynamo, które wchodzą w interakcje z modelami programu Revit.

Kategorie metod

Metody w pliku GeometryPrimitiveConverter.cs można podzielić na cztery główne kategorie:

  1. Z typów Proto na typy programu Revit: metody, które konwertują typy dodatku Dynamo (Proto) na typy programu Revit.

  2. Z typów programu Revit na typy Proto: metody, które konwertują typy programu Revit na typy dodatku Dynamo (Proto).

  3. Stopnie i radiany: metody konwersji między stopniami i radianami.

  4. X i UZ: metody do pobierania wektorów prostopadłych.

Z typów Proto na typy programu Revit

ToRevitBoundingBox

Tworzy obiekt BoundingBoxXYZ programu Revit na podstawie układu współrzędnych dodatku Dynamo i dwóch punktów definiujących (minimalnego i maksymalnego).

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)

ToRevitType (BoundingBox)

Konwertuje obiekt BoundingBox dodatku Dynamo na obiekt BoundingBoxXYZ programu Revit.

Flaga convertUnits, z wartością domyślną true (prawda), określa, czy współrzędne powinny zostać przekonwertowane z układu jednostek dodatku Dynamo na jednostki wewnętrzne programu Revit.

public static Autodesk.Revit.DB.BoundingBoxXYZ ToRevitType(this Autodesk.DesignScript.Geometry.BoundingBox bb, bool convertUnits = true)

ToRevitType (Point)

Konwertuje punkt dodatku Dynamo na zestaw współrzędnych XYZ programu Revit.

Flaga convertUnits, z wartością domyślną true (prawda), konwertuje współrzędne, jeśli jest to konieczne.

public static Autodesk.Revit.DB.XYZ ToRevitType(this Autodesk.DesignScript.Geometry.Point pt, bool convertUnits = true)

ToRevitType (Vector)

Konwertuje wektor dodatku Dynamo na wektor XYZ programu Revit.

Zwróć uwagę, że flaga convertUnits ma domyślnie ustawioną wartość false (fałsz), ponieważ wektory reprezentują kierunek i moduł, które zazwyczaj nie wymagają konwersji jednostek. Konwersja może wpłynąć na kierunek i długość wektora.

public static Autodesk.Revit.DB.XYZ ToRevitType(this Vector vec, bool convertUnits = false)

ToXyz (Point)

Konwertuje punkt dodatku Dynamo na zestaw współrzędnych XYZ programu Revit.

public static Autodesk.Revit.DB.XYZ ToXyz(this Autodesk.DesignScript.Geometry.Point pt, bool convertUnits = true)

ToXyz (Vector)

Konwertuje wektor dodatku Dynamo na wektor XYZ programu Revit.

Zwróć uwagę, że flaga convertUnits ma domyślnie ustawioną wartość false (fałsz), ponieważ wektory reprezentują kierunek i moduł, które zazwyczaj nie wymagają konwersji jednostek. Konwersja może wpłynąć na kierunek i długość wektora.

public static Autodesk.Revit.DB.XYZ ToXyz(this Vector vec, bool convertUnits = false)

ToTransform

Konwertuje układ CoordinateSystem dodatku Dynamo na przekształcenie programu Revit.

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

ToPlane

Konwertuje płaszczyznę dodatku Dynamo na płaszczyznę programu Revit.

public static Autodesk.Revit.DB.Plane ToPlane(this Autodesk.DesignScript.Geometry.Plane plane, bool convertUnits = true)

ToXyzs (Points)

Konwertuje kolekcje obiektów punktów Dynamo na kolekcje zestawów współrzędnych XYZ programu Revit.

Zwraca listę zestawów współrzędnych XYZ. public static List<XYZ> ToXyzs(this List<Autodesk.DesignScript.Geometry.Point> list, bool convertUnits = true)

Zwraca szyk zestawów współrzędnych XYZ. public static XYZ[] ToXyzs(this Autodesk.DesignScript.Geometry.Point[] list, bool convertUnits = true)

ToXyzs (Vectors)

Konwertuje szyk obiektów wektorów dodatku Dynamo na szyk wektorów XYZ programu Revit.

public static XYZ[] ToXyzs(this Autodesk.DesignScript.Geometry.Vector[] list, bool convertUnits = false)

ToDoubleArray

Konwertuje szyk wartości double na szyk DoubleArray programu Revit.

public static DoubleArray ToDoubleArray(this double[] list)

ToUvs

Konwertuje szyk dwuwymiarowy (double[][]), w którym każdy szyk wewnętrzny reprezentuje parę wartości (U i V), na szyk obiektów UV programu Revit.

internal static Autodesk.Revit.DB.UV[] ToUvs(this double[][] uvArr)

ToDSUvs

Konwertuje szyk dwuwymiarowy (double[][]), w którym każdy szyk wewnętrzny reprezentuje parę wartości (U i V), na szyk obiektów UV dodatku Dynamo.

internal static Autodesk.DesignScript.Geometry.UV[] ToDSUvs(this double[][] uvArr)

Przykład konwersji typów Proto na typy programu Revit

W tym przykładzie pokazano szybkie i łatwe użycie metody .ToXyz (Point) do przekonwertowania punktu Point.ByCoordinates dodatku Dynamo na zestaw współrzędnych XYZ programu Revit.

Konwertowanie punktu Point.ByCoordinates dodatku Dynamo na zestaw współrzędnych XYZ programu Revit
# 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

Z typów programu Revit na typy Proto

ToProtoType (BoundingBox)

Konwertuje obiekt BoundingBoxXYZ programu Revit na obiekt BoundingBox dodatku Dynamo.

public static Autodesk.DesignScript.Geometry.BoundingBox ToProtoType(this Autodesk.Revit.DB.BoundingBoxXYZ xyz, bool convertUnits = true)

ToPoint (XYZ)

Konwertuje zestaw współrzędnych XYZ programu Revit na punkt dodatku Dynamo.

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

ToProtoType (Point)

Konwertuje punkt programu Revit na punkt dodatku Dynamo.

public static Autodesk.DesignScript.Geometry.Point ToProtoType(this Autodesk.Revit.DB.Point point, bool convertUnits = true)

ToVector (XYZ)

Konwertuje zestaw współrzędnych XYZ programu Revit na wektor dodatku Dynamo.

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

ToProtoType (UV)

Konwertuje zestaw współrzędnych UV programu Revit na zestaw współrzędnych UV dodatku Dynamo.

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

ToPlane (Revit Plane)

Konwertuje płaszczyznę programu Revit na płaszczyznę dodatku Dynamo.

public static Autodesk.DesignScript.Geometry.Plane ToPlane(this Autodesk.Revit.DB.Plane plane, bool convertUnits = true)

ToCoordinateSystem

Konwertuje przekształcenie programu Revit na układ CoordinateSystem dodatku Dynamo.

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

ToPoints

Konwertuje listę punktów XYZ programu Revit na listę punktów dodatku Dynamo.

public static List<Autodesk.DesignScript.Geometry.Point> ToPoints(this List<XYZ> list, bool convertUnits = true)

Przykład konwersji typów programu Revit na typy Proto

W tym przykładzie pokazano szybkie i łatwe użycie metody .ToPoint (XYZ) do przekonwertowania zestawu współrzędnych XYZ programu Revit na punkt dodatku Dynamo.

Konwertowanie zestawu współrzędnych XYZ programu Revit na punkt Point.ByCoordinates dodatku Dynamo
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

Stopnie i radiany

ToRadians

Konwertuje stopnie na radiany.

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

ToDegrees

Konwertuje radiany na stopnie.

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

Przykładowe użycie stopni i radianów

W tym przykładzie pokazano szybkie i łatwe użycie metody .ToRadians do przekonwertowania stopni na radiany.

Ze stopni na radiany
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

X i UZ

GetPerpendicular (XYZ)

Ta metoda zwraca wektor XYZ prostopadły do danego wektora XYZ.

public static XYZ GetPerpendicular(this XYZ xyz)

GetPerpendicular (Vector)

Ta metoda zwraca wektor Vector dodatku Dynamo prostopadły do danego wektora Vector dodatku Dynamo.

public static Vector GetPerpendicular(this Vector vector)

Przykładowe użycie metod X i UZ

W tym przykładzie pokazano szybkie i łatwe użycie metody .GetPerpendicular do wygenerowania wektora prostopadłego do wektora wejściowego.

Pobieranie wektora prostopadłego
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

Rozszerzenia

Rozszerzenia są zaawansowanym narzędziem programistycznym w ekosystemie dodatku Dynamo. Umożliwiają programistom sterowanie funkcjami niestandardowymi opartymi na interakcjach i logice dodatku Dynamo. Rozszerzenia można podzielić na dwie główne kategorie, rozszerzenia i rozszerzenia widoku. Jak sugeruje nazwa, struktura rozszerzeń widoku umożliwia rozszerzenie interfejsu użytkownika dodatku Dynamo przez zarejestrowanie niestandardowych elementów menu. Zwykłe rozszerzenia działają w bardzo podobny sposób, ale bez interfejsu użytkownika. Przykładowo można utworzyć rozszerzenie rejestrujące określone informacje w konsoli dodatku Dynamo. Ten scenariusz nie wymaga niestandardowego interfejsu użytkownika i dlatego można go zrealizować również za pomocą rozszerzenia.

Analiza przypadku rozszerzenia

Korzystając z przykładu SampleViewExtension z repozytorium DynamoSamples z serwisu Github, przeanalizujemy czynności niezbędne do utworzenia prostego okna niemodalnego, w którym wyświetlane są aktywne węzły na wykresie w czasie rzeczywistym. Rozszerzenie widoku wymaga utworzenia interfejsu użytkownika dla tego okna i powiązania wartości z modelem widoku.

Okno rozszerzenia widoku
  1. To okno rozszerzenia widoku opracowano na podstawie przykładu SampleViewExtension z repozytorium Github.

Mimo że utworzymy tu ten przykład od podstaw, można również pobrać i skompilować repozytorium DynamoSamples, a następnie używać go jako odniesienia.

Repozytorium DynamoSamples: https://github.com/DynamoDS/DynamoSamples

W tym przewodniku będziemy odwoływać się konkretnie do projektu o nazwie SampleViewExtension znajdującego się w folderze DynamoSamples/src/.

Jak zaimplementować rozszerzenie widoku

Rozszerzenie widoku zawiera trzy zasadnicze części:

  • Zespół zawierający klasę z zaimplementowanym interfejsem IViewExtension oraz klasę tworzącą model widoku

  • Plik .xml informujący dodatek Dynamo, gdzie należy szukać tego zespołu w czasie wykonywania oraz jaki jest typ rozszerzenia

  • Plik .xaml, który wiąże dane z wyświetlaniem grafiki i określa wygląd okna

1. Tworzenie struktury projektu

Rozpocznij od utworzenia nowego projektu Class Library o nazwie SampleViewExtension.

Tworzenie nowej biblioteki klas
Konfigurowanie nowego projektu
  1. Utwórz nowy projekt, wybierając opcję File > New > Project

  2. Wybierz opcję Class Library

  3. Nadaj projektowi nazwę SampleViewExtension

  4. Wybierz przycisk Ok

W tym projekcie będą potrzebne dwie klasy. W jednej klasie zostanie zaimplementowany interfejs IViewExtension, a w drugiej — klasa NotificationObject. Interfejs IViewExtension będzie zawierać wszystkie informacje o sposobie wdrażania, wczytywania, i usuwania rozszerzenia oraz odwoływania się do niego. Klasa NotificationObject będzie udostępniać powiadomienia o zmianach w dodatku Dynamo i interfejsie IDisposable. Po wprowadzeniu zmiany liczba zostanie odpowiednio zaktualizowana.

Wyświetlanie plików klas rozszerzeń
  1. Plik klasy o nazwie SampleViewExtension.cs, w której zostanie zaimplementowany interfejs IViewExtension

  2. Plik klasy o nazwie SampleWindowViewMode.cs, w której zostanie zaimplementowana klasa NotificationObject

Aby można było użyć interfejsu IViewExtension, potrzebny jest pakiet NuGet WpfUILibrary. Zainstalowanie tego pakietu spowoduje automatyczne zainstalowanie pakietów Core, Services i ZeroTouchLibrary.

Wyświetlanie pakietów rozszerzeń
  1. Wybierz pakiet WpfUILibrary

  2. Wybierz opcję Install, aby zainstalować wszystkie pakiety zależne

2. Implementowanie klasy IViewExtension

W klasie IViewExtension określimy, co się dzieje podczas uruchamiania dodatku Dynamo, gdy rozszerzenie jest wczytywane i gdy dodatek Dynamo zostaje zamknięty. W pliku klasy SampleViewExtension.cs dodaj następujący kod:

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";
            }
        } 

    }
}

Klasa SampleViewExtension tworzy element menu, który można kliknąć, służący do otwierania okna, i łączy go z oknem i modelem widoku.

  • Instrukcja public class SampleViewExtension : IViewExtension SampleViewExtension powoduje dziedziczenie po interfejsie IViewExtension i udostępnia wszystkie funkcje potrzebne do utworzenia elementu menu.

  • Instrukcja sampleMenuItem = new MenuItem { Header = "Show View Extension Sample Window" }; tworzy element MenuItem i dodaje go do menu View.

Element menu
  1. Element menu

  • Instrukcja sampleMenuItem.Click += (sender, args) wyzwala zdarzenie, które powoduje otwarcie nowego okna po kliknięciu elementu menu

  • Instrukcja MainGrid = { DataContext = viewModel } ustawia kontekst danych dla siatki głównej w oknie, odwołując się do elementu Main Grid w pliku .xaml, który zostanie utworzony

  • Instrukcja Owner = p.DynamoWindow ustawia dodatek Dynamo jako właściciela wyskakującego okna. Oznacza to, że nowe okno jest zależne od dodatku Dynamo, więc takie operacje jak zminimalizowanie, zmaksymalizowanie i przywrócenie dodatku Dynamo spowodują, że nowe okno będzie działało tak samo

  • Metoda window.Show(); wyświetla okno, w którym ustawiono dodatkowe właściwości okna

3. Implementowanie modelu widoku

Po ustaleniu niektórych podstawowych parametrów okna dodamy logikę reagowania na różne zdarzenia związane z dodatkiem Dynamo i poinstruujemy interfejs użytkownika, aby dokonał aktualizacji na podstawie tych zdarzeń. Skopiuj następujący kod do pliku klasy SampleWindowViewModel.cs:

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;
        }
    }
}

Ta implementacja klasy modelu widoku nasłuchuje elementu CurrentWorkspaceModel i wyzwala zdarzenie w przypadku dodania lub usunięcia węzła z obszaru roboczego. Powoduje to zgłoszenie zmiany właściwości i powiadomienie interfejsu użytkownika lub powiązanych elementów o zmianie danych i konieczności ich zaktualizowania. Wywoływany jest mechanizm pobierania ActiveNodeTypes, który wewnętrznie wywołuje dodatkową funkcję pomocniczą getNodeTypes(). Ta funkcja iteruje przez wszystkie aktywne węzły w obszarze rysunku, wypełnia ciąg zawierający nazwy tych węzłów i zwraca ten ciąg do powiązania w pliku .xaml do wyświetlenia w wyskakującym oknie.

Po zdefiniowaniu logiki podstawowej rozszerzenia określimy teraz szczegóły wyglądu okna za pomocą pliku .xaml. Wystarczy proste okno, w którym ten ciąg będzie wyświetlany za pomocą powiązania właściwości ActiveNodeTypes w kontrolce TextBlock Text.

Dodawanie okna
  1. Kliknij prawym przyciskiem myszy projekt i wybierz pozycję Add > New Item...

  2. Wybierz szablon kontroli użytkownika, który zmienimy w celu utworzenia okna

  3. Nadaj nowemu plikowi nazwę SampleWindow.xaml

  4. Wybierz opcję Add

W kodzie .xaml okna należy powiązać element SelectedNodesText z blokiem tekstowym. Dodaj następujący kod do pliku SampleWindow.xaml:

<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>
  • Instrukcja Text="{Binding ActiveNodeTypes}" wiąże wartość właściwości ActiveNodeTypes w pliku SampleWindowViewModel.cs z wartością Text elementu TextBlock w oknie.

Teraz zainicjujemy okno przykładowe w pliku zaplecza pliku C# .xaml: SampleWindow.xaml.cs. Dodaj następujący kod do pliku SampleWindow.xaml:

using System.Windows;

namespace SampleViewExtension
{
    /// <summary>
    /// Interaction logic for SampleWindow.xaml
    /// </summary>
    public partial class SampleWindow : Window
    {
        public SampleWindow()
        {
            InitializeComponent();
        }
    }
}

Rozszerzenie widoku jest teraz gotowe do skompilowania i dodania do dodatku Dynamo. Dodatek Dynamo wymaga pliku xml, aby zarejestrować wynikowy plik .dll jako rozszerzenie.

Dodawanie nowego pliku XML
  1. Kliknij prawym przyciskiem myszy projekt i wybierz pozycję Add > New Item...

  2. Wybierz plik XML

  3. Nadaj plikowi nazwę SampleViewExtension_ViewExtensionDefinition.xml

  4. Wybierz opcję Add

  • Ta nazwa pliku jest zgodna ze standardem dodatku Dynamo dotyczącego odwoływania się do zespołu rozszerzenia: "extensionName"_ViewExtensionDefinition.xml

W pliku xml dodaj następujący kod, aby wskazać dodatkowi Dynamo, gdzie ma szukać zespołu rozszerzenia:

<ViewExtensionDefinition>
  <AssemblyPath>C:\Users\username\Documents\Visual Studio 2015\Projects\SampleViewExtension\SampleViewExtension\bin\Debug\SampleViewExtension.dll</AssemblyPath>
  <TypeName>SampleViewExtension.SampleViewExtension</TypeName>
</ViewExtensionDefinition>
  • W tym przykładzie skompilowaliśmy zespół w domyślnym folderze projektu programu Visual Studio. Zastąp położenie docelowe <AssemblyPath>...</AssemblyPath> położeniem zespołu.

Ostatnią czynnością jest skopiowanie pliku SampleViewExtension_ViewExtensionDefinition.xml do folderu rozszerzeń widoku dodatku Dynamo znajdującego się w katalogu instalacyjnym Dynamo Core C:\Program Files\Dynamo\Dynamo Core\1.3\viewExtensions. Należy pamiętać, że istnieją oddzielne foldery dla rozszerzeń extensions i viewExtensions. Umieszczenie pliku xml w niewłaściwym folderze może spowodować błąd podczas wczytywania pliku w trakcie wykonywania.

Plik XML skopiowany do folderu rozszerzeń
  1. Plik .xml skopiowany do folderu rozszerzeń widoku dodatku Dynamo

Jest to podstawowe wprowadzenie do rozszerzeń widoku. Bardziej zaawansowaną analizę przypadku zawiera pakiet DynaShape, projekt open source w serwisie GitHub. Ten pakiet zawiera rozszerzenie widoku umożliwiające edycję na żywo w widoku modelu dodatku Dynamo.

Instalator pakietu DynaShape można pobrać z forum dodatku Dynamo: https://forum.dynamobim.com/t/dynashape-published/11666

Kod źródłowy można sklonować z serwisu GitHub: https://github.com/LongNguyenP/DynaShape

Definiowanie niestandardowej organizacji pakietów dla dodatku Dynamo 2.0+

Osiągnięcie żądanego układu pakietu zależy od typów węzłów, które zostaną uwzględnione w pakiecie. Węzły pochodne Node Model, węzły ZeroTouch i węzły niestandardowe mają nieco inne procesy definiowania kategoryzacji. Możesz mieszać i zestawiać te typy węzłów w tym samym pakiecie, ale będzie to wymagało łączenia różnych strategii opisanych poniżej.

NodeModel

Biblioteki NodeModel są domyślnie zorganizowane w oparciu o strukturę klas.

Węzeł będzie zlokalizowany w obszarze dodatków w ścieżce:

Kategorię można również nadpisać, używając atrybutu NodeCategory w klasie lub w konstruktorze, jak pokazano poniżej.

Węzeł będzie teraz znajdował się w obszarze dodatków w ścieżce:

ZeroTouch

Biblioteki ZeroTouch są domyślnie organizowane w oparciu o strukturę klas.

Węzeł będzie zlokalizowany w obszarze dodatków w ścieżce:

Położenie struktury klas można również nadpisać za pomocą pliku XML dostosowywania dodatku Dynamo.

  • Plik XML musi mieć odpowiednią nazwę i być umieszczony w folderze extra pakietu

    • PackageName_DynamoCustomization.xml

Węzły niestandardowe

Węzły niestandardowe są organizowane na podstawie wartości Category Name określonej podczas ich tworzenia (za pomocą nowego okna dialogowego Węzeł niestandardowy).

OSTRZEŻENIE! Użycie zapisu kropkowego w nazwach lub kategoriach węzłów spowoduje utworzenie dodatkowych podkategorii zagnieżdżonych. Kropka . będzie pełnić rolę separatora określającego dodatkową hierarchię. Jest to nowe zachowanie w bibliotece dodatku Dynamo 2.0.

Nazwę kategorii można później zaktualizować w pliku .dyf (XML lub JSON)

Strategie migracji węzłów z pakietów

Gdy autor pakietu decyduje się zmienić nazwę wcześniej istniejącego węzła w nowej wersji, powinien zapewnić mechanizmy migracji wykresów zawierających węzły o starych nazwach. Można to zrealizować na następujące sposoby...

Węzły ZeroTouch używają pliku Namespace.Migrations.XML znajdującego się w folderze pakietów bin, na przykład:

MyZeroTouchLib.MyNodes.SayHello na MyZeroTouchLib.MyNodes.SayHelloRENAMED

Węzły pochodne NodeModel używają atrybutu AlsoKnownAs klasy, na przykład:

SampleLibraryUI.Examples.DropDownExample na SampleLibraryUI.Examples.DropDownExampleRENAMED

namespace SampleLibraryUI.Examples
// Class Attribute
[NodeName("MyNodeModel")]
public class MyNewNodeModel : NodeModel

// or

// Constructor
public ButtonCustomNodeModel()
{
    this.Name = "MyNodeModel";
}
SampleLibraryUI/Examples/MyNodeModel
// Class Attribute
[NodeCategory("NewSampleLibraryUI.Examples")]

// or

// Constructor
public ButtonCustomNodeModel()
{
    this.Category = "NewSampleLibraryUI.Examples";
}
NewSampleLibraryUI/Examples/MyNodeModel
namespace 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
    {
        ...
    }
{
Właściwości węzła niestandardowego

Dalsze kroki z Zero-Touch

Po omówieniu tworzenia projektu Zero-Touch możemy teraz lepiej zapoznać się z zagadnieniami dotyczącymi tworzenia węzła, analizując przykład ZeroTouchEssentials w witrynie dodatku Dynamo w serwisie Github.

Węzły Zero-Touch

Wiele węzłów standardowych dodatku Dynamo to w zasadzie węzły Zero-Touch, takie jak większość węzłów Math, Color i DateTime powyżej.

Aby rozpocząć, pobierz projekt ZeroTouchEssentials stąd: https://github.com/DynamoDS/ZeroTouchEssentials

W programie Visual Studio otwórz plik rozwiązania ZeroTouchEssentials.sln i skompiluj to rozwiązanie.

Projekt ZeroTouchEssentials w programie Visual Studio

Plik ZeroTouchEssentials.cs zawiera wszystkie metody, które zaimportujemy do dodatku Dynamo.

Otwórz dodatek Dynamo i zaimportuj plik ZeroTouchEssentials.dll, aby pobrać węzły, do których odwołujemy się w kolejnych przykładach.

Przykłady kodu są ściągane z pliku ZeroTouchEssentials.cs i na ogół są z nim zgodne. Dokumentację XML usunięto, aby były one zwięzłe. Każdy przykład kodu spowoduje utworzenie węzła pokazanego na ilustracji powyżej.

Domyślna wartość wejściowa

Dodatek Dynamo obsługuje definiowanie wartości domyślnych dla portów wejściowych w węźle. Te wartości domyślne zostają dostarczone do węzła, jeśli porty nie mają połączeń. Wartości domyślne są wyrażane za pomocą mechanizmu języka C# do określania argumentów opcjonalnych omówionego w Podręczniku programowania C#. Wartości domyślne określa się w następujący sposób:

  • Ustaw domyślną wartość parametrów metody: inputNumber = 2.0

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;
        }
    }
}
Wartość domyślna
  1. Po umieszczeniu kursora na porcie wejściowym węzła zostanie wyświetlona wartość domyślna

Zwracanie wielu wartości

Zwracanie wielu wartości jest nieco bardziej złożone niż tworzenie wielu danych wejściowych. Aby to zrobić, należy użyć słownika. Pozycje słownika stają się portami po stronie wyjściowej węzła. Wiele portów wartości zwracanych tworzy się w następujący sposób:

  • Dodaj instrukcję using System.Collections.Generic;, aby użyć słownika: Dictionary<>.

  • Dodaj instrukcję using Autodesk.DesignScript.Runtime;, aby użyć atrybutu MultiReturn. Jest to odwołanie do pliku „DynamoServices.dll” z pakietu NuGet dodatku DynamoServices.

  • Dodaj do metody atrybut [MultiReturn(new[] { "string1", "string2", ... more strings here })]. Te ciągi odwołują się do kluczy w słowniku i staną się one nazwami portów wyjściowych.

  • Zwróć słownik Dictionary<> z funkcji z kluczami odpowiadającymi nazwom parametrów w atrybucie: return new Dictionary<string, object>

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) }
            };
        }
    }
}

Zobacz przykład kodu w pliku ZeroTouchEssentials.cs

Węzeł zwracający wiele pozycji danych wyjściowych.

Wiele pozycji danych wyjściowych
  1. Zwróć uwagę, że teraz istnieją dwa porty wyjściowe o nazwach zgodnych z ciągami wprowadzonymi dla kluczy słownika.

Dokumentacja, etykiety narzędzi i wyszukiwanie

Do najlepszych rozwiązań należy dodawanie do węzłów dodatku Dynamo dokumentacji opisującej funkcję węzła, jego dane wejściowe i wyjściowe, tagi wyszukiwania itp. Robi się to za pomocą tagów dokumentacji XML. Dokumentację XML tworzy się w następujący sposób:

  • Każdy tekst komentarza poprzedzony trzema ukośnikami jest traktowany jako należący do dokumentacji

    • Na przykład: /// Documentation text and XML goes here

  • Po trzech ukośnikach utwórz tagi XML powyżej metod, które dodatek Dynamo odczyta podczas importowania pliku .dll

    • Na przykład: /// <summary>...</summary>

  • Włącz dokumentację XML w programie Visual Studio, wybierając opcję Project > [Project] Properties > Build > Output i zaznaczając opcję Documentation file

Generowanie pliku XML
  1. Program Visual Studio wygeneruje plik XML w określonej lokalizacji

Typy tagów są następujące:

  • Tag /// <summary>...</summary> określa dokumentację główną węzła i jego zawartość będzie wyświetlana jako etykieta narzędzi nad węzłem na pasku po lewej stronie paska wyszukiwania

  • Tag /// <param name="inputName">...</param> tworzy dokumentację dla określonych parametrów wejściowych

  • Tag /// <returns>...</returns> tworzy dokumentację dla parametru wyjściowego

  • Tag /// <returns name = "outputName">...</returns> tworzy dokumentację dla wielu parametrów wyjściowych

  • Tag /// <search>...</search> dopasowuje węzeł do wyników wyszukiwania na podstawie listy rozdzielonej przecinkami. Jeśli na przykład tworzymy węzeł, który dzieli siatkę, możemy dodać takie oznaczenia, jak „mesh” (siatka), „subdivision” (podpodział) i „catmull-clark”.

Poniżej przedstawiono przykładowy węzeł z opisami danych wejściowych i wyjściowych oraz podsumowanie, które będzie wyświetlane w bibliotece.

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;
        }
    }
}

Zobacz przykład kodu w pliku ZeroTouchEssentials.cs

Należy zwrócić uwagę, że kod dla tego węzła przykładowego zawiera:

  1. Podsumowanie węzła

  2. Opis danych wejściowych

  3. Opis danych wyjściowych

Opisy węzłów Dynamo — najlepsze praktyki

Opisy węzłów to podsumowania funkcji węzła i danych wyjściowych. W dodatku Dynamo są one wyświetlane w dwóch miejscach:

  • W etykiecie narzędzia węzła

  • W przeglądarce dokumentacji

Opis węzła

Przestrzeganie tych wskazówek zapewnia spójność i pomaga zaoszczędzić czas podczas pisania oraz aktualizowania opisów węzłów.

Przegląd

Opisy powinny składać się z jednego lub dwóch zdań. Jeśli potrzebnych jest więcej informacji, należy podać je w obszarze Szczegółowe informacje w przeglądarce dokumentacji.

Stosuj wielkość liter jak w zdaniu (pierwsza litera pierwszego słowa zdania i pierwsza litera każdej nazwy własnej powinna być wielka). Nie stawiaj kropki na końcu.

Język powinien być tak jasny i prosty, jak to tylko możliwe. Zdefiniuj akronimy przy ich pierwszym użyciu, chyba że są one znane nawet użytkownikom niebędącym ekspertami.

Zawsze stawiaj na pierwszym miejscu jasność, nawet jeśli konieczne będzie odejście od tych wskazówek.

Wskazówki

Co robić
Czego nie robić

Rozpocznij opis od czasownika w trzeciej osobie.

  • Przykład: Określa, czy dany obiekt geometrii przecina się z innym

Nie zaczynaj od czasownika w drugiej osobie ani od żadnego rzeczownika.

  • Przykład: Określ, czy dany obiekt geometrii przecina się z innym

Zamiast słowa „uzyskuje” (gets) używaj słowa „zwraca” (returns), słowa „tworzy” (creates) lub innego czasownika opisowego.

  • Przykład: Zwraca reprezentację Nurbs powierzchni

Nie używaj słów „uzyskaj” ani „uzyskuje” (get, gets). Te słowa są mniej konkretne (a słowo „get” ma kilka możliwych tłumaczeń).

  • Przykład: Uzyskuje reprezentację Nurbs powierzchni

Odnosząc się do danych wejściowych, używaj słowa „dane” (given) albo „dane wejściowe” lub „wejściowe” (input) zamiast „określone” (specified) czy innych terminów. Jeśli to możliwe, pomijaj słowa „dane” (given) albo „dane wejściowe” lub „wejściowe” (input), aby uprościć opis i zmniejszyć liczbę słów.

  • Przykład: Usuwa dany plik

  • Przykład: Rzutuje krzywą wzdłuż danego kierunku rzutowania na daną geometrię bazową

Możesz używać słowa „określone” (specified), jeśli nie odnosi się ono bezpośrednio do danych wejściowych.

  • Przykład: Zapisuje zawartość tekstową w pliku określonym za pomocą danej ścieżki

Odnosząc się do danych wejściowych, aby zapewnić spójność, nie używaj słowa „określone” (specified) ani innych terminów z wyjątkiem „dane” (given) albo „dane wejściowe” lub „wejściowe” (input). Nie mieszaj słów „dane” (given) i„dane wejściowe” lub „wejściowe” (input) w tym samym opisie, chyba że jest to konieczne dla zapewnienia przejrzystości.

  • Przykład: Usuwa określony plik

  • Przykład: Rzutuje krzywą wejściową wzdłuż danego kierunku rzutowania na określoną geometrię bazową

W języku angielskim w pierwszym odniesieniu do danych wejściowych używaj słowa „a” lub „an”. Używaj słów „the given” lub „the input” zamiast „a” lub „an” zgodnie z potrzebami w celu zachowania przejrzystości.

  • Przykład: Sweeps a curve along the path curve

W języku angielskim w pierwszym odniesieniu do danych wejściowych nie używaj słowa „ten” (this).

  • Przykład: Sweeps this curve along the path curve

W języku angielskim w pierwszym odniesieniu do danych wejściowych lub innego rzeczownika, który jest elementem docelowym operacji węzła, używaj słowa „a” lub „an”. Słowa „the” używaj tylko razem ze słowami „given” lub „input”.

  • Przykład: Copies a file

  • Przykład: Copies the given file

W języku angielskim w pierwszym odniesieniu do danych wejściowych lub innego rzeczownika, który jest elementem docelowym operacji węzła, nie używaj samego słowa „the”.

  • Przykład: Copies the file

Pierwsza litera pierwszego słowa zdania i pierwsza litera każdej nazwy własnej, takiej jak nazwa czy rzeczownik tradycyjnie pisany wielkimi literami, powinna być wielka (w języku angielskim wszystkie pierwsze litery nazwy własnej złożonej z wielu słów powinny być wielkie).

  • Przykład: Zwraca przecięcie dwóch elementów BoundingBox

Nie rozpoczynaj wielkimi literami słów opisujących typowe obiekty i pojęciach geometryczne, chyba że jest to konieczne dla zachowania przejrzystości.

  • Przykład: Skaluje niejednorodnie wokół danej Płaszczyzny

Rozpoczynaj słowo Boolean wielką literą. Rozpoczynaj wielkimi literami wartości True (Prawda) i False (Fałsz) w odniesieniu do danych wyjściowych wartości logicznych (Boolean).

  • Przykład: Zwraca wartość True (Prawda), jeśli dwie wartości są różne

  • Przykład: Konwertuje ciąg na ciąg napisany w całości wielkimi terami lub małymi literami na podstawie parametru w postaci wartości logicznej Boolean

Nie rozpoczynaj słowa Boolean małą literą. Nie rozpoczynaj małymi literami wartości True (Prawda) ani False (Fałsz) w odniesieniu do danych wyjściowych wartości logicznych (Boolean).

  • Przykład: Zwraca wartość true (prawda), jeśli dwie wartości są różne

  • Przykład: Konwertuje ciąg na ciąg napisany w całości wielkimi terami lub małymi literami na podstawie parametru w postaci wartości logicznej boolean

Ostrzeżenia i błędy węzła Dynamo

Ostrzeżenia i błędy węzłów informują użytkownika o problemie z wykresem. Powiadamiają one użytkownika o problemach, które zakłócają normalne działanie wykresu, wyświetlając nad węzłem ikonę i rozwinięty dymek tekstowy. Błędy i ostrzeżenia węzłów mogą mieć różną ważność: niektóre wykresy mogą działać wystarczająco dobrze mimo ostrzeżeń, podczas gdy inne blokują oczekiwane wyniki. We wszystkich przypadkach błędy i ostrzeżenia węzłów są ważnymi narzędziami umożliwiającymi informowanie użytkownika na bieżąco o problemach z wykresem.

Wskazówki dotyczące zapewniania spójności i oszczędzania czasu w przypadku pisania lub aktualizowania komunikatów o błędach i ostrzeżeń dotyczących węzłów można znaleźć na stronie wiki Wzorzec zawartości: ostrzeżenia i błędy węzłów.

Obiekty

W dodatku Dynamo nie ma słowa kluczowego new, dlatego obiekty należy konstruować przy użyciu statycznych metod konstrukcji. Obiekty konstruuje się w następujący sposób:

  • Ustaw konstruktor jako wewnętrzny, internal ZeroTouchEssentials(), chyba że jest to niezgodne z wymaganiami

  • Skonstruuj obiekt za pomocą metody statycznej, na przykład public static ZeroTouchEssentials ByTwoDoubles(a, b)

Uwaga: w dodatku Dynamo używa się prefiksu „By”, aby wskazać, że metoda statyczna jest konstruktorem. Chociaż jest to opcjonalne, używanie prefiksu „By” ułatwia zapewnienie zgodności tworzonej biblioteki z istniejącym stylem dodatku Dynamo.

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);
        }
    }
}

Zobacz przykład kodu w pliku ZeroTouchEssentials.cs

Po zaimportowaniu biblioteki DLL przykładu ZeroTouchEssentials w bibliotece będzie znajdował się węzeł ZeroTouchEssentials. Ten obiekt można utworzyć za pomocą węzła ByTwoDoubles.

Węzeł ByTwoDoubles

Używanie typów geometrii dodatku Dynamo

W bibliotekach Dynamo można używać własnych typów geometrii dodatku Dynamo jako danych wejściowych i tworzyć nową geometrię jako dane wyjściowe. Typy geometrii tworzy się w następujący sposób:

  • Utwórz odwołanie do pliku „ProtoGeometry.dll” w projekcie, umieszczając instrukcję using Autodesk.DesignScript.Geometry; u góry pliku z kodem C# i dodając do projektu pakiet NuGet ZeroTouchLibrary.

  • Ważne: zadbaj o zarządzanie zasobami geometrii, które nie są zwracane z funkcji — zobacz sekcję Instrukcje Dispose/using poniżej.

Uwaga: obiekty geometrii dodatku Dynamo są używane tak samo jak wszystkie inne obiekty przekazywane do funkcji.

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;
        }
    }
}

Zobacz przykład kodu w pliku ZeroTouchEssentials.cs

Węzeł, który pobiera długość krzywej i podwaja ją.

Dane wejściowe określające krzywą
  1. Ten węzeł przyjmuje jako dane wejściowe typ geometrii Curve (krzywa).

Instrukcje Dispose/using

Zasobami geometrii, które nie są zwracane z funkcji, należy zarządzać ręcznie, chyba że jest używany dodatek Dynamo w wersji 2.5 lub nowszej. W dodatku Dynamo 2.5 i wersjach późniejszych zasoby geometrii są obsługiwane wewnętrznie przez system, jednak w przypadku złożonego przypadku zastosowania geometrii może być konieczne ręczne usunięcie geometrii lub zmniejszenie pamięci w określonym z góry czasie. Silnik dodatku Dynamo obsługuje wszystkie zasoby geometrii zwracane z funkcji. Niezwrócone zasoby geometrii można obsłużyć ręcznie w następujący sposób:

  • Za pomocą instrukcji using:

    using (Point p1 = Point.ByCoordinates(0, 0, 0))
    {
      using (Point p2 = Point.ByCoordinates(10, 10, 0))
      {
          return Line.ByStartPointEndPoint(p1, p2);
      }
    }

    Instrukcję using opisano tutaj

    Aby dowiedzieć się więcej na temat nowych funkcji zwiększających stabilność wprowadzonych w dodatku Dynamo 2.5, zobacz Ulepszenia stabilności geometrii w dodatku Dynamo.

  • Za pomocą ręcznych wywołań metody Dispose:

    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;

Migracje

Wraz z opublikowaniem nowszej wersji biblioteki nazwy węzłów mogą ulec zmianie. Zmiany nazw można określić w pliku migracji, tak aby wykresy opracowane na podstawie poprzednich wersji biblioteki nadal działały poprawnie po aktualizacji. Migracje implementuje się w następujący sposób:

  • Utwórz plik .xml w tym samym folderze, w którym znajduje się plik .dll, w następującym formacie: „Nazwa_podstawowego_pliku_DLL”.Migrations.xml

  • W pliku .xml utwórz pojedynczy element <migrations>...</migrations>

  • W tym elemencie migrations utwórz elementy <priorNameHint>...</priorNameHint> dla każdej zmiany nazwy

  • Dla każdej zmiany nazwy dodaj element <oldName>...</oldName> i element <newName>...</newName>

Plik migracji
  1. Kliknij prawym przyciskiem myszy i wybierz polecenie Add > New Item

  2. Wybierz opcję XML File

  3. W przypadku tego projektu należy nadać plikowi migracji nazwę ZeroTouchEssentials.Migrations.xml

Ten kod przykładowy informuje dodatek Dynamo, że każdy węzeł o nazwie GetClosestPoint ma teraz nazwę ClosestPointTo.

<?xml version="1.0"?>
<migrations>
  <priorNameHint>
    <oldName>Autodesk.DesignScript.Geometry.Geometry.GetClosestPoint</oldName>
    <newName>Autodesk.DesignScript.Geometry.Geometry.ClosestPointTo</newName>
  </priorNameHint>
</migrations>

Zobacz przykład kodu w pliku ProtoGeometry.Migrations.xml

Typy ogólne

W projekcie Zero-Touch nie jest obecnie obsługiwane używanie typów ogólnych. Mogą one być używane, ale nie w kodzie, który jest bezpośrednio importowany, gdy nie ustawiono typu. Metod, właściwości lub klas, które są ogólne i nie mają ustawionego typu, nie można uwidocznić.

W poniższym przykładzie węzeł Zero-Touch typu T nie zostanie zaimportowany. Jeśli pozostała część biblioteki zostanie zaimportowana do dodatku Dynamo, pojawią się wyjątki wynikające z brakujących typów.

public class SomeGenericClass<T>
{
    public SomeGenericClass()
    {
        Console.WriteLine(typeof(T).ToString());
    }  
}

Użycie typu ogólnego z typem ustawionym w tym przykładzie spowoduje zaimportowanie do dodatku Dynamo.

public class SomeWrapper
{
    public object wrapped;
    public SomeWrapper(SomeGenericClass<double> someConstrainedType)
    {
        Console.WriteLine(this.wrapped.GetType().ToString());
    }
}

Interfejs wiersza polecenia dodatku Dynamo

-o, -O, --OpenFilePath Poinstruuj dodatek Dynamo, aby otworzył plik poleceń i uruchomił zawarte w nim polecenia w tej ścieżce. Ta opcja jest obsługiwana tylko w przypadku uruchamiania z aplikacji DynamoSandbox.

-c, -C, --CommandFilePath Poinstruuj dodatek Dynamo, aby otworzył plik poleceń i uruchomił zawarte w nim polecenia w tej ścieżce. Ta opcja jest obsługiwana tylko w przypadku uruchamiania z aplikacji DynamoSandbox.

-v, -V, --Verbose Poinstruuj dodatek Dynamo, aby wszystkie wykonywane obliczenia zapisywał w pliku XML w określonej ścieżce.

-g, -G, --Geometry Poinstruuj dodatek Dynamo, aby zapisywał geometrię wynikową ze wszystkich obliczeń w pliku JSON w tej ścieżce.

-h, -H, --help Skorzystaj z pomocy.

-i, -I, --Import Poinstruuj dodatek Dynamo, aby zaimportował zespół jako bibliotekę węzłów. Tym argumentem powinna być ścieżka pliku pojedynczego pliku .dll. Jeśli chcesz zaimportować wiele plików .dlls, wymień je, rozdzielając je spacjami: -i 'assembly1.dll' 'assembly2.dll'.

--GeometryPath Ścieżka względna lub bezwzględna katalogu zawierającego ASM. Po podaniu tej ścieżki zamiast przeszukiwania dysku twardego w poszukiwaniu ASM zostanie on wczytany bezpośrednio z tej ścieżki.

-k, -K, --KeepAlive Tryb Keepalive umożliwia pozostawienie uruchomionego procesu dodatku Dynamo do momentu zamknięcia go przez wczytane rozszerzenie.

--HostName Zidentyfikuj odmianę dodatku Dynamo skojarzoną z programem nadrzędnym.

-s, -S, --SessionId Zidentyfikuj identyfikator sesji analizy programu nadrzędnego dodatku Dynamo.

-p, -P, --ParentId Zidentyfikuj identyfikator programu nadrzędnego analizy dodatku Dynamo.

-x, -X, --ConvertFile W połączeniu z flagą -O otwiera plik .dyn z określonej ścieżki i konwertuje go na plik .json. Plik będzie miał rozszerzenie .json i będzie się znajdował w tym samym katalogu co oryginalny plik.

-n, -N, --NoConsole Nie polegaj na oknie konsoli w zakresie interakcji z interfejsem wiersza polecenia w trybie Keepalive.

-u, -U, --UserData Określ folder danych użytkownika, który ma być używany przez narzędzie PathResolver z interfejsem wiersza polecenia.

--CommonData Określ folder danych wspólnych, który ma być używany przez narzędzie PathResolver z interfejsem wiersza polecenia.

--DisableAnalytics Wyłącza analizę w dodatku Dynamo dla okresu istnienia procesu.

--CERLocation Określ narzędzie do zgłaszania błędów powodujących awarię znajdujące się na dysku.

--ServiceMode Określ tryb uruchamiania usługi.

Dlaczego?

Sterowanie dodatkiem Dynamo z poziomu wiersza polecenia może być konieczne z różnych powodów:

  • Automatyzacja wielu przebiegów dodatku Dynamo

  • Testowanie wykresów Dynamo (w przypadku korzystania z aplikacji DynamoSandbox należy również zapoznać się z flagą -c)

  • Uruchamianie sekwencji wykresów Dynamo w określonej kolejności

  • Zapisywanie plików wsadowych, które uruchamiają wiele wykonań wiersza polecenia

  • Pisanie innego programu w celu sterowania działaniem wykresów Dynamo i automatyzowania go oraz wykonywania interesujących zadań dotyczących wyników tych obliczeń

Co?

Interfejs wiersza polecenia (DynamoCLI) jest uzupełnieniem aplikacji DynamoSandbox. Jest to narzędzie wiersza polecenia typu DOS/Terminal zaprojektowane w celu zapewnienia wygody argumentów wiersza polecenia na potrzeby uruchamiania dodatku Dynamo. W pierwszej implementacji ten komponent nie działa samodzielnie — należy go uruchomić z poziomu folderu, w którym znajdują się pliki binarne dodatku Dynamo, ponieważ jest zależny od tych samych bibliotek podstawowych DLL co środowisko Sandbox. Komponent ten nie może współdziałać z innymi kompilacjami dodatku Dynamo.

Istnieją cztery sposoby uruchamiania interfejsu wiersza polecenia: z wiersza polecenia systemu Dos, z plików wsadowych systemu Dos oraz za pomocą skrótu na pulpicie systemu Windows, którego ścieżka jest zmodyfikowana tak, aby zawierała określone flagi wiersza polecenia. Specyfikacja pliku systemu Dos może być w pełni kwalifikowana lub względna. Obsługiwane są też dyski zamapowane i składnia adresów URL. Plik można również utworzyć za pomocą platformy Mono i uruchamiać w systemie Linux lub Mac z poziomu terminala.

Pakiety Dynamo są obsługiwane przez to narzędzie, jednak nie umożliwia ono wczytywania węzłów niestandardowych (DYF), a jedynie wykresy autonomiczne (DYN).

We wstępnych testach narzędzie interfejsu wiersza polecenia obsługuje zlokalizowane wersje systemu Windows i można określać argumenty specyfikacji plików za pomocą wyższych znaków ASCII.

Dostęp do interfejsu wiersza polecenia można uzyskać za pośrednictwem aplikacji DynamoCLI.exe. Ta aplikacja umożliwia użytkownikowi lub innej aplikacji interakcję z modelem ewaluacyjnym dodatku Dynamo przez wywołanie aplikacji DynamoCLI.exe za pomocą ciągu polecenia. Wyniki mogą wyglądać następująco:

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn"

To polecenie poinstruuje dodatek Dynamo, aby otworzył określony plik w ścieżce „C:\someReallyCoolDynamoFile.Dyn” bez wyświetlania interfejsu użytkownika, a następnie uruchomi go. Dodatek Dynamo zostanie zamknięty po zakończeniu działania wykresu.

Nowości w wersji 2.1: aplikacja DynamoWPFCLI.exe. Ta aplikacja obsługuje wszystko to, co obsługuje aplikacja DynamoCLI.exe, z dodatkiem opcji Geometry (-g). Aplikacja DynamoWPFCLI.exe jest przeznaczona tylko dla systemu Windows.

Ważne uwagi

  • Preferowaną metodą interakcji z interfejsem DynamoCLI jest interfejs wiersza polecenia.

  • Obecnie należy uruchamiać interfejs DynamoCLI z jego lokalizacji instalacji w folderze [Wersja dodatku Dynamo]. Interfejs wiersza polecenia wymaga dostępu do tych samych plików .dll co dodatek Dynamo, więc nie należy go przenosić.

  • Powinno być możliwe wykonywanie wykresów, które są aktualnie otwarte w dodatku Dynamo, ale może to spowodować niezamierzone skutki uboczne.

  • Wszystkie ścieżki plików są w pełni zgodne z systemem DOS, więc ścieżki względne i w pełni kwalifikowane powinny działać, ale pamiętaj, aby ujmować ścieżki w cudzysłów "C:ścieżka\do\pliku.dyn"

  • Interfejs DynamoCLI to nowa funkcja, która obecnie podlega ciągłym zmianom: ten interfejs wiersza polecenia wczytuje obecnie tylko podzestaw standardowych bibliotek dodatku Dynamo. Należy o tym pamiętać, jeśli wykres nie jest wykonywany poprawnie. Biblioteki te są określone

  • Obecnie nie są dostarczane żadne standardowe dane wyjściowe, jeśli nie wystąpią żadne błędy. Interfejs wiersza polecenia zostanie po prostu zamknięty po zakończeniu przebiegu.

W jaki sposób?

Flaga -o umożliwia otwarcie dodatku Dynamo przez wskazanie pliku .dyn w trybie bezobsługowym, który spowoduje uruchomienie tego wykresu.

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn"

Flagi -v można używać, gdy dodatek Dynamo działa w trybie bezobsługowym (gdy użyto flagi -o do otwarcia pliku). Ta flaga spowoduje iterowanie wszystkich węzłów na wykresie i zrzucenie ich wartości wyjściowych do prostego pliku XML. Ponieważ flaga --ServiceMode może wymusić na dodatku Dynamo uruchomienie wielu obliczeń wykresu, plik wyjściowy będzie zawierać wartości dla każdego wykonania obliczeń.

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -p "C:\aFileWithPresetsInIt.dyn" --ServiceMode "all" -v "C:\output.xml"

Wyjściowy plik XML będzie miał postać:

Flagi -g można używać, gdy dodatek Dynamo działa w trybie bezobsługowym (gdy użyto flagi -o do otwarcia pliku). Ta flaga spowoduje wygenerowanie wykresu, a następnie zrzucenie geometrii wynikowej do pliku JSON.

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoWPFCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -g "C:\geometry.json"

Plik geometrii JSON będzie miał postać:

Do ustalenia — praca w toku

Użycie flagi -h pozwala uzyskać listę możliwych opcji

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -h

Flagi -i można używać wielokrotnie w celu zaimportowania wielu zespołów, których wymaga uruchomienie otwieranego wykresu.

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -i"a.dll" -i"aSecond.dll"

Flagi -i można używać do uruchamiania dodatku Dynamo w ramach innych ustawień regionalnych. Zazwyczaj jednak ustawienia regionalne nie mają wpływu na wyniki wykresu

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -o "C:\someReallyCoolDynamoFile.Dyn" -l "de-DE"

Za pomocą flagi --GeometryPath można wskazać aplikacji DynamoSandbox lub interfejsowi wiersza polecenia konkretny zestaw plików binarnych ASM — używaj jej w następujący sposób:

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoSandbox.exe --GeometryPath "\pathToGeometryBinaries\"

lub

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoSandbox.exe --GeometryPath "\pathToGeometryBinaries\"

Flaga -k umożliwia pozostawienie uruchomionego procesu dodatku Dynamo do momentu zamknięcia go przez wczytane rozszerzenie.

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -k

Flaga --HostName umożliwia zidentyfikowanie odmiany dodatku Dynamo skojarzonej z programem nadrzędnym.

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe --HostName "DynamoFormIt"

lub

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoSandbox.exe --HostName "DynamoFormIt"

Flaga -s służy do identyfikowania identyfikatora sesji analizy programu nadrzędnego dodatku Dynamo

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -s [HostSessionId]

Flaga -p służy do identyfikowania identyfikatora nadrzędnego analizy programu nadrzędnego dodatku Dynamo

C:\Program Files\Dynamo\Dynamo Core\[Dynamo Version]\DynamoCLI.exe -p "RVT&2022&MUI64&22.0.2.392"

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

Analiza przypadku NodeModel — niestandardowy interfejs użytkownika

Węzły oparte na klasie NodeModel zapewniają znacznie większą elastyczność i możliwości niż węzły Zero-Touch. W tym przykładzie przeniesiemy węzeł siatki Zero-Touch na następny poziom, dodając zintegrowany suwak losowo ustawiający rozmiar prostokąta.

Wykres siatki prostokątnej

Ten suwak umożliwia skalowanie komórek względem ich rozmiaru, dzięki czemu użytkownik nie musi udostępniać suwaka z odpowiednim zakresem.

Wzorzec Model-View-Viewmodel

Dodatek Dynamo jest oparty na wzorcu architektury oprogramowania model-view-viewmodel (MVVM), który umożliwia oddzielenie interfejsu użytkownika od zaplecza. W przypadku tworzenia węzłów ZeroTouch dodatek Dynamo tworzy powiązanie danych między danymi węzła a jego interfejsem użytkownika. Aby utworzyć niestandardowy interfejs użytkownika, należy dodać logikę powiązania danych.

Ogólnie istnieją dwie części ustanawiania relacji model-widok (model-view) w dodatku Dynamo:

  • Klasa NodeModel ustanawiająca podstawową logikę węzła („model”)

  • Klasa INodeViewCustomization umożliwiająca dostosowanie sposobu wyświetlania modelu NodeModel („widok”, ang. „view”)

Obiekty NodeModel mają już skojarzoną relację widok-model (NodeViewModel), więc można skupić się na modelu i widoku dla niestandardowego interfejsu użytkownika.

Jak zaimplementować klasę NodeModel

W tym przykładzie omówimy kilka istotnych różnic między węzłami NodeModel a węzłami Zero-Touch. Zanim przejdziemy do dostosowywania interfejsu użytkownika, rozwińmy logikę klasy NodeModel.

1. Tworzenie struktury projektu:

Węzeł NodeModel może tylko wywoływać funkcje, dlatego należy rozdzielić węzeł NodeModel i funkcje między różnymi bibliotekami. Standardowym sposobem realizacji tego w przypadku pakietów dodatku Dynamo jest utworzenie oddzielnych projektów dla obu tych typów zawartości. Zacznij od utworzenia nowego rozwiązania obejmującego te projekty.

  1. Wybierz opcję File > New > Project

  2. Wybierz opcję Other Project Types, aby wywołać opcję rozwiązania

  3. Wybierz opcję Blank Solution

  4. Nadaj rozwiązaniu nazwę CustomNodeModel

  5. Wybierz przycisk Ok

Utwórz w rozwiązaniu dwa projekty biblioteki klas C#: jeden dla funkcji, a drugi dla interfejsu NodeModel.

Dodawanie nowej biblioteki klas
  1. Kliknij prawym przyciskiem myszy rozwiązanie i wybierz pozycję Add > New Project

  2. Wybierz bibliotekę klas

  3. Nadaj jej nazwę CustomNodeModel

  4. Kliknij przycisk Ok

  5. Powtórz ten proces, aby dodać kolejny projekt o nazwie CustomNodeModelFunctions

Następnie należy zmienić nazwy automatycznie utworzonych bibliotek klas i dodać je do projektu CustomNodeModel. Klasa GridNodeModel służy do zaimplementowania klasy abstrakcyjnej NodeModel, a GridNodeView do dostosowania widoku. Natomiast klasa GridFunction ma zawierać wszystkie funkcje, które będą wywoływane.

Eksplorator rozwiązań
  1. Dodaj kolejną klasę, klikając prawym przyciskiem myszy projekt CustomNodeModel, wybierając polecenie Add > New Item... i wybierając opcję Class.

  2. W projekcie CustomNodeModel potrzebne są klasy GridNodeModel.cs i GridNodeView.cs

  3. W projekcie CustomNodeModelFunction potrzebna jest klasa GridFunctions.cs

Przed dodaniem kodu do klas dodaj wymagane dla tego projektu pakiety. Projekt CustomNodeModel będzie wymagać bibliotek ZeroTouchLibrary i WpfUILibrary. Natomiast projekt CustomNodeModelFunction będzie wymagać tylko biblioteki ZeroTouchLibrary. Biblioteka WpfUILibrary zostanie użyta podczas dostosowywania interfejsu użytkownika, które wykonamy później, a biblioteka ZeroTouchLibrary — do tworzenia geometrii. Pakiety można dodawać dla projektów pojedynczo. Ponieważ te pakiety mają zależności, składniki Core i DynamoServices zostaną zainstalowane automatycznie.

Instalowanie pakietów
  1. Kliknij prawym przyciskiem myszy projekt i wybierz pozycję Manage NuGet Packages

  2. Zainstaluj tylko wymagane pakiety dla tego projektu

Program Visual Studio skopiuje pakiety NuGet, do których dodaliśmy odwołania w katalogu kompilacji. Dla tej pozycji można ustawić wartość false (fałsz), aby w pakiecie nie było żadnych niepotrzebnych plików.

Wyłączanie kopii lokalnej pakietu
  1. Wybierz pakiety NuGet dodatku Dynamo

  2. Ustaw wartość false (fałsz) dla pozycji Copy Local

2. Dziedziczenie klasy NodeModel

Jak wspomniano wcześniej, główna różnica między węzłem NodeModel a węzłem ZeroTouch polega na tym, że ten pierwszy zawiera implementację klasy NodeModel. Węzeł NodeModel wymaga kilku funkcji z tej klasy, które można uzyskać, dodając po nazwie klasy :NodeModel.

Skopiuj następujący kod do pliku GridNodeModel.cs.

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

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

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

To różnica w stosunku do węzłów Zero-Touch. Przeanalizujmy funkcje poszczególnych części.

  • Określ atrybuty węzła, takie jak nazwa, kategoria, nazwy portów wejściowych/wyjściowych, typy portów wejściowych/wyjściowych oraz opisy.

  • public class GridNodeModel : NodeModel to klasa dziedzicząca klasę NodeModel z Dynamo.Graph.Nodes.

  • public GridNodeModel() { RegisterAllPorts(); } to konstruktor rejestrujący dane wejściowe i wyjściowe węzła.

  • BuildOutputAst() zwraca drzewo AST (Abstract Syntax Tree), strukturę wymaganą do zwracania danych z węzła NodeModel.

  • metoda AstFactory.BuildFunctionCall() wywołuje funkcję RectangularGrid z pliku GridFunctions.cs.

  • Instrukcja new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid) określa tę funkcję i jej parametry.

  • Instrukcja new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue }); odwzorowuje dane wejściowe węzła na parametry funkcji

  • Metoda AstFactory.BuildNullNode() tworzy węzeł o wartości null, jeśli porty wejściowe nie są połączone. Zapobiega to wyświetleniu ostrzeżenia dotyczącego tego węzła.

  • Instrukcja RaisePropertyChanged("SliderValue") powiadamia interfejs użytkownika o zmianie wartości suwaka

  • Instrukcja var sliderValue = AstFactory.BuildDoubleNode(SliderValue) tworzy węzeł AST reprezentujący wartość suwaka

  • Zmień dane wejściowe na zmienną sliderValue w zmiennej functionCall new List<AssociativeNode> { inputAstNodes[0], sliderValue });

3. Wywoływanie funkcji

Projekt CustomNodeModelFunction zostanie skompilowany jako zespół oddzielny od projektu CustomNodeModel, dzięki czemu będzie można go wywołać.

Skopiuj następujący kod do pliku GridFunction.cs.

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

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

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

            Random rnd = new Random(2);

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

Ta klasa funkcji jest bardzo podobna do tej z analizy przypadku siatki Zero-Touch z jedną różnicą:

  • Instrukcja [IsVisibleInDynamoLibrary(false)] „ukrywa” przed dodatkiem Dynamo następującą metodę i klasę, ponieważ ta funkcja jest już wywoływana z projektu CustomNodeModel.

Tak jak dodaliśmy odwołania do pakietów NuGet, projekt CustomNodeModel musi odwoływać się do projektu CustomNodeModelFunction, aby wywołać funkcję.

Dodawanie odwołania

Instrukcja using dla projektu CustomNodeModel będzie nieaktywna, dopóki nie będzie odwołania do tej funkcji

  1. Kliknij prawym przyciskiem myszy pozycję CustomNodeModel i wybierz polecenie Add > Reference

  2. Wybierz opcję Projects > Solution

  3. Zaznacz pozycję CustomNodeModelFunction

  4. Kliknij przycisk Ok

4. Dostosowywanie widoku

Aby utworzyć suwak, należy dostosować interfejs użytkownika przez zaimplementowanie interfejsu INodeViewCustomization.

Skopiuj następujący kod do pliku GridNodeView.cs

using Dynamo.Controls;
using Dynamo.Wpf;

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

        public void Dispose()
        {
        }
    }
}
  • Instrukcja public class CustomNodeModelView : INodeViewCustomization<GridNodeModel> definiuje funkcje niezbędne do dostosowania interfejsu użytkownika.

Po skonfigurowaniu struktury projektu należy za pomocą środowiska projektowego programu Visual Studio utworzyć element sterujący użytkownika i zdefiniować jego parametry w pliku .xaml. Z pola przybornika dodaj suwak do części <Grid>...</Grid>.

Dodawanie nowego suwaka
  1. Kliknij prawym przyciskiem myszy pozycję CustomNodeModel i wybierz polecenie Add > New Item

  2. Wybierz opcję WPF

  3. Nadaj elementowi sterującemu użytkownika nazwę Slider

  4. Kliknij opcję Add

Skopiuj następujący kod do pliku Slider.xaml

<UserControl x:Class="CustomNodeModel.CustomNodeModel.Slider"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:CustomNodeModel.CustomNodeModel"
             mc:Ignorable="d" 
             d:DesignHeight="75" d:DesignWidth="100">
    <Grid Margin="10">
        <Slider Grid.Row="0" Width="80" Minimum="0" Maximum="1" IsSnapToTickEnabled="True" TickFrequency="0.01" Value="{Binding SliderValue}"/>
    </Grid>
</UserControl>
  • Parametry suwaka są zdefiniowane w pliku .xaml. Atrybuty Minimum i Maximum definiują zakres liczbowy tego suwaka.

  • Wewnątrz tagów <Grid>...</Grid> można umieszczać różne elementy sterujące użytkownika z przybornika programu Visual Studio

Po utworzeniu pliku Slider.xaml program Visual Studio automatycznie utworzył plik z kodem C# o nazwie Slider.xaml.cs, który inicjuje suwak. Zmień przestrzeń nazw w tym pliku.

using System.Windows.Controls;

namespace CustomNodeModel.CustomNodeModel
{
    /// <summary>
    /// Interaction logic for Slider.xaml
    /// </summary>
    public partial class Slider : UserControl
    {
        public Slider()
        {
            InitializeComponent();
        }
    }
}
  • Przestrzenią nazw powinna być CustomNodeModel.CustomNodeModel

Plik GridNodeModel.cs definiuje logikę obliczeń suwaka.

5. Konfigurowanie jako pakiet

Ostatnią czynnością przed rozpoczęciem kompilowania projektu jest dodanie pliku pkg.json, aby umożliwić dodatkowi Dynamo odczytanie pakietu.

Dodawanie pliku JSON
  1. Kliknij prawym przyciskiem myszy pozycję CustomNodeModel i wybierz polecenie Add > New Item

  2. Wybierz opcję Web

  3. Wybierz opcję JSON File

  4. Nadaj plikowi nazwę pkg.json

  5. Kliknij opcję Add

  • Skopiuj następujący kod do pliku pkg.json

{
  "license": "MIT",
  "file_hash": null,
  "name": "CustomNodeModel",
  "version": "1.0.0",
  "description": "Sample node",
  "group": "CustomNodes",
  "keywords": [ "grid", "random" ],
  "dependencies": [],
  "contents": "Sample node",
  "engine_version": "1.3.0",
  "engine": "dynamo",
  "engine_metadata": "",
  "site_url": "",
  "repository_url": "",
  "contains_binaries": true,
  "node_libraries": [
    "CustomNodeModel, Version=1.0.0, Culture=neutral, PublicKeyToken=null",
    "CustomNodeModelFunction, Version=1.0.0, Culture=neutral, PublicKeyToken=null"
  ]
}
  • "name": określa nazwę pakietu i jego grupę w bibliotece dodatku Dynamo

  • "keywords": określa terminy wyszukiwania na potrzeby wyszukiwania w bibliotece dodatku Dynamo

  • "node_libraries": [] biblioteki skojarzone z pakietem

    Ostatnią czynnością jest skompilowanie rozwiązania i opublikowanie go jako pakietu dodatku Dynamo. Zapoznaj się z rozdziałem dotyczącym wdrażania pakietów, aby dowiedzieć się, jak utworzyć pakiet lokalny przed opublikowaniem go online i jak skompilować pakiet bezpośrednio z programu Visual Studio.

Integracja z dodatkiem Dynamo

Witamy w dokumentacji integracji dla języka programowania wizualnego dodatku Dynamo.

W tym podręczniku omówiono różne aspekty osadzania dodatku Dynamo w aplikacji, aby umożliwić użytkownikom interakcję z aplikacją za pomocą programowania wizualnego.

Zawartość:

  • To wprowadzenie — ogólne omówienie tego, co zawiera ten podręcznik oraz czym jest i do czego służy dodatek Dynamo.

  • Niestandardowy punkt wejścia dodatku Dynamo — jak utworzyć DynamoModel i od czego zacząć.

  • Śledzenie i powiązywanie elementów — używanie mechanizmu śledzenia dodatku Dynamo do powiązywania węzłów na wykresie z ich wynikami w programie nadrzędnym.

  • Węzły wyboru dodatku Dynamo Revit — jak zaimplementować węzły umożliwiające użytkownikom wybieranie obiektów lub danych z programu nadrzędnego i przekazywanie ich jako danych wejściowych do wykresu Dynamo.

  • Przegląd pakietów wbudowanych dodatku Dynamo — czym jest standardowa biblioteka dodatku Dynamo i jak używać tego mechanizmu źródłowego do dostarczania pakietów z integracją.

Informacje o terminologii:

W tych dokumentach będziemy używać zamiennie terminów „skrypt”, „wykres” i „program” „dodatku dynamo” w odniesieniu do kodu tworzonego przez użytkowników w dodatku Dynamo.

Niestandardowy punkt wejścia dodatku Dynamo

Dodatek Dynamo Revit jako przykład

https://github.com/DynamoDS/DynamoRevit/blob/master/src/DynamoRevit/DynamoRevit.cs#L534

DynamoModel jest punktem wejścia dla aplikacji nadrzędnej dodatku Dynamo. Reprezentuje on aplikację Dynamo. Ten model jest obiektem głównym najwyższego poziomu, który zawiera odniesienia do innych ważnych struktur danych i obiektów tworzących aplikację Dynamo oraz maszynę wirtualną DesignScript.

Do ustawiania parametrów wspólnych w DynamoModel podczas konstruowania tego modelu służy obiekt konfiguracji.

Przykłady w tym dokumencie zaczerpnięto z implementacji DynamoRevit, czyli integracji, w której program Revit jest programem nadrzędnym DynamoModel używanego jako dodatek. (Architektura wtyczek do programu Revit). Wczytanie tego dodatku powoduje uruchomienie DynamoModel, a następnie wyświetlenie go użytkownikowi z DynamoView i DynamoViewModel.

Dodatek Dynamo jest projektem w języku C# .NET i aby używać go w procesie w aplikacji, musisz mieć możliwość hostowania i wykonywania kodu .NET.

DynamoCore to wieloplatformowy silnik obliczeniowy i kolekcja modeli podstawowych, które można kompilować przy użyciu platformy .NET lub Mono (w przyszłości .NET Core). Jednak narzędzie DynamoCoreWPF zawiera komponenty interfejsu użytkownika dodatku Dynamo tylko dla systemu Windows i nie można go kompilować na innych platformach.

Kroki dostosowywania punktu wejścia dodatku Dynamo

Aby zainicjować DynamoModel, twórcy integracji muszą wykonać te kroki w dowolnym miejscu w kodzie programu nadrzędnego.

Wstępne wczytywanie udostępnionych plików dll dodatku Dynamo z programu nadrzędnego

Obecnie lista w dodatku D4R zawiera tylko plik Revit\SDA\bin\ICSharpCode.AvalonEdit.dll.. Ma to na celu uniknięcie konfliktów wersji bibliotek między dodatkiem Dynamo i programem Revit. np. w przypadku konfliktów dotyczących biblioteki AvalonEdit funkcja bloku kodu może zostać całkowicie uszkodzona. Problem został zgłoszony dla dodatku Dynamo 1.1.x (w https://github.com/DynamoDS/Dynamo/issues/7130) i można go również odtworzyć ręcznie. Jeśli twórcy integracji wykryją konflikty bibliotek między funkcją programu nadrzędnego a dodatkiem Dynamo, zaleca się zrobienie tego w pierwszej kolejności. Czasami jest to wymagane, aby powstrzymać inną wtyczkę lub samą aplikację nadrzędną przed wczytaniem niezgodnej wersji jako zależności współdzielonej. Lepszym rozwiązaniem jest rozstrzygnięcie konfliktu wersji przez dopasowanie wersji — lub użycie przekierowania powiązania .net w pliku app.config programu nadrzędnego, jeśli to możliwe.

Wczytywanie ASM

Czym są ASM i libG

ASM to biblioteka geometrii ADSK, na której opiera się dodatek Dynamo.

Biblioteka libG to przyjazne dla użytkownika platformy .Net opakowanie dla jądra geometrii ASM. Biblioteka libG współdzieli schemat obsługi wersji z biblioteką ASM — używany jest w jej przypadku ten sam numer wersji głównej i pomocniczej co w przypadku ASM, aby wskazać, że jest to odpowiednie opakowanie określonej wersji ASM. Wersja biblioteki libG odpowiadająca danej wersji biblioteki ASM powinna być taka sama. Biblioteka libG w większości przypadków powinna współdziałać ze wszystkimi wersjami biblioteki ASM w określonej wersji głównej. Na przykład biblioteka libG 223 powinna być w stanie wczytać dowolną wersję biblioteki ASM 223.

Środowisko Dynamo Sandbox wczytujące bibliotekę ASM

Środowisko Dynamo Sandbox zaprojektowano pod kątem współdziałania z wieloma wersjami biblioteki ASM. W tym celu z rdzeniem dostarczanych jest wiele wersji biblioteki libG. Menedżer kształtów dodatku Dynamo zawiera wbudowaną funkcję wyszukiwania produktów firmy Autodesk dostarczanych z biblioteką ASM, dzięki czemu dodatek Dynamo może wczytywać bibliotekę ASM z tych produktów i zapewniać działanie węzłów geometrii bez jawnego wczytywania ich do aplikacji nadrzędnej. Aktualna lista produktów przedstawia się następująco:

private static readonly List<string> ProductsWithASM = new List<string>() 

 { "Revit", "Civil", "Robot Structural Analysis", "FormIt" }; 

Dodatek Dynamo przeszuka rejestr systemu Windows i sprawdzi, czy produkty firmy Autodesk z tej listy są zainstalowane na komputerze użytkownika. Jeśli którykolwiek z nich jest zainstalowany, dodatek wyszuka pliki binarne ASM i pobierze tę wersję oraz wyszuka odpowiednią wersję biblioteki libG w dodatku Dynamo.

Na podstawie wersji biblioteki ASM następujący interfejs API ShapeManager wybierze odpowiednią lokalizację mechanizmu wstępnego wczytywania biblioteki libG do wczytania. Jeśli istnieje dokładnie zgodna wersja, zostanie ona użyta. W przeciwnym razie zostanie wczytana najbliższa niższa wersja biblioteki libG, ale z tą samą wersją główną.

np. Jeśli dodatek Dynamo jest zintegrowany z kompilacją deweloperską programu Revit, w której istnieje nowsza kompilacja biblioteki ASM — 225.3.0, dodatek Dynamo spróbuje użyć biblioteki libG 225.3.0, jeśli ta biblioteka istnieje. W przeciwnym razie spróbuje użyć najbliższej wersji głównej niższej niż pierwsza wybrana, czyli 225.0.0.

public static string GetLibGPreloaderLocation(Version asmVersion, string dynRootFolder)

Wewnątrzprocesowa integracja dodatku Dynamo wczytująca bibliotekę z poziomu programu nadrzędnego

Program Revit jest pierwszą pozycją na liście wyszukiwania produktów z biblioteką ASM, co oznacza, że domyślnie program DynamoSandbox.exe będzie próbował wczytać bibliotekę ASM z programu Revit. Następnie chcemy się upewnić, że zintegrowana sesja robocza dodatku D4R wczytuje bibliotekę ASM z bieżącego programu nadrzędnego Revit: np. jeśli użytkownik ma na komputerze zarówno wersję R2018, jak i wersję R2020, podczas uruchamiania dodatku D4R z wersji R2020 dodatek D4R powinien używać biblioteki ASM 225 z wersji R2020, a nie ASM 223 z R2018. Twórcy integracji muszą zaimplementować wywołania podobne do poniższych, aby wymusić wczytanie określonej wersji.

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; 

} 

Dodatek Dynamo wczytuje bibliotekę ASM z dostosowanej ścieżki

Ostatnio dodaliśmy możliwość wczytywania określonej wersji biblioteki ASM przez programy DynamoSandbox.exe i DynamoCLI.exe. Aby pominąć normalne przeszukiwanie rejestru, można użyć flagi --GeometryPath, aby wymusić na dodatku Dynamo wczytywanie biblioteki ASM z określonej ścieżki.

DynamoSandbox.exe --GeometryPath "somePath/To/ASMDirectory"

Tworzenie konfiguracji początkowej

Konfiguracja początkowa (StartupConfiguration) jest przekazywana jako parametr do inicjowania DynamoModel, co wskazuje, że zawiera ona prawie wszystkie definicje sposobu dostosowywania ustawień sesji dodatku Dynamo. W zależności od sposobu ustawienia następujących właściwości integracja dodatku Dynamo może się różnić w zależności od różnych twórców integracji. Np. różni twórcy integracji mogą ustawiać różne ścieżki szablonów w języku Python lub wyświetlane formaty liczb.

Ten komponent składa się z następujących elementów:

  • DynamoCorePath // Gdzie znajdują się pliki binarne DynamoCore wczytywania

  • DynamoHostPath // Gdzie znajdują się pliki binarne integracji dodatku Dynamo

  • GeometryFactoryPath // Gdzie znajdują się wczytywane pliki binarne biblioteki libG

  • PathResolver //obiekt, który pomaga w rozstrzyganiu lokalizacji różnych plików

  • PreloadLibraryPaths // Gdzie znajdują się wstępnie wczytywane pliki binarne węzłów, np. DSOffice.dll

  • AdditionalNodeDirectories // Gdzie znajdują się dodatkowe pliki binarne węzłów

  • AdditionalResolutionPaths // Dodatkowe ścieżki rozstrzygania zespołów dla innych zależności, które mogą być wymagane podczas wczytywania bibliotek

  • UserDataRootFolder // Folder danych użytkownika, np. "AppData\Roaming\Dynamo\Dynamo Revit"

  • CommonDataRootFolder // Domyślny folder do zapisywania definicji niestandardowych, przykładów itp.

  • Context // Nazwa i wersja programu nadrzędnego twórcy integracji (Revit<BuildNum>)

  • SchedulerThread // Wątek harmonogramu twórcy integracji implementujący ISchedulerThread — w przypadku większości twórców integracji jest to główny wątek interfejsu użytkownika lub dowolny wątek, z którego mogą uzyskać dostęp do interfejsu API.

  • StartInTestMode // Czy bieżąca sesja jest sesją automatyzacji testów — modyfikuje zestaw zachowań dodatku Dynamo — nie należy używać tej funkcji, chyba że podczas pisania testów.

  • AuthProvider // Implementacja interfejsu IAuthProvider danego twórcy integracji, np. implementacja RevitOxygenProvider znajduje się w bibliotece Greg.dll używanej do integracji przekazywania packageManager.

Preferencje

Domyślną ścieżką ustawień preferencji zarządza się za pomocą wartości PathManager.PreferenceFilePath, np. "AppData\\Roaming\\Dynamo\\Dynamo Revit\\2.5\\DynamoSettings.xml". Twórcy integracji mogą zdecydować, czy chcą również dostarczyć niestandardowy plik ustawień preferencji do lokalizacji, która musi być zgodna z menedżerem ścieżek. Poniżej przedstawiono właściwości ustawień preferencji, które są serializowane:

  • IsFirstRun // Wskazuje, czy jest to pierwsze uruchomienie danej wersji dodatku Dynamo, np. służy do określenia, czy należy wyświetlić komunikat o wyrażeniu zgody na lub rezygnacji z GA. Służy również do określenia, czy jest wymagana migracja starszych ustawień preferencji dodatku Dynamo podczas uruchamiania nowej wersji dodatku Dynamo, aby zapewnić użytkownikom spójne środowisko

  • IsUsageReportingApproved // Wskazuje, czy zatwierdzono raporty użycia

  • IsAnalyticsReportingApproved // Wskazuje, czy zatwierdzono raporty analityczne

  • LibraryWidth // Szerokość lewego panelu biblioteki dodatku Dynamo.

  • ConsoleHeight // Wysokość ekranu konsoli

  • ShowPreviewBubbles // Wskazuje, czy dymki podglądu powinny być wyświetlane

  • ShowConnector // Wskazuje, czy są wyświetlane złącza

  • ConnectorType //Wskazuje typ złącza: Beziera lub polilinia

  • BackgroundPreviews // Wskazuje aktywny stan określonego podglądu tła

  • RenderPrecision: // Poziom dokładności renderowania — niższy generuje siatki z mniejszą liczbą trójkątów. Ustawienie wyższego spowoduje wygenerowanie gładszej geometrii w podglądzie tła. Wartość 128 zapewnia dobry i szybki podgląd geometrii.

  • ShowEdges // Wskazuje, czy będą renderowane krawędzie powierzchni i bryły

  • ShowDetailedLayout // Nieużywane

  • WindowX, WindowY // Ostatnia współrzędna X, Y okna dodatku Dynamo

  • WindowW, WindowH // Ostatnia szerokość, wysokość okna dodatku Dynamo

  • UseHardwareAcceleration // Określa, czy dodatek Dynamo powinien używać przyspieszenia sprzętowego, jeśli jest ono obsługiwane

  • NumberFormat // Dokładność dziesiętna używana do wyświetlania liczb w dymku podglądu funkcji toString().

  • MaxNumRecentFiles // Maksymalna liczba ostatnio używanych ścieżek plików do zapisania

  • RecentFiles // Lista ścieżek ostatnio otwartych plików — zmiana tej listy wpłynie bezpośrednio na listę ostatnio używanych plików na stronie startowej dodatku Dynamo

  • BackupFiles // Lista ścieżek plików kopii zapasowej

  • CustomPackageFolders // Lista folderów zawierających pliki binarne typu Zero Touch i ścieżki katalogów, które będą skanowane w poszukiwaniu pakietów i węzłów niestandardowych.

  • PackageDirectoriesToUninstall // Lista pakietów używana przez Menedżera pakietów do określenia, które pakiety mają zostać oznaczone do usunięcia. Te ścieżki zostaną usunięte, jeśli będzie to możliwe podczas uruchamiania dodatku Dynamo.

  • PythonTemplateFilePath // Ścieżka pliku w języku Python (.py) używana jako szablon początkowy podczas tworzenia nowego węzła PythonScript — tej pozycji można użyć do skonfigurowania szablonu niestandardowego w języku Python dla integracji.

  • BackupInterval // Wskazuje, co jaki czas (w milisekundach) wykres będzie automatycznie zapisywany

  • BackupFilesCount // Wskazuje, ile kopii zapasowych zostanie utworzonych

  • PackageDownloadTouAccepted // Wskazuje, czy użytkownik zaakceptował Warunki użytkowania pobierania pakietów z Menedżera pakietów

  • OpenFileInManualExecutionMode // Wskazuje domyślny stan pola wyboru „Otwórz w trybie ręcznym” w oknie dialogowym OpenFileDialog

  • NamespacesToExcludeFromLibrary // Wskazuje, które (jeśli w ogóle jakieś) przestrzenie nazw nie powinny być wyświetlane w bibliotece węzłów dodatku Dynamo. Format ciągu: „[nazwa biblioteki]:[w pełni kwalifikowana przestrzeń nazw]”

Przykład zserializowanych ustawień preferencji:

<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> 
  • Extensions // Lista rozszerzeń implementujących interfejs IExtension; jeśli ma wartość null, dodatek Dynamo będzie wczytywać rozszerzenia ze ścieżki domyślnej (folderu extensions w folderze dodatku Dynamo)

  • IsHeadless // Wskazuje, czy dodatek Dynamo został uruchomiony bez interfejsu użytkownika — wpływa na analizę.

  • UpdateManager // Implementacja UpdateManager danego twórcy integracji, patrz opis powyżej

  • ProcessMode // Odpowiednik TaskProcessMode; synchroniczny w trybie testowym; w przeciwnym razie asynchroniczny — steruje zachowaniem harmonogramu. W środowiskach jednowątkowych można również ustawić dla tej opcji wartość synchroniczną.

Używanie docelowej konfiguracji StartConfiguration do uruchomienia DynamoModel

Po przekazaniu parametru StartConfig w celu uruchomienia DynamoModel dodatek DynamoCore będzie nadzorował rzeczywiste konkretne elementy, aby upewnić się, że sesja dodatku Dynamo została poprawnie zainicjowana z określonymi szczegółami. Integratorzy powinni wykonać pewne kroki pokonfiguracyjne po zainicjowaniu DynamoModel, np. w dodatku D4R subskrybowane są zdarzenia do obserwowania transakcji programu nadrzędnego Revit lub aktualizacji dokumentów, dostosowywania węzłów w języku Python itp.

Czas na „programowanie wizualne”

Aby zainicjować DynamoViewModel i DynamoView, należy najpierw utworzyć DynamoViewModel — można to zrobić za pomocą metody statycznej DynamoViewModel.Start. Zobacz poniżej:


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

Konfiguracja DynamoViewModel.StartConfiguration zapewnia znacznie mniej opcji niż konfiguracja modelu. Są one w większości oczywiste — CommandFilePath można zignorować, chyba że piszesz przypadek testowy.

Parametr Watch3DViewModel określa, w jaki sposób w węzłach podglądu tła i watch3d jest wyświetlana geometria 3D. Możesz użyć własnej implementacji, jeśli zaimplementujesz wymagane interfejsy.

Do skonstruowania DynamoView wystarczy DynamoViewModel. Ten widok jest kontrolką okna i może być wyświetlany przy użyciu platformy WPF.

Przykład dotyczący programu DynamoSandbox.exe:

DynamoSandbox.exe to środowisko programistyczne do testowania i używania dodatku DynamoCore oraz eksperymentowania z nim. Jest to doskonały przykład pozwalający przekonać się, w jaki sposób są wczytywane i konfigurowane komponenty DynamoCore i DynamoCoreWPF. Niektóre punkty wejścia można zobaczyć tutaj.

Śledzenie i powiązywanie elementów

przegląd

Śledzenie jest mechanizmem dodatku Dynamo Core, który umożliwia serializowanie danych do pliku .dyn (pliku dodatku Dynamo). Co najważniejsze, dane te są powiązywane z miejscami wywołań (callsite) węzłów na wykresie Dynamo.

W razie otwarcia wykresu Dynamo z dysku zapisane w nim dane śledzenia zostają ponownie skojarzone z węzłami wykresu.

słownik:

  • Mechanizm śledzenia:

    • Implementuje powiązywanie elementów w dodatku Dynamo

    • Mechanizm śledzenia może być używany do zapewnienia ponownego powiązywania obiektów z geometrią, którą utworzyły

    • Mechanizm miejsca wywołania (Callsite) i śledzenia obsługuje dostarczanie trwałego identyfikatora GUID, którego można użyć w ramach implementacji węzła do ponownego połączenia

  • Miejsce wywołania (Callsite)

    • Plik wykonywalny zawiera wiele miejsc wywołań. Te miejsca wywołań służą do wykonania wysyłania do różnych miejsc, w których należy wykonać wysyłanie:

      • Biblioteka C#

      • Metoda wbudowana

      • Funkcja DesignScript

      • Węzeł niestandardowy (funkcja DS)

  • TraceSerializer

    • Serializuje oznaczone klasy ISerializable i [Serializable] do postaci śladu.

    • Obsługuje serializację i deserializację danych do postaci śladu.

    • Komponent TraceBinder steruje powiązywaniem zdeserializowanych danych z typem środowiska uruchomieniowego. (Tworzy wystąpienie klasy rzeczywistej)

Jak to wygląda?


Dane śledzenia są serializowane do pliku .dyn wewnątrz właściwości o nazwie Bindings. Jest to szyk: identyfikatory miejsc wywołań -> dane. Miejsce wywołania to określone położenie/wystąpienie, w którym na maszynie wirtualnej DesignScript jest wywoływany węzeł. Warto wspomnieć, że węzły na wykresie Dynamo mogą być wywoływane wielokrotnie, w związku z czym dla jednego wystąpienia węzła może zostać utworzonych wiele miejsc wywołań.

"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"
      }
    }
  ],

 

NIE zaleca się polegania na formacie zserializowanych danych Base64Encoded.

Jaki problem próbujemy rozwiązać.


Istnieje wiele powodów do zapisywania dowolnych danych w wyniku wykonania funkcji, ale w tym przypadku śledzenie opracowano w celu rozwiązania konkretnego problemu, z którym użytkownicy często spotykają się podczas tworzenia i iterowania programów oprogramowania tworzących elementy w aplikacjach nadrzędnych.

Problem to ten określony jako Element Binding, a pomysł jest następujący:

Gdy użytkownik opracowuje i uruchamia wykres Dynamo, prawdopodobnie będzie generował nowe elementy w modelu aplikacji nadrzędnej. W naszym przykładzie załóżmy, że użytkownik ma mały program, który generuje 100 par drzwi w modelu architektonicznym. Liczba i lokalizacja tych drzwi są kontrolowane przez ten program.

Przy pierwszym uruchomieniu programu generuje on te 100 par drzwi.

Później, gdy użytkownik zmodyfikuje dane wejściowe programu i wykona go ponownie, program (bez powiązywania elementów) utworzy 100 nowych par drzwi, stare pary drzwi będą nadal istnieć w modelu wraz z nowymi.


Ponieważ dodatek Dynamo jest środowiskiem programowania na żywo i obejmuje tryb uruchamiania "Automatic", w ramach którego zmiany na wykresie wyzwalają nowy wykonanie, może to szybko zaśmiecić model wynikami z wielu przebiegów programu.

Stwierdziliśmy, że zwykle nie tego oczekują użytkownicy. Zamiast tego przy włączonym powiązywaniu elementów wyniki poprzedniego wykonania wykresu są czyszczone, usuwane lub modyfikowane. To, które z tych rozwiązań (usunięcie czy zmodyfikowanie) zostanie zastosowane, zależy od elastyczności interfejsu API programu nadrzędnego. Przy włączonym powiązywaniu elementów po drugim, trzecim lub pięćdziesiątym wykonaniu programu dodatku Dynamo użytkownika w modelu pozostaje tylko 100 par drzwi.

Wymaga to czegoś więcej niż tylko możliwości serializacji danych do pliku .dyn — jak pokazano poniżej, w dodatku DynamoRevit istnieją mechanizmy oparte na śledzeniu, które obsługują te procesy robocze ponownego powiązywania.


Jest to odpowiedni moment, aby wspomnieć o innym ważnym przypadku użycia powiązywania elementów w przypadku programów nadrzędnych, takich jak program Revit. Ponieważ elementy utworzone przy włączonym powiązywaniu elementów będą próbowały zachować istniejące identyfikatory elementów (zmodyfikować istniejące elementy) — logika utworzona na podstawie tych elementów w aplikacji nadrzędnej będzie nadal istnieć po uruchomieniu programu dodatku Dynamo. Przykładowo:

Wróćmy do naszego przykładowego modelu architektonicznego.

Najpierw przeanalizujmy przykład z wyłączonym powiązywaniem elementów — tym razem użytkownik ma program, który generuje pewne ściany architektoniczne.

Użytkownik uruchamia ten program, a ten generuje pewne ściany w aplikacji nadrzędnej. Następnie użytkownik opuszcza wykres Dynamo i za pomocą zwykłych narzędzi programu Revit umieszcza kilka okien w tych ścianach. Okna są powiązane z tymi konkretnymi ścianami jako część modelu programu Revit.

Użytkownik ponownie uruchamia dodatek Dynamo i ponownie uruchamia wykres — teraz, podobnie jak w ostatnim przykładzie, ma dwa zestawy ścian. Pierwszy zestaw ma dodane okna, ale nowy zestaw ścian — nie.

Gdyby włączono powiązywanie elementów, można by było zachować dotychczasową pracę wykonaną ręcznie w aplikacji nadrzędnej bez dodatku Dynamo. Przykładowo jeśli powiązanie byłoby włączone, gdy użytkownik uruchomił program po raz drugi, ściany zostałyby zmodyfikowane, a nie usunięte, a dalsze zmiany wprowadzone w aplikacji nadrzędnej zostałyby zachowane. Model zawierałby ściany z oknami, zamiast dwóch zestawów ścian w różnych stanach.


Tworzenie ścian

Powiązywanie elementów w porównaniu ze śledzeniem


Śledzenie jest mechanizmem w dodatku Dynamo Core — wykorzystuje zmienną statyczną miejsc wywołań danych (callsite), aby odwzorowywać dane na miejsce wywołania funkcji na wykresie, jak opisano powyżej.

Mechanizm ten umożliwia też serializację dowolnych danych do pliku .dyn podczas zapisywania węzłów Dynamo typu Zero Touch. Na ogół nie jest to zalecane, ponieważ oznacza to, że potencjalnie przenoszony kod Zero Touch staje się zależny od dodatku Dynamo Core.

Nie należy polegać na serializowanym formacie danych w pliku .dyn — zamiast tego należy używać atrybutu [Serializable] oraz interfejsu

Natomiast mechanizm powiązywania elementów (ElementBinding) jest oparty na interfejsach API śledzenia i jest zaimplementowany w integracji dodatku Dynamo (DynamoRevit, Dynamo4Civil itp.)

Interfejsy API śledzenia

Niektóre z niskopoziomowych interfejsów API śledzenia, o których warto wiedzieć, to:

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

Poniżej przedstawiono przykład ich zastosowania

Na potrzeby interakcji z danymi śledzenia wczytanymi przez dodatek Dynamo z istniejącego pliku lub wygenerowanymi można obejrzeć następujące elementy:

 public IDictionary<Guid, List<CallSite.RawTraceData>> 
 GetTraceDataForNodes(IEnumerable<Guid> nodeGuids, Executable executable)

GetTraceDataForNodes

RuntimeTrace.cs

Przykład prostego śledzenia z węzła


Przykład węzła Dynamo, który bezpośrednio używa funkcji śledzenia, znajduje się tutaj w repozytorium DynamoSamples

Podsumowanie klasy zawiera wyjaśnienie istotę tego, o co chodzi w śledzeniu:

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

W tym przykładzie interfejsy API śledzenia w dodatku DynamoCore są używane bezpośrednio do zapisywania niektórych danych za każdym razem, gdy dany węzeł jest wykonywany. W tym przypadku słownik odgrywa rolę modelu aplikacji nadrzędnej, podobnie jak baza danych modelu programu Revit.

Ogólnie konfiguracja jest następująca:

Statyczna klasa narzędziowa TraceExampleWrapper jest importowana jako węzeł do dodatku Dynamo. Zawiera pojedynczą metodę ByString tworzącą element TraceExampleItem — są to zwykłe obiekty .net, które zawierają właściwość description.

Każdy obiekt TraceExampleItem jest serializowany do postaci śladu reprezentowanego za pomocą TraceableId — jest to po prostu klasa zawierająca IntId z oznaczeniem [Serializeable], aby umożliwić serializację za pomocą elementu formatującego SOAP. Tutaj można uzyskać więcej informacji na temat atrybutu serializable

Należy również zaimplementować interfejs ISerializable zdefiniowany tutaj

    [IsVisibleInDynamoLibrary(false)]
    [Serializable]
    public class TraceableId : ISerializable
    {
    }

Ta klasa jest tworzona dla każdego obiektu TraceExampleItem, który chcemy zapisać w postaci śladu, zserializować, zakodować w formacie base64 i zapisać na dysku podczas zapisywania wykresu, aby można było ponownie skojarzyć powiązania, nawet później, gdy wykres zostanie otwarty z powrotem na tle istniejącego słownika elementów. Nie będzie to działać poprawnie w tym przykładzie, ponieważ słownik nie jest tak naprawdę trwały, tak jak dokument programu Revit.

Ostatnią częścią równania jest TraceableObjectManager, który jest podobny do ElementBinder w DynamoRevit — zarządza relacją między obiektami obecnymi w modelu dokumentu programu nadrzędnego a danymi przechowywanymi w śladzie dodatku Dynamo.

Gdy użytkownik uruchamia wykres zawierający węzeł TraceExampleWrapper.ByString po raz pierwszy, zostaje utworzony nowy element TraceableId z nowym identyfikatorem, obiekt TraceExampleItem zostaje zapisany w słowniku zamapowanym na ten nowy identyfikator, a element TraceableID zostaje zapisany w śladzie.

Przy następnym uruchomieniu wykresu szukamy w śladzie, znajdujemy zapisany tam identyfikator, znajdujemy obiekt zamapowany na ten identyfikator i zwracamy ten obiekt. Zamiast tworzyć zupełnie nowy obiekt, modyfikujemy istniejący.

Przepływ dwóch kolejnych wykonań wykresu, który tworzy pojedynczy obiekt TraceExampleItem wygląda następująco:

Pierwsze wywołanie
Drugie wywołanie

Ten sam pomysł przedstawiono w następnym przykładzie z bardziej realistycznym przypadkiem użycia węzła DynamoRevit.

Diagram śledzenia

Kroki śledzenia
Przepływ śledzenia

UWAGA:

W najnowszych wersjach dodatku Dynamo używanie TLS (lokalnego magazynu wątków) zastąpiono używaniem elementu statycznego.

Przykład implementacji powiązywania elementów


Przyjrzyjmy się pokrótce temu, jak wygląda węzeł korzystający z powiązywania elementów w przypadku zaimplementowaniu go w dodatku DynamoRevit. Jest to analogiczne do typu węzła używanego powyżej w podanych przykładach z tworzeniem ścian.


    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);
        }

Powyższy kod ilustruje przykładowy konstruktor elementu ściany — ten konstruktor zostałby wywołany z węzła w dodatku Dynamo, na przykład: Wall.byParams

Oto ważne etapy wykonywania konstruktora w odniesieniu do powiązywania elementów:

  1. Użyj elementBinder, aby sprawdzić, czy istnieją wcześniej utworzone obiekty, które były powiązane z tym miejscem wywołania w poprzednim uruchomieniu. ElementBinder.GetElementFromTrace<Autodesk.Revit.DB.Wall>

  2. Jeśli tak, spróbuj zmodyfikować tę ścianę, zamiast tworzyć nową.

 if(!CurveUtils.CurvesAreSimilar(wallLocation.Curve, curve))
                        wallLocation.Curve = curve;
  1. W przeciwnym razie utwórz nową ścianę.

  var wall = successfullyUsedExistingWall ? wallElem :
                     Autodesk.Revit.DB.Wall.Create(Document, curve, wallType.Id, baseLevel.Id, height, offset, flip, isStructural);
                     
  1. Usuń stary element, który właśnie pobrano ze śladu, i dodaj nowy, aby można było wyszukać ten element w przyszłości:

 ElementBinder.CleanupAndSetElementForTrace(Document, InternalWall);

Omówienie

Sprawność

  • Obecnie każdy obiekt śledzenia z serializowaniem jest serializowany przy użyciu formatowania xml SOAP — jest to dość rozwlekłe i obejmuje powielanie dużej ilości informacji. Następnie dane są kodowane dwukrotnie do postaci base64 — nie jest to wydajne pod względem serializacji ani deserializacji. Może to zostać poprawione w przyszłości, jeśli format wewnętrzny nie jest oparty na innym. Jeszcze raz przypominamy, że nie należy polegać na formacie danych zserializowanych w spoczynku.

Czy powiązywanie elementów (ElementBinding) powinno być domyślnie włączone?

  • Istnieją przykłady zastosowań, w których powiązywanie elementów nie jest pożądane. Co zrobić w sytuacji, gdy zaawansowany użytkownik dodatku Dynamo tworzy program, który powinien być wielokrotnie uruchamiany w celu generowania losowych elementów grupowań? Celem programu jest utworzenie dodatkowych elementów przy każdym uruchomieniu programu. Nie jest łatwo zrealizować ten przypadek bez stosowania obejść na potrzeby zapobiegania działaniu powiązywania elementów. Powiązywanie elementów można wyłączyć na poziomie integracji, ale prawdopodobnie powinna to być funkcja podstawowa dodatku Dynamo. Nie jest jasne, jak szeroki powinien być zasięg tej funkcjonalności: na poziomie węzła, na poziomie miejsca wywołania, na poziomie całej sesji dodatku Dynamo czy może na poziomie obszaru roboczego — itd.

Węzły wyboru dodatku Dynamo Revit (czym są?)

Ogólnie rzecz biorąc, węzły te umożliwiają użytkownikowi opisanie podzestawu aktywnego dokumentu programu Revit, do którego chce utworzyć odniesienie. Istnieją różne sposoby, w jakie użytkownik może odwoływać się do elementu programu Revit (opisane poniżej), a wynikowe dane wyjściowe węzła mogą być opakowaniem elementu programu Revit (opakowaniem dodatku DynamoRevit) lub geometrią dodatku Dynamo (przekonwertowaną z geometrii programu Revit). Różnica między tymi typami danych wyjściowych będzie przydatna do rozważenia w kontekście innych integracji programu nadrzędnego.

Ogólnie rzecz biorąc, dobrym sposobem myślenia o tych węzłach jest traktowanie ich jako funkcji, która przyjmuje identyfikator elementu i zwraca wskaźnik do tego elementu lub geometrię reprezentującą ten element.

W dodatku DynamoRevit istnieje wiele węzłów wyboru (Selection). Można je podzielić na co najmniej dwie grupy:

Węzły wyboru programu Revit
  1. Wskazywanie w interfejsie użytkownika:

    Przykładowe węzły DynamoRevit w tej kategorii to SelectModelElement, SelectElementFace

    Te węzły umożliwiają użytkownikowi przełączenie się do kontekstu interfejsu użytkownika programu Revit i wybranie elementu lub zestawu elementów. Identyfikatory tych elementów są przechwytywane i uruchamiana jest jedna z funkcji konwersji — utworzone zostaje opakowanie lub z elementu zostaje wyodrębniona i przekonwertowana geometria. Przebieg konwersji zależy od typu węzła wybranego przez użytkownika.

  2. Zapytanie dotyczące dokumentu:

    Przykładowe węzły w tej kategorii to AllElementsOfClass, AllElementsOfCategory

    Te węzły umożliwiają użytkownikowi zbadanie całego dokumentu w poszukiwaniu podzestawu elementów. Węzły te zazwyczaj zwracają opakowania, które wskazują źródłowe elementy programu Revit. Te opakowania są integralną częścią środowiska dodatku DynamoRevit. Udostępniają one bardziej zaawansowane funkcje, takie jak powiązywanie elementów, i umożliwiają twórcom integracji dodatku Dynamo wybieranie, które interfejsy API programu nadrzędnego mają być udostępniane użytkownikom jako węzły.

Procesy użytkownika dodatku Dynamo Revit:

Przykłady

    • Użytkownik wybiera ścianę programu Revit za pomocą węzła SelectModelElement — do wykresu zwracane jest opakowanie ściany dodatku Dynamo (widoczne w dymku podglądu węzła).

    • Użytkownik umieszcza węzeł Element.Geometry i dołącza do tego nowego węzła dane wyjściowe węzła SelectModelElement. Geometria ściany w opakowaniu zostaje wyodrębniona i przekonwertowana na geometrię dodatku Dynamo przy użyciu interfejsu API libG.

    • Użytkownik przełącza wykres w tryb uruchamiania automatycznego.

    • Użytkownik modyfikuje ścianę pierwotną w programie Revit.

    • Wykres jest automatycznie ponownie uruchamiany, ponieważ dokument programu Revit wywołał zdarzenie sygnalizujące zaktualizowanie niektórych elementów. Węzeł wyboru (Selection) obserwuje to zdarzenie i dostrzega, że identyfikator wybranego elementu został zmodyfikowany.

Procesy użytkownika dodatku DynamoCivil:

Procesy robocze w dodatku D4C są bardzo podobne do opisanych powyżej dla programu Revit. Poniżej przedstawiono dwa typowe zestawy węzłów wyboru w dodatku D4C:

Węzły wyboru programu Civil 3D

Problemy:

  • Z powodu aktualizatora modyfikacji dokumentu, który jest implementowany w węzłach wyboru w DynamoRevit, można łatwo wytworzyć pętle nieskończone: wyobraźmy sobie, że węzeł obserwuje dokument pod kątem wszystkich elementów, a następnie tworzy nowe elementy gdzieś na dalszym etapie po danym węźle. Ten program po uruchomieniu wyzwoli pętlę. Dodatek DynamoRevit stara się wychwycić ten przypadek na różne sposoby, używając identyfikatorów transakcji, aby uniknąć zmodyfikowania dokumentu, gdy dane wejściowe konstruktorów elementów nie uległy zmianie.

    Należy to uwzględnić, jeśli po zmodyfikowaniu wybranego elementu w aplikacji nadrzędnej jest inicjowane automatyczne wykonanie wykresu.

  • Węzły wyboru (Selection) w dodatku DynamoRevit są implementowane w bibliotece RevitUINodes.dll, która odwołuje się do platformy WPF. Może to nie stanowić problemu, ale warto mieć tego świadomość w zależności od platformy docelowej.

Diagramy przepływu danych

Przepływ wyboru
Przepływ wyboru2

Implementacja techniczna: (patrz powyższe schematy):

Węzły wyboru są implementowane przez dziedziczenie z typów ogólnych SelectionBase: SelectionBase<TSelection, TResult> i minimalnego zestawu elementów:

  • Implementacja metody BuildOutputAST: ta metoda musi zwrócić drzewo AST, które zostanie wykonane w pewnym momencie w przyszłości, kiedy ma zostać wykonany węzeł. W przypadku węzłów wyboru (Selection) powinny zostać zwrócone elementy lub geometria na podstawie identyfikatorów elementów. https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodesUI/Selection.cs#L280

  • Implementacja metody BuildOutputAST jest jedną z najtrudniejszych części implementacji węzłów NodeModel/interfejsu użytkownika. Najlepiej jest umieścić jak największą część logiki w funkcji C# i po prostu osadzić węzeł z wywołaniem funkcji AST w drzewie AST. Należy pamiętać, że w tym przypadku node jest węzłem AST w drzewie składni abstrakcyjnej, a nie węzłem wykresu Dynamo.

Przepływ wyboru2
  • Serializacja —

    • Ponieważ są to jawne typy pochodne NodeModel (a nie ZeroTouch), wymagają one również zaimplementowania konstruktora [JsonConstructor], który będzie używany podczas deserializacji węzła z pliku .dyn.

      Odniesienia do elementów z programu nadrzędnego powinny być zapisane w pliku .dyn, tak aby po otwarciu przez użytkownika wykresu zawierającego ten węzeł wybór był nadal ustawiony. Węzły NodeModel w dodatku Dynamo używają biblioteki Json.net do serializacji. Wszystkie właściwości publiczne są serializowane automatycznie przy użyciu biblioteki Json.net — użyj atrybutu [JsonIgnore] w celu serializowania tylko tego, co jest niezbędne.

  • Węzły zapytań dotyczących dokumentu (Document Query) są nieco prostsze, ponieważ nie muszą przechowywać odwołań do żadnych identyfikatorów elementów. Zobacz poniżej, aby zapoznać się z implementacjami klasy ElementQueryBase i klas pochodnych. W przypadku wykonania węzły te wywołują interfejs API programu Revit i wysyłają zapytanie dotyczące elementów do dokumentu źródłowego, a następnie wykonują wspomnianą wcześniej konwersję na geometrię lub opakowania elementów programu Revit.

Odniesienia:

Klasy bazowe DynamoCore:

  • https://github.com/DynamoDS/Dynamo/blob/ec10f936824152e7dd7d6d019efdcda0d78a5264/src/Libraries/CoreNodeModels/Selection.cs

  • Analiza przypadku NodeModel — niestandardowy interfejs użytkownika

  • Aktualizowanie pakietów i bibliotek dodatku Dynamo dla dodatku Dynamo 2.x

  • Aktualizowanie pakietów i bibliotek dodatku Dynamo dla dodatku Dynamo 3.x

DynamoRevit:

  • https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodesUI/Selection.cs

  • https://github.com/DynamoDS/DynamoRevit/blob/master/src/Libraries/RevitNodesUI/Elements.cs

Przegląd pakietów wbudowanych dodatku Dynamo

Mechanizm pakietów wbudowanych ma na celu dołączenie do dodatku Dynamo Core większej ilości zawartości węzłów bez rozszerzania samego rdzenia (Core) przez wykorzystanie funkcji wczytywania pakietów dodatku Dynamo zaimplementowanej przez rozszerzenia PackageLoader i PackageManager.

W tym dokumencie będziemy używać zamiennie terminów „pakiety wbudowane” i „pakiety wbudowane dodatku Dynamo” — oznaczają one to samo.

Czy należy dostarczyć pakiet jako pakiet wbudowany?

  • Pakiet musi mieć podpisane binarne punkty wejścia — w przeciwnym razie nie zostanie wczytany.

  • Należy dołożyć wszelkich starań w celu uniknięcia zmian powodujących niezgodności w tych pakietach. Oznacza to, że zawartość pakietu powinna obejmować testy automatyczne.

  • Semantyczna obsługa wersji — prawdopodobnie dobrym pomysłem jest obsługa wersji pakietu przy użyciu semantycznego schematu obsługi wersji i poinformowanie o tym użytkowników w opisie lub dokumentacji pakietu.

  • Testy automatyczne. Patrz powyżej: jeśli pakiet jest dołączony za pomocą mechanizmu pakietów wbudowanych, dla użytkownika wygląda on jak część produktu i powinien być testowany jak produkt.

  • Wysoki poziom dopracowania: ikony, dokumentacja węzłów, zlokalizowana treść.

  • Nie dostarczaj pakietów, których Ty lub Twój zespół nie możecie obsługiwać.

  • Nie dostarczaj pakietów innych firm tą metodą (patrz wyżej).

Ogólnie użytkownik powinien mieć pełną kontrolę nad pakietem, możliwość jego naprawiania, aktualizowania i testowania pod kątem najnowszych zmian w dodatku Dynamo i w produkcie. Musisz też być w stanie podpisać pakiet.

Pakiety wbudowane a pakiety charakterystyczne dla integracji z programem nadrzędnym

Built-In Packages to ma być funkcja podstawowa — zestaw pakietów, do których dostęp uzyskują wszyscy użytkownicy, nawet jeśli nie mają dostępu do Menedżera pakietów. Obecnie mechanizmem źródłowym obsługującym tę funkcję jest dodatkowa domyślna lokalizacja wczytywania pakietów bezpośrednio w katalogu Dynamo Core — względna wobec biblioteki DynamoCore.dll.

Z pewnymi ograniczeniami tej lokalizacji mogą używać klienci i twórcy integracji dodatku ADSK Dynamo do dystrybucji pakietów charakterystycznych dla integracji. (Na przykład integracja dodatku Dynamo z programem Formit wymaga niestandardowego pakietu Dynamo dla programu Formit).

Ponieważ mechanizm źródłowy wczytywania jest taki sam zarówno dla pakietów podstawowych, jak i dla pakietów charakterystycznych dla integracji z programem nadrzędnym, konieczne będzie upewnienie się, że pakiety dystrybuowane w ten sposób nie powodują u użytkowników mylenia pakietów podstawowych Built-In Packages z pakietami charakterystycznymi dla integracji, które są dostępne tylko w jednym produkcie programu nadrzędnego. Zaleca się, aby w celu uniknięcia pomyłek u użytkowników przedstawić wprowadzenie dotyczące pakietów charakterystycznych dla programu nadrzędnego w ramach dyskusji z zespołami ds. dodatku Dynamo.

Lokalizacja pakietu

Ponieważ pakiety z zestawu Built-In Packages będą dostępne dla większej liczby klientów, a gwarancje, których w związku z nimi udzielamy, będą bardziej rygorystyczne (patrz wyżej), powinny one być zlokalizowane.

W przypadku wewnętrznych pakietów ADSK przeznaczonych do dołączenia do zestawu Built-In Packages — bieżące ograniczenia związane z brakiem możliwości opublikowania zlokalizowanej zawartości w Menedżerze pakietów nie blokują działań, ponieważ pakiety niekoniecznie muszą być publikowane w Menedżerze pakietów.

Korzystając z obejścia, można ręcznie tworzyć (a nawet publikować) pakiety z podkatalogami kultur w folderze /bin pakietu.

Najpierw ręcznie utwórz potrzebne podkatalogi charakterystyczne dla kultur w folderze /bin pakietów.

Jeśli z jakiegoś powodu pakiet musi zostać opublikowany również w Menedżerze pakietów, należy najpierw opublikować wersję pakietu bez tych podkatalogów kultur, a następnie opublikować nową wersję pakietu za pomocą DynamoUI publish package version. Przekazanie nowej wersji w dodatku Dynamo nie powinno skutkować usunięciem folderów i plików w folderze /bin, które zostały dodane ręcznie za pomocą Eksploratora plików systemu Windows. Proces przekazywania pakietów w dodatku Dynamo zostanie zaktualizowany, aby w przyszłości spełniał wymagania dotyczące zlokalizowanych plików.

Te podkatalogi kultur są bez problemu wczytywane przez środowisko uruchomieniowe platformy .net, jeśli znajdują się w tym samym katalogu co pliki binarne węzłów/rozszerzeń.

Aby uzyskać więcej informacji na temat zespołów zasobów i plików resx, zobacz: https://docs.microsoft.com/pl-pl/dotnet/framework/resources/creating-resource-files-for-desktop-apps.

Prawdopodobnie będziesz tworzyć pliki .resx i kompilować je za pomocą programu Visual Studio. Dla danego pliku xyz.dll zespołu — wynikowe zasoby zostaną skompilowane do postaci nowego pliku xyz.resources.dll zespołu — jak opisano powyżej, ważne są położenie i nazwa tego zespołu.

Wygenerowany plik xyz.resources.dll powinien znajdować się w następującej ścieżce: package\bin\culture\xyz.resources.dll.

Aby uzyskać dostęp do zlokalizowanych ciągów w pakiecie, można użyć komponentu ResourceManager — jest jednak jeszcze prostszy sposób: powinno być możliwe odwoływanie się do zasobu Properties.Resources.YourLocalizedResourceName z poziomu zespołu, dla którego dodano plik .resx. Zobacz:

https://github.com/DynamoDS/Dynamo/blob/master/src/Libraries/CoreNodes/List.cs#L457, aby zapoznać się z przykładem zlokalizowanego komunikatu o błędzie.

Lub https://github.com/DynamoDS/Dynamo/blob/master/src/Libraries/CoreNodeModels/ColorRange.cs#L19, aby poznać przykład zlokalizowanego ciągu atrybutu NodeDescription charakterystycznego dla dodatku Dynamo.

Lub https://github.com/DynamoDS/DynamoSamples/blob/master/src/SampleLibraryUI/Examples/LocalizedCustomNodeModel.cs, aby poznać inny przykład.

Układ biblioteki węzłów

Zazwyczaj gdy dodatek Dynamo wczytuje węzły z pakietu, umieszcza je w sekcji Addons w bibliotece węzłów. Aby lepiej zintegrować węzły pakietów wbudowanych z inną zawartością wbudowaną, dodaliśmy możliwość dostarczania przez autorów pakietów wbudowanych częściowego pliku layout specification w celu ułatwienia umieszczania nowych węzłów we właściwej kategorii najwyższego poziomu w sekcji biblioteki default.

Na przykład jeśli następujący plik JSON specyfikacji układu zostanie znaleziony w ścieżce package/extra/layoutspecs.json, spowoduje umieszczenie węzłów określonych przez path w kategorii Revit w sekcji default, która jest główną sekcją węzłów wbudowanych.

Należy pamiętać, że węzły zaimportowane z pakietu wbudowanego będą miały przedrostek bltinpkg://, gdy będzie rozważane ich dopasowanie względem ścieżki uwzględnionej w specyfikacji układu.

{
  "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": []
            }
          ]
        }
      ]
    }
  ]
}

Złożone modyfikacje układu nie zostały dobrze przetestowane ani nie są dobrze obsługiwane. Celem wczytywania tej konkretnej specyfikacji układu jest przeniesienie całej przestrzeni nazw pakietu do określonej kategorii programu nadrzędnego, takiej jak Revit lub Formit.

Aktualizowanie pakietów i bibliotek dodatku Dynamo dla dodatku Dynamo 2.x

Wprowadzenie:

Dodatek Dynamo 2.0 jest wersją główną i niektóre interfejsy API zostały w nim zmienione lub usunięte. Jedną z największych zmian istotnych dla twórców węzłów i pakietów jest przejście na format pliku JSON.

Ogólnie twórcy węzłów Zero Touch nie muszą robić wiele albo w ogóle nic, aby zadbać o działanie pakietów w wersji 2.0.

Zadbanie o działanie w wersji 2.x węzłów interfejsu użytkownika i węzłów pochodnych bezpośrednio od klasy NodeModel wymaga więcej pracy.

Twórcy rozszerzeń również mogą być zmuszeni do wprowadzenia pewnych zmian w zależności od tego, w jakim stopniu wykorzystują w rozszerzeniach podstawowe interfejsy API dodatku Dynamo.


Ogólne zasady dotyczące pakowania:

  • Nie należy łączyć z pakietem plików .dll dodatku Dynamo ani dodatku Dynamo Revit. Te biblioteki dll zostaną już wczytane przez dodatek Dynamo. W przypadku utworzenia pakietu z wersją inną niż wersja wczytana przez użytkownika (na przykład zostanie utworzona dystrybucja Dynamo Core 1.3, podczas gdy użytkownik uruchamia pakiet w dodatku Dynamo 2.0) wystąpią tajemnicze błędy w czasie wykonywania. Obejmuje to pliki dll takie jak DynamoCore.dll, DynamoServices.dll, DSCodeNodes.dll, ProtoGeometry.dll

  • Należy w miarę możliwości unikać dodawania do pakietu i dystrybuowania z pakietem pliku newtonsoft.json.net. Ten plik dll również zostanie wcześniej wczytany przez dodatek Dynamo 2.x. Może wystąpić ten sam problem co powyżej.

  • Należy w miarę możliwości unikać dodawania do pakietu i dystrybuowania z pakietem pliku CEFSharp. Ten plik dll również zostanie wcześniej wczytany przez dodatek Dynamo 2.x. Może wystąpić ten sam problem co powyżej.

  • Ogólnie należy unikać udostępniania zależności wraz z dodatkiem Dynamo lub programem Revit, jeśli zachodzi potrzeba kontrolowania wersji tej zależności.

Typowe problemy:

  1. Po otwarciu wykresu niektóre węzły mają wiele portów o tej samej nazwie, mimo że wykres wyglądał dobrze podczas zapisywania. Ten problem może mieć kilka przyczyn.

Typową przyczyną jest to, że węzeł utworzono za pomocą konstruktora ponownie tworzącego porty. Zamiast tego należało użyć konstruktora wczytującego porty. Te konstruktory mają zwykle oznaczenie [JsonConstructor] zobacz przykłady poniżej

Uszkodzony kod JSON

Inna możliwa przyczyna:

  • Nie było zgodnych elementów [JsonConstructor] lub nie przekazano elementów Inports i Outports z pliku JSON.dyn.

  • W tym samym czasie do tego samego procesu wczytano dwie wersje JSON.net, co spowodowało błąd środowiska uruchomieniowego .NET, więc nie można było poprawnie użyć atrybutu [JsonConstructor] do oznaczenia konstruktora.

  • Do pakietu dołączono plik DynamoServices.dll w wersji innej niż bieżąca wersja dodatku Dynamo i powoduje to, że środowisko uruchomieniowe .NET nie może zidentyfikować atrybutu [MultiReturn], więc dla węzłów Zero-Touch oznaczonych różnymi atrybutami nie można zastosować tych atrybutów. Może się okazać, że węzeł zwraca jeden słownik wyjściowy zamiast wielu portów.

  1. Całkowicie brakuje węzłów po wczytaniu wykresu z pewnymi błędami w konsoli.

  • Może tak się zdarzyć, jeśli z jakiegoś powodu nie powiedzie się deserializacja. Zaleca się serializowanie tylko potrzebnych właściwości. Można używać atrybutu [JsonIgnore] w przypadku złożonych właściwości, których nie trzeba wczytywać ani zapisywać, aby je zignorować. Chodzi o właściwości takie jak function pointer, delegate, action, czy event. Nie należy ich serializować, ponieważ zazwyczaj nie można ich zdeserializować i powodują one błąd w trakcie wykonywania.

Szczegółowe omówienie uaktualnienia:

Węzły niestandardowe z wersji 1.3 do wersji 2.0

Organizowanie węzłów niestandardowych w pliku librarie.js

Znane problemy:

  • Zbieżna nazwa węzła niestandardowego i nazwa kategorii na tym samym poziomie w pliku librarie.js skutkuje nieoczekiwanym zachowaniem. QNTM-3653 — unikaj używania tych samych nazw kategorii i węzłów.

  • Komentarze zostaną zamienione na komentarze blokowe zamiast komentarzy jednowierszowych.

  • Krótkie nazwy typów zostaną zastąpione pełnymi nazwami. Jeśli na przykład podczas ponownego wczytywania węzła niestandardowego nie został określony typ, pojawi się var[]..[] — ponieważ jest to typ domyślny.

Węzły Zero-Touch z wersji 1.3 do wersji 2.0

  • W dodatku Dynamo 2.0 typy List (lista) i Dictionary (słownik) zostały rozdzielone, a składnia tworzenia list i słowników została zmieniona. Listy inicjuje się przy użyciu [], a słowniki przy użyciu {}. Jeśli wcześniej używano atrybutu DefaultArgument do oznaczania parametrów w węzłach Zero-Touch i używano składni listy w celu utworzenia konkretnej listy domyślnej, takiej jak someFunc([DefaultArgument("{0,1,2}")]), nie będzie to już poprawne. Należy zmodyfikować fragment kodu DesignScript, stosując nową składnię inicjowania list.

  • Jak wspomniano powyżej, nie należy dystrybuować plików dll dodatku Dynamo wraz z pakietami. (DynamoCore, DynamoServices itp.)

Węzły Node Model z wersji 1.3 do wersji 2.0

Zaktualizowanie węzłów Node Model do wersji Dynamo 2.x wymaga najwięcej pracy. Ogólnie należy zaimplementować konstruktory, które będą używane tylko do wczytywania węzłów z pliku json obok zwykłych konstruktorów klasy nodeModel używanych do tworzenia nowych wystąpień typów węzłów. Aby odróżnić te elementy, należy oznaczyć konstruktory czasu ładowania atrybutem [JsonConstructor], który jest atrybutem z biblioteki newtonsoft.Json.net.

Nazwy parametrów w konstruktorze powinny zasadniczo odpowiadać nazwom właściwości JSON — jednak to odwzorowanie jest bardziej skomplikowane w przypadku nadpisywania nazw serializowanych przy użyciu atrybutów [JsonProperty]. Więcej informacji można znaleźć w dokumentacji Json.net.

Konstruktory JSON

Najczęstszą zmianą, jaką należy wprowadzić w celu zaktualizowania węzłów pochodnych od klasy bazowej NodeModel (lub innych klas bazowych dodatku Dynamo, na przykład DSDropDownBase), jest konieczność dodania do klasy konstruktora JSON.

Oryginalny konstruktor bez parametrów nadal będzie obsługiwał inicjowanie nowego węzła tworzonego w dodatku Dynamo (na przykład za pomocą biblioteki). Konstruktor JSON jest wymagany do zainicjowania węzła, który został zdeserializowany (wczytany) z zapisanego pliku .dyn lub .dyf.

Konstruktor JSON różni się od konstruktora bazowego tym, że ma parametry PortModel dla portów inPorts i outPorts, które są dostarczane przez logikę ładowania JSON. Wywołanie w celu zarejestrowania portów dla węzła nie jest tutaj wymagane, ponieważ dane istnieją w pliku .dyn. Przykład konstruktora JSON wygląda tak:

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) { }

Ta składnia :base(Inports,outPorts){} wywołuje konstruktor bazowy nodeModel i przekazuje do niego zdeserializowane porty.

Nie jest wymagane powtarzanie w tym konstruktorze żadnej specjalnej logiki istniejącej w konstruktorze klasy, która obejmuje zainicjowanie określonych danych zserializowanych do pliku .dyn (na przykład ustawiania rejestracji portu, strategii skratowania itp.), ponieważ te wartości można odczytać z pliku JSON.

Jest to główna różnica między konstruktorami JSON i innymi konstruktorami NC w przypadku klas nodeModel. Konstruktory JSON są wywoływane podczas wczytywania z pliku i są do nich przekazywane wczytane dane. W konstruktorze JSON należy jednak powielić inną logikę użytkownika (na przykład inicjowanie obsługi zdarzeń dla węzła lub dołączanie).

Przykłady można znaleźć tutaj w repozytorium DynamoSamples -> ButtonCustomNodeModel, DropDown lub SliderCustomNodeModel

Właściwości publiczne i serializowanie

Wcześniej programista mógł serializować i deserializować określone dane modelu do dokumentu xml za pomocą metod SerializeCore i DeserializeCore. Te metody nadal istnieją w interfejsie API, ale zostaną wycofane w przyszłej wersji dodatku Dynamo (przykład można znaleźć tutaj). Dzięki implementacji JSON.NET właściwości public klasy pochodnej od klasy NodeModel można teraz serializować bezpośrednio do pliku .dyn. W środowisku JSON.Net dostępnych jest wiele atrybutów umożliwiających sterowanie sposobem serializowania właściwości.

W repozytorium dodatku Dynamo, tutaj, można znaleźć przykład określający atrybut PropertyName.

[JsonProperty(PropertyName = "InputValue")]

public DSColor DsColor {...

Konwertery:

Uwaga Jeśli tworzysz własną klasę konwertera JSON.net: dodatek Dynamo nie ma obecnie mechanizmu umożliwiającego wstrzyknięcie jej do metod wczytywania i zapisywania, więc nawet jeśli oznaczysz tę klasę atrybutem [JsonConverter], może ona nie zostać użyta. Zamiast tego możesz wywołać ten konwerter bezpośrednio w mechanizmie ustawiania (setter) lub pobierania (getter). //DO OPRACOWANIA Wymagane jest potwierdzenie tego ograniczenia. Wszelkie dowody są mile widziane.

W repozytorium dodatku Dynamo, tutaj, można znaleźć przykład określający metodę serializacji do konwertowania właściwości na ciąg.

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

public ConversionMetricUnit SelectedMetricConversion{...

Ignorowanie właściwości

Właściwości public, które nie są przeznaczone do serializacji, muszą mieć dodany atrybut [JsonIgnore]. Po zapisaniu węzłów w pliku .dyn zapewnia to ignorowanie tych danych przez mechanizm serializowania, więc nie będą one powodować nieoczekiwanych konsekwencji po ponownym otwarciu wykresu. Przykład tego można znaleźć tutaj w repozytorium dodatku Dynamo.


Cofanie/ponawianie

Jak wspomniano powyżej, w przeszłości używano metod SerializeCore i DeserializeCore do zapisywania i wczytywania węzłów do pliku xml .dyn. Dodatkowo były też używane do zapisywania i wczytywania stanu węzła na potrzeby operacji cofania/ponawiania — i nadal są. Aby zaimplementować złożone funkcje cofania/ponawiania dla węzła interfejsu użytkownika nodeModel, należy zaimplementować te metody i zserializować je w obiekcie dokumentu XML dostarczanym jako parametr tych metod. Powinno to być stosowane rzadko, w przypadku złożonych węzłów interfejsu użytkownika.

Interfejsy API portów wejściowych i wyjściowych

Jedną z typowych sytuacji w przypadku węzłów nodeModel, na którą wpływają zmiany interfejsu API 2.0, jest rejestracja portów w konstruktorze węzła. Wcześniej podczas przyglądania się przykładom w repozytorium Dynamo lub DynamoSamples można było znaleźć przypadki użycia metody InPortData.Add() lub OutPortData.Add(). Wcześniej w interfejsie API dodatku Dynamo właściwości publiczne InPortData i OutPortData były oznaczone jako wycofane. W wersji 2.0 właściwości te zostały usunięte. Programiści powinni teraz korzystać z metod InPorts.Add() i OutPorts.Add(). Ponadto te dwie metody Add() mają nieco inne sygnatury:

InPortData.Add(new PortData("Port Name", "Port Description")); //Old version valid in 1.3 but now deprecated

w porównaniu z nową

InPorts.Add(new PortModel(PortType.Input, this, new PortData("Port Name", "Port Description"))); //Recommended 2.0

Przykłady przekonwertowanego kodu można znaleźć tutaj w repozytorium dodatku Dynamo -> DynamoConvert.cs lub FileSystem.cs

Inny typowy przypadek użycia, na który wpływają zmiany interfejsu API 2.0, dotyczy metod powszechnie używanych w metodzie BuildAst() w celu określania zachowania węzłów na podstawie występowania lub braku złączy portów. Wcześniej do sprawdzania stanu połączenia portu używano metody HasConnectedInput(index). Programiści powinni teraz sprawdzać stan połączenia portu za pomocą właściwości InPorts[0].IsConnected. Przykład tego można znaleźć w pliku ColorRange.cs w repozytorium dodatku Dynamo.

Przykłady:

Przeanalizujmy proces uaktualniania węzła interfejsu użytkownika w wersji 1.3 do wersji Dynamo 2.x.

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) };
        }
    }
}

W przypadku klasy nodeModel, aby zapewnić poprawne wczytywanie i zapisywanie portów w wersji 2.0, wystarczy tylko dodać konstruktor jsonConstructor do obsługi wczytywania portów. Po prostu przekazujemy porty do konstruktora bazowego, a ta implementacja jest pusta.

[JsonConstructor]
protected GridNodeModel(IEnumerable<PortModel> Inports, IEnumerable<PortModel> Outports ) :
base(Inports,Outports)
{

}

Uwaga: nie należy wywoływać operacji RegisterPorts() ani jej odmian w konstruktorze JsonConstructor — użyje ona atrybutów parametrów wejściowych i wyjściowych w klasie węzła w celu utworzenia nowych portów. Nie chcemy, aby tak się stało, ponieważ chcemy używać wczytanych portów, które są przekazywane do konstruktora.

[InPortNames("xCount", "yCount")]
[InPortTypes("double", "double")]

W tym przykładzie dodano minimalny konstruktor JSON wczytywania. Co jednak zrobić, jeśli trzeba utworzyć bardziej złożoną logikę konstrukcji, na przykład skonfigurować pewne detektory do obsługi zdarzeń wewnątrz konstruktora. Następny przykład pochodzący z repozytorium DynamoSamples połączono powyżej części JsonConstructors Section w tym dokumencie.

Poniżej przedstawiono bardziej złożony konstruktor węzła interfejsu użytkownika:

 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;
        }

Podczas dodawania konstruktora JSON na potrzeby wczytywania tego węzła z pliku należy ponownie utworzyć niektóre elementy tej logiki, ale nie należy dodawać kodu tworzącego porty, ustawiającego skratowanie ani ustawiającego wartości domyślne właściwości, który można wczytać z pliku.

        // 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);
        }

Należy pamiętać, że inne właściwości publiczne zserializowane do pliku JSON, takie jak ButtonText i WindowText, nie powinny być dodawane do konstruktora jako parametry jawne — są one ustawiane automatycznie przez środowisko JSON.net za pomocą mechanizmów ustawiania (setter) tych właściwości.

Zaawansowane dostosowywanie węzłów dodatku Dynamo

Masz już ugruntowaną wiedzę na temat węzłów ZeroTouch. W tej sekcji omówiono zalety dostosowywania węzłów dodatku Dynamo w celu usprawniania funkcjonalności i środowiska użytkownika. Dodając funkcje, takie jak komunikaty ostrzegawcze, komunikaty informacyjne i ikony niestandardowe, można tworzyć węzły, które są bardziej intuicyjne i atrakcyjne wizualnie oraz dostarczają więcej informacji. Te dostosowania nie tylko pomagają użytkownikom zrozumieć potencjalne problemy lub zoptymalizować proces, ale sprawiają też, że węzły te wyróżniają się jako profesjonalne i przyjazne dla użytkownika narzędzia.

Dostosowywanie węzłów to doskonały sposób na zapewnienie, że rozwiązania będą przejrzyste, niezawodne i dopasowane do konkretnych potrzeb projektu.

Generowanie niestandardowych komunikatów ostrzegawczych za pomocą metody OnLogWarningMessage

W dodatku Dynamo metoda OnLogWarningMessage umożliwia rejestrowanie komunikatów ostrzegawczych bezpośrednio w konsoli dodatku Dynamo. Jest to zaawansowana funkcja, szczególnie w przypadku węzłów Zero Touch, ponieważ umożliwia programistom ostrzeganie użytkowników o problemach z danymi wejściowymi lub parametrami, które mogą prowadzić do nieoczekiwanego zachowania. Z tego podręcznika dowiesz się, jak zaimplementować metodę OnLogWarningMessage w dowolnym węźle Zero-Touch.

Kroki implementacji metody OnLogWarningMessage

Krok 1. Zaimportuj wymaganą przestrzeń nazw

Metoda OnLogWarningMessage jest częścią przestrzeni nazw DynamoServices, więc zacznij od dodania jej do pliku projektu.

using DynamoServices;

Krok 2. Określ, kiedy należy rejestrować ostrzeżenia

Przed dodaniem komunikatu ostrzegawczego należy wziąć pod uwagę logikę metody:

  • Jakie warunki mogą spowodować niepoprawne lub nieoczekiwane wyniki?

  • Czy istnieją określone wartości lub parametry wejściowe wymagane do poprawnego działania metody?

Przykłady warunków do sprawdzenia:

  • Wartości spoza zakresu (np. if (inputValue < 0)).

  • Kolekcje o wartości null lub puste (np. if (list == null || list.Count == 0)).

  • Niezgodny typ danych (np. jeśli typ pliku nie jest obsługiwany).

Krok 3. Zarejestruj ostrzeżenie za pomocą metody OnLogWarningMessage

Umieść wywołania metody OnLogWarningMessage, w których będziesz wykrywać warunki mogące powodować problemy. Gdy warunek zostanie spełniony, zarejestruj komunikat ostrzegawczy, który zawiera jasne wskazówki dla użytkownika.

Składnia metody OnLogWarningMessage

LogWarningMessageEvents.OnLogWarningMessage("Your warning message here.");

Przykładowe implementacje metody OnLogWarningMessage

Aby zademonstrować metodę OnLogWarningMessage w działaniu, poniżej przedstawiono różne scenariusze, które można napotkać podczas tworzenia węzła Zero Touch.

Przykład 1. Sprawdzanie wejściowych wartości liczbowych

W tym przykładzie wykorzystaliśmy węzeł niestandardowy utworzony w poprzedniej części „Analiza przypadku Zero-Touch — węzeł siatki” do utworzenia metody o nazwie RectangularGrid, która generuje siatkę prostokątów na podstawie danych wejściowych xCount i yCount. Przeanalizujemy testowanie przypadku, w którym dane wejściowe są nieprawidłowe, i użyjemy metody OnLogWarningMessage do zarejestrowania ostrzeżenia oraz zatrzymamy przetwarzanie.

OnLogWarningMessage — przykład 1

Używanie metody OnLogWarningMessage do weryfikowania danych wejściowych

Podczas generowania siatki na podstawie danych xCount i yCount przed kontynuowaniem należy się upewnić, że obie wartości są dodatnimi liczbami całkowitymi.

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

W tym przykładzie:

  • Warunek: jeśli wartość xCount lub yCount jest mniejsza niż lub równa zero.

  • Komunikat: "Grid count values must be positive integers."

Spowoduje to wyświetlenie ostrzeżenia w dodatku Dynamo, jeśli użytkownik wprowadzi wartości zerowe lub ujemne, co ułatwi zrozumienie oczekiwanych danych wejściowych.

Wiemy już, jak to wygląda, więc możemy zaimplementować to w przykładowym węźle Grids:

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;
        }
    }
}

Przykład 2. Sprawdzanie pod kątem kolekcji o wartości null lub pustych

Jeśli metoda wymaga listy punktów, ale użytkownik przekaże listę pustą lub listę o wartości null, możesz poinformować go o problemie za pomocą metody OnLogWarningMessage.

OnLogWarningMessage — przykład 2
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...
}

W tym przykładzie:

  • Warunek: jeśli lista points ma wartość null lub zawiera mniej niż trzy punkty.

  • Komunikat: "Point list cannot be null or have fewer than three points."

Ostrzega to użytkowników, że muszą przekazać prawidłową listę z co najmniej trzema punktami, aby utworzyć wielokąt.


Przykład 3. Sprawdzanie zgodności typu pliku

W przypadku węzła, który przetwarza ścieżki plików, warto zadbać o to, aby dozwolone były tylko niektóre typy plików. Jeśli zostanie wykryty nieobsługiwany typ pliku, powinno zostać zarejestrowane ostrzeżenie.

OnLogWarningMessage — przykład 3
public static void ProcessFile(string filePath)
{
    if (!filePath.EndsWith(".csv"))
    {
        LogWarningMessageEvents.OnLogWarningMessage("Only CSV files are supported.");
        return;
    }
    // Proceed with file processing...
}

W tym przykładzie:

  • Warunek: jeśli ścieżka pliku nie kończy się na „.csv”.

  • Komunikat: "Only CSV files are supported."

Powoduje to zwrócenie użytkownikom ostrzeżenia, że powinni upewnić się, iż przekazują plik CSV, co pomaga zapobiegać problemom związanym z niezgodnymi formatami plików.

Dodawanie komunikatów informacyjnych za pomocą metody OnLogInfoMessage

W dodatku Dynamo metoda OnLogInfoMessage z przestrzeni nazw DynamoServices umożliwia programistom rejestrowanie komunikatów informacyjnych bezpośrednio w konsoli dodatku Dynamo. Jest to przydatne do potwierdzania pomyślnych operacji, komunikowania postępu lub dostarczania dodatkowych szczegółowych informacji na temat działań węzłów. Z tego podręcznika dowiesz się, jak dodać metodę OnLogInfoMessage w dowolnym węźle Zero Touch w celu udoskonalenia informacji zwrotnych i poprawy środowiska użytkownika.

Kroki implementacji metody OnLogInfoMessage

Krok 1. Zaimportuj wymaganą przestrzeń nazw

Metoda OnLogInfoMessage jest częścią przestrzeni nazw DynamoServices, więc zacznij od dodania jej do pliku projektu.

Krok 2. Określ, kiedy należy rejestrować komunikaty informacyjne

Przed dodaniem komunikatu informacyjnego zastanów się nad celem stosowania metody:

  • Potwierdzenie jakich informacji będzie przydatne po zakończeniu operacji?

  • Czy w metodzie istnieją kluczowe kroki lub kamienie milowe, o których warto poinformować użytkowników?

Przykłady przydatnych potwierdzeń:

  • Komunikaty o ukończeniu (np. gdy siatka lub model są w pełni utworzone).

  • Szczegóły przetwarzanych danych (np. „Pomyślnie przetworzono 10 elementów”).

  • Podsumowania wykonania (np. parametry używane w procesie).

Krok 3. Zarejestruj komunikaty informacyjne za pomocą metody OnLogInfoMessage

Umieść wywołania metody OnLogInfoMessage na znaczących etapach metody. Po wykonaniu kluczowego kroku lub ukończeniu etapu zarejestruj komunikat informacyjny, aby poinformować użytkownika o tym, co się stało.

Składnia metody OnLogInfoMessage

LogWarningMessageEvents.OnLogInfoMessage("Your info message here.");

Przykładowe implementacje metody OnLogInfoMessage

Poniżej przedstawiono różne scenariusze w celu zademonstrowania stosowania metody OnLogInfoMessage w węzłach Zero-Touch.

Przykład 1. Sprawdzanie wejściowych wartości liczbowych

W tym przykładzie wykorzystaliśmy węzeł niestandardowy utworzony w poprzedniej części „Analiza przypadku Zero-Touch — węzeł siatki” do utworzenia metody o nazwie RectangularGrid, która generuje siatkę prostokątów na podstawie danych wejściowych xCount i yCount. Przeanalizujemy testowanie przypadku, w którym dane wejściowe są nieprawidłowe, i użyjemy metody OnLogInfoMessage do podania informacji po ukończeniu działania węzła.

OnLogInfoMessage — przykład 1

Używanie metody OnLogInfoMessage do weryfikowania danych wejściowych

Podczas generowania siatki na podstawie danych xCount i yCount Po wygenerowaniu siatki chcesz potwierdzić jej utworzenie, rejestrując komunikat informacyjny z wymiarami siatki.

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;
}

W tym przykładzie:

  • Warunek: proces tworzenia siatki został zakończony.

  • Komunikat: "Successfully created a grid with dimensions {xCount}x{yCount}."

Ten komunikat informuje użytkowników, że siatka została utworzona zgodnie z oczekiwaniami, co pomaga im potwierdzić, że węzeł zadziałał zgodnie z oczekiwaniami.

Wiemy już, jak to wygląda, więc możemy zaimplementować to w przykładowym węźle Grids:

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;
        }
    }
}

Przykład 2. Dostarczanie informacji o liczbie pozycji danych

Jeśli tworzysz węzeł, który przetwarza listę punktów, być może warto zarejestrować, ile punktów przetworzono pomyślnie. Może to być przydatne w przypadku dużych zestawów danych.

OnLogInfoMessage — przykład 2
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;
}

W tym przykładzie:

  • Warunek: po ukończeniu pętli pokazywanie liczby przetworzonych elementów.

  • Komunikat: "6 points were processed successfully."

Ten komunikat pomoże użytkownikom zrozumieć wynik przetwarzania i potwierdzić, że wszystkie punkty zostały przetworzone.

Przykład 3. Podsumowywanie użytych parametrów

W niektórych przypadkach przydatne jest potwierdzenie parametrów wejściowych używanych przez węzeł do ukończenia działania. Jeśli na przykład węzeł eksportuje dane do pliku, zarejestrowanie nazwy i ścieżki pliku pozwala poinformować użytkowników, że został użyty poprawny plik.

OnLogInfoMessage — przykład 3
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}.");

}

W tym przykładzie:

  • Warunek: proces eksportu został ukończony pomyślnie.

  • Komunikat: "Data exported successfully to {filePath}."

Ten komunikat potwierdza użytkownikom, że eksport zadziałał, i pokazuje dokładną ścieżkę pliku, co pomaga uniknąć nieporozumień co do lokalizacji plików.

Tworzenie i dodawanie dokumentacji niestandardowej do węzłów

Dokumentacja węzłów niestandardowych

W przeszłości w dodatku Dynamo istniały ograniczenia dotyczące sposobu, w jaki autorzy pakietów mogli dostarczać dokumentację dla tworzonych węzłów. Autorów węzłów niestandardowych obowiązywało ograniczenie, w ramach którego mogli dodawać tylko krótki opis wyświetlany w etykiecie narzędzia węzła lub mogli dostarczać pakiet z intensywnie opisanymi wykresami przykładowymi.

Opis etykiety narzędzia węzła

Nowy sposób

Dodatek Dynamo udostępnia teraz autorom pakietów ulepszony system, który pozwala na tworzenie lepszej i zapewniającej szersze informacje dokumentacji węzłów niestandardowych. W tym nowym podejściu wykorzystywany jest przyjazny dla użytkownika język Markdown do tworzenia tekstu i rozszerzenie widoku Przeglądarka dokumentacji do wyświetlania znaczników Markdown w dodatku Dynamo. Używanie języka Markdown zapewnia autorom pakietów szeroki wachlarz nowych możliwości podczas dokumentowania węzłów niestandardowych.

Co to jest Markdown?

Markdown to lekki język znaczników, którego można używać do formatowania dokumentów w postaci zwykłego tekstu. Od czasu powstania języka Markdown w 2004 roku jego popularność tylko wzrosła i jest obecnie jednym z najpopularniejszych języków znaczników na świecie.

Wprowadzenie do języka Markdown

Rozpoczęcie tworzenia plików Markdown jest łatwe — wystarczy prosty edytor tekstu, taki jak Notatnik, i można zaczynać. Istnieją jednak łatwiejsze sposoby pisania treści Markdown niż korzystanie z Notatnika. Dostępnych jest kilka edytorów online, takich jak Dillinger, które pozwalają zobaczyć zmiany w czasie rzeczywistym podczas ich wprowadzania. Innym popularnym sposobem edytowania plików Markdown jest używanie edytora kodu, takiego jak Visual Studio Code.

Co umożliwia język Markdown?

Język Markdown jest bardzo elastyczny i powinien zapewniać wystarczającą funkcjonalność, aby łatwo tworzyć dobrą dokumentację — w tym dodawanie plików multimedialnych, takich jak obrazy lub filmy, tworzenie tabel z różnymi formami treści i oczywiście stosowanie prostego formatowania tekstu, takiego jak pogrubienie lub kursywa. Wszystko to i wiele więcej jest możliwe podczas pisania dokumentów Markdown — aby uzyskać więcej informacji, zapoznaj się z tym przewodnikiem, w którym wyjaśniono podstawową składnię języka Markdown.

Dodawanie rozszerzonej dokumentacji do węzłów

Dodawanie dokumentacji do węzłów jest łatwe. Dokumentację można dodać do wszystkich odmian węzłów niestandardowych. Obejmuje to:

  • Gotowe węzły dodatku Dynamo.

  • Węzły niestandardowe (.dyf) — kolekcje gotowych i/lub innych węzłów z pakietów.

  • Węzły niestandardowe z pakietów języka C# (znane również jako Zerotouch; te węzły niestandardowe wyglądają jak gotowe węzły).

  • Węzły NodeModel (węzły, które zawierają specjalne elementy interfejsu użytkownika, takie jak listy rozwijane lub przyciski wyboru).

  • Węzły NodeModel z niestandardowym interfejsem użytkownika (węzły, które zawierają unikatowe elementy interfejsu użytkownika, takie jak grafika w węźle)

Wykonaj te kilka czynności, aby wyświetlić pliki Markdown w dodatku Dynamo.

Otwieranie plików dokumentacji w dodatku Dynamo

Dodatek Dynamo wyświetla dokumentację węzłów za pomocą rozszerzenia widoku Przeglądarka dokumentacji. Aby otworzyć dokumentację węzła, kliknij węzeł prawym przyciskiem myszy i wybierz polecenie Pomoc. Spowoduje to otwarcie Przeglądarki dokumentacji i wyświetlenie treści Markdown skojarzonej z tym węzłem, jeśli jest dostępna.

Przeglądarka dokumentacji

Dokumentacja wyświetlana w Przeglądarce dokumentacji składa się z dwóch części. Pierwszą z nich jest sekcja Node Info, która jest generowana automatycznie na podstawie informacji wyodrębnionych z węzła, takich jak dane wejściowe/wyjściowe, kategoria węzła, nazwa/przestrzeń nazw węzłów i krótki opis węzłów. Druga część przedstawia dokumentację węzłów niestandardowych, która jest plikiem Markdown dostarczanym w celu udokumentowania węzła.

Dokumentacja węzłów niestandardowych

Folder doc pakietu

Aby dodać pliki dokumentacji do węzłów w dodatku Dynamo, utwórz nowy folder w katalogu pakietu o nazwie /doc. Po wczytaniu pakietu dodatek Dynamo przeskanuje ten katalog i pobierze wszystkie znajdujące się w nim pliki Markdown dokumentacji.

Nazewnictwo plików Markdown

Aby dodatek Dynamo wiedział, który plik należy otworzyć na żądanie dla określonego węzła, nazwa pliku Markdown musi mieć określony format. Plik Markdown powinien być nazwany zgodnie z dokumentowaną przestrzenią nazw węzła. Jeśli nie masz pewności co do przestrzeni nazw węzła, zajrzyj do sekcji Node Info po naciśnięciu pozycji Help na węźle, a pod nazwą węzła zobaczysz pełną przestrzeń nazw wybranego węzła.

Ta przestrzeń nazw powinna być nazwą pliku Markdown dla tego konkretnego węzła. Na przykład przestrzeń nazw CustomNodeExample z powyższych obrazów to TestPackage.TestCategory.CustomNodeExample, dlatego plik Markdown dla tego węzła powinien mieć nazwę TestPackage.TestCategory.CustomNodeExample.md

W szczególnych przypadkach, gdy występują przeciążenia węzłów (występują węzły o tej samej nazwie, ale różnych zestawach danych wejściowych), należy dodać nazwy pozycji danych wejściowych ujęte w () po przestrzeni nazw węzła. Na przykład wbudowany węzeł Geometry.Translate ma wiele przeciążeń. W tym przypadku plikom Markdown dla poniższych węzłów nadamy następujące nazwy: Autodesk.DesignScript.Geometry.Geometry.Translate(geometry,direction).md Autodesk.DesignScript.Geometry.Geometry.Translate(geometry,direction,distance).md

Przeciążanie węzłów

Modyfikowanie plików Markdown, gdy są otwarte w dodatku Dynamo

Aby ułatwić modyfikowanie plików dokumentacji, Przeglądarka dokumentacji implementuje funkcję obserwatora plików w otwartym pliku dokumentacji. Umożliwia to wprowadzanie zmian w pliku Markdown i natychmiastowe oglądanie zmian w dodatku Dynamo.

Ponowne wczytywanie „na gorąco”

Nowe pliki dokumentacji można również dodawać, gdy dodatek Dynamo jest otwarty. Po prostu dodaj do folderu /doc nowy plik Markdown o nazwie odpowiadającej węzłowi, który dokumentuje.

Dodawanie ikon niestandardowych do węzłów Zero Touch

Przegląd

Ikony niestandardowe dla węzłów Zero Touch w dodatku Dynamo umożliwiają wizualne wyróżnienie węzłów i ułatwienie ich rozpoznania w bibliotece. Dodając ikony niestandardowe, wyróżnisz swoje węzły na tle innych, umożliwiając użytkownikom szybkie identyfikowanie ich na liście.

Z tego podręcznika dowiesz się, jak dodawać ikony do węzłów Zero Touch.

Kroki dodawania niestandardowych ikon węzłów

Krok 1. Skonfiguruj projekt

Aby rozpocząć, utwórz projekt biblioteki klas programu Visual Studio (.NET Framework) dla węzłów Zero Touch. Jeśli nie masz jeszcze projektu, zapoznaj się z sekcją Pierwsze kroki, aby uzyskać instrukcje krok po kroku dotyczące jego tworzenia.

Tworzenie nowego projektu programu Visual Studio
Konfigurowanie nowego projektu w programie Visual Studio

Upewnij się, że masz co najmniej jeden działający węzeł Zero Touch, ponieważ ikony można dodawać tylko do istniejących węzłów. Aby uzyskać wskazówki, zobacz Analiza przypadku Zero-Touch — węzeł siatki.

Krok 2. Utwórz obrazy ikon

Tworzenie ikon niestandardowych:

  1. Zaprojektuj ikony: użyj edytora obrazów, aby utworzyć proste i przejrzyste wizualnie ikony dla węzłów.

  2. Specyfikacje obrazów:

    • Mała ikona: 32x32 piksele (używana na pasku bocznym Biblioteki i w samym węźle).

    • Duża ikona: 128x128 pikseli (używana we właściwościach węzła po umieszczeniu wskaźnika myszy na węźle w bibliotece).

  3. Konwencja nazewnictwa plików:

    • Nazwy plików muszą być zgodne z poniższym formatem, aby można było skojarzyć je z odpowiednim węzłem:

      • <ProjectName>.<ClassName>.<MethodName>.Small.png (w przypadku małej ikony).

      • <ProjectName>.<ClassName>.<MethodName>.Large.png (w przypadku dużej ikony).

Przykład: jeśli projekt to ZeroTouchNodeIcons, klasa to Grids, a metoda to RectangularGrid, pliki będą miały nazwy:

  • ZeroTouchNodeIcons.Grids.RectangularGrid.Small.png

  • ZeroTouchNodeIcons.Grids.RectangularGrid.Large.png

Wskazówka: stosuj spójny motyw projektu we wszystkich ikonach, aby uzyskać profesjonalny wygląd.

Krok 3. Dodaj plik zasobów do projektu

Aby osadzić ikony w pliku .dll, utwórz plik zasobów:

  1. Dodaj nowy plik zasobów:

  • Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań.

Dodawanie nowego elementu
  • Przejdź do obszaru Dodaj > Nowy element i wybierz opcję Plik zasobów.

Dodawanie pliku zasobów
  • Nadaj plikowi nazwę <ProjectName>Images.resx. Przykładowo: ZeroTouchNodeIconsImages.resx.

  1. Wyczyść właściwość narzędzia niestandardowego:

    • Wybierz plik zasobów w Eksploratorze rozwiązań.

    • W panelu Właściwości wyczyść pole Custom Tool, usuwając wartość ResXFileCodeGenerator.

  2. Ustaw opcję „Operacja kompilacji” na „Brak”.

    • Niedługo samodzielnie skompilujemy ten zasób, więc nie trzeba tego robić automatycznie.

Czyszczenie właściwości narzędzia niestandardowego

UWAGA: wyczyszczenie pola narzędzia niestandardowego (Custom Tool) spowoduje, że program Visual Studio przekonwertuje kropki na podkreślenia w nazwach zasobów. Przed rozpoczęciem kompilacji sprawdź, czy nazwy zasobów mają kropki oddzielające nazwy klas, a nie podkreślenia.

Krok 4. Dodaj obrazy jako zasoby

  1. Kliknij dwukrotnie utworzony plik zasobu:

    • Dodawaj po jednym obrazie za pomocą przycisku „+”.

    • Ustaw typ zasobu na Plik.

    • Przejdź do lokalizacji pliku obrazu i dołącz ikony węzła Duży oraz Mały.

Dodaj zasoby...

UWAGA: Umieszczenie obrazów w folderze Zasoby, a nawet w podfolderach Duży i Mały, nie jest wymagane, ale jest to dobra praktyka, która zapewnia porządek w zasobach.

Krok 5: Konwertuj projekt na styl SDK (w przypadku starszych projektów)

Jeśli projekt nie jest jeszcze w stylu zestawu SDK (co jest wymagane do osadzenia zasobów), przekonwertuj go:

  1. Zainstaluj rozszerzenie .NET Upgrade Assistant za pomocą menu Rozszerzenia > Zarządzaj rozszerzeniami programu Visual Studio.

Zarządzaj rozszerzeniami
Instalowanie narzędzia .NET Upgrade Assistant
  1. Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz polecenie Uaktualnij > Przekonwertuj projekt na styl SDK.

Uaktualnianie projektu
Konwertowanie na styl SDK
  1. Poczekaj na zakończenie konwersji.

Uaktualnianie ukończone

Krok 6. Dodaj skrypt po kompilacji w celu osadzenia zasobów

  1. Usuń projekt z pamięci:

    • Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz opcję Usuń projekt.

Usuwanie projektu z pamięci
  1. Edytuj plik .csproj:

    • Dodaj następujący element <Target> między elementami </ItemGroup> i </Project>:

<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>
Dodawanie kodu po kompilacji
  1. Zastąp wszystkie wystąpienia ZeroTouchNodeIcons nazwą projektu.

  2. Wczytaj ponownie projekt:

    • Kliknij prawym przyciskiem myszy projekt usunięty z pamięci i wybierz opcję Załaduj ponownie projekt.

Ponowne wczytywanie projektu

Krok 7. Skompiluj i wczytaj plik .dll do dodatku Dynamo

  1. Skompiluj projekt:

    • Po dodaniu skryptu po kompilacji skompiluj projekt w programie Visual Studio.

Kompilowanie rozwiązania
  1. Sprawdź pliki wyjściowe:

    • Upewnij się, że pliki .dll i .customization.dll znajdują się w folderze bin.

  2. Dodaj plik .dll do dodatku Dynamo:

    • W dodatku Dynamo użyj przycisku Importuj bibliotekę, aby zaimportować plik .dll do dodatku Dynamo.

Przycisk Importuj bibliotekę
  1. Węzły niestandardowe powinny być teraz wyświetlane z odpowiednimi ikonami.