All pages
Powered by GitBook
1 of 18

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Loading...

Entwickeln für Dynamo

Unabhängig vom Kenntnisstand ist die Dynamo-Plattform dafür konzipiert, dass alle Benutzer ihre Beiträge leisten können. Es gibt mehrere Entwicklungsoptionen, die auf unterschiedliche Fähigkeiten und Qualifikationen ausgerichtet sind und je nach Ziel alle ihre Stärken und Schwächen haben. Nachfolgend werden die verschiedenen Optionen und die Möglichkeiten zur Auswahl einer Option erläutert.

Drei Entwicklungsumgebungen

Drei Entwicklungsumgebungen: Visual Studio, Python Editor und Code Block DesignScript

Welche Optionen stehen zur Auswahl?

Die Entwicklungsoptionen für Dynamo lassen sich primär in zwei Kategorien einteilen: für Dynamo im Vergleich zu in Dynamo. Sie können sich die beiden Kategorien folgendermaßen vorstellen: In Dynamo impliziert Inhalte, die mit der Dynamo-IDE zur Verwendung in Dynamo erstellt werden, und für Dynamo impliziert die Verwendung externer Werkzeuge zur Erstellung von Inhalten, die zur Verwendung in Dynamo importiert werden. Obwohl sich dieses Handbuch auf die Entwicklung für Dynamo konzentriert, werden im Folgenden Ressourcen für alle Prozesse beschrieben.

Für Dynamo

Diese Blöcke gestatten die größtmögliche Anpassung. Viele Pakete werden mit dieser Methode erstellt. Sie ist erforderlich, um zur Quelle von Dynamo beizutragen. Der Prozess ihrer Erstellung wird in diesem Handbuch behandelt.

  • Zero-Touch-Blöcke

  • Von NodeModel abgeleitete Blöcke

  • Erweiterungen

Der Primer enthält eine Anleitung zum .

Für die folgende Beschreibung wird Visual Studio als Entwicklungsumgebung für Zero-Touch- und NodeModel-Blöcke verwendet.

Visual Studio-Benutzeroberfläche mit einem Projekt, das wir entwickeln werden

In Dynamo

Diese Prozesse befinden sich zwar im Arbeitsbereich für visuelle Programmierung und sind relativ einfach durchzuführen. Es handelt sich jedoch bei allen um realisierbare Optionen zur Anpassung von Dynamo. Der Primer behandelt diese Prozesse ausführlich und bietet im Kapitel Tipps und Best Practices für die Skripterstellung.

  • Codeblöcke stellen DesignScript in der visuellen Programmierumgebung bereit und ermöglichen so flexible Text-Skript- und Block-Arbeitsabläufe. Eine Funktion in einem Codeblock kann von jedem beliebigen Element im Arbeitsbereich aufgerufen werden.

    Laden Sie ein Codeblock-Beispiel herunter (klicken Sie mit der rechten Maustaste und dann auf Speichern unter), oder sehen Sie sich im eine detaillierte exemplarische Vorgehensweise an.

  • Benutzerdefinierte Blöcke sind Container für Sammlungen von Blöcken oder sogar ganzen Diagrammen. Sie stellen eine effektive Methode dar, um häufig verwendete Routinen zu sammeln und sie mit der Community zu teilen.

    Laden Sie ein Beispiel für einen benutzerdefinierten Block herunter (klicken Sie mit der rechten Maustaste und dann auf Speichern unter), oder sehen Sie sich im

Die Entwicklung im Dynamo-Arbeitsbereich ist ein leistungsstarkes Werkzeug, um unmittelbar Feedback zu erhalten.

Entwickeln im Dynamo-Arbeitsbereich mit dem Python-Block

Welche Vor- und Nachteile haben die einzelnen Optionen?

Die Entwicklungsoptionen für Dynamo wurden speziell auf die Komplexität bei der Anpassung ausgelegt. Unabhängig davon, ob das Ziel darin besteht, ein rekursives Skript in Python zu schreiben oder eine vollständig angepasste Block-Benutzeroberfläche zu erstellen, gibt es Optionen zum Implementieren von Code, die nur das umfassen, was für den Einstieg erforderlich ist.

Codeblöcke, der Python-Block und benutzerdefinierte Blöcke in Dynamo

Mit diesen Optionen können Sie sehr einfach Code in der visuellen Programmierumgebung von Dynamo schreiben. Der Arbeitsbereich für visuelle Programmierung in Dynamo bietet Zugriff auf Python und DesignScript und umfasst die Möglichkeit, mehrere Blöcke in einem benutzerdefinierten Block zu enthalten.

Mit diesen Methoden haben wir folgende Möglichkeiten:

  • Einstieg in das Schreiben mit Python oder DesignScript ohne oder mit geringem Einrichtungsaufwand

  • Importieren von Python-Bibliotheken in Dynamo

  • Gemeinsame Nutzung von Codeblöcken, Python-Blöcken und benutzerdefinierten Blöcken mit der Dynamo-Community im Rahmen eines Pakets

Zero-Touch-Blöcke

Unter Zero-Touch versteht man ein einfaches Verfahren zum Importieren von C#-Bibliotheken durch Zeigen und Klicken. Dynamo liest die öffentlichen Methoden einer .dll-Datei und konvertiert sie in Dynamo-Blöcke. Sie können Zero-Touch verwenden, um Ihre eigenen benutzerdefinierten Blöcke und Pakete zu entwickeln.

Mit dieser Methode haben wir folgende Möglichkeiten:

  • Importieren von Bibliotheken, die nicht unbedingt für Dynamo entwickelt wurden, und automatisches Erstellen einer Suite mit neuen Blöcken, z. B. wie im im Primer beschrieben.

  • Schreiben von C#-Methoden und einfache Nutzung der Methoden als Blöcke in Dynamo

  • Gemeinsame Nutzung einer C#-Bibliothek als Blöcke mit der Dynamo-Community in einem Paket

Von NodeModel abgeleitete Blöcke

Diese Blöcke gehen ein Schritt tiefer in die Struktur von Dynamo. Sie basieren auf der NodeModel-Klasse und sind in C# geschrieben. Diese Methode bietet die größte Flexibilität und Leistung. Die meisten Aspekte des Blocks müssen jedoch explizit definiert werden, und Funktionen müssen in einer separaten Assembly ausgeführt werden.

Mit dieser Methode haben wir folgende Möglichkeiten:

  • Erstellen einer vollständig anpassbaren Block-Benutzeroberfläche mit Schiebereglern, Bildern, Farben usw. (z. B. ColorRange-Block)

  • Zugreifen und Bearbeiten von Vorgängen im Dynamo-Ansichtsbereich

  • Anpassen der Vergitterung

  • Laden als Paket in Dynamo

Wissenswertes über Dynamo-Versionierung und API-Änderungen (1.x → 2.x)

Da Dynamo regelmäßig aktualisiert wird, können Änderungen an Teilen der API vorgenommen werden, die von einem Paket verwendet wird. Die Nachverfolgung dieser Änderungen ist wichtig, um sicherzustellen, dass vorhandene Pakete weiterhin ordnungsgemäß funktionieren.

Änderungen an der API werden im nachverfolgt. Hier werden Änderungen an DynamoCore, Bibliotheken und Arbeitsbereichen behandelt.

Ein Beispiel für eine bevorstehende, signifikante Änderung ist der Wechsel von XML zum JSON-Dateiformat in Version 2.0. Von NodeModel abgeleitete Blöcke benötigen jetzt einen , da sie sonst nicht in Dynamo 2.0 geöffnet werden können.

Die API-Dokumentation von Dynamo deckt derzeit die Kernfunktionen ab: .

Berechtigung zum Verteilen von Binärdateien in einem Paket

Achten Sie auf DLL-Dateien, die in einem Paket enthalten sind, das in den Package Manager hochgeladen wird. Wenn der Autor des Pakets die DLL-Datei nicht erstellt hat, muss er über die Rechte zum Freigeben verfügen.

Wenn ein Paket Binärdateien enthält, müssen die Benutzer beim Herunterladen darüber informiert werden, dass das Paket Binärdateien enthält.

Überlegungen zur Leistung der Dynamo-Benutzeroberfläche

Zum Zeitpunkt der Erstellung dieses Dokuments verwendet Dynamo hauptsächlich WPF (Windows Presentation Foundation), um die Benutzeroberfläche zu rendern. WPF ist ein komplexes und leistungsstarkes XAML-/bindungsbasiertes System. Da Dynamo über eine komplexe Benutzeroberfläche verfügt, werden leicht Probleme mit der Benutzeroberfläche oder Speicherverluste verursacht bzw. die Diagrammausführung und Aktualisierungen der Benutzeroberfläche so zusammengefasst, dass die Leistung beeinträchtigt wird.

Weitere Informationen finden Sie auf der . Hier finden Sie Hilfestellung, um einige häufige Fallstricke bei Änderungen am Code von Dynamo zu vermeiden.

eine detaillierte exemplarische Vorgehensweise an.
  • Python-Blöcke stellen eine Skripterstellungs-Schnittstelle im Arbeitsbereich für visuelle Programmierung dar, ähnlich wie Codeblöcke. Die Autodesk.DesignScript-Bibliotheken verwenden eine Punktnotation ähnlich der von DesignScript.

    Laden Sie ein Beispiel für einen Python-Block herunter (klicken Sie mit der rechten Maustaste und dann auf Speichern unter), oder sehen Sie sich im Primer eine detaillierte exemplarische Vorgehensweise an.

  • Importieren von Zero-Touch-Bibliotheken
    Vorgehensweisen zur Skripterstellung
    Primer
    A-Forge-Beispiel
    Dynamo-GitHub-Wiki
    JSON-Konstruktor
    http://dynamods.github.io/DynamoAPI
    Wiki-Seite zu den Überlegungen zur Leistung von Dynamo
    Visual Studio-Benutzeroberfläche
    Entwickeln im Dynamo-Arbeitsbereich mit dem Python-Block
    Codeblock, Python-Skript und benutzerdefinierter Block
    Zero-Touch-Blöcke
    Von NodeModel abgeleitete Blöcke
    Dokument mit Dynamo-API-Änderungen
    API-Dokumentation
    Primer

    Aktualisieren der Pakete und Dynamo-Bibliotheken für Dynamo 3.x

    Einführung:

    Dieser Abschnitt enthält Informationen zu Problemen, die möglicherweise beim Migrieren Ihrer Diagramme, Pakete und Bibliotheken in Dynamo 3.x auftreten können.

    Dynamo 3.0 ist eine Hauptversion, und einige APIs wurden geändert oder entfernt. Die größte Änderung, die Sie als Entwickler oder Benutzer von Dynamo 3.x wahrscheinlich betreffen wird, ist der Umstieg auf .NET 8.

    Dotnet/.NET ist die Laufzeitumgebung, die die C#-Sprache unterstützt, in der Dynamo geschrieben ist. Wir haben zusammen mit der restlichen Autodesk-Umgebung auf eine moderne Version dieser Laufzeitumgebung aktualisiert.

    Weitere Informationen finden Sie in unserem Blog-Post.


    Paketkompatibilität

    Verwenden von Dynamo 2.x-Paketen in Dynamo 3.x

    Da Dynamo 3.x jetzt unter der .NET 8-Laufzeitumgebung ausgeführt wird, kann die Funktionsweise von Paketen, die für Dynamo 2.x (mit .NET 48) erstellt wurden, in Dynamo 3.x nicht garantiert werden. Wenn Sie versuchen, ein Paket in Dynamo 3.x herunterzuladen, das mit einer Dynamo-Version unter 3.0 veröffentlicht wurde, erhalten Sie eine Warnung, dass das Paket aus einer älteren Version von Dynamo stammt.

    Das bedeutet nicht, dass das Paket nicht funktioniert. Es ist lediglich eine Warnung davor, dass Kompatibilitätsprobleme auftreten können. Im Allgemeinen ist es empfehlenswert, zu überprüfen, ob eine neuere Version speziell für Dynamo 3.x erstellt wurde.

    Möglicherweise wird diese Art von Warnung auch in den Dynamo-Protokolldateien zur Paketladedauer angezeigt. Wenn alles ordnungsgemäß funktioniert, können Sie dies ignorieren.

    Verwenden von Dynamo 3.x-Paketen in Dynamo 2.x

    Es ist sehr unwahrscheinlich, dass ein für Dynamo 3.x (mit .NET 8) erstelltes Paket mit Dynamo 2.x kompatibel ist. Außerdem wird eine Warnung angezeigt, wenn Sie Pakete herunterladen, die für neuere Versionen von Dynamo erstellt wurden, während Sie eine ältere Version verwenden.

    Erweiterungen als Pakete

    Erweiterungen als Pakete

    Überblick

    Dynamo-Erweiterungen können wie normale Dynamo-Blockbibliotheken im Package Manager bereitgestellt werden. Wenn ein installiertes Paket eine Ansichtserweiterung enthält, wird die Erweiterung zur Laufzeit geladen, wenn Dynamo geladen wird. Sie können in der Dynamo-Konsole überprüfen, ob die Erweiterung ordnungsgemäß geladen wurde.

    Paketstruktur

    Die Struktur eines Erweiterungspakets ist dieselbe wie die eines normalen Pakets und enthält Folgendes:

    Wenn Sie die Erweiterung bereits erstellt haben, verfügen Sie (mindestens) über eine .NET-Assembly und eine Manifestdatei. Die Assembly sollte eine Klasse enthalten, die IViewExtension oder IExtension implementiert. Die XML-Manifestdatei teilt Dynamo mit, welche Klasse instanziiert werden soll, um die Erweiterung zu starten. Damit der Package Manager die Erweiterung ordnungsgemäß findet, muss die Manifestdatei genau dem Assembly-Speicherort und dem -Namen entsprechen.

    Platzieren Sie alle Assembly-Dateien im Ordner bin und die Manifestdatei im Ordner extra. In diesem Ordner können auch weitere Objekte platziert werden.

    Beispiel für .XML-Manifestdatei:

    Hochladen

    Sobald Sie einen Ordner mit den oben aufgeführten Unterverzeichnissen erstellt haben, können Sie mit dem Übertragen (Hochladen) in den Package Manager beginnen. Beachten Sie, dass Sie derzeit keine Pakete aus Dynamo Sandbox publizieren können. Dies bedeutet, dass Sie Dynamo Revit verwenden müssen. Navigieren Sie in Dynamo Revit zu Pakete => Neues Paket publizieren. Dadurch wird der Benutzer aufgefordert, sich bei seinem Konto bei Autodesk Account anzumelden, mit dem er das Paket verknüpfen möchte.

    An dieser Stelle sollten Sie sich im normalen Fenster zum Publizieren des Pakets befinden, in dem Sie alle erforderlichen Felder für Ihr Paket/Ihre Erweiterung ausfüllen. Es gibt einen sehr wichtigen zusätzlichen Schritt, bei dem Sie sicherstellen müssen, dass keine der Assembly-Dateien als Blockbibliothek markiert ist. Klicken Sie dazu mit der rechten Maustaste auf die importierten Dateien (den oben erstellten Paketordner). Ein Kontextmenü wird angezeigt, in dem Sie diese Option aktivieren (oder deaktivieren) können. Alle Erweiterungs-Assemblys sollten deaktiviert werden.

    Vor dem öffentlichen Publizieren sollten Sie immer lokal publizieren, um sicherzustellen, dass alles wie erwartet funktioniert. Nachdem Sie sich dahingehend vergewissert haben, können Sie durch Auswahl von Publizieren die Publizierung starten.

    Abrufen

    Um zu überprüfen, ob das Paket erfolgreich hochgeladen wurde, können Sie es anhand des im Publizierungsschritt angegebenen Namens und der Schlüsselwörter suchen. Beachten Sie zum Schluss noch, dass die Erweiterungen einen Neustart von Dynamo erfordern, bevor sie funktionieren. In der Regel erfordern diese Erweiterungen Parameter, die beim Starten von Dynamo angegeben werden.

    Verwenden von COM-Typen (Interop-Typen) in Dynamo-Paketen

    Einige allgemeine Informationen zu Interop-Typen

    Was sind COM-Typen? – https://learn.microsoft.com/de-de/windows/win32/com/the-component-object-model

    Die Standardmethode zur Verwendung von COM-Typen in C# besteht darin, die primären Interop-Assemblys (im Wesentlichen eine große Sammlung von APIs) mit dem Paket zu referenzieren und zu liefern.

    Eine Alternative dazu besteht darin, die PIA (primäre Interop-Assemblys) in die verwaltete Assembly einzubetten. Dies umfasst im Grunde nur die Typen und Elemente, die tatsächlich von einer verwalteten Assembly verwendet werden. Dieser Ansatz weist jedoch noch einige andere Probleme auf, wie z. B. die Typäquivalenz.

    Dieser Post beschreibt das Problem ziemlich gut:

    So verwaltet Dynamo die Typäquivalenz

    Dynamo delegiert Typäquivalenzen an die .NET-Runtime (dotnet). Ein Beispiel hierfür wäre, dass zwei Typen mit demselben Namen und Namensbereich, die aus unterschiedlichen Assemblys stammen, nicht als äquivalent angesehen werden und Dynamo beim Laden der in Konflikt stehenden Assemblys einen Fehler ausgibt. Bei Interop-Typen überprüft Dynamo mithilfe der , ob die Interop-Typen äquivalent sind.

    So vermeiden Sie Konflikte zwischen eingebetteten Interop-Typen

    Einige Pakete wurden bereits mit eingebetteten Interop-Typen erstellt (z. B. CivilConnection). Das Laden von zwei Paketen mit eingebetteten Interop-Assemblys, die nicht als äquivalent angesehen werden (unterschiedliche Versionen, wie definiert), führt zu einem package load error. Aus diesem Grund empfehlen wir Paketautoren, die dynamische Bindung (auch späte Bindung genannt) für Interop-Typen zu verwenden (die Lösung wird auch beschrieben).

    Sie können sich dieses Beispiel ansehen:

    Zero-Touch-Fallstudie - Rasterblock

    Bei geöffnetem und gestartetem Visual Studio-Projekt werden Sie durch die Erstellung eines benutzerdefinierten Blocks geführt, mit dem ein rechteckiges Zellenraster erstellt wird. Auch wenn wir für die Erstellung mehrere Standardblöcke verwenden könnten, ist dies ein nützliches Werkzeug, das sich problemlos in einen Zero-Touch-Block integrieren lässt. Im Gegensatz zu Rasterlinien können Zellen um ihre Mittelpunkte skaliert, nach Eckscheitelpunkten abgefragt oder in Flächen integriert werden.

    In diesem Beispiel werden einige der Funktionen und Konzepte behandelt, die Sie beim Erstellen eines Zero-Touch-Blocks beachten sollten. Nachdem wir den benutzerdefinierten Block erstellt und zu Dynamo hinzugefügt haben, informieren Sie sich auf der Seite Weitere Schritte mit Zero-Touch im Detail über die vorgegebenen Eingabewerte, das Zurückgeben mehrerer Werte, die Dokumentation, die Objekte, die Verwendung von Dynamo-Geometrietypen und Migrationen.

    Ausführen von Python-Skripts in Zero-Touch-Blöcken (C#)

    Ausführen von Python-Skripts in Zero-Touch-Blöcken (C#)

    Wenn wir mit dem Schreiben von Skripts in Python vertraut sind und mehr Funktionen aus den Dynamo-Python-Standardblöcken herausholen möchten, können wir mit Zero-Touch eigene Blöcke erstellen. Beginnen wir mit einem einfachen Beispiel, in dem ein Python-Skript als Zeichenfolge an einen Zero-Touch-Block übergeben werden kann, in dem das Skript ausgeführt und ein Ergebnis zurückgegeben wird. Diese Fallstudie baut auf den exemplarischen Vorgehensweisen und Beispielen im Abschnitt Erste Schritte auf. Wenn Sie mit der Erstellung von Zero-Touch-Blöcken noch nicht vertraut sind, finden Sie dort weitere Informationen.

    Publizieren eines Pakets
    Suchen nach Paketen
    https://learn.microsoft.com/de-de/dotnet/framework/interop/type-equivalence-and-embedded-interop-types
    IsEquivalentTo-API
    hier
    hier
    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>
    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*/)
                {}
            }
        }
    }
    Benutzerdefinierter, rechteckiger Rasterblock

    Um mit dem Erstellen des Rasterblocks zu beginnen, erstellen Sie ein neues Visual Studio-Klassenbibliotheksprojekt. Eine ausführliche exemplarische Vorgehensweise zum Einrichten eines Projekts finden Sie auf der Seite Erste Schritte.

    Erstellen eines neuen Projekts in Visual Studio
    Konfigurieren eines neuen Projekts in Visual Studio
    1. Wählen Sie Class Library für den Projekttyp.

    2. Geben Sie dem Projekt den Namen CustomNodes.

    Da wir Geometrie erstellen, müssen wir das entsprechende NuGet-Paket referenzieren. Installieren Sie das ZeroTouchLibrary-Paket über den NuGet Package Manager. Dieses Paket ist für die Anweisung using Autodesk.DesignScript.Geometry; erforderlich.

    ZeroTouchLibrary-Paket
    1. Suchen Sie nach dem ZeroTouchLibrary-Paket.

    2. Wir verwenden diesen Block im aktuellen Build von Dynamo Studio (Version 1.3). Wählen Sie die Paketversion aus, die dieser Version entspricht.

    3. Beachten Sie, dass wir auch die Klassendatei in Grids.cs umbenannt haben.

    Als Nächstes müssen wir einen Namensbereich und eine Klasse einrichten, in denen die Methode RectangularGrid gespeichert wird. Der Block wird in Dynamo entsprechend den Methoden- und Klassennamen benannt. Wir müssen diesen Vorgang noch nicht in Visual Studio kopieren.

    Autodesk.DesignScript.Geometry; referenziert die Datei ProtoGeometry.dll im ZeroTouchLibrary-Paket. System.Collections.Generic ist zum Erstellen von Listen erforderlich.

    Jetzt können wir die Methode zum Zeichnen der Rechtecke hinzufügen. Die Klassendatei sollte der folgenden Abbildung entsprechen und kann in Visual Studio kopiert werden.

    Wenn das Projekt ähnlich aussieht wie hier gezeigt, versuchen Sie, die .dll-Datei zu erstellen.

    Erstellen einer DLL-Datei
    1. Wählen Sie Build > Projektmappe erstellen.

    Prüfen Sie, ob im Ordner bin des Projekts eine .dll-Datei enthalten ist. Wenn der Build erfolgreich war, können wir die .dll-Datei zu Dynamo hinzufügen.

    Benutzerdefinierte Blöcke in Dynamo
    1. Der benutzerdefinierte Block RectangularGrids in der Dynamo-Bibliothek

    2. Der benutzerdefinierte Block im Ansichtsbereich

    3. Die Schaltfläche Hinzufügen zum Hinzufügen der .dll-Datei zu Dynamo

    Benutzerdefinierte Blockänderungen

    Im obigen Beispiel haben wir einen recht einfachen Block erstellt, der außerhalb der Methode RectangularGrids nicht viel mehr definiert hat. Es ist jedoch eventuell empfehlenswert, QuickInfos für Eingabeanschlüsse zu erstellen oder dem Block eine Zusammenfassung hinzuzufügen, wie bei den Dynamo-Standardblöcken. Das Hinzufügen dieser Elemente zu benutzerdefinierten Blöcken erleichtert deren Verwendung, insbesondere dann, wenn ein Benutzer in der Bibliothek nach ihnen suchen möchte.

    Eingabe-QuickInfo
    1. Ein Vorgabe-Eingabewert

    2. Eine QuickInfo für die xCount-Eingabe

    Der Block RectangularGrid benötigt einige dieser grundlegenden Funktionen. Im folgenden Code wurden Beschreibungen der Eingabe- und Ausgabeanschlüsse, eine Zusammenfassung und vorgabemäßige Eingabewerte hinzugefügt.

    • Legen Sie Vorgabewerte für die Eingaben fest, indem Sie den Methodenparametern Werte zuweisen: RectangularGrid(int xCount = 10, int yCount = 10)

    • Erstellen Sie QuickInfos für Ein- und Ausgabe, Suchbegriffe und eine Zusammenfassung mit XML-Dokumentation, der /// vorangestellt ist.

    Um QuickInfos hinzuzufügen, benötigen wir eine XML-Datei im Projektverzeichnis. Eine .xml-Datei kann automatisch von Visual Studio generiert werden, indem Sie die Option aktivieren.

    Aktivieren der XML-Dokumentation
    1. Aktivieren Sie hier die XML-Dokumentationsdatei, und geben Sie einen Dateipfad an. Dadurch wird eine XML-Datei erstellt.

    Das ist alles. Wir haben einen neuen Block mit mehreren Standardelementen erstellt. Im folgenden Kapitel zu den Zero-Touch-Grundlagen wird ausführlicher auf die Zero-Touch-Blockentwicklung und die zu beachtenden Aspekte eingegangen.

    Rechteckiges Rasterdiagramm
    Ein Zero-Touch-Block, der eine Python-Skriptzeichenfolge ausführt

    Python-Modul

    Dieser Block ist von einer Instanz des IronPython-Skriptmoduls abhängig. Dazu müssen wir einige zusätzliche Assemblys referenzieren. Führen Sie die folgenden Schritte aus, um eine grundlegende Vorlage in Visual Studio einzurichten:

    • Erstellen Sie ein neues Visual Studio-Klassenprojekt.

    • Fügen Sie eine Referenz zur Datei IronPython.dll hinzu, die sich im Ordner C:\Program Files (x86)\IronPython 2.7\IronPython.dll befindet.

    • Fügen Sie eine Referenz zur Datei Microsoft.Scripting.dll hinzu, die sich im Ordner C:\Program Files (x86)\IronPython 2.7\Platforms\Net40\Microsoft.Scripting.dll befindet.

    • Berücksichtigen Sie die using-Anweisungen IronPython.Hosting und Microsoft.Scripting.Hosting in Ihrer Klasse.

    • Fügen Sie einen privaten, leeren Konstruktor hinzu, um zu verhindern, dass mit dem Paket ein zusätzlicher Block zur Dynamo-Bibliothek hinzugefügt wird.

    • Erstellen Sie eine neue Methode, die eine einzelne Zeichenfolge als Eingabeparameter akzeptiert.

    • Bei dieser Methode wird ein neues Python-Modul instanziiert und ein leerer Skriptbereich erstellt. Sie können sich diesen Bereich als globale Variablen innerhalb einer Instanz des Python-Interpreters vorstellen.

    • Rufen Sie anschließend Execute im Modul auf, das die Eingabezeichenfolge und den Bereich als Parameter übergibt.

    • Rufen Sie abschließend die Ergebnisse des Skripts ab, und geben Sie sie zurück, indem Sie GetVariable für den Bereich aufrufen und den Namen der Variablen aus dem Python-Skript übergeben, das den Wert enthält, den Sie zurückgeben möchten. (Weitere Informationen finden Sie im folgenden Beispiel.)

    Der folgende Code stellt ein Beispiel für den oben genannten Schritt dar. Beim Erstellen der Projektmappe wird eine neue .dll-Datei im Ordner bin des Projekts erstellt. Diese .dll-Datei kann jetzt als Teil eines Pakets oder durch Navigieren zu File < Import Library... in Dynamo importiert werden.

    Das Python-Skript gibt die Variable output zurück, d. h., wir benötigen eine output-Variable im Python-Skript. Verwenden Sie dieses Beispielskript, um den Block in Dynamo zu testen. Wenn Sie den Python-Block schon einmal in Dynamo verwendet haben, sollte Ihnen die folgende Darstellung bekannt sein. Weitere Informationen finden Sie im Primer-Abschnitt zu Python.

    Mehrere Ausgaben

    Eine Einschränkung der Python-Standardblöcke besteht darin, dass sie nur einen einzigen Ausgabeanschluss haben. Wenn wir also mehrere Objekte zurückgeben möchten, müssen wir eine Liste erstellen und jedes Objekt abrufen. Wenn wir das obige Beispiel ändern, um ein Wörterbuch zurückzugeben, können wir beliebig viele Ausgabeanschlüsse hinzufügen. Weitere Informationen zu Wörterbüchern finden Sie im Abschnitt Zurückgeben mehrerer Werte unter Weitere Schritte mit Zero-Touch.

    Mit diesem Block können wir sowohl das Volumen des Quaders als auch seinen Schwerpunkt zurückgeben.

    Mit diesem Block können wir sowohl das Volumen des Quaders als auch seinen Schwerpunkt zurückgeben.

    Wir ändern das vorherige Beispiel mit den folgenden Schritten:

    • Fügen Sie im NuGet-Paket-Manager eine Referenz auf DynamoServices.dll hinzu.

    • Schließen Sie zusätzlich zu den vorherigen Assemblys System.Collections.Generic und Autodesk.DesignScript.Runtime mit ein.

    • Ändern Sie den Rückgabetyp für die Methode, um ein Wörterbuch mit unseren Ausgaben zurückzugeben.

    • Jede Ausgabe muss einzeln aus dem Bereich abgerufen werden. (Richten Sie ggf. eine einfache Schleife für größere Ausgabesätze ein.)

    Außerdem wurde dem Beispiel-Python-Skript eine zusätzliche Ausgabevariable (output2) hinzugefügt. Beachten Sie, dass diese Variablen alle gültigen Python-Namenskonventionen verwenden können. Der Name Output wurde in diesem Beispiel einzig aus Gründen der Übersichtlichkeit verwendet.

    Ein Zero-Touch-Block, der eine Python-Skriptzeichenfolge ausführt

    Definieren einer benutzerdefinierten Paketorganisation für Dynamo 2.0+

    Das gewünschte Layout für Ihr Paket hängt von den Blocktypen ab, die Sie in das Paket aufnehmen. Vom Blockmodell abgeleitete Blöcke, ZeroTouch-Blöcke und benutzerdefinierte Blöcke weisen alle einen leicht unterschiedlichen Prozess zum Definieren der Kategorisierung auf. Sie können diese Blocktypen innerhalb desselben Pakets mischen und anpassen. Dies erfordert jedoch eine Kombination der unten beschriebenen Strategien.

    NodeModel

    NodeModel-Bibliotheken sind vorgabemäßig basierend auf der Klassenstruktur organisiert.

    Der Block befindet sich in Add-Ons unter:

    Sie können die Kategorie auch überschreiben, indem Sie das NodeCategory-Attribut für die Klasse oder im Konstruktor verwenden, wie unten gezeigt.

    Der Block befindet sich nun in Add-Ons unter:

    ZeroTouch

    ZeroTouch-Bibliotheken sind vorgabemäßig ebenfalls basierend auf der Klassenstruktur organisiert.

    Der Block befindet sich in Add-Ons unter:

    Sie können den Speicherort der Klassenstruktur auch mithilfe einer XML-Datei für die Dynamo-Anpassung überschreiben.

    • Die XML-Datei muss entsprechend benannt und im Ordner extra des Pakets enthalten sein.

      • PackageName_DynamoCustomization.xml

    CustomNodes

    Benutzerdefinierte Blöcke werden während der Blockerstellung auf Grundlage des angegebenen Category Name organisiert (mithilfe des neuen Dialogfelds Benutzerdefinierter Block).

    WARNUNG! Die Verwendung der Punktnotation in Blocknamen oder -kategorien führt zu zusätzlichen verschachtelten Unterkategorien. . dient als Trennzeichen, um die zusätzliche Hierarchie festzulegen. Dies ist ein neues Verhalten in der Bibliothek für Dynamo 2.0.

    Der Kategoriename kann später in der DYF-Datei (XML oder JSON) aktualisiert werden

    Strategien für die Paketblock-Migration

    Wenn ein Paketautor beschließt, zuvor vorhandene Blöcke in einer neuen Version umzubenennen, sollte er eine Möglichkeit zum Migrieren von Diagrammen bereitstellen, die Blöcke mit den alten Namen enthalten. Dies kann auf folgende Weise erreicht werden...

    ZeroTouch-Blöcke verwenden eine Namespace.Migrations.XML-Datei, die sich im Ordner bin der Pakete befindet, z. B.:

    MyZeroTouchLib.MyNodes.SayHello bis MyZeroTouchLib.MyNodes.SayHelloRENAMED

    Von NodeModel abgeleitete Blöcke verwenden das AlsoKnownAs-Attribut für die Klasse, z. B.:

    SampleLibraryUI.Examples.DropDownExample bis SampleLibraryUI.Examples.DropDownExampleRENAMED

    Erste Schritte

    Bevor wir mit der Entwicklung beginnen, ist es wichtig, ein solides Fundament für ein neues Projekt zu schaffen. Die Dynamo-Entwickler-Community verfügt über mehrere Projektvorlagen, die sich hervorragend als Ausgangspunkt eignen. Ein umfassendes Verständnis, wie Sie ein Projekt von Grund auf neu beginnen, ist jedoch noch wertvoller. Der Aufbau eines Projekts von Grund auf ermöglicht ein tieferes Verständnis des Entwicklungsprozesses.

    Erstellen eines Visual Studio-Projekts

    Visual Studio ist eine leistungsstarke IDE, in der wir ein Projekt erstellen, Referenzen hinzufügen, .dll-Dateien generieren und debuggen können. Beim Erstellen eines neuen Projekts erstellt Visual Studio außerdem eine Projektmappe, eine Struktur zum Organisieren von Projekten. In einer einzelnen Projektmappe können mehrere Projekte enthalten sein, die zusammen erstellt werden können. Um einen Zero-Touch-Block zu erstellen, müssen wir ein neues Visual Studio-Projekt starten, in im wir eine C#-Klassenbibliothek schreiben und eine

    Erstellen eines Pakets in Visual Studio

    Wenn Sie Assemblys entwickeln, die als Paket für Dynamo publiziert werden sollen, kann das Projekt so konfiguriert werden, dass alle erforderlichen Objekte gruppiert und in einer paketkompatiblen Verzeichnisstruktur abgelegt werden. Dadurch kann das Projekt schnell als Paket getestet werden und die Benutzererfahrung simuliert werden.

    So erstellen Sie Pakete direkt im Paketordner

    Es gibt zwei Methoden zum Erstellen eines Pakets in Visual Studio:

    • Hinzufügen von Postbuildereignissen über das Dialogfeld Projekteinstellungen, die XCopy- oder Python-Skripts zum Kopieren der erforderlichen Dateien verwenden

    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;
            }
        }
    }
    using IronPython.Hosting;
    using Microsoft.Scripting.Hosting;
    
    namespace PythonLibrary
    {
        public class PythonZT
        {
            // Unless a constructor is provided, Dynamo will automatically create one and add it to the library
            // To avoid this, create a private constructor
            private PythonZT() { }
    
            // The method that executes the Python string
            public static string executePyString(string pyString)
            {
                ScriptEngine engine = Python.CreateEngine();
                ScriptScope scope = engine.CreateScope();
                engine.Execute(pyString, scope);
                // Return the value of the 'output' variable from the Python script below
                var output = scope.GetVariable("output");
                return (output);
            }
        }
    }
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    cube = Cuboid.ByLengths(10,10,10);
    volume = cube.Volume
    output = str(volume)
    using IronPython.Hosting;
    using Microsoft.Scripting.Hosting;
    using System.Collections.Generic;
    using Autodesk.DesignScript.Runtime;
    
    namespace PythonLibrary
    {
        public class PythonZT
        {
            private PythonZT() { }
    
            [MultiReturn(new[] { "output1", "output2" })]
            public static Dictionary<string, object> executePyString(string pyString)
            {
                ScriptEngine engine = Python.CreateEngine();
                ScriptScope scope = engine.CreateScope();
                engine.Execute(pyString, scope);
                // Return the value of 'output1' from script
                var output1 = scope.GetVariable("output1");
                // Return the value of 'output2' from script
                var output2 = scope.GetVariable("output2");
                // Define the names of outputs and the objects to return
                return new Dictionary<string, object> {
                    { "output1", (output1) },
                    { "output2", (output2) }
                };
            }
        }
    }
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    cube = Cuboid.ByLengths(10,10,10);
    centroid = Cuboid.Centroid(cube);
    volume = cube.Volume
    output1 = str(volume)
    output2 = str(centroid)
    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";
    }
    Eigenschaften von benutzerdefinierten Blöcken
    NewSampleLibraryUI/Examples/MyNodeModel
    namespace MyZTLibrary
    public class Utilities
    {
        public double doubleValue(double num)
        {
            return num * 2;
        }
    }
    MyZTLibrary/Utilities/doubleValue
    <?xml version="1.0"?>
    <doc>
        <assembly>
            <name>MeshToolkit</name>
        </assembly>
        <namespaces>
            <!--Remap Namespaces-->
            <namespace name="Autodesk.Dynamo.MeshToolkit">
                <category>MeshToolkit</category>
            </namespace>
            <namespace name="Autodesk.Dynamo.MeshToolkit.Display">
                    <category>Display</category>
            </namespace>
        </namespaces>
        <classes>
            <!--Remap Class Names-->
            <class name="Autodesk.Dynamo.MeshToolkit.Display.MeshDisplay" shortname="MeshDisplay"/>
            <class name="Autodesk.Dynamo.MeshToolkit.Mesh" shortname="Mesh"/>
        </classes>
    </doc>
    
    {
      "Uuid": "85066088-1616-40b1-96e1-c33e685c6948",
      "IsCustomNode": true,
      "Category": "MyCustomNodes.Utilities.Actions",
      "Description": "This is an example custom nodes.",
      "Name": "doubleValue",
      "ElementResolver": {
        "ResolutionMap": {}
      },...
    <Workspace Version="1.3.0.0000" X="100" Y="100" zoom="1.0000000" Description="This is an example custom nodes." Category="MyCustomNodes.Utilities.Actions" Name="doubleValue" ID="85066088-1616-40b1-96e1-c33e685c6948">
    <?xml version="1.0"?>
    <migrations>
      <priorNameHint>
        <oldName>MyZeroTouchLib.MyNodes.SayHello</oldName>
        <newName>MyZeroTouchLib.MyNodes.SayHelloRENAMED</newName>
      </priorNameHint>
    </migrations>
    namespace SampleLibraryUI.Examples
    {
        [NodeName("Drop Down Example")]
        [NodeDescription("An example drop down node.")]
        [IsDesignScriptCompatible]
        [AlsoKnownAs("SampleLibraryUI.Examples.DropDownExample")]
        public class DropDownExampleRENAMED : DSDropDownBase
        {
            ...
        }
    {
    .dll
    -Datei erstellen.
    Erstellen eines neuen Projekts in Visual Studio
    Konfigurieren eines neuen Projekts in Visual Studio

    Fenster Neues Projekt in Visual Studio

    1. Öffnen Sie zunächst Visual Studio, und erstellen Sie ein neues Projekt: File > New > Project

    2. Wählen Sie die Projektvorlage Class Library.

    3. Geben Sie dem Projekt einen Namen (wir haben das Projekt MyCustomNode genannt).

    4. Legen Sie den Dateipfad für das Projekt fest. In diesem Beispiel belassen wir den Vorgabespeicherort.

    5. Wählen Sie Ok aus.

    Visual Studio erstellt und öffnet automatisch eine C#-Datei. Sie sollten einen angemessenen Namen vergeben, den Arbeitsbereich einrichten und den Vorgabecode durch diese Multiplikationsmethode ersetzen:

    Verwenden des Projektmappen-Explorers
    1. Öffnen Sie den Projektmappen-Explorer und die Ausgabefenster über View.

    2. Benennen Sie die Datei Class1.cs im Projektmappen-Explorer auf der rechten Seite in SampleFunctions.cs um.

    3. Fügen Sie den oben genannten Code für die Multiplikationsfunktion hinzu. Die Details dazu, wie Dynamo Ihre C#-Klassen liest, werden wir später behandeln.

    4. Projektmappen-Explorer: Hiermit erhalten Sie Zugriff auf alle Elemente in Ihrem Projekt.

    5. Ausgabefenster: Dieses wird später benötigt, um zu sehen, ob der Build erfolgreich war.

    Der nächste Schritt besteht darin, das Projekt zu erstellen. Zuvor müssen wir jedoch einige Einstellungen überprüfen. Stellen Sie zunächst sicher, dass Any CPU oder x64 als Plattformziel ausgewählt und Prefer 32-bit in den Projekteigenschaften deaktiviert ist.

    Build-Einstellungen in Visual Studio
    1. Öffnen Sie die Projekteigenschaften, indem Sie Project > "ProjectName" Properties auswählen.

    2. Wählen Sie die Seite Build aus.

    3. Wählen Sie im Dropdown-Menü die Option Any CPU oder x64 aus.

    4. Stellen Sie sicher, dass Prefer 32-bit deaktiviert ist.

    Jetzt können wir das Projekt erstellen, um eine .dll-Datei zu generieren. Wählen Sie dazu entweder Build Solution aus dem Menü Build aus, oder verwenden Sie den Kurzbefehl CTRL+SHIFT+B.

    Erstellen einer Projektmappe
    1. Wählen Sie Build > Build Solution aus.

    2. Sie können feststellen, ob Ihr Projekt erfolgreich erstellt wurde, indem Sie das Ausgabefenster überprüfen.

    Wenn das Projekt erfolgreich erstellt wurde, wird im Ordner bin des Projekts eine .dll-Datei mit dem Namen MyCustomNode angezeigt. In diesem Beispiel haben wir die Visual Studio-Vorgabe für den Projektdateipfad c:\users\username\documents\visual studio 2015\Projects beibehalten. Sehen wir uns nun die Dateistruktur des Projekts an.

    Dateistruktur des Projekts
    1. Der Ordner bin enthält die in Visual Studio erstellte .dll-Datei.

    2. Die Visual Studio-Projektdatei

    3. Die Klassendatei

    4. Da unsere Projektmappen-Konfiguration auf Debug festgelegt wurde, wird die .dll-Datei unter bin\Debug erstellt.

    Jetzt können wir Dynamo öffnen und die .dll-Datei importieren. Navigieren Sie mit der Funktion Hinzufügen zum bin-Speicherort des Projekts, und wählen Sie die zu öffnende .dll-Datei aus.

    Öffnen der DLL-Datei des Projekts
    1. Wählen Sie die Schaltfläche Hinzufügen, um eine .dll-Datei zu importieren.

    2. Navigieren Sie zum Projektspeicherort. Das Projekt befindet sich unter dem Vorgabedateipfad von Visual Studio: C:\Users\username\Documents\Visual Studio 2015\Projects\MyCustomNode.

    3. Wählen Sie die zu importierende Datei MyCustomNode.dll aus.

    4. Klicken Sie auf Open, um die .dll-Datei zu laden.

    Wenn eine Kategorie mit dem Namen MyCustomNode in der Bibliothek erstellt wird, wurde die DLL-Datei erfolgreich importiert. Dynamo hat jedoch zwei Blöcke erstellt, obwohl wir einen einzelnen Block erhalten wollten. Im nächsten Abschnitt werden wir erläutern, warum dies geschieht und wie Dynamo DLL-Dateien liest.

    Benutzerdefinierte Blöcke
    1. MyCustomNode in der Dynamo-Bibliothek. Die Bibliothekskategorie wird durch den Namen der .dll-Datei bestimmt.

    2. SampleFunctions.MultiplyByTwo im Ansichtsbereich.

    So liest Dynamo Klassen und Methoden

    Wenn Dynamo eine DLL-Datei lädt, werden alle öffentlichen statischen Methoden als Blöcke angezeigt. Konstruktoren, Methoden und Eigenschaften werden in Erstellungs-, Aktions- und Abfrageblöcke umgewandelt. In unserem Multiplikationsbeispiel wird die Methode MultiplyByTwo() zu einem Aktionsblock in Dynamo. Dies liegt daran, dass der Block basierend auf der zugehörigen Methode und Klasse benannt wurde.

    Block SampleFunction.MultiplyByTwo in einem Diagramm
    1. Die Eingabe erhält basierend auf dem Parameternamen der Methode den Namen inputNumber.

    2. Die Ausgabe erhält vorgabemäßig den Namen double, da es sich hierbei um den zurückgegebenen Datentyp handelt.

    3. Der Block erhält den Namen SampleFunctions.MultiplyByTwo, da dies die Klassen- und Methodennamen sind.

    Im obigen Beispiel wurde der zusätzliche Erstellungsblock SampleFunctions erzeugt, da wir nicht explizit einen Konstruktor bereitgestellt haben, und daher automatisch einer erstellt wurde. Dies kann durch Erstellen eines leeren privaten Konstruktors in der Klasse SampleFunctions vermieden werden.

    Methode als Erstellungsblock importiert
    1. Dynamo hat unsere Methode als Erstellungsblock importiert.

    Hinzufügen von Dynamo-NuGet-Paketreferenzen

    Der Block für die Multiplikation ist sehr einfach, und es sind keine Referenzen auf Dynamo erforderlich. Wenn wir beispielsweise auf eine Dynamo-Funktion zum Erstellen von Geometrie zugreifen möchten, müssen wir die Dynamo-NuGet-Pakete referenzieren.

    • ZeroTouchLibrary: Paket zum Erstellen von Zero-Touch-Blockbibliotheken für Dynamo mit den folgenden Bibliotheken: DynamoUnits.dll, ProtoGeometry.dll.

    • WpfUILibrary: Paket zum Erstellen von Blockbibliotheken für Dynamo mit angepasster Benutzeroberfläche in WPF, die die folgenden Bibliotheken enthält: DynamoCoreWpf.dll, CoreNodeModels.dll, CoreNodeModelWpf.dll.

    • DynamoServices: DynamoServices-Bibliothek für Dynamo.

    • : Komponenten- und System-Testinfrastruktur für Dynamo, die die folgenden Bibliotheken enthält: DSIronPython.dll, DynamoApplications.dll, DynamoCore.dll, DynamoInstallDetective.dll, DynamoShapeManager.dll, DynamoUtilities.dll, ProtoCore.dll, VMDataBridge.Bridge.dll.

    • : Komponenten- und System-Testinfrastruktur für Dynamo, die die folgenden Bibliotheken enthält: DynamoCoreTests.dll, SystemTestServices.dll, TestServices.dll.

    • : Paket zum Erstellen von Core-Blöcken für Dynamo, das die folgenden Bibliotheken enthält: Analysis.dll, GeometryColor.dll, DSCoreNodes.dll.

    Um diese Pakete in einem Visual Studio-Projekt zu referenzieren, laden Sie das Paket entweder von NuGet unter den oben genannten Links herunter und referenzieren die DLL-Dateien manuell, oder verwenden Sie den NuGet-Paket-Manager in Visual Studio. Zunächst gehen wir die Schritte zum Installieren mit NuGet in Visual Studio durch.

    Öffnen des NuGet-Paket-Managers
    1. Öffnen Sie den NuGet-Paket-Manager, indem Sie Tools > NuGet Package Manager > Manage NuGet Packages for Solution... auswählen.

    Dies ist der NuGet-Paket-Manager. In diesem Fenster wird angezeigt, welche Pakete für das Projekt installiert wurden, und der Benutzer kann nach anderen Paketen suchen. Wenn eine neue Version des DynamoServices-Pakets veröffentlicht wird, können Pakete von hier aus aktualisiert oder auf eine frühere Version zurückgesetzt werden.

    NuGet-Paket-Manager
    1. Wählen Sie Durchsuchen, und suchen Sie nach DynamoVisualProgramming, um die Dynamo-Pakete aufzurufen.

    2. Die Dynamo-Pakete. Wenn Sie eines auswählen, werden die aktuelle Version und eine Beschreibung des Inhalts angezeigt.

    3. Wählen Sie die gewünschte Paketversion aus, und klicken Sie auf Installieren. Dadurch wird ein Paket für das spezifische Projekt installiert, an dem Sie gerade arbeiten. Da wir die neueste stabile Version von Dynamo, Version 1.3, verwenden, wählen Sie die entsprechende Paketversion aus.

    Um ein aus dem Browser heruntergeladenes Paket manuell hinzuzufügen, öffnen Sie den Verweis-Manager im Projektmappen-Explorer und suchen nach dem Paket.

    Verweis-Manager
    1. Klicken Sie mit der rechten Maustaste auf References, und wählen Sie Add Reference aus.

    2. Wählen Sie Browse aus, um zum Paketspeicherort zu navigieren.

    Nachdem Visual Studio ordnungsgemäß konfiguriert wurde und wir erfolgreich eine .dll-Datei zu Dynamo hinzugefügt haben, verfügen wir über eine solide Grundlage für die nun folgenden Konzepte. Dies ist nur der Anfang. Bleiben Sie daher weiter dabei, um mehr über das Erstellen eines benutzerdefinierten Blocks zu erfahren.

    Visual Studio
  • Verwenden des Build-Ziels AfterBuild in der .csproj-Datei, um Aufgaben zum Kopieren von Dateien und Verzeichnissen zu erstellen

  • AfterBuild ist die bevorzugte Methode für diese Operationstypen (und die in diesem Handbuch beschriebenen), da sie nicht auf dem Kopieren von Dateien beruht, die möglicherweise nicht auf dem Build-Computer verfügbar sind.

    Kopieren von Paketdateien mit der AfterBuild-Methode

    Richten Sie die Verzeichnisstruktur im Repository so ein, dass die Quelldateien von den Paketdateien getrennt sind. Platzieren Sie das Visual Studio-Projekt und alle zugehörigen Dateien in einem neuen src-Ordner, und arbeiten Sie dabei mit der Fallstudie CustomNodeModel. Sie speichern alle vom Projekt generierten Pakete in diesem Ordner. Die Ordnerstruktur sollte nun wie folgt aussehen:

    Verschieben von Projektdateien
    1. Verschieben Sie die Projektdateien in den neuen src-Ordner.

    Nachdem sich die Quelldateien in einem separaten Ordner befinden, fügen Sie der Datei CustomNodeModel.csproj in Visual Studio ein AfterBuild-Ziel hinzu. Dadurch sollten die erforderlichen Dateien in einen neuen Paketordner kopiert werden. Öffnen Sie die Datei CustomNodeModel.csproj in einem Texteditor (wir haben Atom verwendet), und platzieren Sie das Build-Ziel vor dem schließenden </Project>-Tag. Dieses AfterBuild-Ziel kopiert alle DLL-, PBD-, XML- und CONFIG-Dateien in einen neuen bin-Ordner und erstellt einen dyf-Ordner sowie zusätzliche Ordner.

    Platzieren des AfterBuild-Ziels

    Wir müssen sicherstellen, dass das Ziel der Datei CustomNodeModel.csproj hinzugefügt wurde (nicht einer anderen Projektdatei) und dass das Projekt keine vorhandenen Postbuild-Einstellungen aufweist.

    1. Platzieren Sie das AfterBuild-Ziel vor dem </Project>-End-Tag.

    Im Abschnitt <ItemGroup> sind eine Reihe von Variablen definiert, die bestimmte Dateitypen darstellen. Die Variable Dll stellt beispielsweise alle Dateien im Ausgabeverzeichnis mit der Erweiterung .dll dar.

    Die Aufgabe Copy besteht darin, alle .dll-Dateien in ein Verzeichnis zu kopieren, insbesondere den Paketordner, in dem die Erstellung erfolgt.

    Dynamo-Pakete verfügen in der Regel über einen dyf- und einen extra-Ordner für benutzerdefinierte Dynamo-Blöcke und andere Objekte, z. B. Bilder. Um diese Ordner zu erstellen, müssen wir eine MakeDir-Aufgabe verwenden. Diese Aufgabe erstellt einen Ordner, wenn er noch nicht vorhanden ist. Sie können diesem Ordner manuell Dateien hinzufügen.

    Wenn Sie das Projekt erstellen, sollte der Projektordner jetzt einen packages-Ordner neben dem zuvor erstellten src-Ordner enthalten. Im packages-Verzeichnis befindet sich ein Ordner, der alle für das Paket erforderlichen Elemente enthält. Außerdem müssen wir die Datei pkg.json in den Paketordner kopieren, damit Dynamo erkennt, dass das Paket geladen werden soll.

    Kopieren von Dateien
    1. Der neue Paketordner, den das AfterBuild-Ziel erstellt hat.

    2. Der vorhandene src-Ordner mit dem Projekt.

    3. Die Ordner dyf und extra, die aus dem AfterBuild-Ziel erstellt wurden.

    4. Kopieren Sie die Datei pkg.json manuell.

    Jetzt können Sie das Paket mithilfe des Paket-Managers von Dynamo publizieren oder es direkt in das Paketverzeichnis von Dynamo kopieren: <user>\AppData\Roaming\Dynamo\1.3\packages.

    Dynamo-Befehlszeilenschnittstelle

    -o, -O, --OpenFilePath: Weisen Sie Dynamo an, eine Befehlsdatei zu öffnen und die enthaltenen Befehle unter diesem Pfad auszuführen. Diese Option wird nur unterstützt, wenn die Ausführung über DynamoSandbox erfolgt.

    -c, -C, --CommandFilePath: Weisen Sie Dynamo an, eine Befehlsdatei zu öffnen und die enthaltenen Befehle unter diesem Pfad auszuführen. Diese Option wird nur unterstützt, wenn die Ausführung über DynamoSandbox erfolgt.

    -v, -V, --Verbose: Weisen Sie Dynamo an, alle vom Programm durchgeführten Auswertungen in einer XML-Datei im angegebenen Pfad auszugeben.

    -g, -G, --Geometry: Weisen Sie Dynamo an, die Geometrie aller Auswertungen in einer JSON-Datei unter diesem Pfad auszugeben.

    -h, -H, --help: Rufen Sie die Hilfe ab.

    -i, -I, --Import: Weisen Sie Dynamo an, eine Assembly als Blockbibliothek zu importieren. Dieses Argument sollte ein Dateipfad zu einer einzelnen .dll sein. Wenn Sie mehrere .dlls importieren möchten, listen Sie diese durch ein Leerzeichen getrennt auf: -i 'assembly1.dll' 'assembly2.dll'.

    --GeometryPath: Relativer oder absoluter Pfad zu einem Verzeichnis, das ASM-Dateien enthält. Wenn bereitgestellt, wird auf der Festplatte nicht nach der ASM-Datei gesucht, sondern diese wird direkt aus diesem Pfad geladen.

    -k, -K, --KeepAlive: Im Keepalive-Modus können Sie den Dynamo-Prozess so lange ausführen, bis er durch eine geladene Erweiterung beendet wird.

    --HostName: Identifizieren Sie die mit dem Host verknüpfte Dynamo-Variante.

    -s, -S, --SessionId: Identifizieren Sie die Sitzungs-ID von Dynamo-Host-Analysen.

    -p, -P, --ParentId: Identifizieren Sie die übergeordnete ID von Dynamo-Host-Analysen.

    -x, -X, --ConvertFile: Wird dies in Kombination mit dem Flag -O verwendet, wird eine .dyn-Datei aus dem angegebenen Pfad geöffnet und in .json konvertiert. Die Datei hat die Erweiterung .json und befindet sich im selben Verzeichnis wie die ursprüngliche Datei.

    -n, -N, --NoConsole: Verlassen Sie sich nicht auf das Konsolenfenster, um im Keepalive-Modus mit der CLI zu interagieren.

    -u, -U, --UserData: Geben Sie den Benutzerdatenordner an, der von PathResolver mit der CLI verwendet werden soll.

    --CommonData: Geben Sie den gemeinsamen Datenordner an, der von PathResolver mit der CLI verwendet werden soll.

    --DisableAnalytics: Deaktiviert Analysen in Dynamo für die Dauer des Prozesses.

    --CERLocation: Geben Sie das Werkzeug für den Absturzfehlerbericht an, das sich auf der Festplatte befindet.

    --ServiceMode: Geben Sie den Startvorgang für den Servicemodus an.

    Warum?

    Aus unterschiedlichen Gründen kann es erforderlich sein, Dynamo über die Befehlszeile zu steuern. Dazu zählen die folgenden:

    • Automatisieren vieler Dynamo-Läufe

    • Testen von Dynamo-Diagrammen (bei Verwendung von DynamoSandbox siehe auch unter -c)

    • Ausführen einer Sequenz von Dynamo-Diagrammen in einer bestimmten Reihenfolge

    • Schreiben von Stapeldateien für mehrere Befehlszeilenausführungen

    Was?

    Die Befehlszeilenschnittstelle (DynamoCLI) ist eine Ergänzung zu DynamoSandbox. Es handelt sich um ein DOS/TERMINAL-Befehlszeilen-Dienstprogramm, mit dem Dynamo komfortabel über Befehlszeilenargumente ausgeführt werden kann. In der ersten Implementierung kann das Programm nicht eigenständig ausgeführt werden, sondern muss in dem Ordner ausgeführt werden, in dem sich die Dynamo-Binärdateien befinden, da es von denselben DLL-Kerndateien wie Sandbox abhängt. Es funktioniert nicht mit anderen Builds von Dynamo.

    Es gibt vier Möglichkeiten zum Ausführen der CLI: über eine DOS-Eingabeaufforderung, über DOS-Stapeldateien und als Windows-Desktop-Verknüpfung, deren Pfad so geändert wird, dass er die angegebenen Befehlszeilen-Flags enthält. Die Spezifikation für die DOS-Datei kann vollständig qualifiziert oder relativ sein, und zugeordnete Laufwerke und URL-Syntax werden ebenfalls unterstützt. Sie kann auch mit Mono erstellt und unter Linux oder Mac vom Terminal aus ausgeführt werden.

    Das Dienstprogramm unterstützt Dynamo-Pakete, Sie können jedoch keine benutzerdefinierten Blöcke (dyf), sondern nur eigenständige Diagramme (dyn) laden.

    In vorläufigen Tests unterstützt das CLI-Dienstprogramm lokalisierte Versionen von Windows, und Sie können filespec-Argumente mit ASCII-Großbuchstaben angeben.

    Auf die CLI kann über die Anwendung DynamoCLI.exe zugegriffen werden. Diese Anwendung ermöglicht es Benutzern oder einer anderen Anwendung, mit dem Dynamo-Auswertungsmodell zu interagieren, indem DynamoCLI.exe mit einer Befehlszeichenfolge aufgerufen wird. Dies kann in etwa wie folgt aussehen:

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

    Mit diesem Befehl wird Dynamo angewiesen, die angegebene Datei unter "C:\BeliebigeDynamoDatei.Dyn" zu öffnen, ohne eine Benutzeroberfläche anzuzeigen, und sie dann auszuführen. Dynamo wird beendet, wenn die Ausführung des Diagramms abgeschlossen ist.

    Neu in Version 2.1: Anwendung DynamoWPFCLI.exe. Diese Anwendung unterstützt all das, was auch die Anwendung DynamoCLI.exe unterstützt, weist aber zusätzlich die Option Geometrie (-g) auf. Die Anwendung DynamoWPFCLI.exe ist nur für Windows verfügbar.

    Wichtige Anmerkungen

    • Die bevorzugte Methode für die Interaktion mit DynamoCLI erfolgt über eine Schnittstelle für Eingabeaufforderungen.

    • Derzeit müssen Sie DynamoCLI vom Installationsverzeichnis im Ordner [Dynamo-Version] aus ausführen. Die CLI benötigt Zugriff auf dieselben DLL-Dateien wie Dynamo und sollte daher nicht verschoben werden.

    • Sie sollten Diagramme ausführen können, die derzeit in Dynamo geöffnet sind. Dies kann jedoch zu unbeabsichtigten Nebeneffekten führen.

    • Alle Dateipfade sind vollständig DOS-konform; relative und vollständig qualifizierte Pfade sollten daher funktionieren. Stellen Sie jedoch sicher, dass Sie Ihre Pfade in Anführungszeichen setzen:

    wie

    -o: Sie können Dynamo mit Verweis auf eine DYN-Datei im Headless-Modus öffnen, in dem das Diagramm ausgeführt wird.

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

    -v kann verwendet werden, wenn Dynamo im Headless-Modus ausgeführt wird (wenn Sie -o zum Öffnen eines Datei verwendet haben). Dieses Flag wiederholt alle Blöcke im Diagramm und gibt ihre Ausgabewerte in einer einfachen XML-Datei aus. Da das Flag --ServiceMode Dynamo dazu zwingen kann, mehrere Diagrammauswertungen auszuführen, enthält die Ausgabedatei Werte für jede auftretende Auswertung.

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

    Die XML-Ausgabedatei hat folgende Form:

    -g kann verwendet werden, wenn Dynamo im Headless-Modus ausgeführt wird (wenn Sie -o zum Öffnen einer Datei verwendet haben). Dieses Flag generiert das Diagramm und gibt dann die resultierende Geometrie in einer JSON-Datei aus.

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

    Die JSON-Geometriedatei hat folgende Form:

    Noch offen – In Bearbeitung

    -h: Verwenden Sie diese Option, um eine Liste der möglichen Optionen abzurufen.

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

    Das Flag -i kann mehrmals verwendet werden, um mehrere Assemblys zu importieren, die zum Ausführen des zu öffnenden Diagramms erforderlich sind.

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

    Das Flag -l kann verwendet werden, um Dynamo unter einer anderen Gebietsschema-Einstellung auszuführen. In der Regel wirkt sich die Gebietsschema-Einstellung jedoch nicht auf die Diagrammergebnisse aus.

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

    Das Flag --GeometryPath kann verwendet werden, um DynamoSandbox oder die CLI auf einen bestimmten Satz von ASM-Binärdateien zu verweisen. Verwenden Sie es wie

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

    oder

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

    Mit dem Flag -k können Sie den Dynamo-Prozess so lange ausführen, bis er durch eine geladene Erweiterung beendet wird.

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

    Das Flag --HostName kann verwendet werden, um die mit dem Host verknüpfte Dynamo-Variante zu identifizieren.

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

    oder

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

    Das Flag -s kann verwendet werden, um die Sitzungs-ID von Dynamo-Host-Analysen zu ermitteln.

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

    Das Flag -p kann verwendet werden, um die übergeordnete ID von Dynamo-Host-Analysen zu ermitteln.

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

     namespace MyCustomNode
     {
         public class SampleFunctions
         {
             public static double MultiplyByTwo(double inputNumber)
             {
                 return inputNumber * 2.0;
             }
         }
     }
    namespace MyCustomNode
    {
        public class SampleFunctions
        {
            //The empty private constructor.
            //This will be not imported into Dynamo.
            private SampleFunctions() { }
    
            //The public multiplication method. 
            //This will be imported into Dynamo.
            public static double MultiplyByTwo(double inputNumber)
            {
                return inputNumber * 2.0;
            }
        }
    }
    CustomNodeModel
    > src
      > CustomNodeModel
      > CustomNodeModelFunction
      > packages
      > CustomNodeModel.sln
      <Target Name="AfterBuild">
        <ItemGroup>
          <Dlls Include="$(OutDir)*.dll" />
          <Pdbs Include="$(OutDir)*.pdb" />
          <Xmls Include="$(OutDir)*.xml" />
          <Configs Include="$(OutDir)*.config" />
        </ItemGroup>
        <Copy SourceFiles="@(Dlls)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
        <Copy SourceFiles="@(Pdbs)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
        <Copy SourceFiles="@(Xmls)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
        <Copy SourceFiles="@(Configs)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
        <MakeDir Directories="$(SolutionDir)..\packages\CustomNodeModel\dyf" />
        <MakeDir Directories="$(SolutionDir)..\packages\CustomNodeModel\extra" />
      </Target>
    <ItemGroup>
      <Dlls Include="$(OutDir)*.dll" />
    </ItemGroup>
    <Copy SourceFiles="@(Dlls)" DestinationFolder="$(SolutionDir)..\packages\CustomNodeModel\bin\" />
    <MakeDir Directories="$(SolutionDir)..\packages\CustomNodeModel\extra" />
    Core
    Tests
    DynamoCoreNodes

    Schreiben eines weiteren Programms, um die Ausführung von Dynamo-Diagrammen zu steuern und zu automatisieren sowie die Ergebnisse dieser Berechnungen für verschiedene Aufgaben zu verwenden

    "C:Pfad\zur\Datei.dyn"
    .
  • DynamoCLI ist eine neue Funktion, die sich derzeit noch stark im Wandel befindet: Die CLI lädt derzeit nur einen Teilsatz der Standardbibliotheken von Dynamo. Beachten Sie dies, wenn ein Diagramm nicht ordnungsgemäß ausgeführt wird. Diese Bibliotheken werden hier angegeben.

  • Derzeit wird keine Standardausgabe bereitgestellt. Wenn keine Fehler gefunden werden, wird die CLI nach der Ausführung einfach beendet.

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

    Publizieren eines Pakets

    Publizieren eines Pakets

    Pakete sind eine einfache Möglichkeit, Blöcke zu speichern und gemeinsam mit der Dynamo-Community zu nutzen. Ein Paket kann alle möglichen Elemente enthalten, von benutzerdefinierten Blöcken, die im Dynamo-Arbeitsbereich erstellt wurden, bis hin zu von NodeModel abgeleiteten Blöcken. Pakete werden mit dem Package Manager publiziert und installiert. Zusätzlich zu dieser Seite enthält der Primer eine allgemeine Anleitung für Pakete.

    Was ist ein Package Manager?

    Der Dynamo Package Manager ist eine Softwareregistrierung (ähnlich wie npm), auf die Sie über Dynamo oder über einen Webbrowser zugreifen können. Der Package Manager umfasst das Installieren, Publizieren, Aktualisieren und Anzeigen von Paketen. Wie npm verwaltet er verschiedene Versionen von Paketen. Außerdem können Sie so die Abhängigkeiten Ihres Projekts verwalten.

    Suchen Sie im Browser nach Paketen, und zeigen Sie Statistiken an: .

    • In Dynamo umfasst der Package Manager das Installieren, Publizieren und Aktualisieren von Paketen.

    1. Online-Suche nach Paketen: Packages > Search for a Package...

    2. Anzeigen/Bearbeiten von installierten Paketen: Packages > Manage Packages...

    3. Publizieren eines neuen Pakets: Packages > Publish New Package...

    Pakete werden in Dynamo über den Package Manager publiziert. Es wird empfohlen, lokal zu publizieren, das Paket zu testen und dann online zu publizieren, um das Paket gemeinsam mit der Community zu nutzen. Anhand der NodeModel-Fallstudie werden die erforderlichen Schritte zum Publizieren des RectangularGrid-Blocks als Paket lokal und dann online beschrieben.

    Starten Sie Dynamo, und wählen Sie Packages > Publish New Package..., um das Fenster Publish a Package zu öffnen.

    1. Wählen Sie Add file..., um nach Dateien zu suchen, die dem Paket hinzugefügt werden sollen.

    2. Wählen Sie die beiden .dll-Dateien aus der NodeModel-Fallstudie aus.

    3. Wählen Sie Ok aus.

    Geben Sie dem Paket einen Namen, eine Beschreibung und eine Versionsbezeichnung, wenn die Dateien dem Paketinhalt hinzugefügt wurden. Beim Publizieren eines Pakets mit Dynamo wird automatisch eine pkg.json-Datei erstellt.

    Ein Paket, das bereit für die Publizierung ist

    1. Geben Sie die erforderlichen Informationen für Name, Beschreibung und Version ein.

    2. Publizieren Sie das Paket, indem Sie auf Lokal publizieren klicken und den Dynamo-Paketordner AppData\Roaming\Dynamo\Dynamo Core\1.3\packages auswählen, damit der Block in Core verfügbar ist. Publizieren Sie immer lokal, bis das Paket so weit ist, dass es freigegeben werden kann.

    Nach dem Publizieren eines Pakets sind die Blöcke in der Dynamo-Bibliothek unter der Kategorie CustomNodeModel verfügbar.

    1. Das soeben in der Dynamo-Bibliothek erstellte Paket.

    Wenn das Paket online publiziert werden kann, öffnen Sie den Package Manager, wählen Sie Publish und dann Publish Online.

    1. Um zu sehen, wie Dynamo das Paket formatiert hat, klicken Sie auf die drei vertikalen Punkte rechts neben CustomNodeModel und wählen Stammverzeichnis anzeigen.

    2. Wählen Sie im Fenster zum Publizieren von Dynamo-Paketen Publish und dann Publish Online aus.

    3. Um ein Paket zu löschen, wählen Sie Delete.

    Wie aktualisiere ich ein Paket?

    Das Aktualisieren eines Pakets ist ein ähnlicher Vorgang wie das Publizieren. Öffnen Sie den Package Manager, wählen Sie Publish Version... für das Paket aus, das aktualisiert werden muss, und geben Sie eine höhere Version ein.

    1. Wählen Sie Publish Version, um ein vorhandenes Paket mit neuen Dateien im Stammverzeichnis zu aktualisieren, und wählen Sie dann, ob es lokal oder online publiziert werden soll.

    Web-Client des Package Manager

    Mit dem Web-Client des Package Manager können Benutzer nach Paketdaten suchen und diese anzeigen, einschließlich Versionierung, Download-Statistiken und anderen relevanten Informationen. Darüber hinaus können sich Paketautoren anmelden, um ihre Paketdetails, wie z. B. Kompatibilitätsinformationen, direkt über den Web-Client zu aktualisieren.

    Weitere Informationen zu diesen Funktionen finden Sie im folgenden Blog-Post: .

    Der Web-Client des Package Manager ist über folgenden Link verfügbar:

    Aktualisieren von Paketdetails

    Autoren können ihre Paketbeschreibung, den Website-Link und den Repository-Link bearbeiten, indem sie die folgenden Schritte ausführen:

    1. Wählen Sie unter Meine Pakete das Paket aus, und klicken Sie auf Paketdetails bearbeiten.

    2. Fügen Sie die Links für die Website und das Repository mithilfe der entsprechenden Felder hinzu, oder ändern Sie sie.

    3. Aktualisieren Sie bei Bedarf die Paketbeschreibung.

    Anmerkung: Die Aktualisierung im Package Manager in Dynamo kann bis zu 15 Minuten dauern, da Server-Updates einige Zeit in Anspruch nehmen. Wir arbeiten daran, um diese Zeit zu reduzieren.

    Bearbeiten von Kompatibilitätsinformationen für publizierte Paketversionen

    Kompatibilitätsinformationen können rückwirkend für zuvor publizierte Paketversionen aktualisiert werden. Führen Sie die folgenden Schritte aus:

    Schritt 1:

    1. Klicken Sie auf die Paketversion, die Sie aktualisieren möchten.

    2. Die Liste Abhängig von wird automatisch mit den Paketen gefüllt, von denen Ihr Paket abhängt.

    3. Klicken Sie auf das Stiftsymbol neben Kompatibilität, um den Arbeitsablauf Kompatibilitätsinformationen bearbeiten zu öffnen.

    Schritt 2:

    Folgen Sie dem Flussdiagramm unten, und prüfen Sie die folgende Tabelle, um zu ermitteln, welche Option für Ihr Paket am besten geeignet ist.

    Sehen wir uns einige Szenarien anhand von Beispielen an:

    Beispielpaket Nr. 1 – Civil Connection: Dieses Paket verfügt über API-Abhängigkeiten in Bezug auf Revit und Civil 3D und enthält keine Sammlung von Kernblöcken (z. B. Geometriefunktionen, mathematische Funktionen und/oder Listenverwaltung). In diesem Fall wäre Option 1 die ideale Option. Das Paket wird in Revit und Civil 3D als kompatibel angezeigt, die dem Versionsbereich und/oder der Liste der einzelnen Versionen entsprechen.

    Beispielpaket Nr. 2 – Rhythm: Dieses Paket ist eine Sammlung aus Revit-spezifischen Blöcken sowie Core-Blöcken. In diesem Fall weist das Paket Host-Abhängigkeiten auf. Es enthält aber auch Core-Blöcke, die in Dynamo Core verwendet werden können. In diesem Fall wäre die ideale Option Option 2. Das Paket wird in der Revit- und Dynamo Core-Umgebung (auch als Dynamo Sandbox bezeichnet) als kompatibel angezeigt, die dem Versionsbereich und/oder der Liste der einzelnen Versionen entspricht.

    Beispielpaket Nr. 3 – Mesh Toolkit: Dieses Paket ist ein Dynamo Core-Paket, bei dem es sich um eine Sammlung von Geometrieblöcken ohne Host-Abhängigkeiten handelt. In diesem Fall wäre die ideale Option Option 3. Das Paket wird in Dynamo und allen Host-Umgebungen als kompatibel angezeigt, die dem Versionsbereich und/oder der Liste der einzelnen Versionen entsprechen.

    Je nach ausgewählter Option werden Dynamo- und/oder Host-spezifische Felder eingeblendet, wie in der folgenden Abbildung gezeigt.

    Entwickeln für Dynamo for Revit

    Verwenden von Methoden in GeometryPrimitiveConverter.cs

    Die Klasse in der Codebibliothek von DynamoRevit bietet verschiedene Methoden zum Konvertieren zwischen geometrischen Typen in Revit und Dynamo. Diese Methoden sind nützlich beim Arbeiten mit Geometrie in Dynamo-Skripten, die mit Revit-Modellen interagieren.

    Klicken Sie auf Änderungen speichern, um die Aktualisierungen anzuwenden.
    https://dynamopackages.com/
    Publizieren von Paketen
    https://dynamobim.org/discover-the-new-dynamo-package-management-experience/
    https://dynamopackages.com/
    Suchen nach Paketen
    Publizieren von Paketen
    Paketeinstellungen
    Paket in der Dynamo-Bibliothek
    Publizieren eines Pakets im Package Manager
    Publizieren einer Paketversion
    Web-Client des Package Manager
    Neue Benutzeroberfläche zum Aktualisieren der Paketdetails für publizierte Pakete
    Bearbeiten der Kompatibilitätsinformationen für publizierte Pakete – Schritt 1
    Welche Option sollte für den Arbeitsablauf Kompatibilitätsinformationen bearbeiten ausgewählt werden?
    Optionen zum Bearbeiten der Kompatibilitätsinformationen
    Kompatibilitätsinformationen bearbeiten – Schritt 2
    Methodenkategorien

    Die Methoden in GeometryPrimitiveConverter.cs können in vier Hauptkategorien eingeteilt werden:

    1. Proto-in-Revit-Typen: Methoden, mit denen Dynamo-(Proto-)Typen in Revit-Typen konvertiert werden.

    2. Revit-in-Proto-Typen: Methoden, mit denen Revit-Typen in Dynamo-Typen (Proto-Typen) konvertiert werden.

    3. Grad und Bogenmaß: Methoden, mit denen zwischen Grad und Bogenmaß gewechselt werden kann.

    4. X und UZ: Methoden, die sich mit dem Abrufen lotrechter Vektoren befassen.

    Proto-in-Revit-Typen

    ToRevitBoundingBox

    Erstellt ein Revit-BoundingBoxXYZ-Objekt aus einem Dynamo-Koordinatensystem und zwei definierenden Punkten (Minimum und Maximum).

    public static Autodesk.Revit.DB.BoundingBoxXYZ ToRevitBoundingBox( Autodesk.DesignScript.Geometry.CoordinateSystem cs, Autodesk.DesignScript.Geometry.Point minPoint, Autodesk.DesignScript.Geometry.Point maxPoint, bool convertUnits = true)

    ToRevitType (BoundingBox)

    Konvertiert ein Dynamo-BoundingBox-Objekt in ein Revit-BoundingBoxXYZ-Objekt.

    Das Flag convertUnits (Vorgabe ist True) bestimmt, ob die Koordinaten vom Dynamo-Einheitensystem in die internen Revit-Einheiten konvertiert werden sollen.

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

    ToRevitType (Point)

    Konvertiert einen Dynamo-Punkt in einen Revit-XYZ-Wert.

    Das Flag convertUnits (Vorgabe ist True) konvertiert die Koordinaten, falls erforderlich.

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

    ToRevitType (Vector)

    Konvertiert einen Dynamo-Vektor in einen Revit-XYZ-Wert.

    Beachten Sie, dass das Flag convertUnits vorgabemäßig auf False gesetzt ist, da Vektoren Richtung und Größe darstellen, für die normalerweise keine Einheitenkonvertierung erforderlich ist. Die Konvertierung kann sich auf Richtung und Länge des Vektors auswirken.

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

    ToXyz (Point)

    Konvertiert einen Dynamo-Punkt in einen Revit-XYZ-Wert.

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

    ToXyz (Vector)

    Konvertiert einen Dynamo-Vektor in einen Revit-XYZ-Wert.

    Beachten Sie, dass das Flag convertUnits vorgabemäßig auf False gesetzt ist, da Vektoren Richtung und Größe darstellen, für die normalerweise keine Einheitenkonvertierung erforderlich ist. Die Konvertierung kann sich auf Richtung und Länge des Vektors auswirken.

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

    ToTransform

    Konvertiert ein Dynamo-CoordinateSystem-Objekt in eine Revit-Transformation.

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

    ToPlane

    Konvertiert eine Dynamo-Ebene in eine Revit-Ebene.

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

    ToXyzs (Points)

    Konvertiert Sammlungen von Dynamo-Punktobjekten in Revit-XYZ-Sammlungen.

    Gibt eine Liste mit XYZ-Werten zurück. public static List<XYZ> ToXyzs(this List<Autodesk.DesignScript.Geometry.Point> list, bool convertUnits = true)

    Gibt ein Array von XYZ-Werten zurück. public static XYZ[] ToXyzs(this Autodesk.DesignScript.Geometry.Point[] list, bool convertUnits = true)

    ToXyzs (Vectors)

    Konvertiert ein Array von Dynamo-Vektorobjekten in ein Array von Revit-XYZ-Vektoren.

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

    ToDoubleArray

    Konvertiert ein Array von double-Werten in ein Revit-DoubleArray-Objekt.

    public static DoubleArray ToDoubleArray(this double[] list)

    ToUvs

    Konvertiert ein zweidimensionales Array (double[][]), in dem jedes innere Array ein Wertepaar (U und V) darstellt, in ein Array von Revit-UV-Objekten.

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

    ToDSUvs

    Konvertiert ein zweidimensionales Array (double[][]), in dem jedes innere Array ein Wertepaar (U und V) darstellt, in ein Array von Dynamo-UV-Objekten.

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

    Beispiel für die Verwendung von Proto-in-Revit-Typen

    Dieses Beispiel zeigt eine schnelle und einfache Methode zur Verwendung der Methode .ToXyz (Point) zum Konvertieren eines Dynamo-Point.ByCoordinates-Objekts in einen Revit-XYZ-Wert.

    Konvertieren eines Dynamo-Point.ByCoordinates-Objekts in einen Revit-XYZ-Wert

    Revit-in-Proto-Typen

    ToProtoType (BoundingBox)

    Konvertiert ein Revit-BoundingBoxXYZ-Objekt in ein Dynamo-BoundingBox-Objekt.

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

    ToPoint (XYZ)

    Konvertiert einen Revit-XYZ-Wert in einen Dynamo-Punkt.

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

    ToProtoType (Point)

    Konvertiert einen Revit-Punkt in einen Dynamo-Punkt.

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

    ToVector (XYZ)

    Konvertiert einen Revit-XYZ-Wert in einen Dynamo-Vektor.

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

    ToProtoType (UV)

    Konvertiert einen Revit-UV-Wert in einen Dynamo-UV-Wert.

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

    ToPlane (Revit Plane)

    Konvertiert eine Revit-Ebene in eine Dynamo-Ebene.

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

    ToCoordinateSystem

    Konvertiert eine Revit-Transformation in ein Dynamo-CoordinateSystem-Objekt.

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

    ToPoints

    Konvertiert eine Liste mit Revit-XYZ-Punkten in eine Liste mit Dynamo-Punkten.

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

    Beispiel für die Verwendung von Revit-in-Proto-Typen

    Dieses Beispiel zeigt eine schnelle und einfache Methode zur Verwendung der Methode .ToPoint (XYZ) zum Konvertieren eines Revit-XYZ-Werts in einen Dynamo-Punkt.

    Konvertieren eines Revit-XYZ-Werts in ein Dynamo-Point.ByCoordinates-Objekt

    Grad und Bogenmaß

    ToRadians

    Wandelt Grad in Bogenmaß um.

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

    ToDegrees

    Wandelt Bogenmaß in Grad um.

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

    Beispiel für die Verwendung von Grad und Bogenmaß

    Dieses Beispiel zeigt eine schnelle und einfache Methode zur Verwendung der Methode .ToRadians zum Umwandeln von Grad in Bogenmaß.

    Grad in Bogenmaß

    X und UZ

    GetPerpendicular (XYZ)

    Diese Methode gibt einen lotrechten XYZ-Vektor für den angegebenen XYZ-Vektor zurück.

    public static XYZ GetPerpendicular(this XYZ xyz)

    GetPerpendicular (Vector)

    Diese Methode gibt einen lotrechten Dynamo-Vector-Wert für den angegebenen Dynamo-Vector-Wert zurück.

    public static Vector GetPerpendicular(this Vector vector)

    Beispiel für die Verwendung von X und UZ

    Dieses Beispiel zeigt eine schnelle und einfache Methode zur Verwendung der Methode .GetPerpendicular zum Abrufen des lotrechten Vektors für einen Eingabevektor.

    Lotrechten Vektor abrufen
    GeometryPrimitiveConverter
    # Load the Python Standard and DesignScript Libraries
    import sys
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    # Revit API
    from Autodesk.Revit.DB import *
    
    # Revit Geometry Conversion Library
    import Revit
    clr.ImportExtensions(Revit.GeometryConversion)
    
    # Input: Dynamo Point
    dyn_point = IN[0]
    
    # Convert to Revit XYZ
    revit_point = dyn_point.ToXyz()
    
    # Output
    OUT = revit_point
    
    import sys
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    # Revit API
    from Autodesk.Revit.DB import *
    
    # Revit Geometry Conversion Library
    import Revit
    clr.ImportExtensions(Revit.GeometryConversion)
    
    # Input: Dynamo Point
    dyn_point = IN[0]
    
    # Convert to Revit XYZ
    revit_point = dyn_point.ToPoint()
    
    # Output
    OUT = revit_point
    import sys
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    # Revit API
    from Autodesk.Revit.DB import *
    
    # Revit Geometry Conversion Library
    import Revit
    clr.ImportExtensions(Revit.GeometryConversion)
    
    # Input: Measure Angle
    degree_angle = IN[0]
    
    # Convert to Radians
    radian_angle = Revit.GeometryConversion.GeometryPrimitiveConverter.ToRadians(degree_angle)
    
    # Output
    OUT = radian_angle
    import clr
    clr.AddReference('ProtoGeometry')
    from Autodesk.DesignScript.Geometry import *
    
    # Revit API
    from Autodesk.Revit.DB import *
    
    # Revit Geometry Conversion Library
    import Revit
    clr.ImportExtensions(Revit.GeometryConversion)
    
    # Input Dynamo Vector
    input_vector = IN[0]
    
    # Get perpendicular vector using GetPerpendicular
    perpendicular_vector = Revit.GeometryConversion.GeometryPrimitiveConverter.GetPerpendicular(input_vector)
    
    # Output the perpendicular vector
    OUT = perpendicular_vector
    

    Weitere Schritte mit Zero-Touch

    Wenn wir wissen, wie wir ein Zero-Touch-Projekt erstellen, können wir uns die Details zum Erstellen eines Blocks anhand des Beispiels ZeroTouchEssentials im Dynamo-GitHub genauer ansehen.

    Zero-Touch-Blöcke

    Viele der Standardblöcke von Dynamo sind im Wesentlichen Zero-Touch-Blöcke, wie die meisten der oben genannten Mathematik-, Farb- und DateTime-Blöcke.

    Laden Sie zunächst hier das Projekt ZeroTouchEssentials herunter: https://github.com/DynamoDS/ZeroTouchEssentials

    Öffnen Sie in Visual Studio die Projektmappendatei ZeroTouchEssentials.sln, und erstellen Sie die Projektmappe.

    ZeroTouchEssentials in Visual Studio

    Die Datei ZeroTouchEssentials.cs enthält alle Methoden, die wir in Dynamo importieren.

    Öffnen Sie Dynamo, und importieren Sie die Datei ZeroTouchEssentials.dll, um die Blöcke abzurufen, die in den folgenden Beispielen referenziert werden.

    Die Codebeispiele werden aus abgerufen und entsprechen im Allgemeinen dieser Datei. Die XML-Dokumentation wurde entfernt, um sie kurz zu halten, und bei jedem Codebeispiel wird der Block in der Abbildung darüber erstellt.

    Vorgegebene Eingabewerte

    Dynamo unterstützt die Definition von Vorgabewerten für Eingabeanschlüsse auf einem Block. Diese Vorgabewerte werden für den Block bereitgestellt, wenn die Anschlüsse keine Verbindungen haben. Vorgaben werden mithilfe des C#-Mechanismus zum Angeben optionaler Argumente im ausgedrückt. Die Vorgaben werden wie folgt angegeben:

    • Stellen Sie die Methodenparameter auf einen Vorgabewert ein: inputNumber = 2.0

    1. Der Vorgabewert wird angezeigt, wenn Sie den Mauszeiger über den Eingabeanschluss des Blocks bewegen.

    Zurückgeben mehrerer Werte

    Das Zurückgeben mehrerer Werte ist etwas komplexer als die Erstellung mehrerer Eingaben, daher müssen sie mithilfe eines Wörterbuchs zurückgegeben werden. Die Einträge im Wörterbuch werden auf der Ausgabeseite des Blocks zu Anschlüssen. Mehrere Rückgabe-Anschlüsse werden auf folgende Weise erstellt:

    • Fügen Sie using System.Collections.Generic; hinzu, um Dictionary<> zu verwenden.

    • Fügen Sie using Autodesk.DesignScript.Runtime; hinzu, um das Attribut MultiReturn zu verwenden. Dieses referenziert DynamoServices.dll aus dem DynamoServices-NuGet-Paket.

    Weitere Informationen finden Sie in diesem Codebeispiel in .

    Ein Block, der mehrere Ausgaben zurückgibt.

    1. Beachten Sie, dass nun zwei Ausgabeanschlüsse vorhanden sind, die entsprechend den Zeichenfolgen benannt sind, die wir für die Wörterbuchschlüssel eingegeben haben.

    Dokumentation, QuickInfos und Suche

    Es wird empfohlen, Dynamo-Blöcken Dokumentation hinzuzufügen, die die Funktion, Eingaben, Ausgaben, Suchbegriffe usw. des Blocks beschreibt. Dies erfolgt über XML-Dokumentations-Tags. XML-Dokumentation wird wie folgt erstellt:

    • Jeder Kommentartext, dem drei Schrägstriche vorangestellt sind, wird als Dokumentation betrachtet.

      • Beispiel: /// Documentation text and XML goes here

    • Erstellen Sie nach den drei Schrägstrichen XML-Tags über Methoden, die Dynamo beim Importieren der DLL-Datei liest.

    1. Visual Studio generiert eine XML-Datei am angegebenen Speicherort.

    Folgende Tag-Typen stehen zur Verfügung:

    • /// <summary>...</summary> ist die Hauptdokumentation für Ihren Block und wird als QuickInfo über dem Block in der linken Suchleiste angezeigt.

    • /// <param name="inputName">...</param> erstellt Dokumentation für bestimmte Eingabeparameter.

    • /// <returns>...</returns> erstellt Dokumentation für einen Ausgabeparameter.

    Im Folgenden sehen Sie einen Beispielblock mit Eingabe- und Ausgabebeschreibungen sowie eine Zusammenfassung, die in der Bibliothek angezeigt wird.

    Weitere Informationen finden Sie in diesem Codebeispiel in .

    Beachten Sie, dass der Code für diesen Beispielblock Folgendes enthält:

    1. Eine Blockzusammenfassung

    2. Eine Eingabebeschreibung

    3. Eine Ausgabebeschreibung

    Optimale Verfahren für Dynamo-Blockbeschreibungen

    Blockbeschreibungen erläutern kurz die Funktion und die Ausgabe eines Blocks. In Dynamo werden sie an zwei Stellen angezeigt:

    • In der QuickInfo des Blocks

    • Im Dokumentationsbrowser

    Befolgen Sie diese Richtlinien, um beim Schreiben oder Aktualisieren von Blockbeschreibungen Konsistenz zu gewährleisten und Zeit zu sparen.

    Überblick

    Beschreibungen sollten aus ein bis zwei Sätzen bestehen. Wenn Sie weitere Informationen benötigen, fügen Sie diese im Dokumentationsbrowser unter Im Detail ein.

    Groß- und Kleinschreibung (Großschreibung des ersten Wortes eines Satzes und von Eigennamen). Kein Punkt am Ende.

    Die Sprache sollte so klar und einfach wie möglich sein. Definieren Sie Akronyme bei der ersten Erwähnung, es sei denn, sie sind auch unter Laien allgemein bekannt.

    Legen Sie immer Wert auf Klarheit, auch wenn das bedeutet, von diesen Richtlinien abzuweichen.

    Richtlinien

    So sollten Sie vorgehen
    So sollten Sie nicht vorgehen

    Warnungen und Fehler in Dynamo-Blöcken

    Blockwarnungen und -fehler machen den Benutzer auf ein Problem mit dem Diagramm aufmerksam. Sie informieren den Benutzer über Probleme, die die normale Ausführung des Diagramms beeinträchtigen, indem ein Symbol und ein erweiterter Text-Beschriftungsblock über dem Block angezeigt werden. Blockfehler und -warnungen können unterschiedliche Schweregrade aufweisen: Einige Diagramme können mit Warnungen dennoch ausgeführt werden, während bei anderen die erwarteten Ergebnisse blockiert werden. In allen Fällen sind Blockfehler und -warnungen wichtige Werkzeuge, um den Benutzer über Probleme mit dem Diagramm auf dem Laufenden zu halten.

    Richtlinien zur Gewährleistung der Konsistenz und zur Zeitersparnis beim Schreiben oder Aktualisieren von Blockwarn- und -fehlermeldungen finden Sie auf der Wiki-Seite .

    Objekte

    Dynamo verfügt nicht über das Schlüsselwort new, sodass Objekte unter Verwendung statischer Konstruktionsmethoden erstellt werden müssen. Objekte werden wie folgt konstruiert:

    • Legen Sie den Konstruktor als intern (internal ZeroTouchEssentials()) fest, sofern nicht anders erforderlich.

    • Konstruieren Sie das Objekt mit einer statischen Methode wie public static ZeroTouchEssentials ByTwoDoubles(a, b).

    Anmerkung: Dynamo verwendet das Präfix Von, um anzugeben, dass eine statische Methode ein Konstruktor ist. Diese Option ist zwar optional, doch die Verwendung von Von hilft Ihnen dabei, die Bibliothek besser in den vorhandenen Dynamo-Stil einzupassen.

    Weitere Informationen finden Sie in diesem Codebeispiel in .

    Nachdem die DLL-Datei ZeroTouchEssentials importiert wurde, befindet sich ein ZeroTouchEssentials-Block in der Bibliothek. Dieses Objekt kann mithilfe des Blocks ByTwoDoubles erstellt werden.

    Verwenden von Dynamo-Geometrietypen

    Dynamo-Bibliotheken können native Dynamo-Geometrietypen als Eingaben verwenden und neue Geometrie als Ausgaben erstellen. Geometrietypen werden wie folgt erstellt:

    • Referenzieren Sie ProtoGeometry.dll im Projekt, indem Sie using Autodesk.DesignScript.Geometry; oben in der C#-Datei einfügen und das ZeroTouchLibrary-NuGet-Paket zum Projekt hinzufügen.

    • Wichtig: Verwalten Sie die Geometrieressourcen, die nicht von Ihren Funktionen zurückgegeben werden, wie im Abschnitt Verwerfen/Verwenden von Anweisungen weiter unten beschrieben.

    Anmerkung: Dynamo-Geometrieobjekte werden wie alle anderen übergebenen Objekte für Funktionen verwendet.

    Weitere Informationen finden Sie in diesem Codebeispiel in .

    Ein Block, der die Länge einer Kurve abruft und diese verdoppelt.

    1. Dieser Block akzeptiert einen Kurvengeometrietyp als Eingabe.

    Verwerfen/Verwenden von Anweisungen

    Geometrieressourcen, die nicht aus Funktionen zurückgegeben werden, müssen manuell verwaltet werden, es sei denn, Sie verwenden die Dynamo-Version 2.5 oder höher. In Dynamo 2.5 und späteren Versionen werden Geometrieressourcen intern vom System verwaltet. Sie müssen Geometrie jedoch möglicherweise weiterhin manuell entfernen, wenn es sich um einen komplexen Anwendungsfall handelt oder wenn Sie zu einem festgelegten Zeitpunkt Speicherplatz reduzieren müssen. Die Dynamo-Engine verarbeitet alle Geometrieressourcen, die aus Funktionen zurückgegeben werden. Nicht zurückgegebene Geometrieressourcen können wie folgt manuell verarbeitet werden:

    • Mit einer using-Anweisung:

      Die using-Anweisung ist dokumentiert.

      Weitere Informationen zu den neuen Stabilitätsfunktionen ab Dynamo 2.5 finden Sie im Artikel zu .

    • Mit manuellen Dispose-Aufrufen:

    Migrationen

    Beim Publizieren einer neueren Version einer Bibliothek können sich Blocknamen ändern. Namensänderungen können in einer Migrationsdatei angegeben werden, sodass in früheren Versionen einer Bibliothek erstellte Diagramme auch nach einer Aktualisierung ordnungsgemäß funktionieren. Migrationen werden wie folgt durchgeführt:

    • Erstellen Sie eine .xml-Datei im selben Ordner wie die .dll-Datei mit folgendem Format: "BaseDLLName".Migrations.xml.

    • Erstellen Sie in der .xml-Datei ein einzelnes <migrations>...</migrations>-Element.

    1. Klicken Sie mit der rechten Maustaste, und wählen Sie Add > New Item aus.

    2. Wählen Sie XML File.

    3. Für dieses Projekt geben wir der Migrationsdatei den Namen ZeroTouchEssentials.Migrations.xml.

    Dieser Beispielcode weist Dynamo an, dass alle Blöcke mit dem Namen GetClosestPoint jetzt den Namen ClosestPointTo erhalten.

    Weitere Informationen finden Sie in diesem Codebeispiel in .

    Generika

    Zero-Touch unterstützt derzeit keine Generika. Sie können verwendet werden, jedoch nicht in dem Code, der direkt importiert wird, wenn der Typ nicht festgelegt ist. Methoden, Eigenschaften oder Klassen, die generisch sind und nicht über einen festgelegten Typ verfügen, können nicht verfügbar gemacht werden.

    Im folgenden Beispiel wird ein Zero-Touch-Block des Typs T nicht importiert. Wenn die restliche Bibliothek in Dynamo importiert wird, fehlen Typausnahmen.

    Wenn Sie in diesem Beispiel einen generischen Typ mit dem festgelegtem Typ verwenden, wird dieser in Dynamo importiert.

    Aktualisieren der Pakete und Dynamo-Bibliotheken für Dynamo 2.x

    Einführung:

    Dynamo 2.0 ist eine Hauptversion, und einige APIs wurden geändert oder entfernt. Eine der größten Änderungen, die sich auf Block- und Paket-Autoren auswirken wird, ist der Wechsel zum JSON-Dateiformat.

    Generell werden Zero-Touch-Block-Autoren wenig bis gar keine Arbeit damit haben, ihre Pakete in der Version 2.0 zu verwenden.

    Benutzeroberflächen-Blöcke und Blöcke, die direkt aus NodeModel abgeleitet werden, erfordern mehr Arbeit, damit sie in der Version 2.x ausgeführt werden können.

    Erweiterungsautoren müssen möglicherweise auch einige Änderungen vornehmen, je nachdem, wie viele der Dynamo Core-APIs sie in ihren Erweiterungen verwenden.


    Allgemeine Paket-Regeln:

    • Bündeln Sie Dynamo- oder Dynamo Revit-DLL-Dateien nicht zusammen mit Ihrem Paket. Diese DLL-Dateien sind bereits von Dynamo geladen worden. Wenn Sie eine andere Version bündeln, als der Benutzer geladen hat (d. h., Sie verteilen zum Beispiel Dynamo Core 1.3, der Benutzer führt Ihr Paket jedoch unter Dynamo 2.0 aus), treten mysteriöse Laufzeitfehler auf. Dazu gehören DLL-Dateien wie DynamoCore.dll, DynamoServices.dll, DSCodeNodes.dll, ProtoGeometry.dll.

    • Bündeln und verteilen Sie newtonsoft.json.net nach Möglichkeit nicht zusammen mit Ihrem Paket. Diese DLL-Datei ist ebenfalls bereits von Dynamo 2.x geladen. Das gleiche Problem wie oben kann auftreten.

    Häufige Probleme:

    1. Beim Öffnen eines Diagramms haben einige Blöcke mehrere Anschlüsse mit demselben Namen, das Diagramm sah beim Speichern jedoch einwandfrei aus. Dieses Problem kann mehrere Ursachen haben.

    Die häufigste Fehlerursache ist, dass der Block mit einem Konstruktor erstellt wurde, der die Anschlüsse neu erstellt hat. Stattdessen hätte ein Konstruktor verwendet werden müssen, der die Anschlüsse geladen hat. Diese Konstruktoren sind gewöhnlich mit [JsonConstructor] gekennzeichnet. Beispiele finden Sie unten.

    Dies kann folgende Ursachen haben:

    • Es gab einfach keinen passenden [JsonConstructor], oder der Datei wurden Inports und Outports aus der JSON-DYN-Datei nicht übergeben.

    • Es wurden zwei Versionen von JSON.net gleichzeitig in denselben Prozess geladen, was einen .NET-Laufzeitfehler verursachte, sodass das Attribut [JsonConstructor] nicht ordnungsgemäß verwendet werden konnte, um den Konstruktor zu markieren.

    1. Beim Laden des Diagramms fehlen Blöcke vollständig, und es treten Fehler in der Konsole auf.

    • Dies kann auftreten, wenn die Deserialisierung aus irgendeinem Grund fehlgeschlagen ist. Es empfiehlt sich, nur die benötigten Eigenschaften zu serialisieren. Wir können [JsonIgnore] für komplexe Eigenschaften verwenden, die Sie nicht laden oder speichern müssen, um sie zu ignorieren. Eigenschaften wie function pointer, delegate, action, oder event usw. Diese sollten nicht serialisiert werden, da sie in der Regel nicht deserialisiert werden können und einen Laufzeitfehler verursachen.

    Aktualisierung im Detail:

    Benutzerdefinierte Blöcke 1.3 - > 2.0

    Bekannte Probleme:

    • Ein gleicher benutzerdefinierter Blockname und Kategoriename auf derselben Ebene in library.js führt zu unerwartetem Verhalten. : Vermeiden Sie die Verwendung derselben Namen für Kategorie und Blöcke.

    • Kommentare werden in Blockkommentare anstatt in Zeilenkommentare umgewandelt.

    • Kurze Typnamen werden durch vollständige Namen ersetzt. Wenn Sie beispielsweise beim erneuten Laden des benutzerdefinierten Blocks keinen Typ angegeben haben, wird var[]..[] angezeigt, da dies der Vorgabetyp ist.

    Zero-Touch-Blöcke 1.3 -> 2.0

    • In Dynamo 2.0 wurden Listen- und Wörterbuchtypen getrennt, und die Syntax zum Erstellen von Listen und Wörterbüchern wurde geändert. Listen werden mit [] initialisiert, während Wörterbücher {} verwenden. Wenn Sie zuvor das Attribut DefaultArgument verwendet haben, um Parameter auf den Zero-Touch-Blöcken zu markieren, und die Listensyntax verwendet haben, um eine bestimmte Liste wie someFunc([DefaultArgument("{0,1,2}")]) als Vorgabe zu verwenden, ist dies nicht mehr gültig. Sie müssen dann das DesignScript-Snippet ändern, um die neue Initialisierungssyntax für Listen zu verwenden.

    • Wie oben erwähnt, sollten Sie Dynamo-DLL-Dateien nicht mit Ihren Paketen verteilen (DynamoCore

    NodeModel-Blöcke 1.3 -> 2.0

    NodeModel-Blöcke erfordern die meiste Arbeit bei der Aktualisierung auf Dynamo 2.x. Auf höherer Ebene müssen Sie Konstruktoren implementieren, die nur zum Laden der Blöcke aus JSON verwendet werden, zusätzlich zu den regulären NodeModel-Konstruktoren, die zum Instanziieren neuer Instanzen der Blocktypen verwendet werden. Um zwischen diesen zu unterscheiden, markieren Sie die Konstruktoren für die Ladezeit mit [JsonConstructor], einem Attribut von newtonsoft.Json.net.

    Die Namen der Parameter im Konstruktor sollten im Allgemeinen mit den Namen der JSON-Eigenschaften übereinstimmen. Diese Zuordnung wird jedoch komplizierter, wenn Sie die Namen überschreiben, die mithilfe von [JsonProperty]-Attributen serialisiert werden.

    JSON-Konstruktoren

    Die häufigste Änderung, die beim Aktualisieren von Blöcken erforderlich ist, die von der NodeModel-Basisklasse (oder anderen Dynamo Core-Basisklassen, z. B. DSDropDownBase) abgeleitet wurden, ist die Notwendigkeit, Ihrer Klasse einen JSON-Konstruktor hinzuzufügen.

    Die Initialisierung eines neuen Blocks, der in Dynamo erstellt wurde (z. B. über die Bibliothek), ist weiterhin durch den ursprünglichen parameterlosen Konstruktor möglich. Der JSON-Konstruktor ist erforderlich, um einen Block zu initialisieren, der aus einer gespeicherten DYN- oder DYF-Datei deserialisiert (geladen) wird.

    Der JSON-Konstruktor unterscheidet sich vom Basiskonstruktor dadurch, dass er über PortModel-Parameter für inPorts und outPorts verfügt, die von der JSON-Ladelogik bereitgestellt werden. Der Aufruf zum Registrieren der Anschlüsse für den Block ist hier nicht erforderlich, da die Daten in der DYN-Datei vorhanden sind. Ein JSON-Konstruktor sieht beispielsweise wie folgt aus:

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

    Diese Syntax :base(Inports,outPorts){} ruft den nodeModel-Basiskonstruktor auf und übergibt die deserialisierten Anschlüsse an diesen.

    Spezielle Logik im Klassenkonstruktor, die die Initialisierung bestimmter Daten umfasst, die in die DYN-Datei serialisiert werden (z. B. Festlegen der Anschlussregistrierung, Vergitterungsstrategie usw.), muss in diesem Konstruktor nicht wiederholt werden, da diese Werte aus dem JSON-Konstruktor gelesen werden können.

    Dies ist der Hauptunterschied zwischen dem JSON-Konstruktor und Nicht-JSON-Konstruktoren für Ihre NodeModels. JSON-Konstruktoren werden beim Laden aus einer Datei aufgerufen und erhalten geladene Daten. Andere Benutzerlogik muss jedoch im JSON-Konstruktor dupliziert werden (z. B. Initialisieren von Ereignis-Steuerprogrammen für den Block oder Anhängen).

    Beispiele finden Sie hier im DynamoSamples-Repository -> , oder .

    Öffentliche Eigenschaften und Serialisierung

    Bisher konnte ein Entwickler bestimmte Modelldaten über die SerializeCore- und DeserializeCore-Methode in das XML-Dokument serialisieren und deserialisieren. Diese Methoden sind weiterhin in der API vorhanden, werden jedoch in einer zukünftigen Version von Dynamo nicht mehr unterstützt (ein Beispiel finden Sie ). Mit der JSON.NET-Implementierung können jetzt public-Eigenschaften in der von NodeModel abgeleiteten Klasse direkt in die DYN-Datei serialisiert werden. JSON.Net stellt mehrere Attribute bereit, mit denen die Serialisierung der Eigenschaft gesteuert wird.

    Dieses Beispiel mit der Angabe eines PropertyName finden Sie im Dynamo-Repository.

    [JsonProperty(PropertyName = "InputValue")]

    public DSColor DsColor {...

    Konverter:

    Anmerkung Wenn Sie eine eigene JSON.net-Konverterklasse erstellen, verfügt Dynamo derzeit über keinen Mechanismus, mit dem Sie diese in die Lade- und Speichermethoden einlesen können. Daher kann die Klasse auch dann nicht verwendet werden, wenn Sie sie mit dem [JsonConverter]-Attribut markieren. Sie können den Konverter stattdessen direkt in Ihrem Setter oder Getter aufrufen. //ZU ERLEDIGEN: Bestätigung dieser Einschränkung erforderlich. Alle Nachweise sind willkommen.

    Ein Beispiel, in dem eine Serialisierungsmethode zum Konvertieren der Eigenschaft in eine Zeichenfolge angegeben ist, finden Sie im Dynamo-Repository.

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

    public ConversionMetricUnit SelectedMetricConversion{...

    Ignorieren von Eigenschaften

    Für public-Eigenschaften, die nicht für die Serialisierung vorgesehen sind, muss das Attribut [JsonIgnore] hinzugefügt werden. Wenn die Blöcke in der DYN-Datei gespeichert werden, wird dadurch sichergestellt, dass diese Daten vom Serialisierungsmechanismus ignoriert werden. Beim erneuten Öffnen des Diagramms treten dann keine unerwarteten Auswirkungen auf. Ein Beispiel dafür finden Sie im Dynamo-Repository.


    Rückgängig/Wiederholen

    Wie bereits erwähnt, wurden in der Vergangenheit die Methoden SerializeCore und DeserializeCore verwendet, um Blöcke zu speichern und in die XML-DYN-Datei zu laden. Außerdem wurden sie und werden weiterhin auch zum Speichern und Laden des Blockstatus zum Rückgängigmachen und Wiederherstellen verwendet. Wenn Sie komplexe Funktionen zum Rückgängigmachen und Wiederherstellen für den NodeModel-Benutzeroberflächen-Block implementieren möchten, müssen Sie diese Methoden implementieren und in das XML-Dokumentobjekt serialisieren, das als Parameter für diese Methoden bereitgestellt wird. Dies sollte ein selten auftretender Anwendungsfall sein, mit Ausnahme von komplexen Benutzeroberflächen-Blöcken.

    APIs für Ein- und Ausgabeanschlüsse

    Ein häufiges Vorkommen in NodeModel-Blöcken, die von 2.0-API-Änderungen betroffen sind, ist die Anschlussregistrierung im Blockkonstruktor. Wenn Sie sich die Beispiele im Dynamo- oder DynamoSamples-Repository ansehen, werden Sie bisher die Verwendung der Methode InPortData.Add() oder OutPortData.Add() gefunden haben. In der Dynamo-API wurden die öffentlichen InPortData- und OutPortData-Eigenschaften bisher als veraltet markiert. In Version 2.0 wurden diese Eigenschaften entfernt. Entwickler sollten jetzt die Methoden InPorts.Add() und OutPorts.Add() verwenden. Darüber hinaus haben diese beiden Add()-Methoden leicht unterschiedliche Signaturen:

    InPortData.Add(new PortData("Port Name", "Port Description")); //Old version valid in 1.3 but now deprecated

    im Vergleich zu

    InPorts.Add(new PortModel(PortType.Input, this, new PortData("Port Name", "Port Description"))); //Recommended 2.0

    Beispiele für konvertierten Code finden Sie hier im Dynamo-Repository -> oder .

    Der andere häufige Anwendungsfall, der von den 2.0-API-Änderungen betroffen ist, bezieht sich auf die Methoden, die häufig in der Methode BuildAst() verwendet werden, um das Blockverhalten basierend auf dem Vorhandensein oder Fehlen von Anschlussverbindungen zu bestimmen. Zuvor wurde HasConnectedInput(index) verwendet, um einen verbundenen Anschlussstatus zu validieren. Entwickler sollten nun die Eigenschaft InPorts[0].IsConnected verwenden, um den Anschlussverbindungsstatus zu überprüfen. Ein Beispiel hierfür finden Sie in im Dynamo-Repository.

    Beispiele:

    Gehen wir nun die Schritte für die Aktualisierung eines 1.3-Benutzeroberflächen-Blocks auf Dynamo 2.x durch.

    Damit die nodeModel-Klasse in der Version 2.0 ordnungsgemäß geladen und gespeichert wird, müssen wir einfach nur einen jsonConstructor hinzufügen, der das Laden der Anschlüsse handhabt. Wir übergeben die Anschlüsse einfach an den Basiskonstruktor, und diese Implementierung ist leer.

    Anmerkung: Rufen Sie RegisterPorts() oder eine Variante davon nicht in Ihrem JsonConstructor auf. Dadurch werden die Eingabe- und Ausgabeparameterattribute in Ihrer Blockklasse zum Erstellen neuer Anschlüsse verwendet. Dies ist nicht erwünscht, da die geladenen Anschlüsse verwendet werden sollen, die an den Konstruktor übergeben werden.

    In diesem Beispiel wird der JSON-Konstruktor mit dem minimalsten Ladeaufwand hinzugefügt. Was passiert aber, wenn wir komplexere Konstruktionslogik ausführen müssen, wie z. B. die Einrichtung einiger Listener für die Ereignisbehandlung im Konstruktor? Das nächste aus dem entnommene Beispiel ist oben im JsonConstructors Section dieses Dokuments verknüpft.

    Im Folgenden wird ein komplexerer Konstruktor für einen Benutzeroberflächen-Block dargestellt:

    Wenn wir einen JSON-Konstruktor hinzufügen, um diesen Block aus einer Datei zu laden, müssen wir einen Teil dieser Logik neu erstellen. Beachten Sie jedoch, dass wir den Code, mit dem Anschlüsse erstellt, Vergitterungen festgelegt oder die Vorgabewerte für Eigenschaften angegeben werden, die aus der Datei geladen werden können, nicht berücksichtigen.

    Beachten Sie, dass andere öffentliche Eigenschaften, die in JSON serialisiert wurden, wie ButtonText und WindowText, nicht als explizite Parameter zum Konstruktor hinzugefügt werden müssen. Sie werden automatisch von JSON.net mit den Settern für diese Eigenschaften festgelegt.

    Erweiterungen

    Erweiterungen sind ein leistungsstarkes Entwicklungswerkzeug im Dynamo-Ökosystem. Sie ermöglichen Entwicklern, benutzerdefinierte Funktionen basierend auf Dynamo-Interaktionen und -Logik zu steuern. Erweiterungen können in zwei Hauptkategorien unterteilt werden: Erweiterungen und Ansichtserweiterungen. Wie die Namen schon sagen, können Sie mit dem Ansichtserweiterungs-Framework die Dynamo-Benutzeroberfläche durch Registrieren benutzerdefinierter Menüelemente erweitern. Normale Erweiterungen funktionieren auf ähnliche Weise, nur ohne Benutzeroberfläche. Wir können beispielsweise eine Erweiterung erstellen, die bestimmte Informationen in der Dynamo-Konsole protokolliert. Dieses Szenario erfordert keine angepasste Benutzeroberfläche und kann daher auch mit einer Erweiterung durchgeführt werden.

    Fallstudie für Erweiterungen

    Im Anschluss an das Beispiel SampleViewExtension aus dem DynamoSamples-GitHub-Repository gehen wir die Schritte zum Erstellen eines einfachen, modusunabhängigen Fensters durch, in dem die aktiven Blöcke im Diagramm in Echtzeit angezeigt werden. Für eine Ansichtserweiterung müssen wir eine Benutzeroberfläche für das Fenster erstellen und Werte an ein Ansichtsmodell binden.

  • Bündeln und verteilen Sie CEFSharp nach Möglichkeit nicht zusammen mit Ihrem Paket. Diese DLL-Datei ist ebenfalls bereits von Dynamo 2.x geladen. Das gleiche Problem wie oben kann auftreten.

  • Im Allgemeinen sollten Sie die Freigabe von Abhängigkeiten für Dynamo oder Revit vermeiden, wenn Sie die Version dieser Abhängigkeit steuern müssen.

  • Die Datei DynamoServices.dll mit einer anderen Version als die aktuelle Dynamo-Version wurde mit dem Paket gebündelt. Dadurch kann ein .NET-Laufzeitfehler beim Ermitteln des Attributs [MultiReturn] auftreten, sodass die mit verschiedenen Attributen markierten Zero-Touch-Blöcke diese nicht anwenden können. Sie werden möglicherweise feststellen, dass ein Block eine einzelne Wörterbuchausgabe anstelle mehrerer Anschlüsse zurückgibt.
    ,
    DynamoServices
    usw.).
    Organisieren von benutzerdefinierten Blöcken in library.js
    QNTM-3653
    Weitere Informationen finden Sie in der Dokumentation zu Json.net.
    ButtonCustomNodeModel
    DropDown
    SliderCustomNodeModel
    hier
    hier
    hier
    hier
    DynamoConvert.cs
    FileSystem.cs
    ColorRange.cs
    DynamoSamples-Repository
    Beschädigte JSON-Datei
    using System;
    using System.Collections.Generic;
    using Dynamo.Graph.Nodes;
    using CustomNodeModel.CustomNodeModelFunction;
    using ProtoCore.AST.AssociativeAST;
    using Autodesk.DesignScript.Geometry;
    
    namespace CustomNodeModel.CustomNodeModel
    {
        [NodeName("RectangularGrid")]
        [NodeDescription("An example NodeModel node that creates a rectangular grid. The slider randomly scales the cells.")]
        [NodeCategory("CustomNodeModel")]
        [InPortNames("xCount", "yCount")]
        [InPortTypes("double", "double")]
        [InPortDescriptions("Number of cells in the X direction", "Number of cells in the Y direction")]
        [OutPortNames("Rectangles")]
        [OutPortTypes("Autodesk.DesignScript.Geometry.Rectangle[]")]
        [OutPortDescriptions("A list of rectangles")]
        [IsDesignScriptCompatible]
        public class GridNodeModel : NodeModel
        {
            private double _sliderValue;
            public double SliderValue
            {
                get { return _sliderValue; }
                set
                {
                    _sliderValue = value;
                    RaisePropertyChanged("SliderValue");
                    OnNodeModified(false);
                }
            }
            public GridNodeModel()
            {
                RegisterAllPorts();
            }
            public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
            {
                if (!HasConnectedInput(0) || !HasConnectedInput(1))
                {
                    return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
                }
                var sliderValue = AstFactory.BuildDoubleNode(SliderValue);
                var functionCall =
                  AstFactory.BuildFunctionCall(
                    new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid),
                    new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue });
    
                return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), functionCall) };
            }
        }
    }
    [JsonConstructor]
    protected GridNodeModel(IEnumerable<PortModel> Inports, IEnumerable<PortModel> Outports ) :
    base(Inports,Outports)
    {
    
    }
    [InPortNames("xCount", "yCount")]
    [InPortTypes("double", "double")]
     public ButtonCustomNodeModel()
            {
                // When you create a UI node, you need to do the
                // work of setting up the ports yourself. To do this,
                // you can populate the InPorts and the OutPorts
                // collections with PortData objects describing your ports.
                InPorts.Add(new PortModel(PortType.Input, this, new PortData("inputString", "a string value displayed on our button")));
    
                // Nodes can have an arbitrary number of inputs and outputs.
                // If you want more ports, just create more PortData objects.
                OutPorts.Add(new PortModel(PortType.Output, this, new PortData("button value", "returns the string value displayed on our button")));
                OutPorts.Add(new PortModel(PortType.Output, this, new PortData("window value", "returns the string value displayed in our window when button is pressed")));
    
                // This call is required to ensure that your ports are
                // properly created.
                RegisterAllPorts();
    
                // Listen for input port disconnection to trigger button UI update
                this.PortDisconnected += ButtonCustomNodeModel_PortDisconnected;
    
                // The arugment lacing is the way in which Dynamo handles
                // inputs of lists. If you don't want your node to
                // support argument lacing, you can set this to LacingStrategy.Disabled.
                ArgumentLacing = LacingStrategy.Disabled;
    
                // We create a DelegateCommand object which will be 
                // bound to our button in our custom UI. Clicking the button 
                // will call the ShowMessage method.
                ButtonCommand = new DelegateCommand(ShowMessage, CanShowMessage);
    
                // Setting our property here will trigger a 
                // property change notification and the UI 
                // will be updated to reflect the new value.
                ButtonText = defaultButtonText;
                WindowText = defaultWindowText;
            }
            // This constructor is called when opening a Json graph.
    
            [JsonConstructor]
            ButtonCustomNodeModel(IEnumerable<PortModel> inPorts, IEnumerable<PortModel> outPorts) : base(inPorts, outPorts)
            {
                this.PortDisconnected += ButtonCustomNodeModel_PortDisconnected;
                ButtonCommand = new DelegateCommand(ShowMessage, CanShowMessage);
            }
    Fügen Sie der Methode das Attribut [MultiReturn(new[] { "string1", "string2", ... more strings here })] hinzu. Die Zeichenfolgen verweisen auf Schlüssel im Wörterbuch und werden zu den Namen der Ausgabeanschlüsse.
  • Geben Sie ein Dictionary<> mit Schlüsseln aus der Funktion zurück, die den Parameternamen im Attribut entsprechen: return new Dictionary<string, object>.

  • Beispiel: /// <summary>...</summary>

  • Aktivieren Sie die XML-Dokumentation in Visual Studio, indem Sie Project > [Project] Properties > Build > Output auswählen und Documentation file aktivieren.

  • /// <returns name = "outputName">...</returns> erstellt Dokumentation für mehrere Ausgabeparameter.

  • /// <search>...</search> gleicht Ihren Block mit Suchergebnissen basierend auf einer durch Kommas getrennten Liste ab. Wenn wir beispielsweise einen Block erstellen, der ein Netz unterteilt, möchten wir möglicherweise Tags wie Netz, Unterteilung und Catmull-Clark hinzufügen.

  • Schreiben Sie Boolesch groß. Schreiben Sie True und False groß, wenn Sie sich auf die Ausgabe von Booleschen Werten beziehen.

    • Beispiel: Gibt True zurück, wenn die beiden Werte unterschiedlich sind.

    • Beispiel: Wandelt eine Zeichenfolge basierend auf einem Booleschen Parameter in Groß- oder Kleinbuchstaben um.

    Boolesche Werte dürfen nicht klein geschrieben werden. Schreiben Sie True und False nicht klein, wenn Sie sich auf die Ausgabe von Booleschen Werten beziehen.

    • Beispiel: Gibt true zurück, wenn die beiden Werte unterschiedlich sind.

    • Beispiel: Wandelt eine Zeichenfolge basierend auf einem booleschen Parameter in Groß- oder Kleinbuchstaben um.

    Erstellen Sie im migrations-Element für jede Namensänderung
    <priorNameHint>...</priorNameHint>
    -Elemente.
  • Geben Sie für jede Namensänderung ein <oldName>...</oldName>- und ein <newName>...</newName>-Element an.

  • Beginnen Sie die Beschreibung mit einem Verb in der dritten Person.

    • Beispiel: Ermittelt, ob sich ein Geometrieobjekt mit einem anderen schneidet.

    Beginnen Sie nicht mit einem Verb in der zweiten Person oder mit einem Substantiv.

    • Beispiel: Ermitteln, ob sich ein Geometrieobjekt mit einem anderen schneidet

    Verwenden Sie "Gibt zurück" oder "Erstellt" bzw. ein anderes beschreibendes Verb anstelle von "Holt".

    • Beispiel: Gibt eine NURBS-Darstellung einer Fläche zurück.

    Verwenden Sie nicht "Holen" oder "Holt". Dieses Verb ist wenig spezifisch und kann sehr unterschiedlich übersetzt werden.

    • Beispiel: Holt eine NURBS-Darstellung der Fläche.

    Wenn Sie sich auf Eingaben beziehen, verwenden Sie "angegeben" oder "eingegeben" anstelle von "festgelegt" oder anderen Begriffen. Lassen Sie "angegeben" oder "eingegeben" nach Möglichkeit weg, um die Beschreibung zu vereinfachen und die Wortzahl zu reduzieren.

    • Beispiel: Löscht die angegebene Datei.

    • Beispiel: Projiziert eine Kurve entlang der angegebenen Projektionsrichtung auf die angegebene Basisgeometrie.

    Sie können "festgelegt" verwenden, wenn Sie sich nicht direkt auf eine Eingabe beziehen.

    • Beispiel: Schreibt Textinhalte in eine Datei, die durch den angegebenen Pfad festgelegt wird.

    Um die Konsistenz zu gewährleisten, sollten Sie bei Eingaben weder "festgelegt" noch einen anderen Begriff außer "angegeben" oder "eingegeben" verwenden. Mischen Sie "angegeben" und "eingegeben" nicht in derselben Beschreibung, es sei denn, dies ist aus Gründen der Übersichtlichkeit erforderlich.

    • Beispiel: Löscht die festgelegte Datei.

    • Beispiel: Projiziert eine eingegebene Kurve entlang einer angegebenen Projektionsrichtung auf eine festgelegte Basisgeometrie.

    Verwenden Sie "ein" oder "eine", wenn Sie sich zum ersten Mal auf eine Eingabe beziehen. Verwenden Sie aus Gründen der Übersichtlichkeit ggf. "der/die/das ein-/angegebene" anstelle von "ein" oder "eine".

    • Beispiel: Sweept eine Kurve entlang der Pfadkurve.

    Verwenden Sie nicht "dies(e/r)", wenn Sie sich zum ersten Mal auf eine Eingabe beziehen.

    • Beispiel: Sweept diese Kurve entlang der Pfadkurve.

    Wenn Sie sich zum ersten Mal auf eine Ausgabe oder ein anderes Substantiv beziehen, das das Ziel der Blockoperation ist, verwenden Sie "ein" oder "eine". Verwenden Sie "der/die/das" nur, wenn Sie den Artikel zusammen mit "eingegeben" oder "angegeben" verwenden.

    • Beispiel: Kopiert eine Datei.

    • Beispiel: Kopiert die angegebene Datei.

    Wenn Sie sich zum ersten Mal auf eine Ausgabe oder ein anderes Substantiv beziehen, das das Ziel der Blockoperation ist, verwenden Sie nicht "der/die/das" allein.

    • Beispiel: Kopiert die Datei.

    Schreiben Sie das erste Wort eines Satzes und alle Eigennamen, Substantive und Wörter, die im Allgemeinen groß geschrieben werden, groß.

    • Beispiel: Gibt den Schnittpunkt zweier Begrenzungsrahmen zurück.

    ZeroTouchEssentials.cs
    C#-Programmierhandbuch
    ZeroTouchEssentials.cs
    ZeroTouchEssentials.cs
    Inhaltsmuster: Blockwarnungen und -fehler
    ZeroTouchEssentials.cs
    ZeroTouchEssentials.cs
    hier
    Verbesserungen der Stabilität der Dynamo-Geometrie
    ProtoGeometry.Migrations.xml
    Vorgabewert
    Mehrere Ausgaben
    Erstellen einer XML-Datei
    Blockbeschreibung
    Block ByTwoDoubles
    Kurveneingabe
    Migrationsdatei

    Schreiben Sie gängige Geometrieobjekte und Konzepte nur groß, wenn dies aus Gründen der Übersichtlichkeit erforderlich ist.

    • Beispiel: Skaliert ungleichmäßig um die angegebene Ebene.

    Fenster der Ansichtserweiterung
    1. Das Fenster der Ansichtserweiterung, das nach dem Beispiel SampleViewExtension im GitHub-Repository entwickelt wurde.

    Wir erstellen das Beispiel zwar von Grund auf. Sie können aber auch das DynamoSamples-Repository herunterladen und erstellen, um es als Referenz zu verwenden.

    DynamoSamples-Repository: https://github.com/DynamoDS/DynamoSamples

    Diese exemplarische Vorgehensweise referenziert speziell das Projekt mit dem Namen SampleViewExtension, das unter DynamoSamples/src/ zu finden ist.

    So implementieren Sie eine Ansichtserweiterung

    Eine Ansichtserweiterung besteht aus drei wesentlichen Teilen:

    • Einer Assembly, die eine Klasse enthält, die IViewExtension implementiert, sowie einer Klasse, die ein Ansichtsmodell erstellt

    • Einer .xml-Datei, die Dynamo mitteilt, wo zur Laufzeit nach dieser Assembly gesucht werden soll, und dem Typ der Erweiterung

    • Einer .xaml-Datei, die Daten an die grafische Darstellung bindet und die Darstellung des Fensters bestimmt

    1. Erstellen der Projektstruktur

    Erstellen Sie zunächst ein neues Class Library-Projekt mit dem Namen SampleViewExtension.

    Erstellen einer neuen Klassenbibliothek
    Konfigurieren eines neuen Projekts
    1. Erstellen Sie ein neues Projekt, indem Sie File > New > Project auswählen.

    2. Wählen Sie Class Library aus.

    3. Geben Sie dem Projekt den Namen SampleViewExtension.

    4. Wählen Sie Ok aus.

    In diesem Projekt benötigen wir zwei Klassen. Eine Klasse, die IViewExtension, und eine andere, die NotificationObject. implementiert. IViewExtension enthält alle Informationen darüber, wie die Erweiterung bereitgestellt, geladen, referenziert und verworfen wird. NotificationObject informiert über Änderungen in Dynamo und IDisposable. Bei einer Änderung wird die Anzahl entsprechend aktualisiert.

    Klassendateien für Ansichtserweiterungen
    1. Eine Klassendatei mit dem Namen SampleViewExtension.cs, die IViewExtension implementiert.

    2. Eine Klassendatei mit dem Namen SampleWindowViewMode.cs, die NotificationObject implementiert.

    Um IViewExtension verwenden zu können, benötigen wir das NuGet-Paket WpfUILibrary. Bei der Installation dieses Pakets werden automatisch die Pakete Core, Services und ZeroTouchLibrary installiert.

    Ansichtserweiterungspakete
    1. Wählen Sie WpfUILibrary aus.

    2. Wählen Sie Install aus, um alle abhängigen Pakete zu installieren.

    2. Implementieren der IViewExtension-Klasse

    In der IViewExtension-Klasse legen wir fest, was geschieht, wenn Dynamo gestartet, die Erweiterung geladen und Dynamo beendet wird. Fügen Sie in der Klassendatei SampleViewExtension.cs den folgenden Code hinzu:

    Die SampleViewExtension-Klasse erstellt ein anklickbares Menüelement, um das Fenster zu öffnen, und verbindet es mit dem Ansichtsmodell und dem Ansichtsfenster.

    • public class SampleViewExtension : IViewExtension SampleViewExtension übernimmt Daten von der IViewExtension-Schnittstelle und stellt alles bereit, was wir zur Erstellung des Menüelements benötigen.

    • sampleMenuItem = new MenuItem { Header = "Show View Extension Sample Window" }; erstellt ein MenuItem und fügt es dem Menü View hinzu.

    Menüelement
    1. Menüelement

    • sampleMenuItem.Click += (sender, args) löst ein Ereignis aus, das ein neues Fenster öffnet, wenn auf das Menüelement geklickt wird.

    • MainGrid = { DataContext = viewModel } legt den Datenkontext für das Hauptraster im Fenster fest, wobei auf Main Grid in der zu erstellenden Datei .xaml verwiesen wird.

    • Owner = p.DynamoWindow legt den Eigentümer des Popup-Fensters auf Dynamo fest. Das bedeutet, dass das neue Fenster von Dynamo abhängig ist. Aktionen wie das Minimieren, Maximieren und Wiederherstellen von Dynamo bewirken daher, dass das neue Fenster dasselbe Verhalten aufweist.

    • window.Show(); zeigt das Fenster an, für das die zusätzlichen Fenstereigenschaften festgelegt wurden.

    3. Implementieren des Ansichtsmodells

    Nachdem wir einige der grundlegenden Parameter des Fensters festgelegt haben, fügen wir die Logik für die Reaktion auf verschiedene Dynamo-bezogene Ereignisse hinzu und weisen die Benutzeroberfläche an, basierend auf diesen Ereignissen zu aktualisieren. Kopieren Sie den folgenden Code in die Klassendatei SampleWindowViewModel.cs:

    Diese Implementierung der Ansichtsmodellklasse überwacht CurrentWorkspaceModel und löst ein Ereignis aus, wenn ein Block zum Arbeitsbereich hinzugefügt oder aus diesem entfernt wird. Dadurch wird eine Eigenschaftsänderung ausgelöst, die die Benutzeroberfläche oder gebundenen Elemente darüber informiert, dass die Daten geändert wurden und aktualisiert werden müssen. Der ActiveNodeTypes-Getter wird aufgerufen, der intern eine zusätzliche Hilfsfunktion getNodeTypes() aufruft. Diese Funktion durchläuft alle aktiven Blöcke im Ansichtsbereich, füllt eine Zeichenfolge mit den Namen dieser Blöcke aus und gibt diese Zeichenfolge an die Bindung in der XAML-Datei zurück, die im Popup-Fenster angezeigt werden soll.

    Nachdem wir die Kernlogik der Erweiterung definiert haben, legen wir nun die Darstellungsdetails des Fensters mit einer .xaml-Datei fest. Wir benötigen lediglich ein einfaches Fenster, in dem die Zeichenfolge über die ActiveNodeTypes-Eigenschaftenbindung in TextBlock Text angezeigt wird.

    Hinzufügen eines Fensters
    1. Klicken Sie mit der rechten Maustaste auf das Projekt, und wählen Sie Add > New Item....

    2. Wählen Sie die Vorlage des Benutzersteuerelements aus, die wir später zum Erstellen eines Fensters ändern werden.

    3. Geben Sie der neuen Datei den Namen SampleWindow.xaml.

    4. Wählen Sie Add aus.

    Im .xaml-Code des Fensters müssen wir SelectedNodesText an einen Textblock binden. Fügen Sie den folgenden Code zu SampleWindow.xaml hinzu:

    • Text="{Binding ActiveNodeTypes}" bindet den Eigenschaftswert von ActiveNodeTypes in SampleWindowViewModel.cs an den Wert TextBlock Text im Fenster.

    Als Nächstes initialisieren wir das Beispielfenster in der XAML-C#-Sicherungsdatei SampleWindow.xaml.cs. Fügen Sie den folgenden Code zu SampleWindow.xaml hinzu:

    Die Ansichtserweiterung kann jetzt erstellt und zu Dynamo hinzugefügt werden. Dynamo benötigt eine xml-Datei, um die .dll-Ausgabedatei als Erweiterung zu registrieren.

    Hinzufügen einer neuen XML-Datei
    1. Klicken Sie mit der rechten Maustaste auf das Projekt, und wählen Sie Add > New Item....

    2. Wählen Sie die XML-Datei aus.

    3. Geben Sie der Datei den Namen SampleViewExtension_ViewExtensionDefinition.xml.

    4. Wählen Sie Add aus.

    • Der Dateiname entspricht dem Dynamo-Standard zum Referenzieren einer Erweiterungs-Assembly wie folgt: "extensionName"_ViewExtensionDefinition.xml

    Fügen Sie in der xml-Datei den folgenden Code hinzu, um Dynamo anzuweisen, wo nach der Erweiterungs-Assembly gesucht werden soll:

    • In diesem Beispiel haben wir die Assembly im Vorgabeprojektordner von Visual Studio erstellt. Ersetzen Sie das Ziel <AssemblyPath>...</AssemblyPath> durch den Speicherort der Assembly.

    Der letzte Schritt besteht darin, die Datei SampleViewExtension_ViewExtensionDefinition.xml in den Ordner der Ansichtserweiterungen von Dynamo zu kopieren, der sich im Dynamo Core-Installationsverzeichnis C:\Program Files\Dynamo\Dynamo Core\1.3\viewExtensions befindet. Beachten Sie, dass separate Ordner für extensions und viewExtensions existieren. Wenn Sie die xml-Datei in den falschen Ordner verschieben, wird sie zur Laufzeit möglicherweise nicht ordnungsgemäß geladen.

    XML-Datei in den Erweiterungsordner kopiert
    1. Die .xml-Datei, die wir in den Dynamo-Ordner mit den Ansichtserweiterungen kopiert haben.

    Dies ist eine grundlegende Einführung in Ansichtserweiterungen. Eine detailliertere Fallstudie finden Sie im DynaShape-Paket, einem Open-Source-Projekt auf GitHub. Das Paket verwendet eine Ansichtserweiterung, die die Live-Bearbeitung in der Dynamo-Modellansicht ermöglicht.

    Ein Paket-Installationsprogramm für DynaShape kann im Dynamo-Forum heruntergeladen werden: https://forum.dynamobim.com/t/dynashape-published/11666.

    Der Quellcode kann von GitHub geklont werden: https://github.com/LongNguyenP/DynaShape.

    NodeModel-Fallstudie – Angepasste Benutzeroberfläche

    Auf NodeModel basierende Blöcke bieten erheblich mehr Flexibilität und Leistung als Zero-Touch-Blöcke. In diesem Beispiel wird der Zero-Touch-Rasterblock weiter optimiert. Dazu wird ein integrierter Schieberegler hinzugefügt, mit dem die Größe des Rechtecks zufällig festgelegt wird.

    Der Schieberegler skaliert die Zellen relativ zu ihrer Größe, sodass der Benutzer keinen Schieberegler mit dem richtigen Bereich zur Verfügung stellen muss.

    Model-View-Viewmodel-Muster

    namespace ZeroTouchEssentials
    {
        public class ZeroTouchEssentials
        {
            // Set the method parameter to a default value
            public static double MultiplyByTwo(double inputNumber = 2.0) 
            {
                return inputNumber * 2.0;
            }
        }
    }
    using System.Collections.Generic;
    using Autodesk.DesignScript.Runtime;
    
    namespace ZeroTouchEssentials
    {
        public class ZeroTouchEssentials
        {
            [MultiReturn(new[] { "add", "mult" })]
            public static Dictionary<string, object> ReturnMultiExample(double a, double b)
            {
                return new Dictionary<string, object>
    
                    { "add", (a + b) },
                    { "mult", (a * b) }
                };
            }
        }
    }
    using Autodesk.DesignScript.Geometry;
    
    namespace ZeroTouchEssentials
    {
        public class ZeroTouchEssentials
        {
            /// <summary>
            /// This method demonstrates how to use a native geometry object from Dynamo
            /// in a custom method
            /// </summary>
            /// <param name="curve">Input Curve. This can be of any type deriving from Curve, such as NurbsCurve, Arc, Circle, etc</param>
            /// <returns>The twice the length of the Curve </returns>
            /// <search>example,curve</search>
            public static double DoubleLength(Curve curve)
            {
                return curve.Length * 2.0;
            }
        }
    }
    namespace ZeroTouchEssentials
    {
        public class ZeroTouchEssentials
        {
            private double _a;
            private double _b;
    
            // Make the constructor internal
            internal ZeroTouchEssentials(double a, double b)
            {
                _a = a;
                _b = b;
            }
    
            // The static method that Dynamo will convert into a Create node
            public static ZeroTouchEssentials ByTwoDoubles(double a, double b)
            {
                return new ZeroTouchEssentials(a, b);
            }
        }
    }
    using Autodesk.DesignScript.Geometry;
    
    namespace ZeroTouchEssentials
    {
        public class ZeroTouchEssentials
        {
            // "Autodesk.DesignScript.Geometry.Curve" is specifying the type of geometry input, 
            // just as you would specify a double, string, or integer 
            public static double DoubleLength(Autodesk.DesignScript.Geometry.Curve curve)
            {
                return curve.Length * 2.0;
            }
        }
    }
    using (Point p1 = Point.ByCoordinates(0, 0, 0))
    {
      using (Point p2 = Point.ByCoordinates(10, 10, 0))
      {
          return Line.ByStartPointEndPoint(p1, p2);
      }
    }
    Point p1 = Point.ByCoordinates(0, 0, 0);
    Point p2 = Point.ByCoordinates(10, 10, 0);
    Line l = Line.ByStartPointEndPoint(p1, p2);
    p1.Dispose();
    p2.Dispose();
    return l;
    <?xml version="1.0"?>
    <migrations>
      <priorNameHint>
        <oldName>Autodesk.DesignScript.Geometry.Geometry.GetClosestPoint</oldName>
        <newName>Autodesk.DesignScript.Geometry.Geometry.ClosestPointTo</newName>
      </priorNameHint>
    </migrations>
    public class SomeGenericClass<T>
    {
        public SomeGenericClass()
        {
            Console.WriteLine(typeof(T).ToString());
        }  
    }
    public class SomeWrapper
    {
        public object wrapped;
        public SomeWrapper(SomeGenericClass<double> someConstrainedType)
        {
            Console.WriteLine(this.wrapped.GetType().ToString());
        }
    }
    using System;
    using System.Windows;
    using System.Windows.Controls;
    using Dynamo.Wpf.Extensions;
    
    namespace SampleViewExtension
    {
    
        public class SampleViewExtension : IViewExtension
        {
            private MenuItem sampleMenuItem;
    
            public void Dispose()
            {
            }
    
            public void Startup(ViewStartupParams p)
            {
            }
    
            public void Loaded(ViewLoadedParams p)
            {
                // Save a reference to your loaded parameters.
                // You'll need these later when you want to use
                // the supplied workspaces
    
                sampleMenuItem = new MenuItem {Header = "Show View Extension Sample Window"};
                sampleMenuItem.Click += (sender, args) =>
                {
                    var viewModel = new SampleWindowViewModel(p);
                    var window = new SampleWindow
                    {
                        // Set the data context for the main grid in the window.
                        MainGrid = { DataContext = viewModel },
    
                        // Set the owner of the window to the Dynamo window.
                        Owner = p.DynamoWindow
                    };
    
                    window.Left = window.Owner.Left + 400;
                    window.Top = window.Owner.Top + 200;
    
                    // Show a modeless window.
                    window.Show();
                };
                p.AddExtensionMenuItem(sampleMenuItem);
            }
    
            public void Shutdown()
            {
            }
    
            public string UniqueId
            {
                get
                {
                    return Guid.NewGuid().ToString();
                }  
            } 
    
            public string Name
            {
                get
                {
                    return "Sample View Extension";
                }
            } 
    
        }
    }
    using System;
    using Dynamo.Core;
    using Dynamo.Extensions;
    using Dynamo.Graph.Nodes;
    
    namespace SampleViewExtension
    {
        public class SampleWindowViewModel : NotificationObject, IDisposable
        {
            private string activeNodeTypes;
            private ReadyParams readyParams;
    
            // Displays active nodes in the workspace
            public string ActiveNodeTypes
            {
                get
                {
                    activeNodeTypes = getNodeTypes();
                    return activeNodeTypes;
                }
            }
    
            // Helper function that builds string of active nodes
            public string getNodeTypes()
            {
                string output = "Active nodes:\n";
    
                foreach (NodeModel node in readyParams.CurrentWorkspaceModel.Nodes)
                {
                    string nickName = node.Name;
                    output += nickName + "\n";
                }
    
                return output;
            }
    
            public SampleWindowViewModel(ReadyParams p)
            {
                readyParams = p;
                p.CurrentWorkspaceModel.NodeAdded += CurrentWorkspaceModel_NodesChanged;
                p.CurrentWorkspaceModel.NodeRemoved += CurrentWorkspaceModel_NodesChanged;
            }
    
            private void CurrentWorkspaceModel_NodesChanged(NodeModel obj)
            {
                RaisePropertyChanged("ActiveNodeTypes");
            }
    
            public void Dispose()
            {
                readyParams.CurrentWorkspaceModel.NodeAdded -= CurrentWorkspaceModel_NodesChanged;
                readyParams.CurrentWorkspaceModel.NodeRemoved -= CurrentWorkspaceModel_NodesChanged;
            }
        }
    }
    <Window x:Class="SampleViewExtension.SampleWindow"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:SampleViewExtension"
                 mc:Ignorable="d" 
                 d:DesignHeight="300" d:DesignWidth="300"
                Width="500" Height="100">
        <Grid Name="MainGrid" 
              HorizontalAlignment="Stretch"
              VerticalAlignment="Stretch">
            <TextBlock HorizontalAlignment="Stretch" Text="{Binding ActiveNodeTypes}" FontFamily="Arial" Padding="10" FontWeight="Medium" FontSize="18" Background="#2d2d2d" Foreground="White"/>
        </Grid>
    </Window>
    using System.Windows;
    
    namespace SampleViewExtension
    {
        /// <summary>
        /// Interaction logic for SampleWindow.xaml
        /// </summary>
        public partial class SampleWindow : Window
        {
            public SampleWindow()
            {
                InitializeComponent();
            }
        }
    }
    <ViewExtensionDefinition>
      <AssemblyPath>C:\Users\username\Documents\Visual Studio 2015\Projects\SampleViewExtension\SampleViewExtension\bin\Debug\SampleViewExtension.dll</AssemblyPath>
      <TypeName>SampleViewExtension.SampleViewExtension</TypeName>
    </ViewExtensionDefinition>
    Dynamo basiert auf dem Software-Architekturmuster
    (MVVM), um die Benutzeroberfläche vom Backend getrennt zu halten. Beim Erstellen von Zero-Touch-Blöcken nimmt Dynamo die Datenbindung zwischen den Daten eines Blocks und der zugehörigen Benutzeroberfläche vor. Um eine angepasste Benutzeroberfläche zu erstellen, müssen wir die Datenbindungslogik hinzufügen.

    Allgemein gehören zur Erstellung einer Model-View-Beziehung in Dynamo zwei Aspekte:

    • Eine NodeModel-Klasse zum Einrichten der Kernlogik des Blocks (Modell)

    • Eine INodeViewCustomization-Klasse zum Anpassen der Anzeige von NodeModel (Ansicht)

    NodeModel-Objekte verfügen bereits über eine verknüpfte View-Model-Beziehung (NodeViewModel). Daher können wir uns auf das Modell und die Ansicht für eine angepasste Benutzeroberfläche konzentrieren.

    So implementieren Sie NodeModel

    NodeModel-Blöcke unterscheiden sich in einigen wichtigen Punkten von Zero-Touch-Blöcken, die in diesem Beispiel behandelt werden. Bevor wir uns mit der Anpassung der Benutzeroberfläche befassen, erstellen wir zunächst die NodeModel-Logik.

    1. Erstellen der Projektstruktur:

    Ein NodeModel-Block kann nur Funktionen aufrufen. Daher müssen wir den Block NodeModel und die Funktionen in verschiedene Bibliotheken unterteilen. Die Standardmethode hierfür besteht für Dynamo-Pakete darin, für jedes Paket ein separates Projekt zu erstellen. Beginnen Sie mit dem Erstellen einer neuen Projektmappe, die die Projekte enthält.

    1. Wählen Sie File > New > Project aus.

    2. Wählen Sie Other Project Types aus, um die Option Projektmappe aufzurufen.

    3. Wählen Sie Blank Solution aus.

    4. Geben Sie der Projektmappe den Namen CustomNodeModel.

    5. Wählen Sie Ok aus.

    Erstellen Sie in der Projektmappe zwei C#-Klassenbibliotheksprojekte: eines für Funktionen und eines zur Implementierung der NodeModel-Schnittstelle.

    Hinzufügen einer neuen Klassenbibliothek
    1. Klicken Sie mit der rechten Maustaste auf die Projektmappe, und wählen Sie Add > New Project.

    2. Wählen Sie die Klassenbibliothek.

    3. Vergeben Sie den Namen CustomNodeModel.

    4. Klicken Sie auf Ok.

    5. Wiederholen Sie den Vorgang, um ein weiteres Projekt mit dem Namen CustomNodeModelFunctions hinzuzufügen.

    Als Nächstes müssen wir die automatisch erstellten Klassenbibliotheken umbenennen und dem Projekt CustomNodeModel eine der Bibliotheken hinzufügen. Die GridNodeModel-Klasse implementiert die abstrakte NodeModel-Klasse, GridNodeView wird zum Anpassen der Ansicht verwendet, und GridFunction enthält alle Funktionen, die aufgerufen werden müssen.

    Projektmappen-Explorer
    1. Fügen Sie eine weitere Klasse hinzu, indem Sie mit der rechten Maustaste auf das Projekt CustomNodeModel klicken, Add > New Item... auswählen und Class wählen.

    2. Im Projekt CustomNodeModel benötigen wir die Klassen GridNodeModel.cs und GridNodeView.cs.

    3. Für das Projekt CustomNodeModelFunction benötigen wir eine GridFunctions.cs-Klasse.

    Bevor wir den Klassen Code hinzufügen, fügen wir die erforderlichen Pakete für dieses Projekt hinzu. CustomNodeModel benötigt ZeroTouchLibrary und WpfUILibrary, CustomNodeModelFunction benötigt nur ZeroTouchLibrary. WpfUILibrary wird später bei der Anpassung der Benutzeroberfläche verwendet, und ZeroTouchLibrary wird zum Erstellen von Geometrie verwendet. Pakete können einzeln für Projekte hinzugefügt werden. Da diese Pakete Abhängigkeiten aufweisen, werden Core und DynamoServices automatisch installiert.

    Installation von Paketen
    1. Klicken Sie mit der rechten Maustaste auf ein Projekt, und wählen Sie Manage NuGet Packages.

    2. Installieren Sie nur die für dieses Projekt erforderlichen Pakete.

    Visual Studio kopiert die NuGet-Pakete, die im Build-Verzeichnis referenziert werden. Dies kann auf False gesetzt werden, damit keine unnötigen Dateien im Paket vorhanden sind.

    Deaktivieren der lokalen Paketkopie
    1. Wählen Sie Dynamo-NuGet-Pakete aus.

    2. Legen Sie Copy Local auf False fest.

    2. Übernehmen der NodeModel-Klasse

    Wie bereits erwähnt, ist der wichtigste Aspekt, der einen NodeModel-Block von einem ZeroTouch-Block unterscheidet, die Implementierung der NodeModel-Klasse. Ein NodeModel-Block benötigt mehrere Funktionen aus dieser Klasse. Fügen Sie nach dem Klassennamen :NodeModel hinzu, um sie abzurufen.

    Kopieren Sie den folgenden Code in GridNodeModel.cs.

    Dies unterscheidet sich von Zero-Touch-Blöcken. Sehen wir uns die einzelnen Aspekte an.

    • Geben Sie die Blockattribute wie Name, Kategorie, InPort-/OutPort-Namen, InPort-/OutPort-Typen und Beschreibungen an.

    • public class GridNodeModel : NodeModel ist eine Klasse, die die NodeModel-Klasse von Dynamo.Graph.Nodes übernimmt.

    • public GridNodeModel() { RegisterAllPorts(); } ist ein Konstruktor, der die Ein- und Ausgaben des Blocks registriert.

    • BuildOutputAst() gibt einen AST (Abstract Syntax Tree, abstrakter Syntaxbaum) zurück, die erforderliche Struktur für die Rückgabe von Daten aus einem NodeModel-Block.

    • AstFactory.BuildFunctionCall() ruft die Funktion RectangularGrid von GridFunctions.cs auf.

    • new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid) gibt die Funktion und ihre Parameter an.

    • new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue }); ordnet die Blockeingaben den Funktionsparametern zu.

    • AstFactory.BuildNullNode() erstellt einen Null-Block, wenn die Eingabeanschlüsse nicht verbunden sind. Dadurch wird vermieden, dass eine Warnung für den Block angezeigt wird.

    • RaisePropertyChanged("SliderValue") benachrichtigt die Benutzeroberfläche, wenn sich der Schiebereglerwert ändert.

    • var sliderValue = AstFactory.BuildDoubleNode(SliderValue) erstellt einen Block im AST, der den Schiebereglerwert darstellt.

    • Ändern Sie eine Eingabe für die Variable sliderValue in der functionCall-Variablen new List<AssociativeNode> { inputAstNodes[0], sliderValue });.

    3. Aufrufen einer Funktion

    Das Projekt CustomNodeModelFunction wird in einer anderen Assembly als CustomNodeModel erstellt, sodass es aufgerufen werden kann.

    Kopieren Sie den folgenden Code in GridFunction.cs.

    Diese Funktionsklasse ist der Zero-Touch-Rasterfallstudie sehr ähnlich, mit einem Unterschied:

    • [IsVisibleInDynamoLibrary(false)] verhindert, dass Dynamo die folgende Methode und Klasse "sieht", da die Funktion bereits von CustomNodeModel aufgerufen wird.

    Genauso wie wir Referenzen für NuGet-Pakete hinzugefügt haben, muss CustomNodeModel auf CustomNodeModelFunction verweisen, um die Funktion aufzurufen.

    Hinzufügen einer Referenz

    Die using-Anweisung für CustomNodeModel ist inaktiv, bis wir die Funktion referenzieren.

    1. Klicken Sie mit der rechten Maustaste auf CustomNodeModel, und wählen Sie Add > Reference aus.

    2. Wählen Sie Projects > Solution.

    3. Aktivieren Sie CustomNodeModelFunction.

    4. Klicken Sie auf Ok.

    4. Anpassen der Ansicht

    Um einen Schieberegler zu erstellen, müssen wir die Benutzeroberfläche durch Implementierung der INodeViewCustomization-Schnittstelle anpassen.

    Kopieren Sie den folgenden Code in GridNodeView.cs:

    • public class CustomNodeModelView : INodeViewCustomization<GridNodeModel> definiert die Funktionen, die zum Anpassen der Benutzeroberfläche erforderlich sind.

    Nachdem die Struktur des Projekts eingerichtet wurde, verwenden Sie die Entwurfsumgebung von Visual Studio, um ein Benutzersteuerelement zu erstellen und dessen Parameter in einer .xaml-Datei zu definieren. Fügen Sie im Werkzeugkasten einen Schieberegler zu <Grid>...</Grid> hinzu.

    Hinzufügen eines neuen Schiebereglers
    1. Klicken Sie mit der rechten Maustaste auf CustomNodeModel, und wählen Sie Add > New Item aus.

    2. Wählen Sie WPF aus.

    3. Geben Sie dem Benutzersteuerelement den Namen Slider.

    4. Klicken Sie auf Add.

    Kopieren Sie den folgenden Code in Slider.xaml:

    • Die Parameter des Schiebereglers werden in der .xaml-Datei definiert. Minimum- und Maximum-Attribute definieren den numerischen Bereich dieses Schiebereglers.

    • In <Grid>...</Grid> können wir verschiedene Benutzersteuerelemente aus dem Visual Studio-Werkzeugkasten platzieren.

    Beim Erstellen der Datei Slider.xaml hat Visual Studio automatisch eine C#-Datei mit dem Namen Slider.xaml.cs erstellt, die den Schieberegler initialisiert. Ändern Sie den Namensbereich in dieser Datei.

    • Der Namensbereich sollte CustomNodeModel.CustomNodeModel lauten.

    In GridNodeModel.cs wird die Berechnungslogik des Schiebereglers definiert.

    5. Konfigurieren als Paket

    Bevor wir das Projekt erstellen, fügen wir im letzten Schritt eine pkg.json-Datei hinzu, damit Dynamo das Paket lesen kann.

    Hinzufügen einer JSON-Datei
    1. Klicken Sie mit der rechten Maustaste auf CustomNodeModel, und wählen Sie Add > New Item aus.

    2. Wählen Sie Web aus.

    3. Wählen Sie JSON File aus.

    4. Geben Sie der Datei den Namen pkg.json.

    5. Klicken Sie auf Add.

    • Kopieren Sie den folgenden Code in pkg.json:

    • "name": Bestimmt den Namen des Pakets und dessen Gruppe in der Dynamo-Bibliothek.

    • "keywords": Geben Sie Suchbegriffe für die Suche in der Dynamo-Bibliothek an.

    • "node_libraries": [] Die mit dem Paket verknüpften Bibliotheken.

      Der letzte Schritt besteht darin, die Projektmappe zu erstellen und als Dynamo-Paket zu publizieren. Im Kapitel Paketbereitstellung finden Sie Informationen zum Erstellen eines lokalen Pakets vor der Online-Publizierung und zum Erstellen eines Pakets direkt in Visual Studio.

    Rechteckiges Rasterdiagramm
    Model-view-viewmodel
    using System;
    using System.Collections.Generic;
    using Dynamo.Graph.Nodes;
    using CustomNodeModel.CustomNodeModelFunction;
    using ProtoCore.AST.AssociativeAST;
    using Autodesk.DesignScript.Geometry;
    
    namespace CustomNodeModel.CustomNodeModel
    {
        [NodeName("RectangularGrid")]
        [NodeDescription("An example NodeModel node that creates a rectangular grid. The slider randomly scales the cells.")]
        [NodeCategory("CustomNodeModel")]
        [InPortNames("xCount", "yCount")]
        [InPortTypes("double", "double")]
        [InPortDescriptions("Number of cells in the X direction", "Number of cells in the Y direction")]
        [OutPortNames("Rectangles")]
        [OutPortTypes("Autodesk.DesignScript.Geometry.Rectangle[]")]
        [OutPortDescriptions("A list of rectangles")]
        [IsDesignScriptCompatible]
        public class GridNodeModel : NodeModel
        {
            private double _sliderValue;
            public double SliderValue
            {
                get { return _sliderValue; }
                set
                {
                    _sliderValue = value;
                    RaisePropertyChanged("SliderValue");
                    OnNodeModified(false);
                }
            }
            public GridNodeModel()
            {
                RegisterAllPorts();
            }
            public override IEnumerable<AssociativeNode> BuildOutputAst(List<AssociativeNode> inputAstNodes)
            {
                if (!HasConnectedInput(0) || !HasConnectedInput(1))
                {
                    return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()) };
                }
                var sliderValue = AstFactory.BuildDoubleNode(SliderValue);
                var functionCall =
                  AstFactory.BuildFunctionCall(
                    new Func<int, int, double, List<Rectangle>>(GridFunction.RectangularGrid),
                    new List<AssociativeNode> { inputAstNodes[0], inputAstNodes[1], sliderValue });
    
                return new[] { AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), functionCall) };
            }
        }
    }
    using Autodesk.DesignScript.Geometry;
    using Autodesk.DesignScript.Runtime;
    using System;
    using System.Collections.Generic;
    
    namespace CustomNodeModel.CustomNodeModelFunction
    {
        [IsVisibleInDynamoLibrary(false)]
        public class GridFunction
        {
            [IsVisibleInDynamoLibrary(false)]
            public static List<Rectangle> RectangularGrid(int xCount = 10, int yCount = 10, double rand = 1)
            {
                double x = 0;
                double y = 0;
    
                Point pt = null;
                Vector vec = null;
                Plane bP = null;
    
                Random rnd = new Random(2);
    
                var pList = new List<Rectangle>();
                for (int i = 0; i < xCount; i++)
                {
                    y++;
                    x = 0;
                    for (int j = 0; j < yCount; j++)
                    {
                        double rNum = rnd.NextDouble();
                        double scale = rNum * (1 - rand) + rand;
                        x++;
                        pt = Point.ByCoordinates(x, y);
                        vec = Vector.ZAxis();
                        bP = Plane.ByOriginNormal(pt, vec);
                        Rectangle rect = Rectangle.ByWidthLength(bP, scale, scale);
                        pList.Add(rect);
                    }
                }
                pt.Dispose();
                vec.Dispose();
                bP.Dispose();
                return pList;
            }
        }
    }
    using Dynamo.Controls;
    using Dynamo.Wpf;
    
    namespace CustomNodeModel.CustomNodeModel
    {
        public class CustomNodeModelView : INodeViewCustomization<GridNodeModel>
        {
            public void CustomizeView(GridNodeModel model, NodeView nodeView)
            {
                var slider = new Slider();
                nodeView.inputGrid.Children.Add(slider);
                slider.DataContext = model;
            }
    
            public void Dispose()
            {
            }
        }
    }
    <UserControl x:Class="CustomNodeModel.CustomNodeModel.Slider"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:CustomNodeModel.CustomNodeModel"
                 mc:Ignorable="d" 
                 d:DesignHeight="75" d:DesignWidth="100">
        <Grid Margin="10">
            <Slider Grid.Row="0" Width="80" Minimum="0" Maximum="1" IsSnapToTickEnabled="True" TickFrequency="0.01" Value="{Binding SliderValue}"/>
        </Grid>
    </UserControl>
    using System.Windows.Controls;
    
    namespace CustomNodeModel.CustomNodeModel
    {
        /// <summary>
        /// Interaction logic for Slider.xaml
        /// </summary>
        public partial class Slider : UserControl
        {
            public Slider()
            {
                InitializeComponent();
            }
        }
    }
    {
      "license": "MIT",
      "file_hash": null,
      "name": "CustomNodeModel",
      "version": "1.0.0",
      "description": "Sample node",
      "group": "CustomNodes",
      "keywords": [ "grid", "random" ],
      "dependencies": [],
      "contents": "Sample node",
      "engine_version": "1.3.0",
      "engine": "dynamo",
      "engine_metadata": "",
      "site_url": "",
      "repository_url": "",
      "contains_binaries": true,
      "node_libraries": [
        "CustomNodeModel, Version=1.0.0, Culture=neutral, PublicKeyToken=null",
        "CustomNodeModelFunction, Version=1.0.0, Culture=neutral, PublicKeyToken=null"
      ]
    }

    Erweiterte Anpassung von Dynamo-Blöcken

    In diesem Abschnitt werden, ein Grundwissen über ZeroTouch vorausgesetzt, die Vorteile der Anpassung von Dynamo-Blöcken erläutert, um sowohl die Funktionalität als auch das Benutzererlebnis zu verbessern. Durch Hinzufügen von Elementen wie Warnmeldungen, Informationsmeldungen und benutzerdefinierten Symbolen können Sie Blöcke erstellen, die intuitiver, informativer und visuell ansprechender sind. Diese Anpassungen helfen den Benutzern nicht nur, potenzielle Probleme zu verstehen oder ihre Arbeitsabläufe zu optimieren, sondern stellen Ihre Blöcke auch als professionelle und benutzerfreundliche Werkzeuge in den Vordergrund.

    Das Anpassen von Blöcken ist eine hervorragende Möglichkeit, um sicherzustellen, dass Ihre Lösungen klar, zuverlässig und auf die spezifischen Projektanforderungen zugeschnitten sind.

    Erstellen von benutzerdefinierten Warnmeldungen mit OnLogWarningMessage

    In Dynamo bietet die Methode OnLogWarningMessage eine Möglichkeit, Warnmeldungen direkt in der Konsole von Dynamo zu protokollieren. Dies ist eine leistungsstarke Funktion, insbesondere für Zero-Touch-Blöcke, da Entwickler Benutzer benachrichtigen können, wenn Probleme mit Eingaben oder Parametern auftreten, die zu unerwartetem Verhalten führen könnten. In dieser Anleitung erfahren Sie, wie Sie OnLogWarningMessage in einem beliebigen Zero-Touch-Block implementieren.

    Implementierungsschritte für OnLogWarningMessage

    Schritt 1: Importieren des erforderlichen Namensbereichs

    OnLogWarningMessage ist Teil des DynamoServices-Namensbereichs. Fügen Sie dies daher zunächst Ihrer Projektdatei hinzu.

    Schritt 2: Ermitteln, wann Warnungen protokolliert werden sollen

    Bevor Sie eine Warnmeldung hinzufügen, beachten Sie die Logik in Ihrer Methode:

    • Welche Bedingungen können zu falschen oder unerwarteten Ergebnissen führen?

    • Gibt es bestimmte Eingabewerte oder Parameter, die für eine ordnungsgemäße Funktionsweise der Methode erforderlich sind?

    Beispiele für zu überprüfende Bedingungen:

    • Werte außerhalb des Bereichs (z. B. if (inputValue < 0))

    • Null oder leere Sammlungen (z. B. if (list == null || list.Count == 0))

    • Nicht übereinstimmende Datentypen (z. B., wenn ein Dateityp nicht unterstützt wird)

    Schritt 3: Verwenden von OnLogWarningMessage, um die Warnung zu protokollieren

    Platzieren Sie OnLogWarningMessage-Aufrufe dort, wo Sie Bedingungen erkennen, die Probleme verursachen könnten. Wenn die Bedingung erfüllt ist, protokollieren Sie eine Warnmeldung mit klaren Anweisungen für den Benutzer.

    Syntax für OnLogWarningMessage

    Implementierungsbeispiele für OnLogWarningMessage

    Um OnLogWarningMessage in der Praxis zu demonstrieren, sehen Sie hier verschiedene Szenarien, die beim Erstellen eines Zero-Touch-Blocks auftreten können.

    Beispiel 1: Überprüfen numerischer Eingaben

    In diesem Beispiel verwenden wir den benutzerdefinierten Block, der im vorherigen Abschnitt Zero-Touch-Fallstudie - Rasterblock erstellt wurde, eine Methode mit der Bezeichnung RectangularGrid, die basierend auf xCount- und yCount-Eingaben ein Raster aus Rechtecken generiert. Wir gehen die Tests durch, wenn eine Eingabe ungültig ist, und verwenden dann OnLogWarningMessage, um eine Warnung zu protokollieren und die Verarbeitung zu stoppen.

    Verwenden von OnLogWarningMessage für die Eingabevalidierung

    Für die Erstellung eines Rasters basierend auf xCount und yCount. Stellen Sie sicher, dass es sich bei beiden Werten um positive Ganzzahlen handelt, bevor Sie fortfahren.

    In diesem Beispiel:

    • Bedingung: Wenn entweder xCount oder yCount kleiner oder gleich null ist

    • Meldung: "Grid count values must be positive integers."

    Dadurch wird die Warnung in Dynamo angezeigt, wenn ein Benutzer null oder negative Werte eingibt. Dies erleichtert das Verständnis der erwarteten Eingabe.

    Nun können wir die Warnung in den Beispielblock Grids implementieren:

    Beispiel 2: Prüfung auf keine oder leere Sammlungen

    Wenn Ihre Methode eine Liste von Punkten erfordert, ein Benutzer jedoch eine leere oder Nullliste übergibt, können Sie OnLogWarningMessage verwenden, um ihn über das Problem zu informieren.

    In diesem Beispiel:

    • Bedingung: Wenn die points-Liste null ist oder weniger als drei Punkte enthält

    • Meldung: "Point list cannot be null or have fewer than three points."

    Dadurch werden Benutzer gewarnt, dass sie eine gültige Liste mit mindestens drei Punkten übergeben müssen, um ein Polygon zu bilden.


    **Beispiel 3: Überprüfen der Dateitypkompatibilität **

    Bei einem Block, der Dateipfade verarbeitet, sollten Sie sicherstellen, dass nur bestimmte Dateitypen zulässig sind. Wenn ein nicht unterstützter Dateityp erkannt wird, protokollieren Sie eine Warnung.

    In diesem Beispiel:

    • Bedingung: Wenn der Dateipfad nicht auf .csv endet

    • Meldung: "Only CSV files are supported."

    Dadurch werden Benutzer darauf aufmerksam gemacht, sicherzustellen, dass sie eine CSV-Datei übermitteln, um Probleme im Zusammenhang mit inkompatiblen Dateiformaten zu vermeiden.

    Hinzufügen von Informationsmeldungen mit OnLogInfoMessage

    In Dynamo ermöglicht es OnLogInfoMessage aus dem DynamoServices-Namensbereich Entwicklern, Informationsmeldungen direkt in der Konsole von Dynamo zu protokollieren. Dies ist hilfreich, um erfolgreiche Vorgänge zu bestätigen, den Fortschritt zu kommunizieren oder zusätzliche Einblicke in Blockaktionen zu erhalten. In dieser Anleitung erfahren Sie, wie Sie OnLogInfoMessage in einen beliebigen Zero-Touch-Block einfügen, um Feedback und Benutzerfreundlichkeit zu verbessern.

    Implementierungsschritte für OnLogInfoMessage

    Schritt 1: Importieren des erforderlichen Namensbereichs

    OnLogInfoMessage ist Teil des DynamoServices-Namensbereichs. Fügen Sie dies daher zunächst Ihrer Projektdatei hinzu.

    Schritt 2: Ermitteln, wann Informationen protokolliert werden sollen

    Bevor Sie eine Informationsmeldung hinzufügen, denken Sie über den Zweck Ihrer Methode nach:

    • Welche Informationen sollten nach Abschluss eines Vorgangs sinnvollerweise bestätigt werden?

    • Gibt es wichtige Schritte oder Meilensteine innerhalb der Methode, über die die Benutzer möglicherweise informiert werden sollten?

    Beispiele für nützliche Bestätigungen:

    • Abschlussmeldungen (z. B., wenn ein Raster oder Modell vollständig erstellt wurde)

    • Details zu verarbeiteten Daten (z. B. 10 Elemente erfolgreich verarbeitet)

    • Zusammenfassung der Ausführung (z. B. im Prozess verwendete Parameter)

    Schritt 3: Verwenden von OnLogInfoMessage zum Protokollieren von Informationsmeldungen

    Platzieren Sie OnLogInfoMessage-Aufrufe an wichtigen Punkten in Ihrer Methode. Wenn ein wichtiger Schritt oder Abschluss erfolgt, protokollieren Sie eine Informationsmeldung, um den Benutzer über den Vorfall zu informieren.

    Syntax für OnLogInfoMessage

    Implementierungsbeispiele für OnLogInfoMessage

    Im Folgenden finden Sie verschiedene Szenarien, um die Verwendung von OnLogInfoMessage in Ihren Zero-Touch-Blöcken zu veranschaulichen.

    Beispiel 1: Überprüfen numerischer Eingaben

    In diesem Beispiel verwenden wir den benutzerdefinierten Block, der im vorherigen Abschnitt Zero-Touch-Fallstudie - Rasterblock erstellt wurde, eine Methode mit der Bezeichnung RectangularGrid, die basierend auf xCount- und yCount-Eingaben ein Raster aus Rechtecken generiert. Wir werden die Tests durchgehen, wenn eine Eingabe ungültig ist, und dann OnLogInfoMessage verwenden, um Informationen bereitzustellen, nachdem der Block fertig ausgeführt wurde.

    Verwenden von OnLogInfoMessage für die Eingabevalidierung

    Für die Erstellung eines Rasters basierend auf xCount und yCount. Nach dem Erstellen des Rasters können Sie dessen Erstellung bestätigen, indem Sie eine Informationsmeldung mit den Bemaßungen des Rasters protokollieren.

    In diesem Beispiel:

    • Bedingung: Die Rastererstellung ist abgeschlossen.

    • Meldung: "Successfully created a grid with dimensions {xCount}x{yCount}."

    Diese Meldung informiert Benutzer darüber, dass das Raster wie angegeben erstellt wurde, und hilft ihnen zu bestätigen, dass der Block wie erwartet funktionierte.

    Nun können wir die Warnung in den Beispielblock Grids implementieren:

    Beispiel 2: Bereitstellen von Informationen zur Datenanzahl

    Wenn Sie einen Block erstellen, der eine Liste von Punkten verarbeitet, können Sie protokollieren, wie viele Punkte erfolgreich verarbeitet wurden. Dies kann für große Datensätze nützlich sein.

    In diesem Beispiel:

    • Bedingung: Nach Abschluss der Schleife, die Anzahl der verarbeiteten Elemente wird angezeigt.

    • Meldung: "6 points were processed successfully."

    Diese Meldung hilft Benutzern, das Ergebnis der Verarbeitung nachzuvollziehen und zu bestätigen, dass alle Punkte verarbeitet wurden.

    Beispiel 3: Zusammenfassung der verwendeten Parameter

    In einigen Fällen ist es hilfreich, die Eingabeparameter zu bestätigen, die ein Block zum Abschließen einer Aktion verwendet hat. Wenn Ihr Block beispielsweise Daten in eine Datei exportiert, können Sie durch das Protokollieren des Dateinamens und -pfads Benutzern die Sicherheit geben, dass die richtige Datei verwendet wurde.

    In diesem Beispiel:

    • Bedingung: Der Exportvorgang wurde erfolgreich abgeschlossen.

    • Meldung: "Data exported successfully to {filePath}."

    Mit dieser Meldung wird den Benutzern bestätigt, dass der Export erfolgreich war, und der genaue Dateipfad wird angezeigt, um Verwirrung über die Dateispeicherorte zu vermeiden.

    Erstellen und Hinzufügen von benutzerdefinierter Dokumentation zu Blöcken

    Dokumentation für benutzerdefinierte Blöcke

    In der Vergangenheit gab es in Dynamo Einschränkungen bei der Art und Weise, wie Paketautoren die Dokumentation für ihre Blöcke bereitstellen konnten. Autoren von benutzerdefinierten Blöcken konnten nur kurze Beschreibungen in der QuickInfo des Blocks angeben oder das Paket mit ausführlich kommentierten Beispieldiagrammen versenden.

    Eine neue Möglichkeit

    Dynamo bietet jetzt ein verbessertes System für Paketautoren, mit dem eine optimierte und mehr beschreibende Dokumentation für Ihre benutzerdefinierten Blöcke bereitgestellt werden kann. Bei diesem neuen Ansatz werden die benutzerfreundliche Markdown-Sprache für die Texterstellung und die Ansichtserweiterung des Dokumentationsbrowsers zur Anzeige von Markdown in Dynamo verwendet. Die Verwendung von Markdown bietet Paketautoren eine Vielzahl neuer Möglichkeiten beim Dokumentieren ihrer benutzerdefinierten Blöcke.

    Was ist Markdown?

    Markdown ist eine einfache Auszeichnungssprache, die Sie zum Formatieren von Klartextdokumenten verwenden können. Seit Markdown im Jahr 2004 ins Leben gerufen wurde, hat ihre Popularität stetig zugenommen, sodass sie heute eine der beliebtesten Auszeichnungssprachen der Welt ist.

    Erste Schritte mit Markdown

    Es ist ganz einfach, Markdown-Dateien zu erstellen. Alles, was Sie brauchen, ist ein einfacher Texteditor, wie den Windows-Editor, und schon kann es losgehen. Es gibt jedoch noch einfachere Möglichkeiten, Markdown-Code zu schreiben, als den Editor zu verwenden. Es gibt mehrere Online-Editoren, wie z. B. , mit denen Sie Ihre Änderungen in Echtzeit sehen können, während Sie sie vornehmen. Eine weitere beliebte Methode zum Bearbeiten von Markdown-Dateien ist die Verwendung eines Code-Editors wie .

    Was kann Markdown?

    Markdown ist sehr flexibel und sollte genügend Funktionen bieten, um auf einfache Weise eine gute Dokumentation zu erstellen. Dazu gehören: Hinzufügen von Mediendateien wie Bildern oder Videos, Erstellen von Tabellen mit verschiedenen Inhaltsformen und natürlich einfache Textformatierungsfunktionen wie fett oder kursiv. All dies und noch viel mehr ist beim Schreiben von Markdown-Dokumenten möglich. Weitere Informationen finden Sie in dieser Anleitung, in der die erklärt wird.

    Hinzufügen erweiterter Dokumentation zu Ihren Blöcken

    Das Hinzufügen von Dokumentation zu Ihren Blöcken ist einfach. Die Dokumentation kann zu allen Varianten benutzerdefinierter Blöcke hinzugefügt werden, dazu gehören:

    • Vordefinierte Dynamo-Blöcke

    • Benutzerdefinierte Blöcke (.dyf): Sammlungen von vordefinierten und/oder anderen Paketblöcken.

    • Benutzerdefinierte C#-Paketblöcke (auch als ZeroTouch bezeichnet). Diese benutzerdefinierten Blöcke sehen wie die vordefinierten Blöcke aus.

    • NodeModel-Blöcke (Blöcke, die spezielle Benutzeroberflächen-Elemente wie Dropdown-Menüs oder Auswahlschaltflächen enthalten)

    Führen Sie die folgenden Schritte aus, damit Ihre Markdown-Dateien in Dynamo angezeigt werden.

    Öffnen von Dokumentationsdateien in Dynamo

    Dynamo verwendet die Ansichtserweiterung des Dokumentationsbrowsers, um die Dokumentation für Blöcke anzuzeigen. Um die Dokumentation eines Blocks zu öffnen, klicken Sie mit der rechten Maustaste auf den Block und wählen Hilfe. Dadurch wird der Dokumentationsbrowser geöffnet, und der mit diesem Block verknüpften Markdown-Code wird angezeigt, sofern vorhanden.

    Die im Dokumentationsbrowser angezeigte Dokumentation besteht aus zwei Teilen. Der erste Teil ist der Abschnitt Node Info. Dieser wird automatisch aus den aus dem Block extrahierten Informationen generiert, wie z. B. Eingaben/Ausgaben, Blockkategorie, Blockname/Namensbereich und Kurzbeschreibung des Blocks. Im zweiten Teil wird die Dokumentation für benutzerdefinierte Blöcke angezeigt. Dabei handelt es sich um die Markdown-Datei, die zur Dokumentation des Blocks bereitgestellt wird.

    doc-Ordner für Pakete

    Um Dokumentationsdateien zu Ihren Blöcken in Dynamo hinzuzufügen, erstellen Sie in Ihrem Paketverzeichnis einen neuen Ordner mit dem Namen /doc. Wenn das Paket geladen ist, durchsucht Dynamo dieses Verzeichnis und ruft alle darin enthaltenen Markdown-Dokumentationsdateien ab.

    Benennen von Markdown-Dateien

    Um sicherzustellen, dass Dynamo weiß, welche Datei geöffnet werden soll, wenn diese für einen bestimmten Block angefordert wird, muss die Benennung der Markdown-Datei in einem bestimmten Format erfolgen. Die Markdown-Datei sollte entsprechend dem Namensbereich des Blocks benannt werden, den sie dokumentiert. Wenn Sie sich beim Namensbereich des Blocks nicht sicher sind, sehen Sie sich den Abschnitt Node Info an, nachdem Sie Help im Block gedrückt haben. Unter dem Blocknamen sehen Sie den vollständigen Namensbereich des ausgewählten Blocks.

    Dieser Namensbereich sollte der Name der Markdown-Datei für diesen bestimmten Block sein. Der Namensbereich von CustomNodeExample aus den obigen Abbildungen lautet beispielsweise TestPackage.TestCategory.CustomNodeExample. Daher sollte die Markdown-Datei für diesen Block den Namen TestPackage.TestCategory.CustomNodeExample.md erhalten.

    In besonderen Fällen, in denen Überlastungen Ihrer Blöcke (Blöcke mit demselben Namen, aber unterschiedlichen Eingaben) vorhanden sind, müssen Sie die Eingabenamen in () nach dem Blocknamensbereich hinzufügen. Der integrierte Block Geometry.Translate weist beispielsweise mehrere Überlastungen auf. In diesem Fall würden wir die Markdown-Dateien für die Blöcke unten wie folgt benennen: Autodesk.DesignScript.Geometry.Geometry.Translate(geometry,direction).md Autodesk.DesignScript.Geometry.Geometry.Translate(geometry,direction,distance).md

    Ändern von Markdown-Dateien, während sie in Dynamo geöffnet sind

    Um das Ändern von Dokumentationsdateien zu erleichtern, implementiert der Dokumentationsbrowser einen Dateibeobachter für die geöffnete Dokumentationsdatei. Dadurch können Sie Änderungen an der Markdown-Datei vornehmen, und die Änderungen werden sofort in Dynamo angezeigt.

    Das Hinzufügen neuer Dokumentationsdateien ist auch möglich, während Dynamo geöffnet ist. Fügen Sie dem Ordner /doc einfach eine neue Markdown-Datei mit einem Namen hinzu, der dem dokumentierten Block entspricht.

    Hinzufügen von benutzerdefinierten Symbolen zu Zero-Touch-Blöcken

    Überblick

    Durch benutzerdefinierte Symbole für Zero-Touch-Blöcke in Dynamo werden Ihre Blöcke optisch unterscheidbar und sind in der Bibliothek leichter zu erkennen. Durch Hinzufügen maßgeschneiderter Symbole können Sie Ihre Blöcke von den anderen besser unterscheidbar machen, sodass Benutzer sie in einer Liste schnell ermitteln können.

    In dieser Anleitung erfahren Sie, wie Sie Symbole zu Ihren Zero-Touch-Blöcken hinzufügen.

    Schritte zum Hinzufügen von benutzerdefinierten Blocksymbolen

    Schritt 1: Einrichten des Projekts

    Erstellen Sie zunächst ein Visual Studio-Klassenbibliotheksprojekt (.NET Framework) für Ihre Zero Touch-Blöcke. Wenn Sie noch kein Projekt haben, finden Sie im Abschnitt Erste Schritte eine Schritt-für-Schritt-Anleitung zum Erstellen eines Projekts.

    Stellen Sie sicher, dass Sie mindestens einen funktionalen Zero-Touch-Block haben, da Symbole nur zu vorhandenen Blöcken hinzugefügt werden können. Weitere Informationen finden Sie unter Zero-Touch-Fallstudie - Rasterblock.

    Schritt 2: Erstellen Ihrer Symbolbilder

    So erstellen Sie benutzerdefinierte Symbole

    1. Entwerfen Sie Ihre Symbole: Verwenden Sie einen Bildeditor, um einfache, visuell klare Symbole für Ihre Blöcke zu erstellen.

    2. Bildspezifikationen:

      • Kleines Symbol: 32 x 32 Pixel (wird in der Seitenleiste der Bibliothek und auf dem Block selbst verwendet).

      • Großes Symbol

    Beispiel: Wenn das Projekt ZeroTouchNodeIcons, Ihre Klasse Grids und Ihre Methode RectangularGrid lauten, werden die Dateien wie folgt benannt:

    • ZeroTouchNodeIcons.Grids.RectangularGrid.Small.png

    • ZeroTouchNodeIcons.Grids.RectangularGrid.Large.png

    Tipp: Verwenden Sie für alle Ihre Symbole einen einheitlichen Designstil, um ein professionelles Aussehen zu erzielen.

    Schritt 3: Hinzufügen einer Ressourcendatei zum Projekt

    Erstellen Sie eine Ressourcendatei, um Ihre Symbole in die .dll einzubetten:

    1. Fügen Sie eine neue Ressourcendatei hinzu:

    • Klicken Sie im Solution Explorer mit der rechten Maustaste auf das Projekt.

    • Wechseln Sie zu Add > New Item und wählen Sie Resources File aus.

    • Geben Sie der Datei den Namen <ProjectName>Images.resx. Beispielsweise ZeroTouchNodeIconsImages.resx.

    1. Deaktivieren Sie die benutzerdefinierte Werkzeugeigenschaft:

      • Wählen Sie die Ressourcendatei im Solution Explorer aus.

      • Löschen Sie in der Gruppe Properties das Feld Custom Tool, indem Sie den Wert ResXFileCodeGenerator entfernen.

    ANMERKUNG: Wenn Sie das Feld Custom Tool nicht bereinigen, konvertiert Visual Studio Punkte in Ihren Ressourcennamen in Unterstriche. Vergewissern Sie sich vor der Erstellung, dass die Ressourcennamen anstelle von Unterstrichen Punkte als Trennzeichen für Klassennamen enthalten.

    Schritt 4: Fügen Sie Ihre Bilder als Ressourcen hinzu

    1. Doppelklicken Sie auf die erstellte Ressourcendatei:

      • Fügen Sie jeweils ein Bild mit der Schaltfläche + hinzu.

      • Setzen Sie den Ressourcentyp auf File.

      • Navigieren Sie zum Speicherort der Bilddatei, und fügen Sie die großen und kleinen

    ANMERKUNG: Sie müssen Ihre Bilder nicht in einem Ressourcenordner oder Unterordnern Large und Small organisieren. Diese Methode hat sich jedoch bewährt.

    Schritt 5: Konvertieren des Projekts in den SDK-Stil (für ältere Projekte)

    Wenn Ihr Projekt noch nicht im SDK-Stil vorliegt (erforderlich zum Einbetten von Ressourcen), konvertieren Sie es:

    1. Installieren Sie die .NET Upgrade Assistant-Erweiterung über das Menü Extensions > Manage Extensions in Visual Studio.

    1. Klicken Sie im Solution Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie Upgrade > Convert project to SDK-style aus.

    1. Warten Sie, bis die Konvertierung abgeschlossen ist.

    Schritt 6: Hinzufügen eines After-Build-Skripts zum Einbetten von Ressourcen

    1. Beenden Sie das Projekt:

      • Klicken Sie im Solution Explorer mit der rechten Maustaste auf das Projekt, und wählen Sie Unload Project aus.

    1. Bearbeiten Sie die Datei .csproj:

      • Fügen Sie das folgende <Target>-Element zwischen </ItemGroup> und </Project> hinzu:

    1. Ersetzen Sie alle Instanzen von ZeroTouchNodeIcons durch Ihren Projektnamen.

    2. Laden Sie das Projekt neu:

      • Klicken Sie mit der rechten Maustaste auf das beendete Projekt, und wählen Sie Reload Project.

    Schritt 7: Erstellen und Laden Ihrer .dll in Dynamo

    1. Erstellen Sie das Projekt:

      • Nachdem Sie das After-Build-Skript hinzugefügt haben, erstellen Sie Ihr Projekt in Visual Studio.

    1. Suchen Sie nach Ausgabedateien:

      • Stellen Sie sicher, dass sich .dll und .customization.dll im Ordner bin befinden.

    2. Fügen Sie die .dll zu Dynamo hinzu:

    1. Ihre benutzerdefinierten Blöcke sollten nun mit den entsprechenden Symbolen angezeigt werden.

    NodeModel-Blöcke mit angepasster Benutzeroberfläche (Blöcke, die eindeutige Benutzeroberflächen-Elemente wie Grafiken im Block enthalten)

    : 128 x 128 Pixel (wird in den Blockeigenschaften verwendet, wenn Sie den Mauszeiger in der Bibliothek über den Block bewegen).
  • Dateibenennungskonvention:

    • Die Dateinamen müssen dem folgenden Format entsprechen, um mit dem richtigen Block verknüpft zu werden:

      • <ProjectName>.<ClassName>.<MethodName>.Small.png (für das kleine Symbol)

      • <ProjectName>.<ClassName>.<MethodName>.Large.png (für das große Symbol)

  • Legen Sie Build Action auf None fest.

    • Da wir diese Ressource etwas weiter unten selbst erstellen werden, müssen wir sie nicht zusätzlich automatisch erstellen.

    Blocksymbole hinzu.
  • Verwenden Sie in Dynamo die Schaltfläche Bibliothek importieren, um Ihre .dll in Dynamo zu importieren.

  • Dillinger
    Visual Studio Code
    grundlegende Markdown-Syntax
    OnLogWarningMessage - Beispiel 1
    OnLogWarningMessage - Beispiel 2
    OnLogWarningMessage - Beispiel 3
    OnLogInfoMessage - Beispiel 1
    OnLogInfoMessage - Beispiel 2
    OnLogInfoMessage - Beispiel 3
    Beschreibung in der Block-QuickInfo
    Dokumentationsbrowser
    Dokumentation für benutzerdefinierte Blöcke
    Überlastete Blöcke
    Hot Reloading
    Erstellen eines Visual Studio-Projekts
    Konfigurieren eines neuen Projekts in Visual Studio
    Hinzufügen eines neuen Elements
    Hinzufügen einer Ressourcendatei
    Bereinigen der Eigenschaft von Custom Tool
    Ressourcen hinzufügen...
    Manage Extensions
    Installieren des .NET-Aktualisierungsassistenten
    Projekt aktualisieren
    In SDK-Stil konvertieren
    Aktualisierung abgeschlossen
    Projekt beenden
    Hinzufügen des After-Build-Codes
    Projekt erneut laden
    Lösung erstellen
    Schaltfläche Bibliothek importieren
    using DynamoServices;
    LogWarningMessageEvents.OnLogWarningMessage("Your warning message here.");
    public static List<Rectangle> CreateGrid(int xCount, int yCount)
    {
        // Check if xCount and yCount are positive
        if (xCount <= 0 || yCount <= 0)
        {
            LogWarningMessageEvents.OnLogWarningMessage("Grid count values must be positive integers.");
            return new List<Rectangle>();  // Return an empty list if inputs are invalid
        }
        // Proceed with grid creation...
    }
    using Autodesk.DesignScript.Geometry;
    using DynamoServices;
    
    namespace CustomNodes
    {
        public class Grids
        {
            // The empty private constructor.
            // This will not be imported into Dynamo.
            private Grids() { }
    
            /// <summary>
            /// This method creates a rectangular grid from an X and Y count.
            /// </summary>
            /// <param name="xCount">Number of grid cells in the X direction</param>
            /// <param name="yCount">Number of grid cells in the Y direction</param>
            /// <returns>A list of rectangles</returns>
            /// <search>grid, rectangle</search>
            public static List<Rectangle> RectangularGrid(int xCount = 10, int yCount = 10)
            {
                // Check for valid input values
                if (xCount <= 0 || yCount <= 0)
                {
                    // Log a warning message if the input values are invalid
                    LogWarningMessageEvents.OnLogWarningMessage("Grid count values must be positive integers.");
                    return new List<Rectangle>(); // Return an empty list if inputs are invalid
                }
    
                double x = 0;
                double y = 0;
    
                var pList = new List<Rectangle>();
    
                for (int i = 0; i < xCount; i++)
                {
                    y++;
                    x = 0;
                    for (int j = 0; j < yCount; j++)
                    {
                        x++;
                        Point pt = Point.ByCoordinates(x, y);
                        Vector vec = Vector.ZAxis();
                        Plane bP = Plane.ByOriginNormal(pt, vec);
                        Rectangle rect = Rectangle.ByWidthLength(bP, 1, 1);
                        pList.Add(rect);
                        Point cPt = rect.Center();
                    }
                }
    
                return pList;
            }
        }
    }
    public static Polygon CreatePolygonFromPoints(List<Point> points)
    {
        if (points == null || points.Count < 3)
        {
            LogWarningMessageEvents.OnLogWarningMessage("Point list cannot be null or have fewer than three points.");
            return null;  // Return null if the input list is invalid
        }
        // Proceed with polygon creation...
    }
    public static void ProcessFile(string filePath)
    {
        if (!filePath.EndsWith(".csv"))
        {
            LogWarningMessageEvents.OnLogWarningMessage("Only CSV files are supported.");
            return;
        }
        // Proceed with file processing...
    }
    LogWarningMessageEvents.OnLogInfoMessage("Your info message here.");
    public static List<Rectangle> CreateGrid(int xCount, int yCount)
    {
        var pList = new List<Rectangle>();
        // Grid creation code here...
    
        // Confirm successful grid creation
        LogWarningMessageEvents.OnLogInfoMessage($"Successfully created a grid with dimensions {xCount}x{yCount}.");
    
        return pList;
    }
    using Autodesk.DesignScript.Geometry;
    using DynamoServices;
    
    namespace CustomNodes
    {
        public class Grids
        {
            // The empty private constructor.
            // This will not be imported into Dynamo.
            private Grids() { }
    
            /// <summary>
            /// This method creates a rectangular grid from an X and Y count.
            /// </summary>
            /// <param name="xCount">Number of grid cells in the X direction</param>
            /// <param name="yCount">Number of grid cells in the Y direction</param>
            /// <returns>A list of rectangles</returns>
            /// <search>grid, rectangle</search>
            public static List<Rectangle> RectangularGrid(int xCount = 10, int yCount = 10)
            {
                double x = 0;
                double y = 0;
    
                var pList = new List<Rectangle>();
    
                for (int i = 0; i < xCount; i++)
                {
                    y++;
                    x = 0;
                    for (int j = 0; j < yCount; j++)
                    {
                        x++;
                        Point pt = Point.ByCoordinates(x, y);
                        Vector vec = Vector.ZAxis();
                        Plane bP = Plane.ByOriginNormal(pt, vec);
                        Rectangle rect = Rectangle.ByWidthLength(bP, 1, 1);
                        pList.Add(rect);
                        Point cPt = rect.Center();
                    }
                }
    
                // Log an info message indicating the grid was successfully created
                LogWarningMessageEvents.OnLogInfoMessage($"Successfully created a grid with dimensions {xCount}x{yCount}.");
    
                return pList;
            }
        }
    }
    public static List<Point> ProcessPoints(List<Point> points)
    {
        var processedPoints = new List<Point>();
        foreach (var point in points)
        {
            // Process each point...
            processedPoints.Add(point);
        }
    
        // Log info about the count of processed points
        LogWarningMessageEvents.OnLogInfoMessage($"{processedPoints.Count} points were processed successfully.");
    
        return processedPoints;
    }
    public static void ExportData(string filePath, List<string> data)
    {
        // Code to write data to the specified file path...
    
        // Log the file path used for export
        LogWarningMessageEvents.OnLogInfoMessage($"Data exported successfully to {filePath}.");
    
    }
    <Target Name="CreateNodeIcons" AfterTargets="PostBuildEvent">
    		<!-- Get System.Drawing.dll     -->
    		<GetReferenceAssemblyPaths TargetFrameworkMoniker=".NETFramework, Version=v4.8">
    			<Output TaskParameter="FullFrameworkReferenceAssemblyPaths" PropertyName="FrameworkAssembliesPath" />
    		</GetReferenceAssemblyPaths>
    		<!-- Get assembly -->
    		<GetAssemblyIdentity AssemblyFiles="$(OutDir)$(TargetName).dll">
    			<Output TaskParameter="Assemblies" ItemName="AssemblyInfo" />
    		</GetAssemblyIdentity>
    		<!-- Generate customization dll -->
    		<GenerateResource SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)" UseSourcePath="true" Sources="$(ProjectDir)ZeroTouchNodeIconsImages.resx" OutputResources="$(ProjectDir)ZeroTouchNodeIconsImages.resources" References="$(FrameworkAssembliesPath)System.Drawing.dll" />
    		<AL SdkToolsPath="$(TargetFrameworkSDKToolsDirectory)" TargetType="library" EmbedResources="$(ProjectDir)ZeroTouchNodeIconsImages.resources" OutputAssembly="$(OutDir)ZeroTouchNodeIcons.customization.dll" Version="%(AssemblyInfo.Version)" />
    	</Target>

    Dynamo-Integration

    Sie haben die Integrationsdokumentation für die visuelle Programmiersprache von Dynamo aufgerufen.

    In diesem Handbuch werden verschiedene Aspekte zum Hosten von Dynamo in Ihrer Anwendung erläutert, damit Benutzer mithilfe visueller Programmierung mit Ihrer Anwendung interagieren können.

    Inhalt:

    • Diese Einführung: Allgemeiner Überblick über den Inhalt dieses Handbuchs und über Dynamo.

    • Benutzerdefinierter Dynamo-Einstiegspunkt: Anleitung zum Erstellen eines DynamoModel-Objekts und wo Sie beginnen sollten.

    • : Verwenden des Trace-Mechanismus von Dynamo zum Binden von Blöcken im Diagramm an deren Ergebnisse in Ihrem Host

    • : Implementieren von Blöcken, mit denen Benutzer Objekte oder Daten aus Ihrem Host auswählen und als Eingaben an das Dynamo-Diagramm weitergeben können

    • : Erläuterung der Dynamo-Standardbibliothek und Verwenden des zugrunde liegenden Mechanismus, um Pakete mit Ihrer Integration zu senden

    Informationen zur Begriffsverwendung:

    In diesen Dokumenten werden die Begriffe Dynamo-Skript, -Diagramm und -Programm synonym verwendet, um auf den Code zu verweisen, den Benutzer in Dynamo erstellen.

    Benutzerdefinierter Dynamo-Einstiegspunkt

    Dynamo Revit als Beispiel

    Das DynamoModel-Objekt ist der Einstiegspunkt für eine Anwendung, die Dynamo hostet. Es stellt eine Dynamo-Anwendung dar. Das Modell ist das Stammobjekt der obersten Ebene, das Referenzen zu den anderen wichtigen Datenstrukturen und Objekten enthält, aus denen die Dynamo-Anwendung und die virtuelle DesignScript-Maschine bestehen.

    Ein Konfigurationsobjekt wird verwendet, um allgemeine Parameter für das DynamoModel-Objekt festzulegen, wenn es konstruiert wird.

    Die Beispiele in diesem Dokument stammen aus der DynamoRevit-Implementierung, einer Integration, bei der Revit ein DynamoModel-Objekt als Zusatzmodul hostet. (Plugin-Architektur für Revit.) Wird dieses Zusatzmodul geladen, wird ein DynamoModel-Objekt gestartet und dem Benutzer mit einem DynamoView- und -DynamoViewModel-Objekt angezeigt.

    Dynamo ist ein C#-.NET-Projekt. Um es in Ihrer Anwendung verwenden zu können, müssen Sie .NET-Code hosten und ausführen können.

    DynamoCore ist eine plattformübergreifende Berechnungs-Engine und Sammlung von Core-Modellen, die mit .NET oder Mono (zukünftig .NET Core) erstellt werden können. DynamoCoreWPF enthält jedoch nur die Windows-Benutzeroberflächenkomponenten von Dynamo und kann nicht auf anderen Plattformen kompiliert werden.

    Schritte zum Anpassen des Dynamo-Einstiegspunkts

    Um das DynamoModel-Objekt zu initialisieren, müssen Integratoren die folgenden Schritte an einer beliebigen Stelle im Host-Code ausführen.

    Laden Sie freigegebene Dynamo-DLL-Dateien vorab vom Host.

    Derzeit enthält die Liste in D4R nur Revit\SDA\bin\ICSharpCode.AvalonEdit.dll. Dies ist erforderlich, um Bibliotheksversionskonflikte zwischen Dynamo und Revit zu vermeiden. Beispiel: Wenn Konflikte bei AvalonEdit auftreten, kann die Funktion des Codeblocks völlig zerstört werden. Das Problem wird in Dynamo 1.1.x unter gemeldet und ist auch manuell reproduzierbar. Wenn Integratoren Bibliothekskonflikte zwischen der Host-Funktion und Dynamo festgestellt haben, sollten sie dies als ersten Schritt ausführen. Dies ist manchmal erforderlich, um zu verhindern, dass andere Plugins oder die Host-Anwendung selbst eine inkompatible Version von freigegebenen Abhängigkeiten laden bzw. lädt. Eine bessere Lösung besteht darin, den Versionskonflikt durch Ausrichten der Version zu lösen oder nach Möglichkeit eine .NET-Bindungsumleitung in der app.config-Datei des Hosts zu verwenden.

    Laden von ASM

    Was sind ASM und LibG?

    ASM ist die ADSK-Geometriebibliothek, auf der Dynamo aufbaut.

    LibG ist ein benutzerfreundlicher .NET-Wrapper für den ASM-Geometrie-Kernel. LibG teilt sein Versionierungsschema mit ASM und verwendet die gleiche Haupt- und Nebenversionsnummer wie ASM, um anzugeben, dass es sich um den entsprechenden Wrapper einer bestimmten ASM-Version handelt. Wenn eine ASM-Version angegeben wird, sollte die entsprechende LibG-Version identisch sein. LibG sollte in den meisten Fällen mit allen Versionen von ASM einer bestimmten Hauptversion funktionieren. Beispiel: Mit LibG 223 sollte jede ASM 223-Version geladen werden können.

    Dynamo Sandbox lädt ASM

    Dynamo Sandbox ist so konzipiert, dass mehrere ASM-Versionen verwendet werden können. Zu diesem Zweck werden mehrere LibG-Versionen gebündelt und mit dem Core ausgeliefert. Es gibt eine integrierte Funktion im Dynamo Shape Manager, um nach Autodesk-Produkten zu suchen, die im Lieferumfang von ASM enthalten sind, sodass Dynamo ASM aus diesen Produkten laden und Geometrieblöcke verwenden kann, ohne explizit in eine Host-Anwendung geladen zu werden. Die Produktliste in ihrer aktuellen Form lautet folgendermaßen:

    Dynamo durchsucht die Windows-Registrierung und ermittelt, ob die Autodesk-Produkte in dieser Liste auf dem Computer des Benutzers installiert sind. Sind diese Produkte installiert, sucht das Programm nach ASM-Binärdateien, ruft die Version ab und sucht in Dynamo nach einer entsprechenden LibG-Version.

    Aufgrund der ASM-Version wählt die folgende ShapeManager-API den entsprechenden LibG-Preloader-Speicherort zum Laden aus. Wenn es eine exakte Versionsübereinstimmung gibt, wird diese verwendet, andernfalls wird die nächstliegende LibG-Version darunter, jedoch mit derselben Hauptversion, geladen.

    Beispiel: Wenn Dynamo in einen Revit-Entwickler-Build integriert ist, in dem ein neuerer ASM-Build 225.3.0 vorhanden ist, versucht Dynamo, LibG 225.3.0 zu verwenden, falls vorhanden. Andernfalls wird versucht, die nächstliegende Hauptversion zu verwenden, die niedriger ist als die erste Wahl, z. B. 225.0.0.

    public static string GetLibGPreloaderLocation(Version asmVersion, string dynRootFolder)

    Prozessinterne Dynamo-Integration lädt ASM vom Host

    Revit ist der erste Eintrag in der ASM-Produktsuchliste. Dies bedeutet, dass DynamoSandbox.exe vorgabemäßig zuerst versucht, ASM aus Revit zu laden. Sie sollten aber dennoch sicherstellen, dass die integrierte D4R-Arbeitssitzung ASM aus dem aktuellen Revit-Host lädt. Beispiel: Wenn der Benutzer sowohl R2018 als auch R2020 auf dem Computer installiert hat, sollte D4R beim Starten über R2020 ASM 225 aus R2020 anstelle von ASM 223 aus R2018 verwenden. Integratoren müssen ähnliche Aufrufe wie die folgenden implementieren, um das Laden ihrer angegebenen Version zu erzwingen.

    Dynamo lädt ASM aus einem benutzerdefinierten Pfad

    Seit Kurzem können DynamoSandbox.exe und DynamoCLI.exe auch eine bestimmte ASM-Version laden. Zum Überspringen des normalen Suchverhaltens in der Registrierung können Sie das Flag --GeometryPath verwenden, um zu erzwingen, dass Dynamo ASM aus einem bestimmten Pfad lädt.

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

    Erstellen eines StartConfiguration-Objekts

    StartupConfiguration wird als Parameter für die Initialisierung des DynamoModel-Objekts übergeben, was darauf hinweist, dass fast alle Definitionen zum Anpassen Ihrer Dynamo-Sitzungseinstellungen enthalten sind. Je nachdem, wie die folgenden Eigenschaften festgelegt sind, kann die Dynamo-Integration zwischen verschiedenen Integratoren variieren. Beispielsweise könnten verschiedene Integratoren unterschiedliche Python-Vorlagenpfade oder angezeigte Zahlenformate einstellen.

    Sie besteht aus folgenden Komponenten:

    • DynamoCorePath // Speicherort der ladenden DynamoCore-Binärdateien

    • DynamoHostPath // Speicherort der Binärdateien der Dynamo-Integration

    • GeometryFactoryPath // Speicherort der geladenen LibG-Binärdateien

    • PathResolver // Objekt, das beim Auflösen verschiedener Dateien hilft

    Voreinstellungen

    Der Pfad für die Vorgabeeinstellungen wird von PathManager.PreferenceFilePath verwaltet, z. B. "AppData\\Roaming\\Dynamo\\Dynamo Revit\\2.5\\DynamoSettings.xml". Integratoren können entscheiden, ob sie auch eine benutzerdefinierte Datei mit den Voreinstellungen an einen Speicherort senden möchten, der mit dem Pfadmanager abgestimmt werden muss. Im Folgenden sind Voreinstellungseigenschaften aufgeführt, die serialisiert werden:

    • IsFirstRun // Gibt an, ob diese Version von Dynamo zum ersten Mal ausgeführt wird, z. B., um zu bestimmen, ob eine Meldung zur Aktivierung/Deaktivierung der allgemeinen Verfügbarkeit angezeigt werden muss. Wird auch verwendet, um zu ermitteln, ob die älteren Dynamo-Voreinstellungen beim Starten einer neuen Dynamo-Version migriert werden müssen, damit Benutzer eine konsistente Erfahrung erhalten.

    • IsUsageReportingApproved // Gibt an, ob Nutzungsberichte genehmigt wurden.

    • IsAnalyticsReportingApproved // Gibt an, ob die Analyse-Berichterstellung genehmigt wurde.

    • LibraryWidth // Breite der linken Bibliotheksgruppe von Dynamo

    Beispiel für serialisierte Voreinstellungen:

    • Extensions // Liste der Erweiterungen, die IExtension implementieren. Wenn die Angabe null lautet, lädt Dynamo Erweiterungen aus dem Vorgabepfad (Ordner extensions im Ordner Dynamo).

    • IsHeadless // Gibt an, ob Dynamo ohne Benutzeroberfläche gestartet wird. Wirkt sich auf Analytics aus.

    • UpdateManager // Implementierung des UpdateManager durch den Integrator, siehe Beschreibung oben.

    Verwenden Sie zum Starten von DynamoModel das StartConfiguration-Zielobjekt.

    Sobald StartConfig übergeben wurde, um DynamoModel zu starten, überwacht DynamoCore die eigentlichen Details, um sicherzustellen, dass die Dynamo-Sitzung korrekt mit den angegebenen Details initialisiert wird. Von den einzelnen Integratoren sollten nach der Initialisierung von DynamoModel einige dem Setup nachgelagerte Schritte ausgeführt werden, z. B. werden in D4R Ereignisse abonniert, um nach Revit-Host-Transaktionen oder Dokumentaktualisierungen, Python-Blockanpassungen usw. zu suchen.

    Weiter geht es mit dem Teil zur visuellen Programmierung

    Um DynamoViewModel und DynamoView zu initialisieren, müssen Sie zunächst ein DynamoViewModel-Objekt erstellen, was mit der statischen Methode DynamoViewModel.Start möglich ist. Siehe unten:

    DynamoViewModel.StartConfiguration verfügt über weit weniger Optionen als die Konfiguration des Modells. Die Optionen sind größtenteils selbsterklärend. CommandFilePath kann ignoriert werden, es sei denn, Sie schreiben einen Testfall.

    Der Parameter Watch3DViewModel steuert, wie die Hintergrundvorschau und Watch3D-Blöcke 3D-Geometrie anzeigen. Sie können Ihre eigene Implementierung verwenden, wenn Sie die erforderlichen Schnittstellen implementieren.

    Um DynamoView zu konstruieren, wird lediglich DynamoViewModel benötigt. Die Ansicht ist ein Fenstersteuerelement und kann mit WPF angezeigt werden.

    Beispiel für DynamoSandbox.exe:

    DynamoSandbox.exe ist eine Entwicklungsumgebung zum Testen und Verwenden von sowie Experimentieren mit DynamoCore. Dies ist ein gutes Beispiel, um zu sehen, wie DynamoCore- und DynamoCoreWPF-Komponenten geladen und eingerichtet werden. Sie können einen Teil des Einstiegspunkts einsehen.

    Elementbindung und Trace

    Überblick

    Trace ist ein Mechanismus in Dynamo Core, mit dem Daten in die DYN-Datei (Dynamo-Datei) serialisiert werden können. Entscheidend ist, dass diese Daten den Callsites von Blöcken im Dynamo-Diagramm zugeordnet sind.

    Wenn Sie ein Dynamo-Diagramm von einem Datenträger aus öffnen, werden die darin gespeicherten Trace-Daten erneut mit den Blöcken des Diagramms verknüpft.

    Glossar:

    • Trace-Mechanismus:

      • Implementiert die Elementbindung in Dynamo.

      • Der Trace-Mechanismus kann verwendet werden, um sicherzustellen, dass Objekte erneut an die von diesen erstellte Geometrie gebunden werden.

      • Der Callsite- und der Trace-Mechanismus sorgen für die Bereitstellung einer dauerhaften GUID, die der Block-Implementierer für die Neuverknüpfung verwenden kann.

    Wie sieht das aus?


    Trace-Daten werden in die DYN-Datei innerhalb einer Eigenschaft namens Bindings serialisiert. Dies ist ein Array von Callsite-IDs -> Daten. Eine Callsite ist die Stelle/Instanz, an der ein Block auf der virtuellen DesignScript-Maschine aufgerufen wird. Es sollte erwähnt werden, dass Blöcke in einem Dynamo-Diagramm mehrmals aufgerufen werden können und somit mehrere Callsites für eine einzelne Blockinstanz erstellt werden können.

    Es ist NICHT ratsam, sich auf das Format der serialisierten Base64-codierten Daten zu verlassen.

    Welches Problem versuchen wir zu lösen?


    Es gibt viele Gründe, warum beliebige Daten als Ergebnis einer Funktionsausführung gespeichert werden sollten. In diesem Fall wurde Trace jedoch entwickelt, um ein spezifisches Problem zu lösen, auf das Benutzer häufig stoßen, wenn sie Software-Programme erstellen und iterieren, die Elemente in Host-Anwendungen erstellen.

    Das Problem haben wir mit Element Binding bezeichnet. Die Idee dahinter ist folgende:

    Wenn ein Benutzer ein Dynamo-Diagramm entwickelt und ausführt, werden wahrscheinlich neue Elemente im Host-Anwendungsmodell generiert. In unserem Beispiel nehmen wir an, der Benutzer verwendet ein kleines Programm, mit dem 100 Türen in einem Architekturmodell generiert werden. Die Anzahl und Position dieser Türen wird durch das Programm gesteuert.

    Wenn der Benutzer das Programm zum ersten Mal ausführt, werden diese 100 Türen generiert.

    Wenn der Benutzer später eine Eingabe in seinem Programm ändert und es erneut ausführt, erstellt das Programm (ohne Elementbindung) 100 neue Türen, und die alten Türen sind zusammen mit den neuen Türen weiterhin im Modell vorhanden.


    Da es sich bei Dynamo um eine Live-Programmierumgebung handelt, die über den Ausführungsmodus "Automatic" verfügt, in dem Änderungen am Diagramm eine neue Ausführung auslösen, kann dies schnell dazu führen, dass ein Modell mit den Ergebnissen vieler Programmausführungen überfüllt wird.

    Wir haben festgestellt, dass dies in der Regel nicht den Erwartungen der Benutzer entspricht. Stattdessen werden bei aktivierter Elementbindung die vorherigen Ergebnisse einer Diagrammausführung bereinigt und gelöscht bzw. geändert. Welche Option (gelöscht oder geändert) verwendet wird, hängt von der Flexibilität der API Ihres Hosts ab. Bei aktivierter Elementbindung bleibt es auch nach der zweiten, dritten oder 50. Ausführung des Dynamo-Programms des Benutzers bei 100 Türen im Modell.

    Dazu ist mehr erforderlich als nur die Möglichkeit, Daten in die DYN-Datei zu serialisieren. Wie Sie unten sehen werden, gibt es in DynamoRevit Mechanismen, die auf der Trace-Funktion aufbauen und diese Arbeitsabläufe für Neubindungen unterstützen.


    An dieser Stelle möchten wir den anderen wichtigen Anwendungsfall der Elementbindung für Hosts wie Revit erwähnen. Da Elemente, die bei aktivierter Elementbindung erstellt wurden, versuchen, die vorhandenen Element-IDs beizubehalten (Änderung vorhandener Elemente), ist die Logik, die in der Host-Anwendung auf Basis dieser Elemente erstellt wurde, nach der Ausführung eines Dynamo-Programms weiterhin vorhanden. Beispiel:

    Kehren wir zu unserem Beispiel des Architekturmodells zurück.

    Wir sehen uns zunächst ein Beispiel mit deaktivierter Elementbindung an. Diesmal verfügt der Benutzer über ein Programm, das nichttragende Wände generiert.

    Er führt sein Programm aus, und es werden einige Wände in der Host-Anwendung generiert. Anschließend verlässt er das Dynamo-Diagramm und verwendet die normalen Revit-Werkzeuge, um einige Fenster in diesen Wänden zu platzieren. Die Fenster sind als Teil des Revit-Modells an diese spezifischen Wände gebunden.

    Der Benutzer kehrt zurück zu Dynamo und führt das Diagramm erneut aus. Wie im letzten Beispiel sind nun zwei Sätze von Wänden vorhanden. Beim ersten Satz wurden die Fenster hinzugefügt, bei den neuen Wänden jedoch nicht.

    Wenn die Elementbindung aktiviert gewesen wäre, könnten wir die bereits geleistete Arbeit, die manuell ohne Dynamo in der Host-Anwendung durchgeführt wurde, weiterverwenden. Wenn z. B. beim zweiten Ausführen des Programms durch den Benutzer die Bindung aktiviert gewesen wäre, wären die Wände geändert, nicht gelöscht worden, und die nachfolgenden Änderungen in der Host-Anwendung wären erhalten geblieben. Das Modell würde Wände mit Fenstern, anstelle von zwei Sätzen von Wänden in verschiedenen Zuständen enthalten.


    Elementbindung und Trace im Vergleich


    Trace ist ein Mechanismus in Dynamo Core. Er verwendet eine statische Variable von Callsites für Daten, um die Daten mit der Callsite einer Funktion im Diagramm zu verknüpfen, wie oben beschrieben.

    Außerdem können Sie beliebige Daten in die DYN-Datei serialisieren, wenn Sie Zero-Touch-Blöcke in Dynamo schreiben. Dies ist im Allgemeinen nicht empfehlenswert, da dies bedeutet, dass der potenziell übertragbare Zero-Touch-Code nun von Dynamo Core abhängig ist.

    Verlassen Sie sich nicht auf das serialisierte Format der Daten in der DYN-Datei, sondern verwenden Sie das Attribut und die Schnittstelle [Serializable].

    ElementBinding hingegen baut auf den Trace-APIs auf und ist in der Dynamo-Integration (DynamoRevit, Dynamo4Civil usw.) implementiert.

    Trace-APIs

    Einige der untergeordneten Trace-APIs, die Sie kennen sollten, sind:

    Sie können deren Verwendung im folgenden Beispiel sehen:

    Um mit den Trace-Daten zu interagieren, die Dynamo aus einer vorhandenen Datei geladen hat oder generiert, können Sie sich Folgendes ansehen:

    Beispiel für eine einfache Trace-Funktion aus einem Block


    Ein Beispiel für einen Dynamo-Block, in dem Trace direkt verwendet wird, finden Sie hier im .

    Die Zusammenfassung der Klasse dort enthält den Kern dessen, worum es bei Trace geht:

    In diesem Beispiel werden die Trace-APIs in DynamoCore direkt verwendet, um Daten zu speichern, wenn ein bestimmter Block ausgeführt wird. In diesem Fall übernimmt ein Wörterbuch die Rolle des Host-Anwendungsmodells, wie die Modelldatenbank von Revit.

    Das grobe Setup lautet:

    Eine statische Dienstprogramm-Klasse TraceExampleWrapper wird als Block in Dynamo importiert. Sie enthält eine einzige Methode ByString, mit der TraceExampleItem erstellt wird. Dies sind normale .NET-Objekte, die eine description-Eigenschaft enthalten.

    Jedes TraceExampleItem-Objekt wird in Trace serialisiert und als TraceableId dargestellt. Dies ist nur eine Klasse, die ein IntId-Objekt enthält, das mit [Serializeable] markiert ist, damit es mit dem SOAP-Formatierer serialisiert werden kann. Weitere Informationen zum Serializable-Attribut finden Sie .

    Sie müssen außerdem die definierte ISerializable-Schnittstelle implementieren.

    Diese Klasse wird für jedes TraceExampleItem-Objekt erstellt, das wir in Trace speichern möchten, serialisiert, Base64-codiert und auf dem Datenträger gespeichert, wenn das Diagramm gespeichert wird, sodass Bindungen neu zugeordnet werden können. Dies ist auch später möglich, wenn das Diagramm wieder zusätzlich zu einem vorhandenen Wörterbuch von Elementen geöffnet wird. Das wird in diesem Beispiel nicht gut funktionieren, da das Wörterbuch nicht wirklich dauerhaft ist, wie es bei einem Revit-Dokument der Fall ist.

    Der letzte Teil der Gleichung ist schließlich das TraceableObjectManager-Objekt. Dieses ähnelt ElementBinder in DynamoRevit. Damit wird die Beziehung zwischen den im Dokumentmodell des Hosts vorhandenen Objekten und den in Trace in Dynamo gespeicherten Daten verwaltet.

    Wenn ein Benutzer ein Diagramm mit dem Block TraceExampleWrapper.ByString zum ersten Mal ausführt, wird ein neues TraceableId-Objekt mit einer neuen ID erstellt, das TraceExampleItem-Objekt wird im Wörterbuch gespeichert, das dieser neuen ID zugeordnet ist, und wir speichern das TraceableID-Objekt in Trace.

    Bei der nächsten Ausführung des Diagramms suchen wir in Trace die dort gespeicherte ID, anschließend das Objekt, das dieser ID zugeordnet ist, und geben dieses Objekt zurück. Anstatt ein neues Objekt zu erstellen, ändern wir das vorhandene.

    Der Ablauf von zwei aufeinander folgenden Ausführungen des Diagramms, mit denen ein einzelnes TraceExampleItem-Objekt erstellt wird, sieht wie folgt aus:

    Die gleiche Idee wird im nächsten Beispiel anhand eines realistischeren Anwendungsfalls mit einem DynamoRevit-Block veranschaulicht.

    Trace-Diagramm

    ANMERKUNG:

    In neueren Versionen von Dynamo TLS (Thread Local Storage, lokaler Thread-Speicher) werden statische Elemente verwendet.

    Beispiel für die Implementierung der Elementbindung


    Sehen wir uns kurz an, wie ein Block aussieht, der Elementbindung verwendet, wenn er für DynamoRevit implementiert wird. Dies entspricht dem Typ eines Blocks, der oben in den Beispielen zur Wanderstellung verwendet wurde.


    Der obige Code zeigt einen Beispielkonstruktor für ein Wandelement. Dieser Konstruktor wird über einen Block in Dynamo wie den folgenden aufgerufen: Wall.byParams.

    Die wichtigsten Phasen der Ausführung des Konstruktors im Zusammenhang mit der Elementbindung lauten:

    1. Verwenden Sie elementBinder, um zu überprüfen, ob zuvor erstellte Objekte vorhanden sind, die in einer vergangenen Ausführung an diese Callsite gebunden wurden. ElementBinder.GetElementFromTrace<Autodesk.Revit.DB.Wall>

    2. Ist dies der Fall, versuchen Sie, diese Wand zu ändern, anstatt eine neue zu erstellen.

    1. Andernfalls erstellen Sie eine neue Wand.

    1. Löschen Sie das alte Element, das wir gerade aus Trace abgerufen haben, und fügen Sie das neue Element hinzu, damit wir dieses Element in Zukunft nachschlagen können:

    Erläuterung

    Wirkungsgrad

    • Derzeit wird jedes serialisierte Trace-Objekt mit der SOAP-XML-Formatierung serialisiert. Diese ist recht ausführlich und dupliziert eine Menge Informationen. Anschließend werden die Daten zweimal Base64-codiert. Dies ist nicht effizient in Bezug auf Serialisierung oder Deserialisierung. In Zukunft kann dies verbessert werden, wenn das interne Format nicht darauf aufbaut. Es sei noch einmal gesagt: Verlassen Sie sich nicht auf das Format der serialisierten Daten im Ruhezustand.

    Sollte ElementBinding vorgabemäßig aktiviert sein?

    • Es gibt Anwendungsfälle, in denen die Elementbindung nicht erwünscht ist, beispielsweise, wenn ein erfahrener Dynamo-Benutzer ein Programm entwickelt, das mehrmals ausgeführt werden soll, um zufällige Elementgruppierungen zu generieren. Ziel des Programms ist es, bei jeder Ausführung zusätzliche Elemente zu erstellen. Dieser Anwendungsfall kann nur mit einer Umgehungslösung ausgeführt werden, mit der die Elementbindung aufgehoben wird. ElementBinding kann auf Integrationsebene deaktiviert werden. Dies sollte jedoch eine Kernfunktionalität von Dynamo sein. Es kann nicht klar bestimmt werden, wie detailliert diese Funktion sein sollte: Auf Blockebene? Auf Callsite-Ebene? Auf Basis der gesamten Dynamo-Sitzung? Auf Basis eines Arbeitsbereichs? usw.

    Dynamo Revit-Auswahlblöcke (was versteht man darunter?)

    Im Allgemeinen kann der Benutzer mit diesen Blöcken eine Teilmenge des aktiven Revit-Dokuments beschreiben, die er referenzieren möchte. Der Benutzer kann ein Revit-Element auf verschiedene Weise referenzieren (siehe unten), und die resultierende Ausgabe des Blocks kann ein Revit-Element-Wrapper (DynamoRevit-Wrapper) oder eine Dynamo-Geometrie (konvertiert aus Revit-Geometrie) sein. Der Unterschied zwischen diesen Ausgabetypen sollte im Kontext anderer Host-Integrationen berücksichtigt werden.

    Im Allgemeinen können Sie diese Blöcke gut als Funktion konzeptualisieren, die eine Element-ID akzeptiert und einen Zeiger auf dieses Element oder eine Geometrie, die dieses Element darstellt, zurückgibt.

    Es sind mehrere Selection-Blöcke in DynamoRevit vorhanden. Sie lassen sich in mindestens zwei Gruppen unterteilen:

    1. Benutzeroberflächen-Auswahl durch Benutzer:

      DynamoRevit-Beispielblöcke in dieser Kategorie sindSelectModelElement und SelectElementFace.

      Diese Blöcke ermöglichen es Benutzern, in den Kontext der Revit-Benutzeroberfläche zu wechseln und ein Element oder einen Elementsatz auszuwählen. Die IDs dieser Elemente werden erfasst, und es wird eine Konvertierungsfunktion ausgeführt. Entweder wird ein Wrapper erstellt, oder Geometrie wird aus dem Element extrahiert und konvertiert. Die ausgeführte Konvertierung hängt vom Typ des Blocks ab, den der Benutzer auswählt.

    2. Dokumentabfrage:

    Dynamo Revit-Benutzerarbeitsabläufe:

    Beispielfälle

      • Der Benutzer wählt eine Revit-Wand mit SelectModelElement aus. Ein Dynamo-Wand-Wrapper wird in das Diagramm zurückgegeben (sichtbar im Vorschaufenster des Blocks).

      • Der Benutzer platziert den Block Element.Geometry und verbindet die Ausgabe SelectModelElement mit diesem neuen Block. Die Geometrie der umhüllten Wand wird extrahiert und mithilfe der LibG-API in Dynamo-Geometrie konvertiert.

    DynamoCivil-Benutzerarbeitsabläufe:

    Die Arbeitsabläufe in D4C ähneln der obigen Beschreibung für Revit. Hier sehen Sie zwei typische Sätze von Auswahlblöcken in D4C:

    Mängel:

    • Aufgrund des Dokumentänderungs-Updaters, den Auswahlblöcke in DynamoRevit implementieren, können Endlosschleifen einfach erstellt werden: Stellen Sie sich einen Block vor, der das Dokument auf alle Elemente hin beobachtet und dann an einer beliebigen Stelle hinter diesem Block neue Elemente erstellt. Wenn dieses Programm ausgeführt wird, löst es eine Schleife aus. DynamoRevit versucht, diese Fälle auf verschiedene Weise mithilfe von Transaktions-IDs zu erkennen, und vermeidet, dass das Dokument geändert wird, wenn sich die Eingaben für Elementkonstruktoren nicht geändert haben.

      Dies muss berücksichtigt werden, wenn die automatische Ausführung des Diagramms initiiert und ein ausgewähltes Element in der Host-Anwendung geändert wird.

    • Auswahlblöcke in DynamoRevit werden im Projekt RevitUINodes.dll

    Datenablaufdiagramme

    Technische Implementierung: (siehe Diagramme oben):

    Auswahlblöcke werden implementiert, indem sie Daten von den generischen SelectionBase-Typen SelectionBase<TSelection, TResult> und einem minimalen Satz von Elementen übernehmen:

    • Implementierung einer BuildOutputAST-Methode. Diese Methode muss einen AST zurückgeben, der irgendwann in der Zukunft ausgeführt wird, wenn der Block ausgeführt werden soll. Im Fall von Auswahlblöcken sollten Elemente oder Geometrie aus den Element-IDs zurückgegeben werden.

    • Die Implementierung von BuildOutputAST ist einer der schwierigsten Aspekte bei der Implementierung von NodeModel-/Benutzeroberflächen-Blöcken. Es empfiehlt sich, einer C#-Funktion so viel Logik wie möglich hinzuzufügen und einfach einen AST-Funktionsaufruf-Block in den AST einzubetten. Beachten Sie, dass node hier ein AST-Block in der abstrakten Syntaxstruktur und kein Block im Dynamo-Diagramm ist.

    • Serialisierung -

      • Da es sich hierbei um explizite abgeleitete NodeModel-Typen (nicht um ZeroTouch) handelt, muss auch ein [JsonConstructor] implementiert werden, der während der Deserialisierung des Blocks aus einer DYN-Datei verwendet wird.

        Die Elementreferenzen vom Host sollten in der DYN-Datei gespeichert werden, sodass beim Öffnen eines Diagramms mit diesem Block durch einen Benutzer dessen Auswahl weiterhin festgelegt ist. NodeModel-Blöcke in Dynamo verwenden Json.NET zum Serialisieren. Alle öffentlichen Eigenschaften werden automatisch mit Json.NET serialisiert. Verwenden Sie das [JsonIgnore]-Attribut, um nur die erforderlichen Elemente zu serialisieren.

    Referenzen

    DynamoCore-Basisklassen:

    DynamoRevit:

    Übersicht über integrierte Dynamo-Pakete

    Mit dem Mechanismus für integrierte Pakete können Sie mehr Blockinhalte mit Dynamo Core bündeln, ohne den Core selbst zu erweitern. Dazu wird die von der Erweiterung PackageLoader und PackageManager implementierte Funktion zum Laden von Dynamo-Paketen genutzt.

    In diesem Dokument werden die Begriffe Integrierte Pakete, Integrierte Dynamo-Pakete und Integrierte Pakete synonym verwendet.

    Sollte ich ein Paket als integriertes Paket senden?

    • Das Paket muss über signierte binäre Einstiegspunkte verfügen, andernfalls wird es nicht geladen.

    • Es sollten alle Anstrengungen unternommen werden, um fehlerhafte Änderungen in diesen Paketen zu vermeiden. Dies bedeutet, dass der Paketinhalt über automatische Tests verfügen sollte.

    • Semantische Versionierung: Es ist wahrscheinlich eine gute Idee, das Paket mithilfe eines semantischen Versionierungsschemas zu versionieren und dies den Benutzern in der Paketbeschreibung oder in Dokumenten mitzuteilen.

    • Automatisierte Tests: Siehe oben. Wenn ein Paket mithilfe des integrierten Paketmechanismus eingeschlossen wird, erscheint es für einen Benutzer als Teil des Produkts und sollte wie ein Produkt getestet werden.

    Grundsätzlich sollten Sie die vollständige Kontrolle über das Paket haben und in der Lage sein, das Paket zu reparieren, es auf dem neuesten Stand zu halten und es mit den neuesten Änderungen in Dynamo und Ihrem Produkt zu vergleichen. Sie müssen es auch signieren können.

    Integrierte Pakete und Host-integrationsspezifische Pakete im Vergleich

    Wir beabsichtigen, die Built-In Packages-Funktion zu einer Kernfunktion zu machen, einem Satz von Paketen, auf den alle Benutzer Zugriff erhalten, auch wenn sie keinen Zugriff auf den Package Manager haben. Derzeit ist der zugrunde liegende Mechanismus zur Unterstützung dieser Funktion ein zusätzlicher vorgegebener Speicherort zum Laden von Paketen direkt im Dynamo Core-Verzeichnis, relativ zu DynamoCore.dll.

    Mit einigen Einschränkungen kann dieser Speicherort von ADSK Dynamo-Clients und -Integratoren verwendet werden, um deren integrationsspezifische Pakete zu verteilen. (Beispiel: Die Dynamo Formit-Integration erfordert ein benutzerdefiniertes Dynamo FormIt-Paket.)

    Da der zugrunde liegende Lademechanismus für Core- und Host-spezifische Pakete derselbe ist, muss sichergestellt werden, dass Pakete, die auf diese Weise verteilt werden, nicht zu Verwirrungen bei den Benutzern hinsichtlich Built-In Packages-Core-Paketen und integrationsspezifischen Paketen führen, die nur in einem einzigen Host-Produkt verfügbar sind. Um Verwirrungen bei den Benutzern zu vermeiden, sollten Host-spezifische Pakete im Austausch mit den Dynamo-Teams eingeführt werden.

    Lokalisierung von Paketen

    Da die in der Built-In Packages-Funktion enthaltenen Pakete für mehr Kunden verfügbar sein werden und die Zusicherungen, die wir dafür geben, strenger sind (siehe oben), sollten sie lokalisiert werden.

    Bei internen ADSK-Paketen, die für die Built-In Packages-Integration vorgesehen sind: Die aktuellen Einschränkungen, dass lokalisierte Inhalte nicht im Package Manager publiziert werden können, sind keine Hindernisse, da die Pakete nicht unbedingt im Package Manager publiziert werden müssen.

    Mithilfe einer Umgehungslösung ist es möglich, Pakete mit Kultur-Unterverzeichnissen im Ordner /bin eines Pakets manuell zu erstellen (und sogar zu publizieren).

    Erstellen Sie zunächst manuell die benötigten kulturspezifischen Unterverzeichnisse im Ordner /bin des Pakets.

    Wenn das Paket aus einem bestimmten Grund auch im Package Manager publiziert werden muss, müssen Sie zunächst eine Version des Pakets ohne diese Kultur-Unterverzeichnisse publizieren. Publizieren Sie dann eine neue Version des Pakets mithilfe der DynamoUI-publish package version-Funktion. Die neue in Dynamo hochgeladene Version sollte Ihre Ordner und Dateien unter /bin, die Sie manuell mit dem Windows-Datei-Explorer hinzugefügt haben, nicht löschen. Der Prozess zum Hochladen von Paketen in Dynamo wird aktualisiert, um die Anforderungen für lokalisierte Dateien in Zukunft zu erfüllen.

    Diese Kultur-Unterverzeichnisse werden ohne Probleme von der .NET Runtime geladen, wenn sie sich im selben Verzeichnis wie die Block-/Erweiterungsbinärdateien befinden.

    Weitere Informationen zu Ressourcen-Assemblys und RESX-Dateien finden Sie unter: .

    Sie werden wahrscheinlich die .resx-Dateien in Visual Studio erstellen und kompilieren. Für eine bestimmte Assembly-xyz.dll werden die resultierenden Ressourcen in eine neue Assembly-xyz.resources.dll kompiliert. Wie oben beschrieben, sind der Speicherort und der Name dieser Assembly wichtig.

    Die generierte xyz.resources.dll sollte sich an folgendem Speicherort befinden: package\bin\culture\xyz.resources.dll.

    Um auf die lokalisierten Zeichenfolgen in Ihrem Paket zuzugreifen, können Sie den ResourceManager verwenden. Noch einfacher ist es jedoch, auf Properties.Resources.YourLocalizedResourceName innerhalb der Assembly zu verweisen, für die Sie eine .resx-Datei hinzugefügt haben. Beispiele finden Sie unter

    - Beispiel für eine lokalisierte Fehlermeldung

    - Beispiel für eine lokalisierte Dynamo-spezifische NodeDescription-Attributzeichenfolge

    - weiteres Beispiel

    Layout der Blockbibliothek

    Wenn Dynamo Blöcke aus einem Paket lädt, werden diese normalerweise im Abschnitt Addons der Blockbibliothek platziert. Um integrierte Paketblöcke besser in andere integrierte Inhalte zu integrieren, haben wir die Möglichkeit hinzugefügt, dass Autoren von integrierten Paketen eine partielle layout specification-Datei bereitstellen können, um die Platzierung der neuen Blöcke in der richtigen Kategorie der obersten Ebene im Abschnitt default der Bibliothek zu unterstützen.

    Beispiel: Wenn die folgende JSON-Layout-Spezifikationsdatei im Pfad package/extra/layoutspecs.json gefunden wird, werden die von path angegebenen Blöcke in der Kategorie Revit im Abschnitt default platziert, welcher der Hauptabschnitt für integrierte Blöcke ist.

    Beachten Sie, dass Blöcke, die aus einem integrierten Paket importiert wurden, das Präfix bltinpkg:// aufweisen, wenn sie mit einem Pfad abgeglichen werden sollen, der in der Layout-Spezifikation enthalten ist.

    Komplexe Layoutänderungen wurden nicht ausreichend getestet und werden nicht umfassend unterstützt. Durch das Laden dieser speziellen Layout-Spezifikation wird beabsichtigt, einen ganzen Paket-Namensbereich unter einer bestimmten Host-Kategorie wie Revit oder Formit zu verschieben.

    PreloadLibraryPaths // Speicherort der Binärdateien der vorgeladenen Blöcke, z. B. DSOffice.dll

  • AdditionalNodeDirectories // Speicherort zusätzlicher Block-Binärdateien

  • AdditionalResolutionPaths // Zusätzliche Assembly-Lösungspfade für andere Abhängigkeiten, die beim Laden von Bibliotheken erforderlich sein können

  • UserDataRootFolder // Benutzerdatenordner, z. B. "AppData\Roaming\Dynamo\Dynamo Revit"

  • CommonDataRootFolder // Vorgabeordner zum Speichern von benutzerdefinierten Definitionen, Beispielen usw.

  • Context // Integrator-Hostname + Version (Revit<BuildNum>)

  • SchedulerThread // Integrator-Scheduler-Thread, der ISchedulerThread implementiert. Für die meisten Integratoren ist dies der Haupt-Benutzeroberflächen-Thread oder der Thread, von dem aus sie auf ihre API zugreifen können.

  • StartInTestMode // Angabe, ob die aktuelle Sitzung eine Testautomatisierungssitzung ist. Ändert eine Reihe von Dynamo-Verhaltensweisen. Verwenden Sie diese Option nur, wenn Sie Tests schreiben.

  • AuthProvider // Implementierung von IAuthProvider des Integrators. Die RevitOxygenProvider-Implementierung befindet sich z. B. in der Datei Greg.dll. Wird für die PackageManager-Upload-Integration verwendet.

  • ConsoleHeight // Höhe der Konsolenanzeige

  • ShowPreviewBubbles // Gibt an, ob Vorschaufenster angezeigt werden sollen.

  • ShowConnector // Gibt an, ob Connectors angezeigt werden.

  • ConnectorType // Gibt den Connector-Typ an: Bezier oder Polylinie.

  • BackgroundPreviews // Gibt den aktiven Status der angegebenen Hintergrundvorschau an.

  • RenderPrecision // Render-Genauigkeitsstufe. Ein niedrigerer Wert generiert Netze mit weniger Dreiecken. Mit einem höheren Wert wird eine glattere Geometrie in der Hintergrundvorschau erzeugt. 128 ist ein guter Mittelwert für die Vorschau von Geometrie.

  • ShowEdges // Gibt an, ob Oberflächen- und Volumenkörperkanten gerendert werden.

  • ShowDetailedLayout // NICHT VERWENDET

  • WindowX, WindowY // Letzte X-, Y-Koordinate des Dynamo-Fensters

  • WindowW, WindowH // Letzte Breite, Höhe des Dynamo-Fensters

  • UseHardwareAcceleration // Angabe, ob Dynamo die Hardwarebeschleunigung verwenden soll, wenn diese unterstützt wird

  • NumberFormat // Dezimalgenauigkeit, die zum Anzeigen von Zahlen im Vorschaufenster toString() verwendet wird

  • MaxNumRecentFiles // Maximale Anzahl der aktuellen Dateipfade, die gespeichert werden sollen

  • RecentFiles // Liste der zuletzt geöffneten Dateipfade. Wenn Sie hier Änderungen vornehmen, wirkt sich dies direkt auf die Liste der zuletzt geöffneten Dateien auf der Startseite von Dynamo aus.

  • BackupFiles // Liste von Sicherungsdateipfaden

  • CustomPackageFolders // Liste von Ordnern mit Zero-Touch-Binärdateien und Verzeichnispfaden, die nach Paketen und benutzerdefinierten Blöcken durchsucht werden.

  • PackageDirectoriesToUninstall // Liste von Paketen, die vom Package Manager verwendet werden, um zu bestimmen, welche Pakete zum Löschen markiert sind. Diese Pfade werden nach Möglichkeit beim Start von Dynamo gelöscht.

  • PythonTemplateFilePath // Pfad zur Python-Datei (.py), die beim Erstellen eines neuen PythonScript-Blocks als Startvorlage verwendet werden soll. Diese Option kann zum Einrichten einer benutzerdefinierten Python-Vorlage für Ihre Integration verwendet werden.

  • BackupInterval // Gibt an, wie lange (in Millisekunden) das Diagramm automatisch gespeichert wird.

  • BackupFilesCount // Gibt an, wie viele Sicherungen erstellt werden.

  • PackageDownloadTouAccepted // Gibt an, ob der Benutzer die Nutzungsbedingungen für das Herunterladen von Paketen aus dem Package Manager akzeptiert hat.

  • OpenFileInManualExecutionMode // Gibt den Vorgabestatus des Kontrollkästchens Im manuellen Ausführungsmodus öffnen in OpenFileDialog an.

  • NamespacesToExcludeFromLibrary // Gibt an, welche Namensbereiche nicht in der Dynamo-Blockbibliothek angezeigt werden sollen (sofern vorhanden). Zeichenfolgenformat: "[Bibliotheksname]:[vollständig qualifizierter Namensbereich]".

  • ProcessMode // Entspricht TaskProcessMode. Synchron, wenn im Testmodus, ansonsten Asynchron. Dies steuert das Verhalten des Schedulers. In Single-Thread-Umgebungen kann dies auch auf Synchron gesetzt werden.

    Callsite

    • Die ausführbare Datei enthält mehrere Callsites. Diese Callsites werden verwendet, um die Ausführung an die verschiedenen Stellen zu verteilen, von denen aus sie verteilt werden müssen:

      • C#-Bibliothek

      • Integrierte Methode

      • DesignScript-Funktion

      • Benutzerdefinierter Block (DS-Funktion)

  • TraceSerializer

    • Serialisiert mit ISerializable und [Serializable] markierte Klassen in Trace.

    • Verarbeitet die Serialisierung und Deserialisierung von Daten in Trace.

    • TraceBinder steuert die Bindung deserialisierter Daten an einen Laufzeittyp (erstellt eine Instanz einer Realklasse).

  • Beispielblöcke in dieser Kategorie sind
    AllElementsOfClass
    und
    AllElementsOfCategory
    .

    Mit diesen Blöcken haben Benutzer die Möglichkeit, das gesamte Dokument nach einer Teilmenge von Elementen zu durchsuchen. Die Blöcke geben in der Regel Wrapper zurück, die auf die zugrunde liegenden Revit-Elemente verweisen. Diese Wrapper sind ein wesentlicher Bestandteil der DynamoRevit-Benutzererfahrung, da sie erweiterte Funktionen wie die Elementbindung ermöglichen. Dynamo-Integratoren können so auswählen, welche Host-APIs den Benutzern als Blöcke zur Verfügung stehen.

    Der Benutzer schaltet das Diagramm in den automatischen Ausführungsmodus um.

  • Der Benutzer ändert die ursprüngliche Wand in Revit.

  • Das Diagramm wird automatisch erneut ausgeführt, da das Revit-Dokument ein Ereignis ausgelöst hat, das signalisiert, dass einige Elemente aktualisiert wurden. Der Auswahlblock beobachtet dieses Ereignis und erkennt, dass die ID des ausgewählten Elements geändert wurde.

  • implementiert, das auf WPF verweist. Dies stellt möglicherweise kein Problem dar, sollte aber je nach Zielplattform berücksichtigt werden.
    Dokumentabfrage-Blöcke sind etwas einfacher, da sie keine Referenz auf Element-IDs speichern müssen. Weitere Informationen zur Implementierung der ElementQueryBase-Klasse und abgeleiteter Klassen finden Sie weiter unten. Wenn sie ausgeführt werden, rufen diese Blöcke die Revit-API auf, fragen das zugrunde liegende Dokument nach Elementen ab und führen die zuvor erwähnte Konvertierung in Geometrie- oder Revit-Element-Wrapper durch.
  • Ausgereifter Zustand: Symbole, Block-Dokumente, lokalisierte Inhalte

  • Versenden Sie keine Pakete, die weder Sie noch Ihr Team verwalten können.

  • Versenden Sie Pakete von Drittanbietern nicht auf diese Weise (siehe oben).

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