diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..aaf2397 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,8 @@ +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: ".github/workflows" + schedule: + interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml new file mode 100644 index 0000000..129e8b8 --- /dev/null +++ b/.github/workflows/build.yml @@ -0,0 +1,85 @@ +# Build SampleIntegration.sln and DynamoSamples.sln with .NET 10.0 +name: Build + +on: + push: + branches: + - master + pull_request: + +jobs: + build: + runs-on: windows-latest + steps: + - name: Checkout DynamoSamples Repo + uses: actions/checkout@v5 + with: + path: DynamoSamples + repository: DynamoDS/DynamoSamples + - name: Setup dotnet + uses: actions/setup-dotnet@v5 + with: + dotnet-version: "10.0.100-preview.5.25277.114" + - name: Disable problem matcher + run: echo "::remove-matcher owner=csc::" + - name: Setup msbuild + uses: microsoft/setup-msbuild@v2 + - name: Install dependencies for SampleIntegration + run: | + dotnet restore ${{ github.workspace }}\DynamoSamples\src\SampleIntegration\SampleIntegration.sln /p:Configuration=Release --runtime=win-x64 + - name: Build SampleIntegration + run: | + msbuild ${{ github.workspace }}\DynamoSamples\src\SampleIntegration\SampleIntegration.sln /p:Configuration=Release + - name: Look for Sample Integration + run: | + if (Test-Path -Path "${{ github.workspace }}\DynamoSamples\src\SampleIntegration\bin\Release\SampleIntegration.dll") { + Write-Output "SampleIntegration.dll exists!" + } else { + Write-Error "SampleIntegration.dll was not found!" + } + - name: Install dependencies for DynamoSamples + run: | + dotnet restore ${{ github.workspace }}\DynamoSamples\src\DynamoSamples.sln /p:Configuration=Release --runtime=win-x64 + - name: Build DynamoSamples + run: | + msbuild ${{ github.workspace }}\DynamoSamples\src\DynamoSamples.sln /p:Configuration=Release + - name: Look for Sample Packages + run: | + $paths = @( + "${{ github.workspace }}\DynamoSamples\dynamo_linter\Sample Linter\bin\SampleLinter.dll", + "${{ github.workspace }}\DynamoSamples\dynamo_package\Dynamo Samples\bin\SampleLibraryUI.dll", + "${{ github.workspace }}\DynamoSamples\dynamo_package\Dynamo Samples\bin\SampleLibraryZeroTouch.dll", + "${{ github.workspace }}\DynamoSamples\dynamo_package\Dynamo Samples\bin\SampleZeroTouchUnits.dll", + "${{ github.workspace }}\DynamoSamples\dynamo_viewExtension\Sample View Extension\bin\SampleViewExtension.dll" + ) + + foreach ($path in $paths) { + if (Test-Path -Path $path) { + Write-Output "$path exists!" + } else { + Write-Error "$path was not found!" + } + } + - name: Get DynamoRuntime from s3 + run: | + curl -o DynamoRuntime.zip https://downloads.dynamobuilds.com/DynamoCoreRuntime3.1.0.zip + ls + - name: Extract DynamoRuntime + run: | + 7z x DynamoRuntime.zip -o${{ github.workspace }}\DynamoSamples\src\SampleLibraryTests\bin\Release\DynamoRuntime + + - name: Run test with the dotnet CLI + run: | + dotnet test ${{ github.workspace }}\DynamoSamples\src\SampleLibraryTests -p:Configuration=Release --filter "TestCategory!=Failure&TestCategory!=NEEDS_GEOM_LIB" --logger "trx;LogFileName=results.trx" --results-directory ${{ github.workspace }}\DynamoSamples\TestResults + - name: Upload build artifact + uses: actions/upload-artifact@v5.0.0 + with: + name: DynamoSamples + path: ${{ github.workspace }}\DynamoSamples\dynamo_package + retention-days: 7 + - name: Upload test artifact + uses: actions/upload-artifact@v5.0.0 + with: + name: TestResults + path: ${{ github.workspace }}\DynamoSamples\TestResults + retention-days: 1 diff --git a/.gitignore b/.gitignore index 1b56052..52a19db 100644 --- a/.gitignore +++ b/.gitignore @@ -40,6 +40,7 @@ local.properties *.suo *.user *.sln.docstates +.vs # Build results diff --git a/LICENSE b/LICENSE index 20efd1b..fb69acf 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 +Copyright (c) 2024 Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/README.md b/README.md index 49d246b..3f42c43 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,29 @@ -[![Build status](https://ci.appveyor.com/api/projects/status/qjdj92r86xb2tbq3?svg=true)](https://ci.appveyor.com/project/ikeough/dynamosamples) +[![Build](https://github.com/DynamoDS/DynamoSamples/actions/workflows/build.yml/badge.svg)](https://github.com/DynamoDS/DynamoSamples/actions/workflows/build.yml) ![Image](https://raw.github.com/ikeough/Dynamo/master/doc/distrib/Images/dynamo_logo_dark.png) # Dynamo Samples + A collection of samples demonstrating how to develop libraries for Dynamo. -These samples make use of the [Dynamo NuGet packages](https://www.nuget.org/packages?q=DynamoVisualProgramming). NuGet should take care of restoring these packages if they are not available on your system at build time. +These samples make use of the [Dynamo NuGet packages](https://www.nuget.org/packages?q=DynamoVisualProgramming). NuGet should take care of restoring these packages if they are not available on your system at build time. # Building the Samples +## Requirements + +- Visual Studio 2022 +- .NET 10.0 + +## Instructions + - Clone the repository. - Choose a branch: - - The master branch of Dynamo Samples corresponds to the master branch of Dynamo. To build against a specific version, choose that version's branch. I.e. 0.8.0, 0.9.0, etc. -- In VisualStudio 2013 or greater, open DynamoSamples.2013.sln. -- Build the Debug/Any CPU configuration. -- The `dynamo_package` folder at the root of the repository will now have the built libraries. The `Dynamo Samples` folder in that directory can be copied directly to your Dynamo packages directory:`C:\Users\\AppData\Roaming\Dynamo\0.8\packages`. -- Run Dynamo. You should find SampleLibraryUI and SampleLibraryZeroTouch categories in your library. - -Assembly Reference -Path to assembly for binaries are defined in CS.props and user_local.props which can be found at $(SolutionDirectory)\Config -user_local.props defines path to binaries found in the bin folder of the local Dynamo repository -If the specified binary is not found, the path to the nuget packages binaries will be used instead which is defined in the CS.props file + - The master branch of Dynamo Samples corresponds to the master branch of Dynamo. To build against a specific version, choose that version's branch or tag. i.e. 0.8.0, 0.9.0, etc. +- Open `DynamoSamples.sln` with Visual Studio. +- Build using the `Debug/Any CPU` configuration. +- The `dynamo_package` folder at the root of the repository will now have the built libraries. The `Dynamo Samples` folder in that directory can be copied directly to your Dynamo packages directory:`C:\Users\\AppData\Roaming\Dynamo Core\\packages`. +- To install the sample view extension the `SampleViewExtension\bin\debug` folder (or release) should contain + - `SampleViewExtension.dll` which should be copied to your root Dynamo build location + - `SampleViewExtension_ViewExtensionDefinition` which should be copied to the `viewExtensions` folder inside your root Dynamo build location +- Run Dynamo. You should find `SampleLibraryUI` and `SampleLibraryZeroTouch` categories in your library and the `View` tab inside of Dynamo should now contain `Show View Extension Sample Window`. diff --git a/appveyor.yml b/appveyor.yml deleted file mode 100644 index 24cdc98..0000000 --- a/appveyor.yml +++ /dev/null @@ -1,14 +0,0 @@ -version: 1.0.{build} - -platform: Any CPU - -configuration: Release - -build: - project: src/DynamoSamples.2013.sln - verbosity: normal - -test: off - -before_build: - - nuget restore .\src\DynamoSamples.2013.sln \ No newline at end of file diff --git a/dynamo_linter/Sample Linter/extra/.gitignore b/dynamo_linter/Sample Linter/extra/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/dynamo_linter/Sample Linter/extra/LinterSettings.xml b/dynamo_linter/Sample Linter/extra/LinterSettings.xml new file mode 100644 index 0000000..008283b --- /dev/null +++ b/dynamo_linter/Sample Linter/extra/LinterSettings.xml @@ -0,0 +1,4 @@ + + + 5 + \ No newline at end of file diff --git a/dynamo_linter/Sample Linter/extra/SampleLinter_ExtensionDefinition.xml b/dynamo_linter/Sample Linter/extra/SampleLinter_ExtensionDefinition.xml new file mode 100644 index 0000000..59a0580 --- /dev/null +++ b/dynamo_linter/Sample Linter/extra/SampleLinter_ExtensionDefinition.xml @@ -0,0 +1,4 @@ + + ..\bin\SampleLinter.dll + SampleLinter.SampleLinter + diff --git a/dynamo_linter/Sample Linter/pkg.json b/dynamo_linter/Sample Linter/pkg.json new file mode 100644 index 0000000..d9f7574 --- /dev/null +++ b/dynamo_linter/Sample Linter/pkg.json @@ -0,0 +1,17 @@ +{ + "file_hash":null, + "name":"Sample Linter Extension", + "version":"2.0.1", + "description":"Dynamo sample linter extension.", + "group":"", + "keywords":["dynamo","samples, view, extension, linter"], + "dependencies":[], + "license":"MIT", + "contents":"", + "engine_version":"2.0.1", + "engine_metadata":"", + "engine":"dynamo", + "site_url": "http://dynamobim.org/", + "repository_url": "https://github.com/DynamoDS/DynamoSamples", + "node_libraries": [ ] +} \ No newline at end of file diff --git a/dynamo_package/Dynamo Samples/extra/SampleExtension_ExtensionDefinition.xml b/dynamo_package/Dynamo Samples/extra/SampleExtension_ExtensionDefinition.xml new file mode 100644 index 0000000..2a3054a --- /dev/null +++ b/dynamo_package/Dynamo Samples/extra/SampleExtension_ExtensionDefinition.xml @@ -0,0 +1,4 @@ + + ..\bin\SampleExtension.dll + SampleExtension.Extension + diff --git a/dynamo_package/Dynamo Samples/pkg.json b/dynamo_package/Dynamo Samples/pkg.json index 11a4888..5eff173 100644 --- a/dynamo_package/Dynamo Samples/pkg.json +++ b/dynamo_package/Dynamo Samples/pkg.json @@ -1,12 +1,12 @@ {"file_hash":null, "name":"Dynamo Samples", -"version":"1.0.0", +"version":"2.0.0", "description":"Dynamo code samples.", "group":"", "keywords":["dynamo","samples"], "dependencies":[], "license":"MIT", "contents":"", -"engine_version":"0.8.2", +"engine_version":"2.0.0", "engine_metadata":"", "engine":"dynamo"} \ No newline at end of file diff --git a/dynamo_viewExtension/Sample View Extension/extra/SampleViewExtension_ViewExtensionDefinition.xml b/dynamo_viewExtension/Sample View Extension/extra/SampleViewExtension_ViewExtensionDefinition.xml new file mode 100644 index 0000000..e9ff08e --- /dev/null +++ b/dynamo_viewExtension/Sample View Extension/extra/SampleViewExtension_ViewExtensionDefinition.xml @@ -0,0 +1,4 @@ + + ..\bin\SampleViewExtension.dll + SampleViewExtension.SampleViewExtension + diff --git a/dynamo_viewExtension/Sample View Extension/pkg.json b/dynamo_viewExtension/Sample View Extension/pkg.json new file mode 100644 index 0000000..45ec8c0 --- /dev/null +++ b/dynamo_viewExtension/Sample View Extension/pkg.json @@ -0,0 +1,17 @@ +{ + "file_hash":null, + "name":"Sample View Extension", + "version":"2.0.1", + "description":"Dynamo sample view extension.", + "group":"", + "keywords":["dynamo","samples, view, extension, nodes"], + "dependencies":[], + "license":"MIT", + "contents":"", + "engine_version":"2.0.1", + "engine_metadata":"", + "engine":"dynamo", + "site_url": "http://dynamobim.org/", + "repository_url": "https://github.com/DynamoDS/DynamoSamples", + "node_libraries": [ ] +} \ No newline at end of file diff --git a/src/Config/CS.props b/src/Config/CS.props index e981e9b..4cd077b 100644 --- a/src/Config/CS.props +++ b/src/Config/CS.props @@ -1,14 +1,40 @@ - - - - - + - $(SolutionDir)\packages\DynamoVisualProgramming.Core.1.0.0-beta3\lib\net45 - $(SolutionDir)\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.0.0-beta3\lib\net45 - $(SolutionDir)\packages\DynamoVisualProgramming.WpfUILibrary.1.0.0-beta4\lib\net45 - $(DynamoWpfUIPath) - $(SolutionDir)\packages\DynamoVisualProgramming.DynamoServices.1.0.0-beta3\lib\net45 - $(SolutionDir)\packages\DynamoVisualProgramming.Tests.1.0.0-beta4\lib\net45 - - + Debug + AnyCPU + x64 + 512 + false + false + prompt + 4 + false + Library + false + None + true + false + + + full + + + true + full + false + bin\Debug\ + TRACE;DEBUG + prompt + 4 + false + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + false + + diff --git a/src/Config/user_local.props b/src/Config/user_local.props deleted file mode 100644 index a5848fb..0000000 --- a/src/Config/user_local.props +++ /dev/null @@ -1,12 +0,0 @@ - - - - $(SolutionDir)..\..\Dynamo\bin\$(Platform)\$(Configuration) - $(DYNAMOAPI) - $(DYNAMOAPI) - $(DYNAMOAPI) - $(DYNAMOAPI)\nodes - $(DYNAMOAPI) - $(DYNAMOAPI) - - \ No newline at end of file diff --git a/src/Directory.Build.props b/src/Directory.Build.props new file mode 100644 index 0000000..daf5058 --- /dev/null +++ b/src/Directory.Build.props @@ -0,0 +1,10 @@ + + + + $(MSBuildThisFileDirectory)\ + + diff --git a/src/DynamoSamples.2013.sln b/src/DynamoSamples.sln similarity index 54% rename from src/DynamoSamples.2013.sln rename to src/DynamoSamples.sln index ea392b5..cdd718b 100644 --- a/src/DynamoSamples.2013.sln +++ b/src/DynamoSamples.sln @@ -1,15 +1,21 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33815.320 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleLibraryTests", "SampleLibraryTests\SampleLibraryTests.csproj", "{933B8108-4E74-470A-86C7-4B7F633115B9}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleLibraryTests", "SampleLibraryTests\SampleLibraryTests.csproj", "{933B8108-4E74-470A-86C7-4B7F633115B9}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleLibraryUI", "SampleLibraryUI\SampleLibraryUI.csproj", "{0A4B4EEA-8FAB-4AC8-90D4-27DBC5B0CF2A}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleLibraryUI", "SampleLibraryUI\SampleLibraryUI.csproj", "{0A4B4EEA-8FAB-4AC8-90D4-27DBC5B0CF2A}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleLibraryZeroTouch", "SampleLibraryZeroTouch\SampleLibraryZeroTouch.csproj", "{BD13C4DC-9045-4E49-B637-B6182B0E3A7F}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleLibraryZeroTouch", "SampleLibraryZeroTouch\SampleLibraryZeroTouch.csproj", "{BD13C4DC-9045-4E49-B637-B6182B0E3A7F}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleViewExtension", "SampleViewExtension\SampleViewExtension.csproj", "{146EBF48-E7A0-4ABE-809D-D7F3059E4EE1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleViewExtension", "SampleViewExtension\SampleViewExtension.csproj", "{146EBF48-E7A0-4ABE-809D-D7F3059E4EE1}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleExtension", "SampleExtension\SampleExtension.csproj", "{8B27B070-8434-49C8-8D43-41A4AE53BC36}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SampleLinter", "SampleLinter\SampleLinter.csproj", "{5F559FDB-99B9-4F4A-9A91-C9EC94C771D8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SampleZeroTouchUnits", "SampleZeroTouchUnits\SampleZeroTouchUnits.csproj", "{4F9ECB35-D321-482A-8ED4-CC8E9342AACE}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -33,6 +39,18 @@ Global {146EBF48-E7A0-4ABE-809D-D7F3059E4EE1}.Debug|Any CPU.Build.0 = Debug|Any CPU {146EBF48-E7A0-4ABE-809D-D7F3059E4EE1}.Release|Any CPU.ActiveCfg = Release|Any CPU {146EBF48-E7A0-4ABE-809D-D7F3059E4EE1}.Release|Any CPU.Build.0 = Release|Any CPU + {8B27B070-8434-49C8-8D43-41A4AE53BC36}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {8B27B070-8434-49C8-8D43-41A4AE53BC36}.Debug|Any CPU.Build.0 = Debug|Any CPU + {8B27B070-8434-49C8-8D43-41A4AE53BC36}.Release|Any CPU.ActiveCfg = Release|Any CPU + {8B27B070-8434-49C8-8D43-41A4AE53BC36}.Release|Any CPU.Build.0 = Release|Any CPU + {5F559FDB-99B9-4F4A-9A91-C9EC94C771D8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5F559FDB-99B9-4F4A-9A91-C9EC94C771D8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5F559FDB-99B9-4F4A-9A91-C9EC94C771D8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5F559FDB-99B9-4F4A-9A91-C9EC94C771D8}.Release|Any CPU.Build.0 = Release|Any CPU + {4F9ECB35-D321-482A-8ED4-CC8E9342AACE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4F9ECB35-D321-482A-8ED4-CC8E9342AACE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4F9ECB35-D321-482A-8ED4-CC8E9342AACE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4F9ECB35-D321-482A-8ED4-CC8E9342AACE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/SampleExtension/Extension.cs b/src/SampleExtension/Extension.cs new file mode 100644 index 0000000..167a3fa --- /dev/null +++ b/src/SampleExtension/Extension.cs @@ -0,0 +1,73 @@ +using Dynamo.Extensions; +using Dynamo.Graph.Nodes; +using Dynamo.Models; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace SampleExtension +{ + /// + /// The Extension framework for Dynamo allows you to extend + /// Dynamo by loading your own classes that can interact with Dynamo's API. + /// An Extension has two components, an assembly containing your class and + /// an xml manifest file telling Dynamo where to find your assembly. Extension + /// manifests are loaded from the Dynamo/Extensions folder or from package/extra + /// folders. + /// + /// This sample demonstrates a simple IExtension which tracks nodes added to the workspace. + /// + public class Extension : IExtension + { + public List nodes = new List(); + public bool readyCalled = false; + + public string Name + { + get + { + return "testExtension"; + } + } + + public string UniqueId + { + get + { + return "49fee64a-4505-4f03-a6b6-0667a793f19a"; + } + } + + public void Dispose() + { + + } + /// + /// Ready is called when the DynamoModel is finished being built, or when the extension is installed + /// sometime after the DynamoModel is already built. ReadyParams provide access to references like the + /// CurrentWorkspace. + /// + /// + public void Ready(ReadyParams sp) + { + sp.CurrentWorkspaceModel.NodeAdded += CurrentWorkspaceModel_NodeAdded; + this.readyCalled = true; + } + + private void CurrentWorkspaceModel_NodeAdded(Dynamo.Graph.Nodes.NodeModel obj) + { + this.nodes.Add(obj); + } + + public void Shutdown() + { + + } + + public void Startup(StartupParams sp) + { + + } + } +} diff --git a/src/SampleExtension/Properties/AssemblyInfo.cs b/src/SampleExtension/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..21e8b2f --- /dev/null +++ b/src/SampleExtension/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("SampleExtension")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("SampleExtension")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("8b27b070-8434-49c8-8d43-41a4ae53bc36")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/SampleExtension/SampleExtension.csproj b/src/SampleExtension/SampleExtension.csproj new file mode 100644 index 0000000..50fab8f --- /dev/null +++ b/src/SampleExtension/SampleExtension.csproj @@ -0,0 +1,22 @@ + + + + + + Debug + SampleExtension + SampleExtension + net10.0 + + + true + + + + Always + + + + + + \ No newline at end of file diff --git a/src/SampleExtension/SampleExtension_ExtensionDefinition.xml b/src/SampleExtension/SampleExtension_ExtensionDefinition.xml new file mode 100644 index 0000000..2a3054a --- /dev/null +++ b/src/SampleExtension/SampleExtension_ExtensionDefinition.xml @@ -0,0 +1,4 @@ + + ..\bin\SampleExtension.dll + SampleExtension.Extension + diff --git a/src/SampleIntegration/SampleIntegration.csproj b/src/SampleIntegration/SampleIntegration.csproj index fc4e073..50d846e 100644 --- a/src/SampleIntegration/SampleIntegration.csproj +++ b/src/SampleIntegration/SampleIntegration.csproj @@ -1,60 +1,13 @@ - - - + + + + - Debug - AnyCPU - {5C06327E-B4AE-4909-AA0F-A0491A424BF0} - Library - Properties SampleIntegration SampleIntegration - v4.0 - 512 + net10.0 - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - {ef879a10-041d-4c68-83e7-3192685f1bae} - DynamoServices - + - - \ No newline at end of file diff --git a/src/SampleIntegration/TracedHog.cs b/src/SampleIntegration/TracedHog.cs index 217ec40..424fa88 100644 --- a/src/SampleIntegration/TracedHog.cs +++ b/src/SampleIntegration/TracedHog.cs @@ -3,8 +3,9 @@ using System.Linq; using System.Runtime.Serialization; using System.Text; - +using Dynamo.Events; using DynamoServices; +using Newtonsoft.Json; class TracedHogManager { @@ -69,8 +70,6 @@ public HogID(SerializationInfo info, StreamingContext context) } } - -[RegisterForTrace] public class TracedHog : IDisposable { //TODO(lukechurch): This really should have been moved into the attribute already @@ -107,7 +106,7 @@ public static TracedHog ByPoint(double x, double y) { TracedHog tHog; - HogID hid = TraceUtils.GetTraceData(REVIT_TRACE_ID) as HogID; + HogID hid = JsonConvert.DeserializeObject(TraceUtils.GetTraceData(REVIT_TRACE_ID)); if (hid == null) { @@ -120,7 +119,7 @@ public static TracedHog ByPoint(double x, double y) } // Set the trace data on the return to be this hog. - TraceUtils.SetTraceData(REVIT_TRACE_ID, new HogID { IntID = tHog.ID }); + TraceUtils.SetTraceData(REVIT_TRACE_ID, JsonConvert.SerializeObject(new HogID { IntID = tHog.ID })); return tHog; } diff --git a/src/SampleLibraryTests/HelloDynamoSystemTest.dyn b/src/SampleLibraryTests/HelloDynamoSystemTest.dyn index 555ce32..11bd319 100644 --- a/src/SampleLibraryTests/HelloDynamoSystemTest.dyn +++ b/src/SampleLibraryTests/HelloDynamoSystemTest.dyn @@ -1,18 +1,235 @@ - - - - - - - - - - - - - - - - - - \ No newline at end of file +{ + "Uuid": "3c9d0464-8643-5ffe-96e5-ab1769818209", + "IsCustomNode": false, + "Description": "", + "Name": "HelloDynamoSystemTest", + "ElementResolver": { + "ResolutionMap": {} + }, + "Inputs": [], + "Outputs": [], + "Nodes": [ + { + "ConcreteType": "CoreNodeModels.Watch, CoreNodeModels", + "WatchWidth": 35.0, + "WatchHeight": 38.0, + "Id": "2c4cdf29f078497c86b8fed323f4b77d", + "NodeType": "ExtensionNode", + "Inputs": [ + { + "Id": "a249fef4a4ce43ed9fa47a4ace364c8c", + "Name": "", + "Description": "Node to show output from", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "6bb8cd0394254f268082f176f97a233a", + "Name": "", + "Description": "Node output", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Visualizes a node's output" + }, + { + "ConcreteType": "Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore", + "Id": "4964a3edb14b46dd8e614d64fad42128", + "NodeType": "FunctionNode", + "Inputs": [ + { + "Id": "2e564722e153444292ce3cf2fd1ea4df", + "Name": "x", + "Description": "Integer value, double value or string\n\nvar[]..[]", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + }, + { + "Id": "c878418229554a8081a2add69a669b4c", + "Name": "y", + "Description": "Integer value, double value or string\n\nvar[]..[]", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "f648d8c8b1b7407eb51174f21f2d4908", + "Name": "var", + "Description": "The sum of two input numbers, or the concatenation of two strings", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "FunctionSignature": "+@var[]..[],var[]..[]", + "Replication": "Auto", + "Description": "Returns addition of x and y\n\n+ (x: var[]..[], y: var[]..[]): var[]..[]" + }, + { + "ConcreteType": "CoreNodeModels.Input.DoubleInput, CoreNodeModels", + "NumberType": "Double", + "Id": "77af56fb6e37432485e008870d79cb40", + "NodeType": "NumberInputNode", + "Inputs": [], + "Outputs": [ + { + "Id": "982234929f014a7dacf16d38836763a1", + "Name": "", + "Description": "Double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Creates a number", + "InputValue": 21.0 + }, + { + "ConcreteType": "CoreNodeModels.Input.DoubleInput, CoreNodeModels", + "NumberType": "Double", + "Id": "a603bf1480404297bea85441d71645ed", + "NodeType": "NumberInputNode", + "Inputs": [], + "Outputs": [ + { + "Id": "e57dc497431840b98db808aca08d846b", + "Name": "", + "Description": "Double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Creates a number", + "InputValue": 21.0 + } + ], + "Connectors": [ + { + "Start": "f648d8c8b1b7407eb51174f21f2d4908", + "End": "a249fef4a4ce43ed9fa47a4ace364c8c", + "Id": "b47128bfe4304b74a01f7b8db90d2c34", + "IsHidden": "False" + }, + { + "Start": "982234929f014a7dacf16d38836763a1", + "End": "2e564722e153444292ce3cf2fd1ea4df", + "Id": "73b3eba3b10e4b1f86c836c5164e01e9", + "IsHidden": "False" + }, + { + "Start": "e57dc497431840b98db808aca08d846b", + "End": "c878418229554a8081a2add69a669b4c", + "Id": "0ebc660b634b4281814460827fd4fa78", + "IsHidden": "False" + } + ], + "Dependencies": [], + "NodeLibraryDependencies": [], + "EnableLegacyPolyCurveBehavior": null, + "Thumbnail": null, + "GraphDocumentationURL": null, + "ExtensionWorkspaceData": [ + { + "ExtensionGuid": "28992e1d-abb9-417f-8b1b-05e053bee670", + "Name": "Properties", + "Version": "3.1", + "Data": {} + } + ], + "Author": "None provided", + "Linting": { + "activeLinter": "None", + "activeLinterId": "7b75fb44-43fd-4631-a878-29f4d5d8399a", + "warningCount": 0, + "errorCount": 0 + }, + "Bindings": [], + "View": { + "Dynamo": { + "ScaleFactor": 1.0, + "HasRunWithoutCrash": true, + "IsVisibleInDynamoLibrary": true, + "Version": "3.1.0.3755", + "RunType": "Manual", + "RunPeriod": "1000" + }, + "Camera": { + "Name": "_Background Preview", + "EyeX": -17.0, + "EyeY": 24.0, + "EyeZ": 50.0, + "LookX": 12.0, + "LookY": -13.0, + "LookZ": -58.0, + "UpX": 0.0, + "UpY": 1.0, + "UpZ": 0.0 + }, + "ConnectorPins": [], + "NodeViews": [ + { + "Id": "2c4cdf29f078497c86b8fed323f4b77d", + "Name": "Watch", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 613.408069206988, + "Y": 243.832684826672 + }, + { + "Id": "4964a3edb14b46dd8e614d64fad42128", + "Name": "+", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 404.715400784895, + "Y": 238.891755796865 + }, + { + "Id": "77af56fb6e37432485e008870d79cb40", + "Name": "Number", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 159.40168436709547, + "Y": 106.14571181066069 + }, + { + "Id": "a603bf1480404297bea85441d71645ed", + "Name": "Number", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 157.2343691937667, + "Y": 282.8144436335819 + } + ], + "Annotations": [], + "X": 146.89726815586, + "Y": 9.96610837046791, + "Zoom": 1.05281788169755 + } +} \ No newline at end of file diff --git a/src/SampleLibraryTests/HelloDynamoSystemTests.cs b/src/SampleLibraryTests/HelloDynamoSystemTests.cs index d037dbc..9a00579 100644 --- a/src/SampleLibraryTests/HelloDynamoSystemTests.cs +++ b/src/SampleLibraryTests/HelloDynamoSystemTests.cs @@ -49,7 +49,7 @@ protected override void GetLibrariesToPreload(List libraries) // The RequiresSTA attribute is required by // NUNit to run tests that use the UI. - [Test, RequiresSTA] + [Test, Apartment(System.Threading.ApartmentState.STA)] public void HelloDynamoTest() { // HelloWorldSystemTest.dyn is a test .dyn file which diff --git a/src/SampleLibraryTests/HelloDynamoZeroTouchTests.cs b/src/SampleLibraryTests/HelloDynamoZeroTouchTests.cs index 276f774..9fcbd12 100644 --- a/src/SampleLibraryTests/HelloDynamoZeroTouchTests.cs +++ b/src/SampleLibraryTests/HelloDynamoZeroTouchTests.cs @@ -36,12 +36,15 @@ namespace SampleLibraryTests // inherit from GeometricTestBase, and you do not need // to supply a config file with the core Dynamo install // location. - + + // Wiki => https://github.com/DynamoDS/Dynamo/wiki/Writing-Unit-Test-Libraries-for-Dynamo + [TestFixture] [IsVisibleInDynamoLibrary(false)] class HelloDynamoZeroTouchTests : GeometricTestBase { [Test] + [Category("NEEDS_GEOM_LIB")] public void PassingTest() { var myObject = Point.ByCoordinates(5, 5, 5); @@ -49,6 +52,7 @@ public void PassingTest() } [Test] + [Category("NEEDS_GEOM_LIB")] public void FailingTest() { var p1 = Point.ByCoordinates(0, 0, 0); diff --git a/src/SampleLibraryTests/Properties/AssemblyInfo.cs b/src/SampleLibraryTests/Properties/AssemblyInfo.cs index 4a4e84a..2ff505a 100644 --- a/src/SampleLibraryTests/Properties/AssemblyInfo.cs +++ b/src/SampleLibraryTests/Properties/AssemblyInfo.cs @@ -1,9 +1,14 @@ -using System.Reflection; -using System.Runtime.CompilerServices; +using NUnit.Framework; +using System.Reflection; using System.Runtime.InteropServices; +using System.Threading; // General Information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. [assembly: AssemblyTitle("SampleLibraryTests")] [assembly: Guid("c3d8c6fc-62ad-4272-91a9-492be76577e5")] + +// The RequiresThread(ApartmentState.STA) attribute is required by +// NUNit to run all tests, that use the UI, on the same thread. +[assembly: RequiresThread(ApartmentState.STA)] \ No newline at end of file diff --git a/src/SampleLibraryTests/RectangleUnitsExample.dyn b/src/SampleLibraryTests/RectangleUnitsExample.dyn new file mode 100644 index 0000000..3952197 --- /dev/null +++ b/src/SampleLibraryTests/RectangleUnitsExample.dyn @@ -0,0 +1,616 @@ +{ + "Uuid": "3ac347e0-9d70-4b12-b979-f0727b83d645", + "IsCustomNode": false, + "Description": "", + "Name": "RectangleUnitsExample", + "ElementResolver": { + "ResolutionMap": {} + }, + "Inputs": [], + "Outputs": [], + "Nodes": [ + { + "ConcreteType": "Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore", + "Id": "1468a989f8d8470d8a1891ffe2a63c04", + "NodeType": "FunctionNode", + "Inputs": [ + { + "Id": "523c2c6971f34847968b5910114b17c5", + "Name": "width", + "Description": "double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + }, + { + "Id": "342cfe4682354c68bbf2b6111463608c", + "Name": "length", + "Description": "double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "c6fe1be34aa94c2c90c94a6eb687068f", + "Name": "RectangleExample", + "Description": "RectangleExample", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "FunctionSignature": "SampleZeroTouchUnits.RectangleExample.RectangleExample@double,double", + "Replication": "Auto", + "Description": "RectangleExample.RectangleExample (width: double, length: double): RectangleExample" + }, + { + "ConcreteType": "CoreNodeModels.Input.DoubleInput, CoreNodeModels", + "NumberType": "Double", + "Id": "ed3d204c241345fba0b32a7aa03ee3c9", + "NodeType": "NumberInputNode", + "Inputs": [], + "Outputs": [ + { + "Id": "d38f49da7d684924a77eeb9cc49833f9", + "Name": "", + "Description": "Double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Creates a number", + "InputValue": 10.0 + }, + { + "ConcreteType": "CoreNodeModels.Input.DoubleInput, CoreNodeModels", + "NumberType": "Double", + "Id": "c9ac861739704856bbe0adaa53c14bbf", + "NodeType": "NumberInputNode", + "Inputs": [], + "Outputs": [ + { + "Id": "f374de24406041318a14a9a45588b464", + "Name": "", + "Description": "Double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Creates a number", + "InputValue": 5.0 + }, + { + "ConcreteType": "Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore", + "Id": "c71a8875053e4e11b8caa8c89f7d2f5b", + "NodeType": "FunctionNode", + "Inputs": [ + { + "Id": "01e1ca45e9d949b39fb78704b084485c", + "Name": "rectangleExample", + "Description": "SampleZeroTouchUnits.RectangleExample", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + }, + { + "Id": "6f8baaafc728429f8816c0ca7f109688", + "Name": "targetUnit", + "Description": "Unit", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "660c8e52a9724e9eb3826e45b364304a", + "Name": "double", + "Description": "double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "FunctionSignature": "SampleZeroTouchUnits.RectangleExample.GetLength@DynamoUnits.Unit", + "Replication": "Auto", + "Description": "RectangleExample.GetLength (targetUnit: Unit): double" + }, + { + "ConcreteType": "Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore", + "Id": "225fd1f75d68410f8a3b41f589105447", + "NodeType": "FunctionNode", + "Inputs": [ + { + "Id": "a39eac5d78a045fdbbeb5ea85a7704ca", + "Name": "rectangleExample", + "Description": "SampleZeroTouchUnits.RectangleExample", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + }, + { + "Id": "0cb47f72df45457bad4583e55b88824b", + "Name": "targetUnit", + "Description": "Unit", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "7cae6a8028f24be48c1313ef8d3135b6", + "Name": "double", + "Description": "double", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "FunctionSignature": "SampleZeroTouchUnits.RectangleExample.GetWidth@DynamoUnits.Unit", + "Replication": "Auto", + "Description": "RectangleExample.GetWidth (targetUnit: Unit): double" + }, + { + "ConcreteType": "Dynamo.Graph.Nodes.ZeroTouch.DSFunction, DynamoCore", + "Id": "aa5a7e113ff94999922b1e4d14295c4d", + "NodeType": "FunctionNode", + "Inputs": [ + { + "Id": "d4d1e255723246a6b3d87c073d1c2f5e", + "Name": "rectangleExample", + "Description": "SampleZeroTouchUnits.RectangleExample", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + }, + { + "Id": "e9cdb2478e374180b9b721f30c1066ec", + "Name": "targetUnit", + "Description": "Unit", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "2bcd40f1919841f7b19d3279db495ec1", + "Name": "string", + "Description": "string", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "FunctionSignature": "SampleZeroTouchUnits.RectangleExample.GetArea@DynamoUnits.Unit", + "Replication": "Auto", + "Description": "RectangleExample.GetArea (targetUnit: Unit): string" + }, + { + "ConcreteType": "UnitsUI.Units, UnitsNodeModels", + "SelectedIndex": 25, + "SelectedString": "Centimeters", + "Id": "e4c3a5250ea4473d99bb4e046319a6bf", + "NodeType": "ExtensionNode", + "Inputs": [], + "Outputs": [ + { + "Id": "b247c85016d648ed96695930382df729", + "Name": "Unit", + "Description": "The selected Unit", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Select a Unit type" + }, + { + "ConcreteType": "UnitsUI.Units, UnitsNodeModels", + "SelectedIndex": 199, + "SelectedString": "Meters", + "Id": "f795ea681a5f496ba73ec083e8ddff00", + "NodeType": "ExtensionNode", + "Inputs": [], + "Outputs": [ + { + "Id": "a4bcecb84c4b4c42b58c8887e48441b8", + "Name": "Unit", + "Description": "The selected Unit", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Select a Unit type" + }, + { + "ConcreteType": "UnitsUI.Units, UnitsNodeModels", + "SelectedIndex": 295, + "SelectedString": "Square feet", + "Id": "69941e465d0a447482ff87f7d208fdc8", + "NodeType": "ExtensionNode", + "Inputs": [], + "Outputs": [ + { + "Id": "6fd7cb28a036466295fa375667bed5a4", + "Name": "Unit", + "Description": "The selected Unit", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Select a Unit type" + }, + { + "ConcreteType": "CoreNodeModels.Watch, CoreNodeModels", + "WatchWidth": 42.0, + "WatchHeight": 38.0, + "Id": "15b2e81d84df4a17ae348ee982ab87d9", + "NodeType": "ExtensionNode", + "Inputs": [ + { + "Id": "8958560939ac47f28472e3d20917fe1d", + "Name": "", + "Description": "Node to show output from", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "fd6fa7d1a0f84b53bc403b0bc71a0c47", + "Name": "", + "Description": "Node output", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Visualizes a node's output" + }, + { + "ConcreteType": "CoreNodeModels.Watch, CoreNodeModels", + "WatchWidth": 28.0, + "WatchHeight": 38.0, + "Id": "77e2a5bb3d464c5694f444ea1e064deb", + "NodeType": "ExtensionNode", + "Inputs": [ + { + "Id": "a4b19c323ae04f139046bf61232ffb65", + "Name": "", + "Description": "Node to show output from", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "1c4ff92ffdaa42d3b31484717ae29926", + "Name": "", + "Description": "Node output", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Visualizes a node's output" + }, + { + "ConcreteType": "CoreNodeModels.Watch, CoreNodeModels", + "WatchWidth": 170.0, + "WatchHeight": 38.0, + "Id": "bbb9d9f6be8e498e8b9cb8cae214c921", + "NodeType": "ExtensionNode", + "Inputs": [ + { + "Id": "69d539c959d04a4faaccd014bde7ca31", + "Name": "", + "Description": "Node to show output from", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Outputs": [ + { + "Id": "b6add764bf564344a4f3fa93f3108a8f", + "Name": "", + "Description": "Node output", + "UsingDefaultValue": false, + "Level": 2, + "UseLevels": false, + "KeepListStructure": false + } + ], + "Replication": "Disabled", + "Description": "Visualizes a node's output" + } + ], + "Connectors": [ + { + "Start": "c6fe1be34aa94c2c90c94a6eb687068f", + "End": "01e1ca45e9d949b39fb78704b084485c", + "Id": "40f11139baf94cc7b0a741c070987e25", + "IsHidden": "False" + }, + { + "Start": "c6fe1be34aa94c2c90c94a6eb687068f", + "End": "a39eac5d78a045fdbbeb5ea85a7704ca", + "Id": "0638b5e3dec84aef90079122f4dd20f1", + "IsHidden": "False" + }, + { + "Start": "c6fe1be34aa94c2c90c94a6eb687068f", + "End": "d4d1e255723246a6b3d87c073d1c2f5e", + "Id": "7cbc02d5c04140fd9fa2addf9a620e84", + "IsHidden": "False" + }, + { + "Start": "d38f49da7d684924a77eeb9cc49833f9", + "End": "523c2c6971f34847968b5910114b17c5", + "Id": "797a725db51c426782fd50dce6cfaada", + "IsHidden": "False" + }, + { + "Start": "f374de24406041318a14a9a45588b464", + "End": "342cfe4682354c68bbf2b6111463608c", + "Id": "6da49122485442aa8a9d605741434d4e", + "IsHidden": "False" + }, + { + "Start": "660c8e52a9724e9eb3826e45b364304a", + "End": "8958560939ac47f28472e3d20917fe1d", + "Id": "9bd621413636438dba36c0e7c2deeea2", + "IsHidden": "False" + }, + { + "Start": "7cae6a8028f24be48c1313ef8d3135b6", + "End": "a4b19c323ae04f139046bf61232ffb65", + "Id": "1d162031b0fe4401afcf5c3b69cdbf11", + "IsHidden": "False" + }, + { + "Start": "2bcd40f1919841f7b19d3279db495ec1", + "End": "69d539c959d04a4faaccd014bde7ca31", + "Id": "2a220a5a2a68450c894a8963931783a9", + "IsHidden": "False" + }, + { + "Start": "b247c85016d648ed96695930382df729", + "End": "6f8baaafc728429f8816c0ca7f109688", + "Id": "b94c50890dcb42b78188ace645d66178", + "IsHidden": "False" + }, + { + "Start": "a4bcecb84c4b4c42b58c8887e48441b8", + "End": "0cb47f72df45457bad4583e55b88824b", + "Id": "2bdf345697d6455da45a27029ed58d75", + "IsHidden": "False" + }, + { + "Start": "6fd7cb28a036466295fa375667bed5a4", + "End": "e9cdb2478e374180b9b721f30c1066ec", + "Id": "de3724ee2ce04af0b9b9e512327fe096", + "IsHidden": "False" + } + ], + "Dependencies": [], + "NodeLibraryDependencies": [ + { + "Name": "SampleZeroTouchUnits.dll", + "ReferenceType": "ZeroTouch", + "Nodes": [ + "1468a989f8d8470d8a1891ffe2a63c04", + "c71a8875053e4e11b8caa8c89f7d2f5b", + "225fd1f75d68410f8a3b41f589105447", + "aa5a7e113ff94999922b1e4d14295c4d" + ] + } + ], + "EnableLegacyPolyCurveBehavior": null, + "Thumbnail": "", + "GraphDocumentationURL": null, + "ExtensionWorkspaceData": [ + { + "ExtensionGuid": "28992e1d-abb9-417f-8b1b-05e053bee670", + "Name": "Properties", + "Version": "3.1", + "Data": {} + } + ], + "Author": "", + "Linting": { + "activeLinter": "None", + "activeLinterId": "7b75fb44-43fd-4631-a878-29f4d5d8399a", + "warningCount": 0, + "errorCount": 0 + }, + "Bindings": [], + "View": { + "Dynamo": { + "ScaleFactor": 1.0, + "HasRunWithoutCrash": true, + "IsVisibleInDynamoLibrary": true, + "Version": "3.1.0.3411", + "RunType": "Automatic", + "RunPeriod": "1000" + }, + "Camera": { + "Name": "_Background Preview", + "EyeX": -17.0, + "EyeY": 24.0, + "EyeZ": 50.0, + "LookX": 12.0, + "LookY": -13.0, + "LookZ": -58.0, + "UpX": 0.0, + "UpY": 1.0, + "UpZ": 0.0 + }, + "ConnectorPins": [], + "NodeViews": [ + { + "Id": "1468a989f8d8470d8a1891ffe2a63c04", + "Name": "RectangleExample.RectangleExample", + "IsSetAsInput": false, + "IsSetAsOutput": true, + "Excluded": false, + "ShowGeometry": true, + "X": 561.5, + "Y": 33.5 + }, + { + "Id": "ed3d204c241345fba0b32a7aa03ee3c9", + "Name": "Number", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 339.11603418889285, + "Y": 35.62147890968433 + }, + { + "Id": "c9ac861739704856bbe0adaa53c14bbf", + "Name": "Number", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 350.15809208781684, + "Y": 163.6425078591463 + }, + { + "Id": "c71a8875053e4e11b8caa8c89f7d2f5b", + "Name": "RectangleExample.GetLength", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 1053.5, + "Y": 33.5 + }, + { + "Id": "225fd1f75d68410f8a3b41f589105447", + "Name": "RectangleExample.GetWidth", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 1052.5, + "Y": 192.5 + }, + { + "Id": "aa5a7e113ff94999922b1e4d14295c4d", + "Name": "RectangleExample.GetArea", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 1063.5, + "Y": 377.5 + }, + { + "Id": "e4c3a5250ea4473d99bb4e046319a6bf", + "Name": "Units", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 626.0, + "Y": 250.0 + }, + { + "Id": "f795ea681a5f496ba73ec083e8ddff00", + "Name": "Units", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 625.0, + "Y": 383.0 + }, + { + "Id": "69941e465d0a447482ff87f7d208fdc8", + "Name": "Units", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 623.0, + "Y": 519.0 + }, + { + "Id": "15b2e81d84df4a17ae348ee982ab87d9", + "Name": "Watch", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 1431.4173995248607, + "Y": 8.41299750528276 + }, + { + "Id": "77e2a5bb3d464c5694f444ea1e064deb", + "Name": "Watch", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 1429.1072443762355, + "Y": 189.94506627386255 + }, + { + "Id": "bbb9d9f6be8e498e8b9cb8cae214c921", + "Name": "Watch", + "IsSetAsInput": false, + "IsSetAsOutput": false, + "Excluded": false, + "ShowGeometry": true, + "X": 1421.8472359898235, + "Y": 374.27115097662556 + } + ], + "Annotations": [], + "X": -42.2040696713932, + "Y": 53.81309391588489, + "Zoom": 0.5974870948157864 + } +} \ No newline at end of file diff --git a/src/SampleLibraryTests/SampleLibraryTests.csproj b/src/SampleLibraryTests/SampleLibraryTests.csproj index cbbeebd..9f52e83 100644 --- a/src/SampleLibraryTests/SampleLibraryTests.csproj +++ b/src/SampleLibraryTests/SampleLibraryTests.csproj @@ -1,143 +1,28 @@ - - - + - + Debug - AnyCPU - {933B8108-4E74-470A-86C7-4B7F633115B9} - Library - Properties SampleLibraryTests SampleLibraryTests - v4.5 - 512 - - - - true - full - false - ..\..\..\Dynamo\bin\AnyCPU\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false + + net10.0-windows + true - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\CoreNodeModels.dll - False - - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\CoreNodeModelsWpf.dll - False - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoCore.dll - False - - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\DynamoCoreWpf.dll - False - - - ..\packages\DynamoVisualProgramming.DynamoServices.1.1.0\lib\net45\DynamoServices.dll - False - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoShapeManager.dll - False - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\DynamoUnits.dll - False - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoUtilities.dll - False - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Expression.Interactions.dll - False - - - False - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Practices.Prism.dll - False - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Practices.Prism.Interactivity.dll - False - - - ..\packages\CommonServiceLocator.1.3\lib\portable-net4+sl5+netcore45+wpa81+wp8\Microsoft.Practices.ServiceLocation.dll - False - - - False - ..\packages\NUnit.2.6.3\lib\nunit.framework.dll - True - - - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\ProtoCore.dll - False - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\ProtoGeometry.dll - False - - - - - ..\packages\Prism.4.1.0.0\lib\NET40\System.Windows.Interactivity.dll - False - - - - ..\packages\DynamoVisualProgramming.Tests.1.1.0\lib\net45\SystemTestServices.dll - False - - - ..\packages\DynamoVisualProgramming.Tests.1.1.0\lib\net45\TestServices.dll - False - - - - - - AssemblySharedInfo.cs - - - - - - - - PreserveNewest + PreserveNewest + + + PreserveNewest - - - PreserveNewest + + Always - - - - - + + + + \ No newline at end of file diff --git a/src/SampleLibraryTests/Setup.cs b/src/SampleLibraryTests/Setup.cs new file mode 100644 index 0000000..c787f75 --- /dev/null +++ b/src/SampleLibraryTests/Setup.cs @@ -0,0 +1,84 @@ +using System; +using System.Collections.Generic; +using System.Configuration; +using System.Globalization; +using System.IO; +using System.Reflection; +using NUnit.Framework; + + +[SetUpFixture] +public class Setup +{ + private string moduleRootFolder; + List resolutionPaths; + + [OneTimeSetUp] + public void RunBeforeAllTests() + { + var thisDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var configPath = Path.Combine(thisDir, "TestServices.dll.config"); + + // Adjust the config file map because the config file + // might not always be in the same directory as the dll. + var map = new ExeConfigurationFileMap { ExeConfigFilename = configPath }; + var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); + + var element = config.AppSettings.Settings["DynamoBasePath"]; + moduleRootFolder = element?.Value ?? string.Empty; + + if (string.IsNullOrEmpty(moduleRootFolder)) + { + throw new Exception("Missing DynamoBasePath in TestServices.dll.config. Please set the DynamoBasePath to a valid Dynamo bin folder."); + } + else if (!File.Exists(Path.Combine(moduleRootFolder, "DynamoCore.dll"))) + { + throw new Exception("Invalid DynamoBasePath in TestServices.dll.config. Please set the DynamoBasePath to a valid Dynamo bin folder."); + } + + resolutionPaths = new List + { + // Search for nodes + Path.Combine(moduleRootFolder, "nodes") + }; + AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; ; + } + + private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) + { + try + { + var targetAssemblyName = new AssemblyName(args.Name).Name + ".dll"; + + // First check the core path + string assemblyPath = Path.Combine(moduleRootFolder, targetAssemblyName); + if (File.Exists(assemblyPath)) + { + return Assembly.LoadFrom(assemblyPath); + } + + // Then check all additional resolution paths + foreach (var resolutionPath in resolutionPaths) + { + assemblyPath = Path.Combine(resolutionPath, targetAssemblyName); + if (File.Exists(assemblyPath)) + { + return Assembly.LoadFrom(assemblyPath); + } + } + + return null; + } + catch (Exception ex) + { + throw new Exception(string.Format("There location of the assembly, " + + "{0} could not be resolved for loading.", args.Name), ex); + } + } + + [OneTimeTearDown] + public void RunAfterAllTests() + { + AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve; + } +} diff --git a/src/SampleLibraryTests/TestServices.dll.config b/src/SampleLibraryTests/TestServices.dll.config index 778f995..fb4d682 100644 --- a/src/SampleLibraryTests/TestServices.dll.config +++ b/src/SampleLibraryTests/TestServices.dll.config @@ -1,7 +1,7 @@ - + - - - - - \ No newline at end of file + + + + + diff --git a/src/SampleLibraryTests/ZeroTouchUnitsSystemTests.cs b/src/SampleLibraryTests/ZeroTouchUnitsSystemTests.cs new file mode 100644 index 0000000..1e56dd7 --- /dev/null +++ b/src/SampleLibraryTests/ZeroTouchUnitsSystemTests.cs @@ -0,0 +1,80 @@ +using System.Collections.Generic; +using SystemTestServices; + +using Autodesk.DesignScript.Runtime; +using Dynamo.Graph.Nodes.ZeroTouch; +using Dynamo.Tests; + +using NUnit.Framework; + +namespace SampleLibraryTests +{ + /// + /// ZeroTouchUnitsSystemTests is a test fixture that contains + /// system tests for Dynamo using Units APIs. System tests test the entire + /// Dynamo system including the UI. They do this by starting + /// a session of Dynamo, then opening .dyn files, executing them + /// and comparing the values returned from Dynamo with those + /// stored on our test class. + /// + /// IMPORTANT! + /// System tests have dependencies on Dynamo core dlls. In + /// order for these tests to work, your test dll needs to be + /// located in the Dynamo core directory. The project currently assumes + /// that Dynamo is built in a directory adjacent to the DynamoSamples + /// repository, so a relative path is set to the debug build folder for Dynamo. + /// If your setup is different, then you will need to explicitly set the output path + /// to your Dynamo installation directory. + /// + [TestFixture] + + public class ZeroTouchUnitsSystemTests : SystemTestBase + { + protected override void GetLibrariesToPreload(List libraries) + { + libraries.Add("FunctionObject.ds"); + libraries.Add("BuiltIn.ds"); + libraries.Add("DSCoreNodes.dll"); + libraries.Add("VMDataBridge.dll"); + libraries.Add("DynamoConversions.dll"); + libraries.Add("DynamoUnits.dll"); + libraries.Add("DesignScriptBuiltin.dll"); + libraries.Add("..\\..\\..\\..\\dynamo_package\\Dynamo Samples\\bin\\SampleZeroTouchUnits.dll"); + base.GetLibrariesToPreload(libraries); + } + + // The RequiresSTA attribute is required by + // NUNit to run tests that use the UI. + [Test, Apartment(System.Threading.ApartmentState.STA)] + public void HelloRectangleUnitsTest() + { + // RectangleUnitsExample.dyn is a test .dyn file which + // should be copied to the output directory, so it's available + // for testing. You can also change this path to anywhere you + // would like to get your test file from, but it has to be + // a relative path from the dynamo core directory (the working directory). + + OpenAndRunDynamoDefinition(@".\RectangleUnitsExample.dyn"); + + // Ensure that the graph opened without any "dummy nodes". + // Dummy nodes would appear if your graph had a node that + // could not be found in the library. + + AssertNoDummyNodes(); + + // Get the nodes from the workspace. + var out1 = Model.CurrentWorkspace.NodeFromWorkspace("{15b2e81d-84df-4a17-ae34-8ee982ab87d9}") as CoreNodeModels.Watch; + var out2 = Model.CurrentWorkspace.NodeFromWorkspace("{77e2a5bb-3d46-4c56-94f4-44ea1e064deb}") as CoreNodeModels.Watch; + var out3 = Model.CurrentWorkspace.NodeFromWorkspace("{bbb9d9f6-be8e-498e-8b9c-b8cae214c921}") as CoreNodeModels.Watch; + Assert.NotNull(out1); + Assert.NotNull(out2); + Assert.NotNull(out3); + + // Ensure that the value of that node after evaluation is + // the value that we are looking for. + Assert.AreEqual(out1.CachedValue, 500); + Assert.AreEqual(out2.CachedValue, 5); + Assert.AreEqual(out3.CachedValue, "538.195520835486ft^2"); + } + } +} diff --git a/src/SampleLibraryTests/app.config b/src/SampleLibraryTests/app.config deleted file mode 100644 index 3109856..0000000 --- a/src/SampleLibraryTests/app.config +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/src/SampleLibraryTests/packages.config b/src/SampleLibraryTests/packages.config deleted file mode 100644 index b2c92eb..0000000 --- a/src/SampleLibraryTests/packages.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/SampleLibraryUI/Controls/ButtonControl.xaml b/src/SampleLibraryUI/Controls/ButtonControl.xaml new file mode 100644 index 0000000..8bfd8ce --- /dev/null +++ b/src/SampleLibraryUI/Controls/ButtonControl.xaml @@ -0,0 +1,17 @@ + + + + + + + + \ No newline at end of file diff --git a/src/SampleLibraryUI/Controls/HelloDynamoControl.xaml.cs b/src/SampleLibraryUI/Controls/ButtonControl.xaml.cs similarity index 54% rename from src/SampleLibraryUI/Controls/HelloDynamoControl.xaml.cs rename to src/SampleLibraryUI/Controls/ButtonControl.xaml.cs index b0bf80b..e83d391 100644 --- a/src/SampleLibraryUI/Controls/HelloDynamoControl.xaml.cs +++ b/src/SampleLibraryUI/Controls/ButtonControl.xaml.cs @@ -3,11 +3,11 @@ namespace SampleLibraryUI.Controls { /// - /// Interaction logic for HellowDynamoControl.xaml + /// Interaction logic for ButtonDynamoControl.xaml /// - public partial class HelloDynamoControl : UserControl + public partial class ButtonControl : UserControl { - public HelloDynamoControl() + public ButtonControl() { InitializeComponent(); } diff --git a/src/SampleLibraryUI/Controls/HelloDynamoControl.xaml b/src/SampleLibraryUI/Controls/HelloDynamoControl.xaml deleted file mode 100644 index 4c335d9..0000000 --- a/src/SampleLibraryUI/Controls/HelloDynamoControl.xaml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - diff --git a/src/SampleLibraryUI/Controls/SliderControl.xaml b/src/SampleLibraryUI/Controls/SliderControl.xaml new file mode 100644 index 0000000..7239623 --- /dev/null +++ b/src/SampleLibraryUI/Controls/SliderControl.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/SampleLibraryUI/Controls/SliderControl.xaml.cs b/src/SampleLibraryUI/Controls/SliderControl.xaml.cs new file mode 100644 index 0000000..2751ebc --- /dev/null +++ b/src/SampleLibraryUI/Controls/SliderControl.xaml.cs @@ -0,0 +1,17 @@ +using System.Windows.Controls; + +namespace SampleLibraryUI.Controls +{ + /// + /// Interaction logic for SliderControl.xaml + /// + public partial class SliderControl : UserControl + { + public SliderControl() + { + InitializeComponent(); + } + + private void Slider_ValueChanged(object sender, System.Windows.RoutedPropertyChangedEventArgs e){ } + } +} diff --git a/src/SampleLibraryUI/Examples/ButtonCustomNodeModel.cs b/src/SampleLibraryUI/Examples/ButtonCustomNodeModel.cs new file mode 100644 index 0000000..89b14ec --- /dev/null +++ b/src/SampleLibraryUI/Examples/ButtonCustomNodeModel.cs @@ -0,0 +1,339 @@ +using System; +using System.Collections.Generic; +using System.Collections; +using System.Windows; +using System.Linq; +using Autodesk.DesignScript.Runtime; +using Dynamo.Controls; +using Dynamo.Graph.Nodes; +using Dynamo.UI.Commands; +using Dynamo.Wpf; +using ProtoCore.AST.AssociativeAST; +using SampleLibraryUI.Controls; +using SampleLibraryZeroTouch; +using Newtonsoft.Json; + +namespace SampleLibraryUI.Examples +{ + /* + * This exmple shows how to create a UI node for Dynamo + * which loads custom data-bound UI into the node's view + * at run time. + + * Dynamo uses the MVVM model of programming, + * in which the UI is data-bound to the view model, which + * exposes data from the underlying model. Custom UI nodes + * are a hybrid because NodeModel objects already have an + * associated NodeViewModel which you should never need to + * edit. So here we will create a data binding between + * properties on our class and our custom UI. + */ + + // The NodeName attribute is what will display on + // top of the node in Dynamo + [NodeName("Button Custom Node Model")] + // The NodeCategory attribute determines how your + // node will be organized in the library. You can + // specify your own category or by default the class + // structure will be used. You can no longer + // add packages or custom nodes to one of the + // built-in OOTB library categories. + [NodeCategory("SampleLibraryUI.Examples")] + // The description will display in the tooltip + // and in the help window for the node. + [NodeDescription("A sample UI node which displays custom UI.")] + // Specifying InPort and OutPort types simply + // adds these types to the help window for the + // node when hovering the name in the library. + [InPortTypes("string")] + [OutPortTypes("string")] + // Add the IsDesignScriptCompatible attribute to ensure + // that it gets loaded in Dynamo. + [IsDesignScriptCompatible] + public class ButtonCustomNodeModel : NodeModel + { + #region private members + + private string buttonText; + private string windowText; + private const string defaultButtonText = "Default Button Text"; + private const string defaultWindowText = "Default Window Text"; + + #endregion + + #region properties + + /// + /// Text that will appear on the button + /// on our node. + /// + public string ButtonText + { + get { return buttonText; } + set + { + buttonText = value; + + // Raise a property changed notification + // to alert the UI that an element needs + // an update. + RaisePropertyChanged("ButtonText"); + } + } + + /// + /// Text that will appear in the message + /// box when button is pressed. + /// + public string WindowText + { + get { return windowText; } + set + { + windowText = value; + } + } + + /// + /// DelegateCommand objects allow you to bind + /// UI interaction to methods on your data context. + /// + [JsonIgnore] + [IsVisibleInDynamoLibrary(false)] + public DelegateCommand ButtonCommand { get; set; } + + #endregion + + #region constructor + + /// + /// The constructor for a NodeModel is used to create + /// the input and output ports and specify the argument + /// lacing. It gets invoked when the node is added to + /// the graph from the library or through copy/paste. + /// + 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; + } + + // Starting with Dynamo v2.0 you must add Json constructors for all nodeModel + // dervived nodes to support the move from an Xml to Json file format. Failing to + // do so will result in incorrect ports being generated upon serialization/deserialization. + // This constructor is called when opening a Json graph. + [JsonConstructor] + ButtonCustomNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts) + { + this.PortDisconnected += ButtonCustomNodeModel_PortDisconnected; + ButtonCommand = new DelegateCommand(ShowMessage, CanShowMessage); + } + + // Restore default button/window text and trigger UI update + private void ButtonCustomNodeModel_PortDisconnected(PortModel obj) + { + ButtonText = defaultButtonText; + WindowText = defaultWindowText; + RaisePropertyChanged("ButtonText"); + } + + #endregion + + // Use the VMDataBridge to safely retrieve our input values + #region databridge callback + /// + /// Register the data bridge callback. + /// + protected override void OnBuilt() + { + base.OnBuilt(); + VMDataBridge.DataBridge.Instance.RegisterCallback(GUID.ToString(), DataBridgeCallback); + } + + /// + /// Unregister the data bridge callback. + /// + public override void Dispose() + { + base.Dispose(); + VMDataBridge.DataBridge.Instance.UnregisterCallback(GUID.ToString()); + } + + /// + /// Callback method for DataBridge mechanism. + /// This callback only gets called when + /// - The AST is executed + /// - After the BuildOutputAST function is executed + /// - The AST is fully built + /// + /// The data passed through the data bridge. + private void DataBridgeCallback(object data) + { + ArrayList inputs = data as ArrayList; + string inputText = ""; + foreach (var input in inputs) + { + inputText += input.ToString() + " "; + } + + WindowText = ("Data bridge callback of node " + GUID.ToString().Substring(0, 5) + ": " + inputText); + ButtonText = inputText; + } + #endregion + + #region public methods + + /// + /// BuildOutputAst is where the outputs of this node are calculated. + /// This method is used to do the work that a compiler usually does + /// by parsing the inputs List inputAstNodes into an abstract syntax tree. + /// + /// + /// + [IsVisibleInDynamoLibrary(false)] + public override IEnumerable BuildOutputAst(List inputAstNodes) + { + // When you create your own UI node you are responsible + // for generating the abstract syntax tree (AST) nodes which + // specify what methods are called, or how your data is passed + // when execution occurs. + + // WARNING!!! + // Do not throw an exception during AST creation. If you + // need to convey a failure of this node, then use + // AstFactory.BuildNullNode to pass out null. + + // If inputs are not connected return null + if (!InPorts[0].Connectors.Any()) + { + return new[] + { + AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), AstFactory.BuildNullNode()), + AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(1), AstFactory.BuildNullNode()), + }; + } + + // A FunctionCallNode can be used to represent the calling of a + // function in the AST. The method specified here must live in + // a separate assembly (in our case SampleUtilities) and have + // been loaded by Dynamo at the time that this AST is built. + // If the method can't be found, you'll get a "De-referencing a + // non -pointer warning." + + AssociativeNode buttonFuncNode = + AstFactory.BuildFunctionCall( + new Func(SampleUtilities.DescribeButtonMessage), + new List { inputAstNodes[0] }); + + AssociativeNode windowFuncNode = + AstFactory.BuildFunctionCall( + new Func(SampleUtilities.DescribeWindowMessage), + new List { AstFactory.BuildStringNode(GUID.ToString()), inputAstNodes[0] }); + + // Using the AstFactory class, we can build AstNode objects + // that assign doubles, assign function calls, build expression lists, etc. + return new[] + { + // In these assignments, GetAstIdentifierForOutputIndex finds + // the unique identifier which represents an output on this node + // and 'assigns' that variable the expression that you create. + + AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(0), buttonFuncNode), + AstFactory.BuildAssignment( + AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"), + VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes))), + + AstFactory.BuildAssignment(GetAstIdentifierForOutputIndex(1), windowFuncNode), + AstFactory.BuildAssignment( + AstFactory.BuildIdentifier(AstIdentifierBase + "_dummy"), + VMDataBridge.DataBridge.GenerateBridgeDataAst(GUID.ToString(), AstFactory.BuildExprList(inputAstNodes))) + }; + } + + #endregion + + #region command methods + private bool CanShowMessage(object obj) + { + return true; + } + + private void ShowMessage(object obj) + { + MessageBox.Show(WindowText); + } + + #endregion + } + + /// + /// View customizer for CustomNodeModel Node Model. + /// + public class ButtonCustomNodeModelNodeViewCustomization : INodeViewCustomization + { + /// + /// At run-time, this method is called during the node + /// creation. Here you can create custom UI elements and + /// add them to the node view, but we recommend designing + /// your UI declaratively using xaml, and binding it to + /// properties on this node as the DataContext. + /// + /// The NodeModel representing the node's core logic. + /// The NodeView representing the node in the graph. + public void CustomizeView(ButtonCustomNodeModel model, NodeView nodeView) + { + // The view variable is a reference to the node's view. + // In the middle of the node is a grid called the InputGrid. + // We reccommend putting your custom UI in this grid, as it has + // been designed for this purpose. + + // Create an instance of our custom UI class (defined in xaml), + // and put it into the input grid. + var buttonControl = new ButtonControl(); + nodeView.inputGrid.Children.Add(buttonControl); + + // Set the data context for our control to be the node model. + // Properties in this class which are data bound will raise + // property change notifications which will update the UI. + buttonControl.DataContext = model; + } + + /// + /// Here you can do any cleanup you require if you've assigned callbacks for particular + /// UI events on your node. + /// + public void Dispose() { } + } + +} diff --git a/src/SampleLibraryUI/Examples/DropDown.cs b/src/SampleLibraryUI/Examples/DropDown.cs index c66c803..71f8f64 100644 --- a/src/SampleLibraryUI/Examples/DropDown.cs +++ b/src/SampleLibraryUI/Examples/DropDown.cs @@ -3,6 +3,7 @@ using Dynamo.Graph.Nodes; using Dynamo.Utilities; using ProtoCore.AST.AssociativeAST; +using Newtonsoft.Json; namespace SampleLibraryUI.Examples { @@ -13,6 +14,14 @@ public class DropDownExample : DSDropDownBase { public DropDownExample() : base("item"){} + // Starting with Dynamo v2.0 you must add Json constructors for all nodeModel + // derived nodes to support the move from an Xml to Json file format. Failing to + // do so will result in incorrect ports being generated upon serialization/deserialization. + // This constructor is called when opening a Json graph. We must also pass the deserialized + // ports with the json constructor and then call the base class passing the ports as parameters. + [JsonConstructor] + public DropDownExample(IEnumerable inPorts, IEnumerable outPorts) : base("item", inPorts, outPorts) { } + protected override SelectionState PopulateItemsCore(string currentSelection) { // The Items collection contains the elements @@ -40,7 +49,7 @@ protected override SelectionState PopulateItemsCore(string currentSelection) // has a pre-selection. SelectedIndex = 0; - return SelectionState.Done; + return SelectionState.Restore; } public override IEnumerable BuildOutputAst(List inputAstNodes) diff --git a/src/SampleLibraryUI/Examples/LocalizedCustomNodeModel.cs b/src/SampleLibraryUI/Examples/LocalizedCustomNodeModel.cs new file mode 100644 index 0000000..ddbeb50 --- /dev/null +++ b/src/SampleLibraryUI/Examples/LocalizedCustomNodeModel.cs @@ -0,0 +1,40 @@ +using Dynamo.Graph.Nodes; +using Newtonsoft.Json; +using ProtoCore.AST.AssociativeAST; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace SampleLibraryUI.Examples +{ + /// + /// This example node uses .net .resx files and generated satellite assemblies to perform runtime lookup of localized content + /// depending on the culture of the system Dynamo is running on. + /// Read more: https://docs.microsoft.com/en-us/dotnet/framework/resources/creating-resource-files-for-desktop-apps + /// You can use the -l "es-ES" flag when starting DynamoSandbox.exe to replace the English strings with Spanish ones. + /// For more info on the CLI interface read more: https://github.com/DynamoDS/Dynamo/wiki/Dynamo-Command-Line-Interface + /// + [NodeName("LocalizedNode")] + [NodeDescription("CustomNodeModelDescription", typeof(Properties.Resources))] + [OutPortNames("string")] + [OutPortTypes("string")] + [IsDesignScriptCompatible] + public class LocalizedCustomNodeModel : NodeModel + { + public LocalizedCustomNodeModel() + { + RegisterAllPorts(); + } + + [JsonConstructor] + public LocalizedCustomNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts) { } + + public override IEnumerable BuildOutputAst(List inputAstNodes) + { + //return a localized string, that is defined in the resx file/resource assembly. + return new List { AstFactory.BuildAssignment(this.AstIdentifierForPreview, AstFactory.BuildPrimitiveNodeFromObject(Properties.Resources.LocalStringResult)) }; + } + } +} diff --git a/src/SampleLibraryUI/Examples/CustomNodeModel.cs b/src/SampleLibraryUI/Examples/SliderCustomNodeModel.cs similarity index 63% rename from src/SampleLibraryUI/Examples/CustomNodeModel.cs rename to src/SampleLibraryUI/Examples/SliderCustomNodeModel.cs index be308a8..1b8a93c 100644 --- a/src/SampleLibraryUI/Examples/CustomNodeModel.cs +++ b/src/SampleLibraryUI/Examples/SliderCustomNodeModel.cs @@ -10,6 +10,7 @@ using SampleLibraryUI.Controls; using SampleLibraryUI.Properties; using SampleLibraryZeroTouch; +using Newtonsoft.Json; namespace SampleLibraryUI.Examples { @@ -34,27 +35,30 @@ namespace SampleLibraryUI.Examples // The NodeName attribute is what will display on // top of the node in Dynamo - [NodeName("Custom Node Model")] - + [NodeName("Slider Custom Node Model")] // The NodeCategory attribute determines how your // node will be organized in the library. You can - // specify your own category or use one of the - // built-ins provided in BuiltInNodeCategories. + // specify your own category or by default the class + // structure will be used. You can no longer + // add packages or custom nodes to one of the + // built-in OOTB library categories. [NodeCategory("SampleLibraryUI.Examples")] - // The description will display in the tooltip // and in the help window for the node. - [NodeDescription("CustomNodeModelDescription",typeof(SampleLibraryUI.Properties.Resources))] - + [NodeDescription("A sample UI node which displays custom UI.")] + // Specifying InPort and OutPort types simply + // adds these types to the help window for the + // node when hovering the name in the library. + //[InPortTypes("double")] + [OutPortTypes("double", "double")] // Add the IsDesignScriptCompatible attribute to ensure // that it gets loaded in Dynamo. [IsDesignScriptCompatible] - public class CustomNodeModel : NodeModel + public class SliderCustomNodeModel : NodeModel { #region private members - private string message; - private double awesome; + private double sliderValue; #endregion @@ -62,45 +66,20 @@ public class CustomNodeModel : NodeModel /// /// A value that will be bound to our - /// custom UI's awesome slider. + /// custom UI's slider. /// - public double Awesome + public double SliderValue { - get { return awesome; } + get { return sliderValue; } set { - awesome = value; - RaisePropertyChanged("Awesome"); + sliderValue = value; + RaisePropertyChanged("SliderValue"); OnNodeModified(); } } - /// - /// A message that will appear on the button - /// on our node. - /// - public string Message - { - get { return message; } - set - { - message = value; - - // Raise a property changed notification - // to alert the UI that an element needs - // an update. - RaisePropertyChanged("NodeMessage"); - } - } - - /// - /// DelegateCommand objects allow you to bind - /// UI interaction to methods on your data context. - /// - [IsVisibleInDynamoLibrary(false)] - public DelegateCommand MessageCommand { get; set; } - #endregion #region constructor @@ -108,20 +87,20 @@ public string Message /// /// The constructor for a NodeModel is used to create /// the input and output ports and specify the argument - /// lacing. + /// lacing. It gets invoked when the node is added to + /// the graph from the library or through copy/paste. /// - public CustomNodeModel() + public SliderCustomNodeModel() { // 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 InPortData and the OutPortData + // you can populate the InPorts and the OutPorts // collections with PortData objects describing your ports. - InPortData.Add(new PortData("something", Resources.CustomNodeModePortDataInputToolTip)); // Nodes can have an arbitrary number of inputs and outputs. // If you want more ports, just create more PortData objects. - OutPortData.Add(new PortData("something", Resources.CustomNodeModePortDataOutputToolTip)); - OutPortData.Add(new PortData("some awesome", Resources.CustomNodeModePortDataOutputToolTip)); + OutPorts.Add(new PortModel(PortType.Output, this, new PortData("upper value", "returns a 0-10 double value"))); + OutPorts.Add(new PortModel(PortType.Output, this, new PortData("lower value", "returns a 0-100 double value"))); // This call is required to ensure that your ports are // properly created. @@ -130,30 +109,27 @@ public CustomNodeModel() // 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.CrossProduct; - - // We create a DelegateCommand object which will be - // bound to our button in our custom UI. Clicking the button - // will call the ShowMessage method. - MessageCommand = new DelegateCommand(ShowMessage, CanShowMessage); + ArgumentLacing = LacingStrategy.Disabled; - // Setting our property here will trigger a - // property change notification and the UI - // will be updated to reflect the new value. - Message = "Say 'Hello Dynamo!'"; - - Awesome = 1; + // Set initial slider value. + sliderValue = 4; } + // Starting with Dynamo v2.0 you must add Json constructors for all nodeModel + // dervived nodes to support the move from an Xml to Json file format. Failing to + // do so will result in incorrect ports being generated upon serialization/deserialization. + // This constructor is called when opening a Json graph. + [JsonConstructor] + SliderCustomNodeModel(IEnumerable inPorts, IEnumerable outPorts) : base(inPorts, outPorts) { } + #endregion #region public methods /// - /// If this method is not overriden, Dynamo will, by default - /// pass data through this node. But we wouldn't be here if - /// we just wanted to pass data through the node, so let's - /// try using the data. + /// BuildOutputAst is where the outputs of this node are calculated. + /// This method is used to do the work that a compiler usually does + /// by parsing the inputs List inputAstNodes into an abstract syntax tree. /// /// /// @@ -170,10 +146,10 @@ public override IEnumerable BuildOutputAst(List BuildOutputAst(List /// View customizer for CustomNodeModel Node Model. /// - public class CustomNodeModelNodeViewCustomization : INodeViewCustomization + public class SliderCustomNodeModelNodeViewCustomization : INodeViewCustomization { /// /// At run-time, this method is called during the node @@ -239,7 +198,7 @@ public class CustomNodeModelNodeViewCustomization : INodeViewCustomization /// The NodeModel representing the node's core logic. /// The NodeView representing the node in the graph. - public void CustomizeView(CustomNodeModel model, NodeView nodeView) + public void CustomizeView(SliderCustomNodeModel model, NodeView nodeView) { // The view variable is a reference to the node's view. // In the middle of the node is a grid called the InputGrid. @@ -248,13 +207,13 @@ public void CustomizeView(CustomNodeModel model, NodeView nodeView) // Create an instance of our custom UI class (defined in xaml), // and put it into the input grid. - var helloDynamoControl = new HelloDynamoControl(); - nodeView.inputGrid.Children.Add(helloDynamoControl); + var sliderControl = new SliderControl(); + nodeView.inputGrid.Children.Add(sliderControl); - // Set the data context for our control to be this class. + // Set the data context for our control to be the node model. // Properties in this class which are data bound will raise // property change notifications which will update the UI. - helloDynamoControl.DataContext = model; + sliderControl.DataContext = model; } /// diff --git a/src/SampleLibraryUI/Properties/Resources.Designer.cs b/src/SampleLibraryUI/Properties/Resources.Designer.cs index ddab141..71c1820 100644 --- a/src/SampleLibraryUI/Properties/Resources.Designer.cs +++ b/src/SampleLibraryUI/Properties/Resources.Designer.cs @@ -1,90 +1,99 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace SampleLibraryUI.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleLibraryUI.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized string similar to A sample UI node which displays custom UI.. - /// - internal static string CustomNodeModeDescription { - get { - return ResourceManager.GetString("CustomNodeModeDescription", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to Input a string.. - /// - internal static string CustomNodeModePortDataInputToolTip { - get { - return ResourceManager.GetString("CustomNodeModePortDataInputToolTip", resourceCulture); - } - } - - /// - /// Looks up a localized string similar to A result.. - /// - internal static string CustomNodeModePortDataOutputToolTip { - get { - return ResourceManager.GetString("CustomNodeModePortDataOutputToolTip", resourceCulture); - } - } - } -} +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleLibraryUI.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleLibraryUI.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to A sample UI node which displays custom UI.. + /// + internal static string CustomNodeModelDescription { + get { + return ResourceManager.GetString("CustomNodeModelDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Input a string.. + /// + internal static string CustomNodeModelPortDataInputToolTip { + get { + return ResourceManager.GetString("CustomNodeModelPortDataInputToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to A result.. + /// + internal static string CustomNodeModelPortDataOutputToolTip { + get { + return ResourceManager.GetString("CustomNodeModelPortDataOutputToolTip", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to I am a localized string.. + /// + internal static string LocalStringResult { + get { + return ResourceManager.GetString("LocalStringResult", resourceCulture); + } + } + } +} diff --git a/src/SampleLibraryUI/Properties/Resources.en-US.resx b/src/SampleLibraryUI/Properties/Resources.en-US.resx index 8a1ae88..19f8875 100644 --- a/src/SampleLibraryUI/Properties/Resources.en-US.resx +++ b/src/SampleLibraryUI/Properties/Resources.en-US.resx @@ -127,4 +127,7 @@ A result. + + I am a localized string. + \ No newline at end of file diff --git a/src/SampleLibraryUI/Properties/Resources.es-ES.resx b/src/SampleLibraryUI/Properties/Resources.es-ES.resx new file mode 100644 index 0000000..4881840 --- /dev/null +++ b/src/SampleLibraryUI/Properties/Resources.es-ES.resx @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Un nodo de interfaz de usuario de muestra que muestra una interfaz de usuario personalizada. + + + Soy una cadena localizada. + + \ No newline at end of file diff --git a/src/SampleLibraryUI/Properties/Resources.resx b/src/SampleLibraryUI/Properties/Resources.resx index bacdc06..fcea6be 100644 --- a/src/SampleLibraryUI/Properties/Resources.resx +++ b/src/SampleLibraryUI/Properties/Resources.resx @@ -117,14 +117,17 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + A sample UI node which displays custom UI. Description for Hello Dynamo - + Input a string. - + A result. + + I am a localized string. + \ No newline at end of file diff --git a/src/SampleLibraryUI/Resources/LargeIcons/SampleLibraryUI.Examples.DropDownExample.Large.png b/src/SampleLibraryUI/Resources/LargeIcons/SampleLibraryUI.Examples.DropDownExample.Large.png new file mode 100644 index 0000000..778a21e Binary files /dev/null and b/src/SampleLibraryUI/Resources/LargeIcons/SampleLibraryUI.Examples.DropDownExample.Large.png differ diff --git a/src/SampleLibraryUI/Resources/SampleLibraryUI.Designer.cs b/src/SampleLibraryUI/Resources/SampleLibraryUI.Designer.cs new file mode 100644 index 0000000..372832f --- /dev/null +++ b/src/SampleLibraryUI/Resources/SampleLibraryUI.Designer.cs @@ -0,0 +1,83 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleLibraryUI.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class SampleLibraryUI { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal SampleLibraryUI() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleLibraryUI.Resources.SampleLibraryUI", typeof(SampleLibraryUI).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + public static byte[] SampleLibraryUI_Examples_DropDownExample_Large { + get { + object obj = ResourceManager.GetObject("SampleLibraryUI.Examples.DropDownExample.Large", resourceCulture); + return ((byte[])(obj)); + } + } + + /// + /// Looks up a localized resource of type System.Byte[]. + /// + public static byte[] SampleLibraryUI_Examples_DropDownExample_Small { + get { + object obj = ResourceManager.GetObject("SampleLibraryUI.Examples.DropDownExample.Small", resourceCulture); + return ((byte[])(obj)); + } + } + } +} diff --git a/src/SampleLibraryUI/Resources/SampleLibraryUI.resx b/src/SampleLibraryUI/Resources/SampleLibraryUI.resx new file mode 100644 index 0000000..fe16409 --- /dev/null +++ b/src/SampleLibraryUI/Resources/SampleLibraryUI.resx @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + .\LargeIcons\SampleLibraryUI.Examples.DropDownExample.Large.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + .\SmallIcons\SampleLibraryUI.Examples.DropDownExample.Small.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/SampleLibraryUI/Resources/SampleLibraryUIImages.resources b/src/SampleLibraryUI/Resources/SampleLibraryUIImages.resources new file mode 100644 index 0000000..7fb109a Binary files /dev/null and b/src/SampleLibraryUI/Resources/SampleLibraryUIImages.resources differ diff --git a/src/SampleLibraryUI/Resources/SmallIcons/SampleLibraryUI.Examples.DropDownExample.Small.png b/src/SampleLibraryUI/Resources/SmallIcons/SampleLibraryUI.Examples.DropDownExample.Small.png new file mode 100644 index 0000000..10dea6c Binary files /dev/null and b/src/SampleLibraryUI/Resources/SmallIcons/SampleLibraryUI.Examples.DropDownExample.Small.png differ diff --git a/src/SampleLibraryUI/SampleLibraryUI.csproj b/src/SampleLibraryUI/SampleLibraryUI.csproj index fa23ed1..2e6a516 100644 --- a/src/SampleLibraryUI/SampleLibraryUI.csproj +++ b/src/SampleLibraryUI/SampleLibraryUI.csproj @@ -1,182 +1,54 @@ - - - + - + - en-US - - - Debug - AnyCPU - {0A4B4EEA-8FAB-4AC8-90D4-27DBC5B0CF2A} - Library - Properties SampleLibraryUI SampleLibraryUI - v4.5 - 512 - - - - true - full - false - bin\Debug\ - TRACE;DEBUG - prompt - 4 - bin\Debug\$(UICulture)\SampleLibraryUI.XML - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\$(UICulture)\SampleLibraryUI.XML - false + + net10.0-windows + true + + + true + bin\$(Configuration)\$(UICulture)\SampleLibraryUI.XML - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\CoreNodeModels.dll - True - - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\CoreNodeModelsWpf.dll - True - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoCore.dll - True - - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\DynamoCoreWpf.dll - True - - - ..\packages\DynamoVisualProgramming.DynamoServices.1.1.0\lib\net45\DynamoServices.dll - True - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoShapeManager.dll - True - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\DynamoUnits.dll - True - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoUtilities.dll - True - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Expression.Interactions.dll - False - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Practices.Prism.dll - False - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Practices.Prism.Interactivity.dll - False - - - ..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll - False - - - ..\packages\NUnit.2.6.3\lib\nunit.framework.dll - False - - - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\ProtoCore.dll - True - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\ProtoGeometry.dll - True - - - - - ..\packages\Prism.4.1.0.0\lib\NET40\System.Windows.Interactivity.dll + + {bd13c4dc-9045-4e49-b637-b6182b0e3a7f} + SampleLibraryZeroTouch False - - - - - - - AssemblySharedInfo.cs - - - HelloDynamoControl.xaml - - - - - - True - True - Resources.resx - - - True - True - Resources.en-US.resx - + - - Designer - MSBuild:Compile - + - - ResXFileCodeGenerator - Resources.Designer.cs - - - PublicResXFileCodeGenerator - Resources.en-US.Designer.cs - + + + - - + + - - {bd13c4dc-9045-4e49-b637-b6182b0e3a7f} - SampleLibraryZeroTouch - False - + + + - - - - - - - - - - - - + + + + + - - + + + - + + \ No newline at end of file diff --git a/src/SampleLibraryUI/app.config b/src/SampleLibraryUI/app.config deleted file mode 100644 index 09682f5..0000000 --- a/src/SampleLibraryUI/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/src/SampleLibraryUI/packages.config b/src/SampleLibraryUI/packages.config deleted file mode 100644 index 96b753c..0000000 --- a/src/SampleLibraryUI/packages.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/SampleLibraryZeroTouch/Examples/BasicExample.cs b/src/SampleLibraryZeroTouch/Examples/BasicExample.cs index 42e14d0..f26cd38 100644 --- a/src/SampleLibraryZeroTouch/Examples/BasicExample.cs +++ b/src/SampleLibraryZeroTouch/Examples/BasicExample.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; -using System.Runtime.Remoting.Metadata.W3cXsd2001; using Autodesk.DesignScript.Geometry; using Autodesk.DesignScript.Interfaces; using Autodesk.DesignScript.Runtime; -namespace SampleLibraryZeroTouch.Examples +namespace Examples { /// /// The HelloDynamoZeroTouch class demonstrates @@ -119,16 +118,19 @@ public static BasicExample Create(double x=42.0, double y=42.0, double z=42.0) /// /// A point. /// A BasicExample object. - public static BasicExample Create([DefaultArgumentAttribute("Point.ByCoordinates(5,5,5);")]Point point) + public static BasicExample Create([DefaultArgumentAttribute("Autodesk.DesignScript.Geometry.Point.ByCoordinates(5,5,5);")]Point point) { return new BasicExample(point.X, point.Y, point.Z); } /// /// The MultiReturn attribute can be used to specify - /// the names of multiple output ports on a node that - /// returns a dictionary. The node must return a dictionary - /// to be recognized as a multi-out node. + /// that a node is a multi-out node. This node must return + /// a Dictionary with its keys matching the attributes specified in the + /// MultiReturn attribute. The names of the output ports + /// match the attribute names if there are no XML returns tags. + /// The returned dictionary displayed in the node preview is displayed + /// in the order of its keys as specified in the MultiReturn attribute. /// /// [MultiReturn(new[] { "thing 1", "thing 2" })] @@ -141,6 +143,30 @@ public static Dictionary> MultiReturnExample() }; } + /// + /// The MultiReturn attribute can be used to specify + /// that a node is a multi-out node. This node must return + /// a Dictionary with its keys matching the attributes specified in the + /// MultiReturn attribute. The names of the output ports + /// match the XML returns tag only if they include descriptions. + /// Otherwise the output ports will match the attribute names. + /// The returned dictionary displayed in the node preview is displayed + /// in the order of its keys as specified in the MultiReturn attribute. + /// E.g. this node will display "thing one" and "thing two" in its output ports + /// but it will show "thing 1" and "thing 2" in the node preview. + /// + /// first thing + /// second thing + [MultiReturn(new[] { "thing 1", "thing 2" })] + public static Dictionary> MultiReturnExample2() + { + return new Dictionary>() + { + { "thing 1", new List{"apple", "banana", "cat"} }, + { "thing 2", new List{"Tywin", "Cersei", "Hodor"} } + }; + } + /// /// OPTIONAL: /// Overriding ToString allows you to control what is diff --git a/src/SampleLibraryZeroTouch/Examples/ColorExample.cs b/src/SampleLibraryZeroTouch/Examples/ColorExample.cs index fe89303..325ef24 100644 --- a/src/SampleLibraryZeroTouch/Examples/ColorExample.cs +++ b/src/SampleLibraryZeroTouch/Examples/ColorExample.cs @@ -1,7 +1,7 @@ using Autodesk.DesignScript.Interfaces; using Autodesk.DesignScript.Runtime; -namespace SampleLibraryZeroTouch.Examples +namespace Examples { public class CustomRenderExample : IGraphicItem { diff --git a/src/SampleLibraryZeroTouch/Examples/PeriodicUpdateExample.cs b/src/SampleLibraryZeroTouch/Examples/PeriodicUpdateExample.cs index c7d9acc..4458e08 100644 --- a/src/SampleLibraryZeroTouch/Examples/PeriodicUpdateExample.cs +++ b/src/SampleLibraryZeroTouch/Examples/PeriodicUpdateExample.cs @@ -3,7 +3,7 @@ using Autodesk.DesignScript.Interfaces; using Autodesk.DesignScript.Runtime; -namespace SampleLibraryZeroTouch.Examples +namespace Examples { // This sample demonstrates the use of the CanUpdatePeriodically // attribute. Placing an instance of the PeriodicUpdateExample.PointField @@ -12,7 +12,7 @@ namespace SampleLibraryZeroTouch.Examples // requires a parameter, 't', that is incremented during each run. // This example also demonstrates how to use trace to store data that // you want to carry over between evaluations. - public class PeriodicUpdateExample : IGraphicItem + public class PeriodicUpdateExample : IGraphicItem { private Point[,] vertexCoords; private const int width = 20; @@ -32,7 +32,7 @@ private PeriodicUpdateExample(double t, int id) } t += 0.1; - if (t > Math.PI*2) t = 0.0; + if (t > Math.PI * 2) t = 0.0; // Remember to store the updated object in the trace object manager, // so it's available to use the next time around. @@ -78,8 +78,8 @@ public void Tessellate(IRenderPackage package, TessellationParameters parameters { for (var j = 0; j < length - 1; j++) { - var a = vertexCoords[i , j]; - var b = vertexCoords[i , j + 1]; + var a = vertexCoords[i, j]; + var b = vertexCoords[i, j + 1]; var c = vertexCoords[i + 1, j]; var d = vertexCoords[i + 1, j + 1]; @@ -101,8 +101,8 @@ private void PushTriangleVertex(IRenderPackage package, Point p, Vector n) { package.AddTriangleVertex(p.X, p.Y, p.Z); package.AddTriangleVertexColor(255, 255, 255, 255); - package.AddTriangleVertexNormal(n.X,n.Y,n.Z); - package.AddTriangleVertexUV(0,0); + package.AddTriangleVertexNormal(n.X, n.Y, n.Z); + package.AddTriangleVertexUV(0, 0); } } -} +} \ No newline at end of file diff --git a/src/SampleLibraryZeroTouch/Examples/TraceExample.cs b/src/SampleLibraryZeroTouch/Examples/TraceExample.cs index f364d3e..f705765 100644 --- a/src/SampleLibraryZeroTouch/Examples/TraceExample.cs +++ b/src/SampleLibraryZeroTouch/Examples/TraceExample.cs @@ -3,8 +3,9 @@ using System.Runtime.Serialization; using Autodesk.DesignScript.Runtime; using DynamoServices; +using Newtonsoft.Json; -namespace SampleLibraryZeroTouch.Examples +namespace Examples { /// /// This is the item that we will store in our data store. @@ -115,7 +116,7 @@ public static int GetNextUnusedID() public static TraceableId GetObjectIdFromTrace() { - return TraceUtils.GetTraceData(REVIT_TRACE_ID) as TraceableId; + return JsonConvert.DeserializeObject(TraceUtils.GetTraceData(REVIT_TRACE_ID)); } public static object GetTracedObjectById(int id) @@ -134,7 +135,8 @@ public static void RegisterTraceableObjectForId(int id, object objectToTrace) else { traceableObjectManager.Add(id, objectToTrace); - TraceUtils.SetTraceData(REVIT_TRACE_ID, new TraceableId(id)); + + TraceUtils.SetTraceData(REVIT_TRACE_ID, JsonConvert.SerializeObject(objectToTrace)); } } @@ -171,4 +173,4 @@ public TraceableId(SerializationInfo info, StreamingContext context) IntID = (int)info.GetValue("intID", typeof(int)); } } -} +} \ No newline at end of file diff --git a/src/SampleLibraryZeroTouch/Examples/TransformableExample.cs b/src/SampleLibraryZeroTouch/Examples/TransformableExample.cs index 223c0de..a9edfe9 100644 --- a/src/SampleLibraryZeroTouch/Examples/TransformableExample.cs +++ b/src/SampleLibraryZeroTouch/Examples/TransformableExample.cs @@ -6,7 +6,7 @@ using System.Text; using System.Threading.Tasks; -namespace SampleLibraryZeroTouch.Examples +namespace Examples { /// /// An object which knows how to draw itself in the background preview and uses a transform to take @@ -20,9 +20,9 @@ public class TransformableExample : IGraphicItem //want to hide this constructor [Autodesk.DesignScript.Runtime.IsVisibleInDynamoLibrary(false)] - public TransformableExample(Geometry geo) + public TransformableExample(Geometry geometry) { - Geometry = geo; + Geometry = geometry; //initial transform is just at the origin transform = CoordinateSystem.ByOrigin(0, 0, 0); } diff --git a/src/SampleLibraryZeroTouch/SampleLibraryZeroTouch.csproj b/src/SampleLibraryZeroTouch/SampleLibraryZeroTouch.csproj index 5982f75..0a86ce9 100644 --- a/src/SampleLibraryZeroTouch/SampleLibraryZeroTouch.csproj +++ b/src/SampleLibraryZeroTouch/SampleLibraryZeroTouch.csproj @@ -1,88 +1,27 @@ - - - - - - - - Debug - AnyCPU - {BD13C4DC-9045-4E49-B637-B6182B0E3A7F} - Library - Properties - SampleLibraryZeroTouch - SampleLibraryZeroTouch - v4.5 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - bin\Debug\$(UICulture)\SampleLibraryZeroTouch.XML - false - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - bin\Release\$(UICulture)\SampleLibraryZeroTouch.XML - false - - - - ..\packages\DynamoVisualProgramming.DynamoServices.1.1.0\lib\net45\DynamoServices.dll - True - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\DynamoUnits.dll - True - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\ProtoGeometry.dll - True - - - - - - - AssemblySharedInfo.cs - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + Properties + SampleLibraryZeroTouch + SampleLibraryZeroTouch + net10.0 + + + true + bin\$(Configuration)\SampleLibraryZeroTouch.XML + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/SampleLibraryZeroTouch/Utils/SampleUtilities.cs b/src/SampleLibraryZeroTouch/Utils/SampleUtilities.cs index 3a50aed..68888a0 100644 --- a/src/SampleLibraryZeroTouch/Utils/SampleUtilities.cs +++ b/src/SampleLibraryZeroTouch/Utils/SampleUtilities.cs @@ -11,7 +11,19 @@ public static class SampleUtilities [IsVisibleInDynamoLibrary(false)] public static double MultiplyInputByNumber(double input) { - return input * 42; + return input * 10; + } + + [IsVisibleInDynamoLibrary(false)] + public static string DescribeButtonMessage(string input) + { + return "Button displays: " + input; + } + + [IsVisibleInDynamoLibrary(false)] + public static string DescribeWindowMessage(string GUID, string input) + { + return "Window displays: Data bridge callback of node " + GUID.Substring(0, 5) + ": " + input; } } } diff --git a/src/SampleLibraryZeroTouch/app.config b/src/SampleLibraryZeroTouch/app.config new file mode 100644 index 0000000..f353fe5 --- /dev/null +++ b/src/SampleLibraryZeroTouch/app.config @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/SampleLibraryZeroTouch/packages.config b/src/SampleLibraryZeroTouch/packages.config deleted file mode 100644 index 3a2dcf9..0000000 --- a/src/SampleLibraryZeroTouch/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/src/SampleLinter/LinterSettings.cs b/src/SampleLinter/LinterSettings.cs new file mode 100644 index 0000000..19014d6 --- /dev/null +++ b/src/SampleLinter/LinterSettings.cs @@ -0,0 +1,30 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Xml.Serialization; + +namespace SampleLinter +{ + public class LinterSettings + { + [XmlElement("AllowedUngroupedNodes")] + public int AllowedUngroupedNodes { get; set; } = 5; + + public static void SerializeModels(string filename, LinterSettings settings) + { + var xmls = new XmlSerializer(settings.GetType()); + var writer = new StreamWriter(filename); + xmls.Serialize(writer, settings); + writer.Close(); + } + public static LinterSettings DeserializeModels(string filename) + { + var fs = new FileStream(filename, FileMode.Open); + var xmls = new XmlSerializer(typeof(LinterSettings)); + return (LinterSettings)xmls.Deserialize(fs); + } + } +} diff --git a/src/SampleLinter/LinterSettings.xml b/src/SampleLinter/LinterSettings.xml new file mode 100644 index 0000000..008283b --- /dev/null +++ b/src/SampleLinter/LinterSettings.xml @@ -0,0 +1,4 @@ + + + 5 + \ No newline at end of file diff --git a/src/SampleLinter/Properties/AssemblyInfo.cs b/src/SampleLinter/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..4f5cdf9 --- /dev/null +++ b/src/SampleLinter/Properties/AssemblyInfo.cs @@ -0,0 +1,11 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2EBDA9A0-722E-4C88-826C-62111D4C2C60")] diff --git a/src/SampleLinter/Properties/Resources.Designer.cs b/src/SampleLinter/Properties/Resources.Designer.cs new file mode 100644 index 0000000..06524c5 --- /dev/null +++ b/src/SampleLinter/Properties/Resources.Designer.cs @@ -0,0 +1,117 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace SampleLinter.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("SampleLinter.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to If the placed dropdowns are needing to be inputs, remember to rename them and mark them as input. If you do not need these as inputs, consider an alternative node.. + /// + public static string DropdownCallToAction { + get { + return ResourceManager.GetString("DropdownCallToAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have dropdown nodes placed that are not inputs.. + /// + public static string DropdownDescription { + get { + return ResourceManager.GetString("DropdownDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have nodes that are not in groups. Grouping your nodes is a best-practice when authoring Dynamo graphs. {0} nodes are allowed outside of groups based on the Linter Settings.. + /// + public static string NodesNotInGroupsCallToAction { + get { + return ResourceManager.GetString("NodesNotInGroupsCallToAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to There are {0} nodes that are not in groups.. + /// + public static string NodesNotInGroupsDescription { + get { + return ResourceManager.GetString("NodesNotInGroupsDescription", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to If the placed number sliders are needing to be inputs, remember to rename them and mark them as input. If you do not need these as inputs, consider an alternative node.. + /// + public static string SlidersCallToAction { + get { + return ResourceManager.GetString("SlidersCallToAction", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to You have number sliders placed that are not inputs.. + /// + public static string SlidersDescription { + get { + return ResourceManager.GetString("SlidersDescription", resourceCulture); + } + } + } +} diff --git a/src/SampleLinter/Properties/Resources.en-US.resx b/src/SampleLinter/Properties/Resources.en-US.resx new file mode 100644 index 0000000..078d87d --- /dev/null +++ b/src/SampleLinter/Properties/Resources.en-US.resx @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + If the placed dropdowns are needing to be inputs, remember to rename them and mark them as input. If you do not need these as inputs, consider an alternative node. + + + You have dropdown nodes placed that are not inputs. + + + You have nodes that are not in groups. Grouping your nodes is a best-practice when authoring Dynamo graphs. {0} nodes are allowed outside of groups based on the Linter Settings. + + + There are {0} nodes that are not in groups. + + + If the placed number sliders are needing to be inputs, remember to rename them and mark them as input. If you do not need these as inputs, consider an alternative node. + + + You have number sliders placed that are not inputs. + + \ No newline at end of file diff --git a/src/SampleLinter/Properties/Resources.es-ES.resx b/src/SampleLinter/Properties/Resources.es-ES.resx new file mode 100644 index 0000000..f997c05 --- /dev/null +++ b/src/SampleLinter/Properties/Resources.es-ES.resx @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Si los dropdowns desplegables colocados deben ser entradas, recuerde cambiarles el nombre y marcarlos como entrada. Si no los necesita como entradas, considere un node alternativo. + + + Tiene dropdowns colocados que no son entradas. + + + Tiene nodes que no están en grupos. Agrupar sus nodos es una práctica recomendada al crear gráficos de Dynamo. Se permiten {0} nodes fuera de los grupos según la configuración de Linter. + + + Hay {0} nodes que no están en grupos. + + + Si los controles deslizantes numéricos colocados deben ser entradas, recuerde cambiarles el nombre y marcarlos como entrada. Si no los necesita como entradas, considere un nodo alternativo. + + + Tiene deslizadores sliders colocados que no son entradas. + + \ No newline at end of file diff --git a/src/SampleLinter/Properties/Resources.resx b/src/SampleLinter/Properties/Resources.resx new file mode 100644 index 0000000..078d87d --- /dev/null +++ b/src/SampleLinter/Properties/Resources.resx @@ -0,0 +1,138 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + If the placed dropdowns are needing to be inputs, remember to rename them and mark them as input. If you do not need these as inputs, consider an alternative node. + + + You have dropdown nodes placed that are not inputs. + + + You have nodes that are not in groups. Grouping your nodes is a best-practice when authoring Dynamo graphs. {0} nodes are allowed outside of groups based on the Linter Settings. + + + There are {0} nodes that are not in groups. + + + If the placed number sliders are needing to be inputs, remember to rename them and mark them as input. If you do not need these as inputs, consider an alternative node. + + + You have number sliders placed that are not inputs. + + \ No newline at end of file diff --git a/src/SampleLinter/Rules/NoGroupsLinterRule.cs b/src/SampleLinter/Rules/NoGroupsLinterRule.cs new file mode 100644 index 0000000..8933840 --- /dev/null +++ b/src/SampleLinter/Rules/NoGroupsLinterRule.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Dynamo.Graph.Nodes; +using Dynamo.Graph.Workspaces; +using Dynamo.Linting.Interfaces; +using Dynamo.Linting.Rules; + +namespace SampleLinter.Rules +{ + /// + /// Having ungrouped nodes is a bad practice. This section allows the linter to flag this behavior based on linter settings in the extra folder in the extension directory. + /// This example node uses .net .resx files and generated satellite assemblies to perform runtime lookup of localized content + /// depending on the culture of the system Dynamo is running on. + /// Read more: https://docs.microsoft.com/en-us/dotnet/framework/resources/creating-resource-files-for-desktop-apps + /// You can use the -l "es-ES" flag when starting DynamoSandbox.exe to replace the English strings with Spanish ones. + /// For more info on the CLI interface read more: https://github.com/DynamoDS/Dynamo/wiki/Dynamo-Command-Line-Interface + /// + public class NoGroupsLinterRule : GraphLinterRule + { + public override string Id => "EF17A093-4E94-4AE9-8876-18631396A23A"; //this id is unique to each linter rule + public override SeverityCodesEnum SeverityCode => SeverityCodesEnum.Warning; + + public override string Description => + string.Format(Properties.Resources.NodesNotInGroupsDescription, _nodesNotInGroups.Count); + public override string CallToAction => string.Format(Properties.Resources.NodesNotInGroupsDescription, _ungroupedAllowed); + + //To store our ungrouped nodes for counts and checks + private readonly List _nodesNotInGroups = new List(); + + //Allow the end-user to have a few nodes outside of groups. We don't want to be too overbearing. + private readonly int _ungroupedAllowed; + + public NoGroupsLinterRule(LinterSettings linterSettings) + { + _ungroupedAllowed = linterSettings.AllowedUngroupedNodes; + } + + public override List EvaluationTriggerEvents => + new List() + { + "Modified" + }; + + protected override Tuple> EvaluateFunction(WorkspaceModel workspaceModel, string changedEvent, NodeModel nodeModel = null) + { + //clear our list as we are reevaluating the graph + _nodesNotInGroups.Clear(); + + if (workspaceModel != null) + { + //check each node for grouping + foreach (var node in workspaceModel.Nodes) + { + CheckNodeForGroup(node, workspaceModel); + } + } + + var result = _nodesNotInGroups.Count > _ungroupedAllowed ? RuleEvaluationStatusEnum.Failed : RuleEvaluationStatusEnum.Passed; + + return new Tuple>(result, new HashSet()); + } + + + + protected override List>> InitFunction(WorkspaceModel workspaceModel) + { + _nodesNotInGroups.Clear(); + + //create a list to hold results information. + //The Tuple should be of a RuleEvaluationStatus and the name of the node + List> results = new List>(); + + //Iterate over all the nodes in the workspace + foreach (NodeModel node in workspaceModel.Nodes) + { + CheckNodeForGroup(node, workspaceModel); + } + + return new List>> { EvaluateFunction(workspaceModel, "initialize") }; + } + + private void CheckNodeForGroup(NodeModel nodeModel, WorkspaceModel workspaceModel) + { + //collect current groups from file + var groups = workspaceModel.Annotations.ToList(); + + //if there are no groups, return all of the current nodes + if (!groups.Any()) + { + _nodesNotInGroups.Clear(); + _nodesNotInGroups.AddRange(workspaceModel.Nodes); + + return; + }; + + //check if the node is in any of the groups. If not add it to our list. + if (!groups.Any(g => g.Nodes.Any(n => n.GUID.Equals(nodeModel.GUID)))) + { + _nodesNotInGroups.Add(nodeModel); + } + //the node is in a group, remove it from the list if applicable + else + { + _nodesNotInGroups.Remove(nodeModel); + } + } + } + + +} diff --git a/src/SampleLinter/Rules/SampleDropdownInputLinterRule.cs b/src/SampleLinter/Rules/SampleDropdownInputLinterRule.cs new file mode 100644 index 0000000..abe200a --- /dev/null +++ b/src/SampleLinter/Rules/SampleDropdownInputLinterRule.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; +using Dynamo.Graph.Nodes; +using Dynamo.Graph.Workspaces; +using Dynamo.Linting.Interfaces; +using Dynamo.Linting.Rules; + +namespace SampleLinter.Rules +{ + /// + /// Similar to the slider rule, but for dropdowns. If you aren't using it as an input, it is worth considering an alternative. + /// Having ungrouped nodes is a bad practice. This section allows the linter to flag this behavior based on linter settings in the extra folder in the extension directory. + /// This example node uses .net .resx files and generated satellite assemblies to perform runtime lookup of localized content + /// depending on the culture of the system Dynamo is running on. + /// Read more: https://docs.microsoft.com/en-us/dotnet/framework/resources/creating-resource-files-for-desktop-apps + /// You can use the -l "es-ES" flag when starting DynamoSandbox.exe to replace the English strings with Spanish ones. + /// For more info on the CLI interface read more: https://github.com/DynamoDS/Dynamo/wiki/Dynamo-Command-Line-Interface + /// + internal class SampleDropdownInputLinterRule : NodeLinterRule + { + public override string Id => "E4EC24B8-8F87-42B3-874F-A3DB3A69098A"; + public override SeverityCodesEnum SeverityCode => SeverityCodesEnum.Warning; + + public override string Description => Properties.Resources.DropdownDescription; + + public override string CallToAction => Properties.Resources.DropdownDescription; + + public override List EvaluationTriggerEvents => + new List() + { + nameof(NodeModel.IsSetAsInput), + nameof(NodeModel.State), + }; + + + protected override RuleEvaluationStatusEnum EvaluateFunction(NodeModel nodeModel, string changedEvent) + { + if (nodeModel != null) + { + if (nodeModel.NodeType.Equals("ExtensionNode")) + { + if (!nodeModel.IsSetAsInput) + { + return RuleEvaluationStatusEnum.Failed; + } + } + } + + return RuleEvaluationStatusEnum.Passed; + } + + + protected override List> InitFunction(WorkspaceModel workspaceModel) + { + //create a list to hold results information. + //The Tuple should be of a RuleEvaluationStatus and the name of the node + List> results = new List>(); + + //Iterate over all the nodes in the workspace + foreach (NodeModel node in workspaceModel.Nodes) + { + //Call the Evaluate function + var evaluationStatus = EvaluateFunction(node, "initialize"); + + //Check what happened for this node. If it passed the we continue + if (evaluationStatus == RuleEvaluationStatusEnum.Passed) + continue; + + //Create the tuple to return and add it to the result list + var valueTuple = Tuple.Create(evaluationStatus, node.GUID.ToString()); + results.Add(valueTuple); + } + + return results; + } + } + + +} diff --git a/src/SampleLinter/Rules/SampleSliderInputLinterRule.cs b/src/SampleLinter/Rules/SampleSliderInputLinterRule.cs new file mode 100644 index 0000000..54c59c0 --- /dev/null +++ b/src/SampleLinter/Rules/SampleSliderInputLinterRule.cs @@ -0,0 +1,74 @@ +using System; +using System.Collections.Generic; +using CoreNodeModels.Input; +using Dynamo.Graph.Nodes; +using Dynamo.Graph.Workspaces; +using Dynamo.Linting.Interfaces; +using Dynamo.Linting.Rules; + +namespace SampleLinter.Rules +{ + /// + /// This rule alerts the end user that they might want to do so if the slider is not input or renamed. If a slider is not being used as input, it is typically unnecessary and a number node or a code block would suffice. + /// + internal class SampleSliderInputLinterRule : NodeLinterRule + { + public override string Id => "54EFD003-FF02-41B6-9F2E-52216BA23844"; + public override SeverityCodesEnum SeverityCode => SeverityCodesEnum.Warning; + + public override string Description => Properties.Resources.SlidersDescription; + + public override string CallToAction => Properties.Resources.SlidersCallToAction; + + public override List EvaluationTriggerEvents => + new List() + { + nameof(NodeModel.IsSetAsInput), + nameof(NodeModel.State), + }; + + + protected override RuleEvaluationStatusEnum EvaluateFunction(NodeModel nodeModel, string changedEvent) + { + if (nodeModel != null) + { + if (nodeModel is DoubleSlider || (nodeModel is IntegerSlider64Bit)) + { + if (!nodeModel.IsSetAsInput) + { + return RuleEvaluationStatusEnum.Failed; + } + } + } + + return RuleEvaluationStatusEnum.Passed; + } + + + protected override List> InitFunction(WorkspaceModel workspaceModel) + { + //create a list to hold results information. + //The Tuple should be of a RuleEvaluationStatus and the name of the node + List> results = new List>(); + + //Iterate over all the nodes in the workspace + foreach (NodeModel node in workspaceModel.Nodes) + { + //Call the Evaluate function + var evaluationStatus = EvaluateFunction(node, "initialize"); + + //Check what happened for this node. If it passed the we continue + if (evaluationStatus == RuleEvaluationStatusEnum.Passed) + continue; + + //Create the tuple to return and add it to the result list + var valueTuple = Tuple.Create(evaluationStatus, node.GUID.ToString()); + results.Add(valueTuple); + } + + return results; + } + } + + +} diff --git a/src/SampleLinter/SampleLinter.cs b/src/SampleLinter/SampleLinter.cs new file mode 100644 index 0000000..5da3873 --- /dev/null +++ b/src/SampleLinter/SampleLinter.cs @@ -0,0 +1,56 @@ +using System; +using System.IO; +using Dynamo.Extensions; +using Dynamo.Logging; +using SampleLinter.Rules; + +namespace SampleLinter +{ + public class SampleLinter : LinterExtensionBase + { + public override string UniqueId => "44BAAD49-4750-47BE-AB60-61DD30962FAE"; //this is unique to this linter + public override string Name => "Sample Linter"; + + + private SampleSliderInputLinterRule _sliderInputRule; + private SampleDropdownInputLinterRule _DropdownRule; + private NoGroupsLinterRule _noGroupsRule; + + private LinterSettings _linterSettings; + + public override void Ready(ReadyParams rp) + { + //load our settings + var extensionDirectory = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)?.Replace("bin","extra"); + var settingsFile = Path.Combine(extensionDirectory, "LinterSettings.xml"); + //if the settings file exists, use it, if not load with default 5 ungrouped allowed + _linterSettings = File.Exists(settingsFile) ? LinterSettings.DeserializeModels(settingsFile) : new LinterSettings(){AllowedUngroupedNodes = 5}; + + + //since we are inheriting from the LinterExtensionBase we need to mark it as ready here + base.Ready(rp); + + //add each of our rules to the linter + _sliderInputRule = new SampleSliderInputLinterRule(); + AddLinterRule(_sliderInputRule); + + _DropdownRule = new SampleDropdownInputLinterRule(); + AddLinterRule(_DropdownRule); + + _noGroupsRule = new NoGroupsLinterRule(_linterSettings); + AddLinterRule(_noGroupsRule); + } + + + + + public override void Shutdown() + { + RemoveLinterRule(_sliderInputRule); + RemoveLinterRule(_DropdownRule); + RemoveLinterRule(_noGroupsRule); + } + + + } +} diff --git a/src/SampleLinter/SampleLinter.csproj b/src/SampleLinter/SampleLinter.csproj new file mode 100644 index 0000000..9879523 --- /dev/null +++ b/src/SampleLinter/SampleLinter.csproj @@ -0,0 +1,41 @@ + + + + + + SampleLinter + SampleLinter + Copyright © 2023 + 2.0.1.0 + 2.0.1.0 + net10.0 + + + true + bin\$(Configuration)\ + + + + + + + + + Always + + + Always + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/SampleLinter/SampleLinter_ExtensionDefinition.xml b/src/SampleLinter/SampleLinter_ExtensionDefinition.xml new file mode 100644 index 0000000..59a0580 --- /dev/null +++ b/src/SampleLinter/SampleLinter_ExtensionDefinition.xml @@ -0,0 +1,4 @@ + + ..\bin\SampleLinter.dll + SampleLinter.SampleLinter + diff --git a/src/SampleViewExtension/Properties/AssemblyInfo.cs b/src/SampleViewExtension/Properties/AssemblyInfo.cs index 4b2ed5b..a04b049 100644 --- a/src/SampleViewExtension/Properties/AssemblyInfo.cs +++ b/src/SampleViewExtension/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] +[assembly: AssemblyVersion("2.0.1.0")] +[assembly: AssemblyFileVersion("2.0.1.0")] diff --git a/src/SampleViewExtension/SampleViewExtension.cs b/src/SampleViewExtension/SampleViewExtension.cs index e1b5b16..4c52069 100644 --- a/src/SampleViewExtension/SampleViewExtension.cs +++ b/src/SampleViewExtension/SampleViewExtension.cs @@ -9,69 +9,72 @@ namespace SampleViewExtension /// The View Extension framework for Dynamo allows you to extend /// the Dynamo UI by registering custom MenuItems. A ViewExtension has /// two components, an assembly containing a class that implements - /// IViewExtension, and an ViewExtensionDefintion xml file used to - /// instruct Dynamo where to find the class containing the - /// IViewExtension implementation. The ViewExtensionDefinition xml file must + /// IViewExtension or extends ViewExtensionBase, and a ViewExtensionDefinition + /// XML file used to instruct Dynamo where to find the class containing the + /// View Extension implementation. The ViewExtensionDefinition XML file must /// be located in your [dynamo]\viewExtensions folder. /// - /// This sample demonstrates an IViewExtension implementation which - /// shows a modeless window when its MenuItem is clicked. + /// This sample demonstrates a View Extension implementation which inherits from + /// ViewExtensionBase. It adds a user interface to Dynamo's extension sidebar + /// when its MenuItem is clicked. /// The Window created tracks the number of nodes in the current workspace, /// by handling the workspace's NodeAdded and NodeRemoved events. /// - public class SampleViewExtension : IViewExtension + public class SampleViewExtension : ViewExtensionBase { private MenuItem sampleMenuItem; - public void Dispose() + public override void Dispose() { } - public void Startup(ViewStartupParams p) + public override void Startup(ViewStartupParams p) { } - public void Loaded(ViewLoadedParams p) + public override 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 { - 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 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 - }; + // 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; + sampleMenuItem = new MenuItem { Header = "Show View Extension Sample Window", IsCheckable = true }; + sampleMenuItem.Checked += (sender, args) => p.AddToExtensionsSideBar(this, window); + sampleMenuItem.Unchecked += (sender, args) => p.CloseExtensioninInSideBar(this); + p.AddExtensionMenuItem(sampleMenuItem); + } - // Show a modeless window. - window.Show(); - }; - p.AddMenuItem(MenuBarType.View, sampleMenuItem); + public override void Shutdown() + { } - public void Shutdown() + public override void Closed() { + if (sampleMenuItem != null) + { + sampleMenuItem.IsChecked = false; + } } - public string UniqueId + public override string UniqueId { get { - return Guid.NewGuid().ToString(); + return "61BB15A8-9B6B-4AB0-8D75-F7C34E0B9112"; } } - public string Name + public override string Name { get { diff --git a/src/SampleViewExtension/SampleViewExtension.csproj b/src/SampleViewExtension/SampleViewExtension.csproj index 57b974b..dfa8ff4 100644 --- a/src/SampleViewExtension/SampleViewExtension.csproj +++ b/src/SampleViewExtension/SampleViewExtension.csproj @@ -1,147 +1,30 @@ - - - + - + - Debug - AnyCPU - {146EBF48-E7A0-4ABE-809D-D7F3059E4EE1} - Library - Properties SampleViewExtension SampleViewExtension - v4.5 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 + + net10.0-windows + true - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\CoreNodeModels.dll - True - - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\CoreNodeModelsWpf.dll - True - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoCore.dll - True - - - ..\packages\DynamoVisualProgramming.WpfUILibrary.1.1.0\lib\net45\DynamoCoreWpf.dll - True - - - ..\packages\DynamoVisualProgramming.DynamoServices.1.1.0\lib\net45\DynamoServices.dll - True - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoShapeManager.dll - True - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\DynamoUnits.dll - True - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\DynamoUtilities.dll - True - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Expression.Interactions.dll - True - False - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Practices.Prism.dll - False - - - ..\packages\Prism.4.1.0.0\lib\NET40\Microsoft.Practices.Prism.Interactivity.dll - False - - - ..\packages\CommonServiceLocator.1.0\lib\NET35\Microsoft.Practices.ServiceLocation.dll - False - - - ..\packages\NUnit.2.6.3\lib\nunit.framework.dll - True - False - - - - - ..\packages\DynamoVisualProgramming.Core.1.1.0\lib\net45\ProtoCore.dll - True - - - ..\packages\DynamoVisualProgramming.ZeroTouchLibrary.1.1.0\lib\net45\ProtoGeometry.dll - True - - - - - ..\packages\Prism.4.1.0.0\lib\NET40\System.Windows.Interactivity.dll - True - False - - - - - - - - - + + + - - - - SampleWindow.xaml - - - - - - Designer - MSBuild:Compile - - - - + Always - - - - + - - \ No newline at end of file diff --git a/src/SampleViewExtension/SampleViewExtension_ViewExtensionDefinition.xml b/src/SampleViewExtension/SampleViewExtension_ViewExtensionDefinition.xml index 3b45e7b..e9ff08e 100644 --- a/src/SampleViewExtension/SampleViewExtension_ViewExtensionDefinition.xml +++ b/src/SampleViewExtension/SampleViewExtension_ViewExtensionDefinition.xml @@ -1,4 +1,4 @@  - ..\SampleViewExtension.dll + ..\bin\SampleViewExtension.dll SampleViewExtension.SampleViewExtension diff --git a/src/SampleViewExtension/SampleWindow.xaml b/src/SampleViewExtension/SampleWindow.xaml index 2818dce..0942306 100644 --- a/src/SampleViewExtension/SampleWindow.xaml +++ b/src/SampleViewExtension/SampleWindow.xaml @@ -10,6 +10,12 @@ - + diff --git a/src/SampleViewExtension/SampleWindowViewModel.cs b/src/SampleViewExtension/SampleWindowViewModel.cs index 264fe15..2b21112 100644 --- a/src/SampleViewExtension/SampleWindowViewModel.cs +++ b/src/SampleViewExtension/SampleWindowViewModel.cs @@ -7,10 +7,32 @@ namespace SampleViewExtension { public class SampleWindowViewModel : NotificationObject, IDisposable { - private string selectedNodesText = "Begin selecting "; + private string activeNodeTypes; private ReadyParams readyParams; - public string SelectedNodesText = @"There are {readyParams.CurrentWorkspaceModel.Nodes.Count()} nodes in the workspace."; + // 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) { @@ -21,7 +43,7 @@ public SampleWindowViewModel(ReadyParams p) private void CurrentWorkspaceModel_NodesChanged(NodeModel obj) { - RaisePropertyChanged("SelectedNodesText"); + RaisePropertyChanged("ActiveNodeTypes"); } public void Dispose() diff --git a/src/SampleViewExtension/packages.config b/src/SampleViewExtension/packages.config deleted file mode 100644 index 96b753c..0000000 --- a/src/SampleViewExtension/packages.config +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - - - - - \ No newline at end of file diff --git a/src/SampleZeroTouchUnits/RectangleExample.cs b/src/SampleZeroTouchUnits/RectangleExample.cs new file mode 100644 index 0000000..288ae02 --- /dev/null +++ b/src/SampleZeroTouchUnits/RectangleExample.cs @@ -0,0 +1,132 @@ +using Autodesk.DesignScript.Interfaces; +using Autodesk.DesignScript.Runtime; +using System.Collections.Generic; +using System; +using DynamoUnits; +using Dynamo.Graph.Nodes.CustomNodes; + +namespace SampleZeroTouchUnits +{ + /// + /// The RectangleExample class demonstrates + /// how to use the Dynamo Units API to convert between units. + /// + public class RectangleExample + { + const string meters = "autodesk.unit.unit:meters"; + const string meters2 = "autodesk.unit.unit:squareMeters"; + + /// + /// The Length value + /// + private readonly double Length; + + /// + /// The Width value + /// + private readonly double Width; + + private Unit LengthUnit; + private Unit WidthUnit; + private Unit AreaUnit; + + /// + /// Creates an instance of RectangleExample with all units defaulted to metric + /// + /// The width of RectangleExample, defaulted to meters + /// The length of RectangleExample, defaulted to meters + public RectangleExample(double width, double length) + { + Length = length; + Width = width; + LengthUnit = Unit.ByTypeID($"{meters}-1.0.1"); + WidthUnit = Unit.ByTypeID($"{meters}-1.0.1"); + AreaUnit = Unit.ByTypeID($"{meters2}-1.0.1"); + } + + /// + /// Creates an instance of RectangleExample with customizable untis + /// + /// The width of RectangleExample + /// The length of RectangleExample + /// The unit for width + /// The unit for length + public RectangleExample(double width, double length, Unit widthUnit, Unit lengthUnit) + { + Width = width; + Length = length; + + LengthUnit = lengthUnit; + WidthUnit = widthUnit; + + AreaUnit = Unit.ByTypeID($"{meters2}-1.0.1"); + } + + /// + /// Get the length converted to a target unit. + /// + /// The target unit. Defaults to null + /// + /// + public double GetLength(Unit targetUnit = null) + { + targetUnit ??= LengthUnit; + ArgumentNullException.ThrowIfNull(targetUnit); + + if (!Unit.AreUnitsConvertible(LengthUnit, targetUnit)) + { + throw new ArgumentException($"{LengthUnit} is not convertible to {targetUnit}"); + } + + var output = Utilities.ConvertByUnits(Length, LengthUnit, targetUnit); + return output; + } + + /// + /// Get the width converted to a target unit. + /// + /// The target unit. Defaults to null + /// + /// + public double GetWidth(Unit targetUnit) + { + targetUnit ??= WidthUnit; + ArgumentNullException.ThrowIfNull(targetUnit); + if (!Unit.AreUnitsConvertible(WidthUnit, targetUnit)) + { + throw new ArgumentException($"{LengthUnit} is not convertible to {targetUnit}"); + } + + var output = Utilities.ConvertByUnits(Length, WidthUnit, targetUnit); + return output; + } + + string GetFirstSymbolText(Unit unit) + { + var symbols = DynamoUnits.Symbol.SymbolsByUnit(unit); + foreach (var symbol in symbols) + { + return symbol.Text; + } + return string.Empty; + } + + /// + /// Get the area of the rectangle. Computed as width * length + /// + /// The target unit for the area value, defaults to null + /// A string containing the area value and unit symbol. Ex. "100ft^2" + /// + public string GetArea(Unit targetUnit = null) + { + targetUnit ??= AreaUnit; + if (!Unit.AreUnitsConvertible(AreaUnit, targetUnit)) + { + throw new ArgumentException($"{targetUnit.Name} is not a valid area unit"); + } + + double area = Utilities.ParseExpressionByUnit(targetUnit, $"{Length}{GetFirstSymbolText(LengthUnit)} * {Width}{GetFirstSymbolText(WidthUnit)}"); + return $"{area}{GetFirstSymbolText(targetUnit)}"; + } + } +} diff --git a/src/SampleZeroTouchUnits/SampleZeroTouchUnits.csproj b/src/SampleZeroTouchUnits/SampleZeroTouchUnits.csproj new file mode 100644 index 0000000..f21e4b2 --- /dev/null +++ b/src/SampleZeroTouchUnits/SampleZeroTouchUnits.csproj @@ -0,0 +1,27 @@ + + + + + + Properties + SampleZeroTouchUnits + SampleZeroTouchUnits + net10.0 + + + true + bin\$(Configuration)\SampleZeroTouchUnits.XML + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/build.xml b/src/build.xml index a010ecc..cfead66 100644 --- a/src/build.xml +++ b/src/build.xml @@ -4,7 +4,7 @@ DefaultTargets="Build"> - DynamoSamples.2013.sln + DynamoSamples.sln