Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
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: program Visual Studio, Edytor języka Python i język Code Block DesignScript
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.
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 z projektem, który będziemy opracowywać
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
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.
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.
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.
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
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.
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
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.
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.






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.
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.
Okno nowego projektu w programie Visual Studio
Zacznij od otwarcia programu Visual Studio i utworzenia nowego projektu:
File > New > ProjectWybierz szablon projektu
Class LibraryNadaj projektowi nazwę (w tym przypadku nazwaliśmy projekt MyCustomNode)
Ustaw ścieżkę pliku dla projektu. W tym przykładzie pozostawimy go w położeniu domyślnym
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;
}
}
}
Otwórz Eksplorator rozwiązań i okna danych wyjściowych z poziomu obszaru
View.W Eksploratorze rozwiązań po prawej stronie zmień nazwę pliku
Class1.csnaSampleFunctions.cs.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.
Eksplorator rozwiązań: umożliwia dostęp do wszystkich elementów w projekcie.
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.
Otwórz właściwości projektu, wybierając opcję
Project > "ProjectName" PropertiesWybierz stronę
BuildWybierz z menu rozwijanego opcję
Any CPUlubx64Upewnij się, że opcja
Prefer 32-bitnie 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.
Wybierz opcję
Build > Build SolutionAby 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.
Folder
binzawiera plik.dllskompilowany w programie Visual Studio.Plik projektu programu Visual Studio.
Plik klasy.
Ponieważ jako konfigurację rozwiązania ustawiono
Debug, plik.dllzostanie utworzony w folderzebin\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ć.
Wybierz przycisk Add (Dodaj), aby zaimportować plik
.dllPrzejdź 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\MyCustomNodeWybierz plik
MyCustomNode.dlldo zaimportowaniaKliknij 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ęzeł MyCustomNode w bibliotece dodatku Dynamo. Kategoria biblioteki jest określana przez nazwę pliku
.dll.Węzeł SampleFunctions.MultiplyByTwo w obszarze rysunku.
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.
Nazwa danych wejściowych to
inputNumberna podstawie nazwy parametru metody.Nazwa danych wyjściowych to domyślnie
double, ponieważ jest to zwracany typ danych.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;
}
}
}
Dodatek Dynamo zaimportował metodę jako węzeł tworzenia
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.
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ę.
Wybierz opcję przeglądania i wyszukaj dodatek DynamoVisualProgramming, aby wywołać pakiety dodatku Dynamo.
Pakiety dodatku Dynamo. Wybranie jednego z nich spowoduje wyświetlenie bieżącej wersji i opisu zawartości.
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.
Kliknij prawym przyciskiem myszy opcję
Referencesi wybierz polecenieAdd Reference.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.














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

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:
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
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*/)
{}
}
}
}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.
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.
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
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>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).
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.
Nowy folder packages utworzony przez obiekt docelowy AfterBuild
Istniejący folder src z projektem
Foldery
dyfiextrautworzone z obiektu docelowego AfterBuildRę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.



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
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)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.
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)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.
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.
Wyszukaj pakiety online:
Packages > Search for a Package...Wyświetl/edytuj zainstalowane pakiety:
Packages > Manage Packages...Opublikuj nowy pakiet:
Packages > Publish New Package...
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.
Wybierz opcję
Add file..., aby wyszukać pliki, które mają zostać dodane do pakietuWybierz dwa pliki
.dllz analizy przypadku NodeModelWybierz 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.
Pakiet gotowy do opublikowania.
Podaj wymagane informacje dotyczące nazwy, opisu i wersji.
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.
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.
Aby sprawdzić, jak dodatek Dynamo sformatował pakiet, kliknij pionowy trzykropek po prawej stronie pozycji „CustomNodeModel” i wybierz opcję „Pokaż katalog główny”.
Wybierz opcję
Publish, a następnie opcjęPublish Onlinew oknie „Publikowanie pakietów Dynamo”.Aby usunąć pakiet, wybierz opcję
Delete.
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ę.
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 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/
Aktualizowanie szczegółów pakietu
Autorzy mogą edytować opis pakietu, link do witryny internetowej i link do repozytorium, wykonując następujące kroki:
W obszarze Moje pakiety wybierz pakiet i kliknij opcję Edytuj szczegóły pakietu.
Dodaj lub zmodyfikuj łącza Witryna i Repozytorium przy użyciu odpowiednich pól.
Zaktualizuj pole Opis pakietu zgodnie z potrzebami.
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.
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:
Krok 1:
Kliknij wersję pakietu, którą chcesz zaktualizować.
Lista Zależy od zostanie automatycznie wypełniona pakietami, od których zależy pakiet.
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.
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.
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.
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.
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.
Jako typ projektu wybierz
Class LibraryNadaj 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;.
Odszukaj pakiet ZeroTouchLibrary
Użyjemy tego węzła w bieżącej kompilacji programu Dynamo Studio, czyli 1.3. Wybierz wersję pakietu zgodną z tą wersją.
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 ZeroTouchLibrarySystem.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.
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.
Węzeł niestandardowy RectangularGrids w bibliotece Dynamo
Węzeł niestandardowy w obszarze rysunku
Przycisk Add (Dodaj) umożliwiający dodanie pliku
.dlldo dodatku Dynamo
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.
Domyślna wartość wejściowa
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.
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;
}
}
}





















GeometryPrimitiveConverter.csKlasa 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.
Metody w pliku GeometryPrimitiveConverter.cs można podzielić na cztery główne kategorie:
Z typów Proto na typy programu Revit: metody, które konwertują typy dodatku Dynamo (Proto) na typy programu Revit.
Z typów programu Revit na typy Proto: metody, które konwertują typy programu Revit na typy dodatku Dynamo (Proto).
Stopnie i radiany: metody konwersji między stopniami i radianami.
X i UZ: metody do pobierania wektorów prostopadłych.
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)
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)
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)
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)
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)
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)
Konwertuje układ CoordinateSystem dodatku Dynamo na przekształcenie programu Revit.
public static Autodesk.Revit.DB.Transform ToTransform(this CoordinateSystem cs, bool convertUnits = true)
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)
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)
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)
Konwertuje szyk wartości double na szyk DoubleArray programu Revit.
public static DoubleArray ToDoubleArray(this double[] list)
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)
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)
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.
# 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
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)
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)
Konwertuje punkt programu Revit na punkt dodatku Dynamo.
public static Autodesk.DesignScript.Geometry.Point ToProtoType(this Autodesk.Revit.DB.Point point, bool convertUnits = true)
Konwertuje zestaw współrzędnych XYZ programu Revit na wektor dodatku Dynamo.
public static Vector ToVector(this XYZ xyz, bool convertUnits = false)
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)
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)
Konwertuje przekształcenie programu Revit na układ CoordinateSystem dodatku Dynamo.
public static CoordinateSystem ToCoordinateSystem(this Transform t, bool convertUnits = true)
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)
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.
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_pointKonwertuje stopnie na radiany.
public static double ToRadians(this double degrees) { return degrees * Math.PI / 180.0; }
Konwertuje radiany na stopnie.
public static double ToDegrees(this double degrees) { return degrees * 180.0 / Math.PI; }
W tym przykładzie pokazano szybkie i łatwe użycie metody .ToRadians do przekonwertowania 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_angleTa metoda zwraca wektor XYZ prostopadły do danego wektora XYZ.
public static XYZ GetPerpendicular(this XYZ xyz)
Ta metoda zwraca wektor Vector dodatku Dynamo prostopadły do danego wektora Vector dodatku Dynamo.
public static Vector GetPerpendicular(this Vector vector)
W tym przykładzie pokazano szybkie i łatwe użycie metody .GetPerpendicular do wygenerowania wektora prostopadłego do wektora wejściowego.
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 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.
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.
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/.
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.
Utwórz nowy projekt, wybierając opcję
File > New > ProjectWybierz opcję
Class LibraryNadaj projektowi nazwę
SampleViewExtensionWybierz 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.
Plik klasy o nazwie
SampleViewExtension.cs, w której zostanie zaimplementowany interfejsIViewExtensionPlik klasy o nazwie
SampleWindowViewMode.cs, w której zostanie zaimplementowana klasaNotificationObject
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.
Wybierz pakiet WpfUILibrary
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
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.
Kliknij prawym przyciskiem myszy projekt i wybierz pozycję
Add > New Item...Wybierz szablon kontroli użytkownika, który zmienimy w celu utworzenia okna
Nadaj nowemu plikowi nazwę
SampleWindow.xamlWybierz 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.
Kliknij prawym przyciskiem myszy projekt i wybierz pozycję
Add > New Item...Wybierz plik XML
Nadaj plikowi nazwę
SampleViewExtension_ViewExtensionDefinition.xmlWybierz 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
.xmlskopiowany 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
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.
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:
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 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)
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/MyNodeModelnamespace MyZTLibrarypublic class Utilities
{
public double doubleValue(double num)
{
return num * 2;
}
}MyZTLibrary/Utilities/doubleValue<?xml version="1.0"?>
<doc>
<assembly>
<name>MeshToolkit</name>
</assembly>
<namespaces>
<!--Remap Namespaces-->
<namespace name="Autodesk.Dynamo.MeshToolkit">
<category>MeshToolkit</category>
</namespace>
<namespace name="Autodesk.Dynamo.MeshToolkit.Display">
<category>Display</category>
</namespace>
</namespaces>
<classes>
<!--Remap Class Names-->
<class name="Autodesk.Dynamo.MeshToolkit.Display.MeshDisplay" shortname="MeshDisplay"/>
<class name="Autodesk.Dynamo.MeshToolkit.Mesh" shortname="Mesh"/>
</classes>
</doc>
{
"Uuid": "85066088-1616-40b1-96e1-c33e685c6948",
"IsCustomNode": true,
"Category": "MyCustomNodes.Utilities.Actions",
"Description": "This is an example custom nodes.",
"Name": "doubleValue",
"ElementResolver": {
"ResolutionMap": {}
},...<Workspace Version="1.3.0.0000" X="100" Y="100" zoom="1.0000000" Description="This is an example custom nodes." Category="MyCustomNodes.Utilities.Actions" Name="doubleValue" ID="85066088-1616-40b1-96e1-c33e685c6948"><?xml version="1.0"?>
<migrations>
<priorNameHint>
<oldName>MyZeroTouchLib.MyNodes.SayHello</oldName>
<newName>MyZeroTouchLib.MyNodes.SayHelloRENAMED</newName>
</priorNameHint>
</migrations>namespace SampleLibraryUI.Examples
{
[NodeName("Drop Down Example")]
[NodeDescription("An example drop down node.")]
[IsDesignScriptCompatible]
[AlsoKnownAs("SampleLibraryUI.Examples.DropDownExample")]
public class DropDownExampleRENAMED : DSDropDownBase
{
...
}
{
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.
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.
Plik
ZeroTouchEssentials.cszawiera 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.
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;
}
}
}
Po umieszczeniu kursora na porcie wejściowym węzła zostanie wyświetlona wartość domyślna
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.
Zwróć uwagę, że teraz istnieją dwa porty wyjściowe o nazwach zgodnych z ciągami wprowadzonymi dla kluczy słownika.
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
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:
Podsumowanie węzła
Opis danych wejściowych
Opis danych wyjściowych
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
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
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łó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.
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 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ą.
Ten węzeł przyjmuje jako dane wejściowe typ geometrii Curve (krzywa).
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;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>
Kliknij prawym przyciskiem myszy i wybierz polecenie
Add > New ItemWybierz opcję
XML FileW 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
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());
}
}-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.
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ń
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.
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.
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>












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.
Ten suwak umożliwia skalowanie komórek względem ich rozmiaru, dzięki czemu użytkownik nie musi udostępniać suwaka z odpowiednim zakresem.
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.
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.
Wybierz opcję
File > New > ProjectWybierz opcję
Other Project Types, aby wywołać opcję rozwiązaniaWybierz opcję
Blank SolutionNadaj rozwiązaniu nazwę
CustomNodeModelWybierz przycisk
Ok
Utwórz w rozwiązaniu dwa projekty biblioteki klas C#: jeden dla funkcji, a drugi dla interfejsu NodeModel.
Kliknij prawym przyciskiem myszy rozwiązanie i wybierz pozycję
Add > New ProjectWybierz bibliotekę klas
Nadaj jej nazwę
CustomNodeModelKliknij przycisk
OkPowtó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.
Dodaj kolejną klasę, klikając prawym przyciskiem myszy projekt
CustomNodeModel, wybierając polecenieAdd > New Item...i wybierając opcjęClass.W projekcie
CustomNodeModelpotrzebne są klasyGridNodeModel.csiGridNodeView.csW projekcie
CustomNodeModelFunctionpotrzebna jest klasaGridFunctions.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.
Kliknij prawym przyciskiem myszy projekt i wybierz pozycję
Manage NuGet PackagesZainstaluj 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.
Wybierz pakiety NuGet dodatku Dynamo
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ę.
Instrukcja using dla projektu CustomNodeModel będzie nieaktywna, dopóki nie będzie odwołania do tej funkcji
Kliknij prawym przyciskiem myszy pozycję
CustomNodeModeli wybierz polecenieAdd > ReferenceWybierz opcję
Projects > SolutionZaznacz pozycję
CustomNodeModelFunctionKliknij 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>.
Kliknij prawym przyciskiem myszy pozycję
CustomNodeModeli wybierz polecenieAdd > New ItemWybierz opcję
WPFNadaj elementowi sterującemu użytkownika nazwę
SliderKliknij 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.
Kliknij prawym przyciskiem myszy pozycję
CustomNodeModeli wybierz polecenieAdd > New ItemWybierz opcję
WebWybierz opcję
JSON FileNadaj plikowi nazwę
pkg.jsonKliknij 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.








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.
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.
Aby zainicjować DynamoModel, twórcy integracji muszą wykonać te kroki w dowolnym miejscu w kodzie 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.
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 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)
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;
} 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"
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.
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.
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.
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 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.
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)
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.
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.
Ś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.)
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 keyPoniż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)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:
Ten sam pomysł przedstawiono w następnym przykładzie z bardziej realistycznym przypadkiem użycia węzła DynamoRevit.
W najnowszych wersjach dodatku Dynamo używanie TLS (lokalnego magazynu wątków) zastąpiono używaniem elementu statycznego.
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:
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>
Jeśli tak, spróbuj zmodyfikować tę ścianę, zamiast tworzyć nową.
if(!CurveUtils.CurvesAreSimilar(wallLocation.Curve, curve))
wallLocation.Curve = curve;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);
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);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.
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.
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:
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.
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.
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 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:
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.
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.
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.
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.
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.
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.
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.
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.










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

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.
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.
OnLogWarningMessageMetoda OnLogWarningMessage jest częścią przestrzeni nazw DynamoServices, więc zacznij od dodania jej do pliku projektu.
using DynamoServices;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).
OnLogWarningMessageUmieść 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.
OnLogWarningMessageLogWarningMessageEvents.OnLogWarningMessage("Your warning message here.");OnLogWarningMessageAby zademonstrować metodę OnLogWarningMessage w działaniu, poniżej przedstawiono różne scenariusze, które można napotkać podczas tworzenia węzła Zero Touch.
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.
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.
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.
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.
OnLogInfoMessageW 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.
OnLogInfoMessageMetoda OnLogInfoMessage jest częścią przestrzeni nazw DynamoServices, więc zacznij od dodania jej do pliku projektu.
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).
OnLogInfoMessageUmieść 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.
OnLogInfoMessageLogWarningMessageEvents.OnLogInfoMessage("Your info message here.");OnLogInfoMessagePoniżej przedstawiono różne scenariusze w celu zademonstrowania stosowania metody OnLogInfoMessage w węzłach Zero-Touch.
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.
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;
}
}
}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.
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.
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.
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.
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.
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.
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.
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.
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 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.
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.
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.
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.
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
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.
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.
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.
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.
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.
Tworzenie ikon niestandardowych:
Zaprojektuj ikony: użyj edytora obrazów, aby utworzyć proste i przejrzyste wizualnie ikony dla węzłów.
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).
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.
Aby osadzić ikony w pliku .dll, utwórz plik zasobów:
Dodaj nowy plik zasobów:
Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań.
Przejdź do obszaru Dodaj > Nowy element i wybierz opcję Plik zasobów.
Nadaj plikowi nazwę <ProjectName>Images.resx. Przykładowo: ZeroTouchNodeIconsImages.resx.
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.
Ustaw opcję „Operacja kompilacji” na „Brak”.
Niedługo samodzielnie skompilujemy ten zasób, więc nie trzeba tego robić automatycznie.
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.
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.
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.
Jeśli projekt nie jest jeszcze w stylu zestawu SDK (co jest wymagane do osadzenia zasobów), przekonwertuj go:
Zainstaluj rozszerzenie .NET Upgrade Assistant za pomocą menu Rozszerzenia > Zarządzaj rozszerzeniami programu Visual Studio.
Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz polecenie Uaktualnij > Przekonwertuj projekt na styl SDK.
Poczekaj na zakończenie konwersji.
Usuń projekt z pamięci:
Kliknij prawym przyciskiem myszy projekt w Eksploratorze rozwiązań i wybierz opcję Usuń projekt.
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>Zastąp wszystkie wystąpienia ZeroTouchNodeIcons nazwą projektu.
Wczytaj ponownie projekt:
Kliknij prawym przyciskiem myszy projekt usunięty z pamięci i wybierz opcję Załaduj ponownie projekt.
Skompiluj projekt:
Po dodaniu skryptu po kompilacji skompiluj projekt w programie Visual Studio.
Sprawdź pliki wyjściowe:
Upewnij się, że pliki .dll i .customization.dll znajdują się w folderze bin.
Dodaj plik .dll do dodatku Dynamo:
W dodatku Dynamo użyj przycisku Importuj bibliotekę, aby zaimportować plik .dll do dodatku Dynamo.
Węzły niestandardowe powinny być teraz wyświetlane z odpowiednimi ikonami.











