├── yak
├── yak_login.bat
├── yak_search.bat
├── yak_push.bat
└── manifest.yml
├── .gitignore
├── References
└── MacOS
│ ├── .gitignore
│ └── README.md
├── Shared
├── README.md
├── src
│ └── SharedExample.cs
├── interface
│ └── ISharedExample.cs
└── Shared.csproj
├── SharedRhino
├── README.md
├── interface
│ └── ISharedRhinoExample.cs
├── src
│ └── SharedRhinoExample.cs
└── SharedRhino.csproj
├── TestShared
├── README.md
├── TestShared.csproj
└── TestSharedExample.cs
├── TestSharedRhino
├── README.md
├── TestSharedRhino.csproj
├── TestSharedRhinoExample.cs
└── RhinoInsideInit.cs
├── Artwork
├── PluginRhino.ico
├── PluginRhino.xcf
├── PluginRhino.webp
├── PluginRhino_1024.png
├── PluginRhino_128.png
├── PluginRhino_16.png
├── PluginRhino_24.png
├── PluginRhino_256.png
├── PluginRhino_32.png
├── PluginRhino_64.png
├── PluginGrasshopper.ico
├── PluginGrasshopper.webp
├── PluginGrasshopper.xcf
├── PluginGrasshopper_128.png
├── PluginGrasshopper_16.png
├── PluginGrasshopper_24.png
├── PluginGrasshopper_256.png
├── PluginGrasshopper_32.png
└── PluginGrasshopper_1024.png
├── TODO.md
├── PluginRhino
├── README.md
├── EmbeddedResources
│ └── PluginRhino.ico
├── Properties
│ └── AssemblyInfo.cs
├── PluginRhino.cs
├── Commands
│ └── ExampleCommand.cs
└── PluginRhino.csproj
├── PluginGrasshopper
├── README.md
├── EmbeddedResources
│ ├── PluginGrasshopper_16.png
│ └── PluginGrasshopper_24.png
├── Properties
│ ├── AssemblyInfo.cs
│ └── ResourceLoader.cs
├── PluginLoader.cs
├── PluginGrasshopper.csproj
├── Components
│ └── ExampleComponent.cs
└── PluginInfo.cs
├── test.DebugR7.runsettings
├── test.DebugR8.runsettings
├── CommonSettingsFinal.csproj
├── Packages.props
├── CommonReferencesTests.csproj
├── BuildYakOnlyRhino7.bat
├── BuildYakOnlyRhino8.bat
├── CommonReferencesGrasshopper.csproj
├── PackagesRhino7.props
├── CommonVariables.bat
├── PackagesRhino8.props
├── BuildRhino7.bat
├── BuildRhino8.bat
├── LICENSE
├── Directory.Packages.props
├── CommonTasks.csproj
├── CommonReferencesRhino.csproj
├── CommonReferencesSystemDrawing.csproj
├── CommonVariables.csproj
├── CommonTargets.csproj
├── README.md
├── CommonSettings.csproj
└── PluginTemplate.sln
/yak/yak_login.bat:
--------------------------------------------------------------------------------
1 | yak login
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vs/
2 | bin/
3 | obj/
4 |
--------------------------------------------------------------------------------
/References/MacOS/.gitignore:
--------------------------------------------------------------------------------
1 | System.Drawing.Common.dll
--------------------------------------------------------------------------------
/Shared/README.md:
--------------------------------------------------------------------------------
1 | # Shared functionality NOT depending on Rhino
2 |
--------------------------------------------------------------------------------
/SharedRhino/README.md:
--------------------------------------------------------------------------------
1 | # Shared functionality depending on Rhino
2 |
--------------------------------------------------------------------------------
/TestShared/README.md:
--------------------------------------------------------------------------------
1 | # Test assembly for shared functionality NOT depending on Rhino
2 |
3 |
--------------------------------------------------------------------------------
/TestSharedRhino/README.md:
--------------------------------------------------------------------------------
1 | # Test assembly for shared functionality depending on Rhino
2 |
--------------------------------------------------------------------------------
/yak/yak_search.bat:
--------------------------------------------------------------------------------
1 |
2 | yak search --all --prerelease PLUGIN_NAME
3 |
4 | set /p=Hit ENTER to continue...
5 |
--------------------------------------------------------------------------------
/Artwork/PluginRhino.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino.ico
--------------------------------------------------------------------------------
/Artwork/PluginRhino.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino.xcf
--------------------------------------------------------------------------------
/Artwork/PluginRhino.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino.webp
--------------------------------------------------------------------------------
/Artwork/PluginRhino_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino_1024.png
--------------------------------------------------------------------------------
/Artwork/PluginRhino_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino_128.png
--------------------------------------------------------------------------------
/Artwork/PluginRhino_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino_16.png
--------------------------------------------------------------------------------
/Artwork/PluginRhino_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino_24.png
--------------------------------------------------------------------------------
/Artwork/PluginRhino_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino_256.png
--------------------------------------------------------------------------------
/Artwork/PluginRhino_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino_32.png
--------------------------------------------------------------------------------
/Artwork/PluginRhino_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginRhino_64.png
--------------------------------------------------------------------------------
/TODO.md:
--------------------------------------------------------------------------------
1 |
2 | * Create PluginRhino/Properties/AssemblyInfo.cs automatically based on metadata in CommonVariables.csproj
3 |
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper.ico
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper.webp
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper.xcf
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper_128.png
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper_16.png
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper_24.png
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper_256.png
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper_32.png
--------------------------------------------------------------------------------
/Artwork/PluginGrasshopper_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/Artwork/PluginGrasshopper_1024.png
--------------------------------------------------------------------------------
/PluginRhino/README.md:
--------------------------------------------------------------------------------
1 | # Rhino plug-in
2 |
3 | Directory [EmbeddedResources](EmbeddedResources) contains images which you might want to adapt.
4 |
5 |
--------------------------------------------------------------------------------
/PluginRhino/EmbeddedResources/PluginRhino.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/PluginRhino/EmbeddedResources/PluginRhino.ico
--------------------------------------------------------------------------------
/PluginGrasshopper/README.md:
--------------------------------------------------------------------------------
1 | # Grasshopper plug-in
2 |
3 | Directory [EmbeddedResources](EmbeddedResources) contains images which you might want to adapt.
4 |
5 |
--------------------------------------------------------------------------------
/PluginGrasshopper/EmbeddedResources/PluginGrasshopper_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/PluginGrasshopper/EmbeddedResources/PluginGrasshopper_16.png
--------------------------------------------------------------------------------
/PluginGrasshopper/EmbeddedResources/PluginGrasshopper_24.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/shapediver/GrasshopperPluginTemplate/HEAD/PluginGrasshopper/EmbeddedResources/PluginGrasshopper_24.png
--------------------------------------------------------------------------------
/yak/yak_push.bat:
--------------------------------------------------------------------------------
1 |
2 | cd bin/yak
3 |
4 | dir *.yak
5 |
6 | set /p=Hit ENTER to push the Yak packages shown above...
7 | yak push *.yak
8 |
9 | set /p=Hit ENTER to continue...
10 |
--------------------------------------------------------------------------------
/yak/manifest.yml:
--------------------------------------------------------------------------------
1 | ---
2 | name: $name$
3 | version: $version$
4 | authors:
5 | - $authors$
6 | description: >
7 | $description$
8 | url: $url$
9 | icon: icon.png
10 | keywords:
11 | $keywords$
12 |
--------------------------------------------------------------------------------
/PluginGrasshopper/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper.Kernel;
2 |
3 | // Define the loading mechanism Grasshopper shall use for this plugin
4 | // see https://www.grasshopper3d.com/forum/topics/how-to-define-per-gha-loading-mechanism
5 | // for more information
6 | [assembly: Grasshopper.Kernel.GH_Loading(GH_LoadingDemand.Default)]
7 |
--------------------------------------------------------------------------------
/Shared/src/SharedExample.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace PluginTemplate.Shared
3 | {
4 |
5 | ///
6 | /// Example implementation of a shared interface not dependent on RhinoCommon.
7 | ///
8 | public class SharedExample : ISharedExample
9 | {
10 | public int Add(int a, int b)
11 | {
12 | return a + b;
13 | }
14 | }
15 |
16 | }
--------------------------------------------------------------------------------
/References/MacOS/README.md:
--------------------------------------------------------------------------------
1 | Copy `System.Drawing.Common.dll` from a Rhino 8 Mac application bundle here.
2 | Right-click the Rhino 8 app icon, choose "Show content," and navigate to Contents/Frameworks/RhCore.framework/Versions/Current/Resources/
3 |
4 | See the related [thread](https://discourse.mcneel.com/t/windows-forms-on-gh-and-rhino-8/171307/23) on McNeel Discourse. Looks like there is a better solution already, which still has to be incorporated here.
5 |
--------------------------------------------------------------------------------
/Shared/interface/ISharedExample.cs:
--------------------------------------------------------------------------------
1 |
2 | namespace PluginTemplate.Shared
3 | {
4 |
5 | ///
6 | /// Example of a shared interface not dependent on RhinoCommon.
7 | ///
8 | public interface ISharedExample {
9 |
10 | ///
11 | /// Compute the sum of two integers.
12 | ///
13 | ///
14 | ///
15 | ///
16 | int Add(int a, int b);
17 |
18 | }
19 |
20 | }
--------------------------------------------------------------------------------
/test.DebugR7.runsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | x64
7 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/test.DebugR8.runsettings:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | x64
7 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/CommonSettingsFinal.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 | $(AssemblyName)
9 | $(AssemblyName)
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SharedRhino/interface/ISharedRhinoExample.cs:
--------------------------------------------------------------------------------
1 | using Rhino.Geometry;
2 |
3 | namespace PluginTemplate.SharedRhino
4 | {
5 |
6 | ///
7 | /// Example of a shared interface dependent on RhinoCommon.
8 | ///
9 | public interface ISharedRhinoExample {
10 |
11 | ///
12 | /// Intersect a plane with a line.
13 | ///
14 | ///
15 | ///
16 | ///
17 | Point3d PlaneLineIntersection(Plane plane, Line line);
18 |
19 |
20 | }
21 |
22 | }
--------------------------------------------------------------------------------
/Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/CommonReferencesTests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | true
13 |
14 |
15 | $(MSBuildThisFileDirectory)\test.$(Configuration).runsettings
16 |
17 |
18 |
--------------------------------------------------------------------------------
/BuildYakOnlyRhino7.bat:
--------------------------------------------------------------------------------
1 | call "CommonVariables.bat"
2 | call "%VsDevTools%"
3 |
4 | set Configuration=ReleaseR7
5 |
6 | REM build Yak package
7 | set Stage=BuildYakPackage
8 | msbuild /t:%Stage% /p:Configuration=%Configuration% PluginGrasshopper\PluginGrasshopper.csproj || GOTO error
9 |
10 | :done
11 | if "%~1"=="" (
12 | set /p=Done. Hit ENTER to close...
13 | %SystemRoot%\explorer.exe %YakTargetDir%
14 | )
15 | exit /b 0
16 |
17 | :error
18 | if "%~1"=="" (
19 | if "%Stage%"=="" (
20 | set /p=An error happened. Hit ENTER to close...
21 | ) else (
22 | set /p=An error happened in stage %Stage%. Hit ENTER to close...
23 | )
24 | )
25 | exit /b 1
26 |
--------------------------------------------------------------------------------
/BuildYakOnlyRhino8.bat:
--------------------------------------------------------------------------------
1 | call "CommonVariables.bat"
2 | call "%VsDevTools%"
3 |
4 | set Configuration=ReleaseR8
5 |
6 | REM build Yak package
7 | set Stage=BuildYakPackage
8 | msbuild /t:%Stage% /p:Configuration=%Configuration% PluginGrasshopper\PluginGrasshopper.csproj || GOTO error
9 |
10 | :done
11 | if "%~1"=="" (
12 | set /p=Done. Hit ENTER to close...
13 | %SystemRoot%\explorer.exe %YakTargetDir%
14 | )
15 | exit /b 0
16 |
17 | :error
18 | if "%~1"=="" (
19 | if "%Stage%"=="" (
20 | set /p=An error happened. Hit ENTER to close...
21 | ) else (
22 | set /p=An error happened in stage %Stage%. Hit ENTER to close...
23 | )
24 | )
25 | exit /b 1
26 |
--------------------------------------------------------------------------------
/CommonReferencesGrasshopper.csproj:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/PluginGrasshopper/PluginLoader.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper;
2 | using Grasshopper.Kernel;
3 | using System;
4 | using System.Drawing;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 |
8 | namespace PluginTemplate.PluginGrasshopper
9 | {
10 | public class PluginLoader : GH_AssemblyPriority
11 | {
12 | public override GH_LoadingInstruction PriorityLoad()
13 | {
14 | Instances.ComponentServer.AddCategoryIcon("PluginTemplate", ResourceLoader.LoadBitmap("PluginGrasshopper_16.png"));
15 | Instances.ComponentServer.AddCategorySymbolName("PluginTemplate", 'P');
16 | return GH_LoadingInstruction.Proceed;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/SharedRhino/src/SharedRhinoExample.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Rhino.Geometry;
3 |
4 | namespace PluginTemplate.SharedRhino
5 | {
6 |
7 | ///
8 | /// Example implementation of a shared interface dependent on RhinoCommon.
9 | ///
10 | public class SharedRhinoExample : ISharedRhinoExample
11 | {
12 | public Point3d PlaneLineIntersection(Plane plane, Line line)
13 | {
14 | if (Rhino.Geometry.Intersect.Intersection.LinePlane(line, plane, out double lineParameter))
15 | {
16 | return line.PointAt(lineParameter);
17 | }
18 | throw new Exception("Line does not intersect plane.");
19 | }
20 | }
21 |
22 | }
23 |
--------------------------------------------------------------------------------
/PackagesRhino7.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/CommonVariables.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 |
3 | REM VsDevTools might need to be adapted according your installation of Visual Studio
4 | set "VsDevTools=C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd.bat"
5 |
6 | REM where to find yak
7 | if exist "C:\Program Files\Rhino 8\System\yak.exe" (
8 | set "YakExecutable=C:\Program Files\Rhino 8\System\yak.exe"
9 | ) else if exist "C:\Program Files\Rhino 7\System\yak.exe" (
10 | set "YakExecutable=C:\Program Files\Rhino 7\System\yak.exe"
11 | ) else (
12 | echo [WARN] yak.exe not found in default Rhino 7/8 locations.
13 | set "YakExecutable="
14 | )
15 |
16 | REM name of the solution to build
17 | set "Name=PluginTemplate"
18 |
19 | REM where to copy resulting yak packages
20 | set "YakTargetDir=bin\packages"
21 |
22 |
--------------------------------------------------------------------------------
/PackagesRhino8.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/PluginRhino/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using Rhino.PlugIns;
2 | using System.Reflection;
3 | using System.Runtime.CompilerServices;
4 | using System.Runtime.InteropServices;
5 |
6 | // Plug-in Description Attributes - all of these are optional.
7 | // These will show in Rhino's option dialog, in the tab Plug-ins.
8 | [assembly: PlugInDescription(DescriptionType.Address, "")]
9 | [assembly: PlugInDescription(DescriptionType.Country, "")]
10 | [assembly: PlugInDescription(DescriptionType.Email, "")]
11 | [assembly: PlugInDescription(DescriptionType.Phone, "")]
12 | [assembly: PlugInDescription(DescriptionType.Fax, "")]
13 | [assembly: PlugInDescription(DescriptionType.Organization, "")]
14 | [assembly: PlugInDescription(DescriptionType.UpdateUrl, "")]
15 | [assembly: PlugInDescription(DescriptionType.WebSite, "")]
16 |
17 | // Icons should be Windows .ico files and contain 32-bit images in the following sizes: 16, 24, 32, 48, and 256.
18 | [assembly: PlugInDescription(DescriptionType.Icon, "PluginTemplate.PluginRhino.EmbeddedResources.PluginRhino.ico")]
19 |
20 |
--------------------------------------------------------------------------------
/PluginRhino/PluginRhino.cs:
--------------------------------------------------------------------------------
1 | using Rhino;
2 | using System;
3 |
4 | namespace PluginTemplate.PluginRhino
5 | {
6 | ///
7 | /// Every RhinoCommon .rhp assembly must have one and only one PlugIn-derived
8 | /// class. DO NOT create instances of this class yourself. It is the
9 | /// responsibility of Rhino to create an instance of this class.
10 | /// To complete plug-in information, please also see all PlugInDescription
11 | /// attributes in AssemblyInfo.cs
12 | ///
13 | public class PluginRhino : Rhino.PlugIns.PlugIn
14 | {
15 | public PluginRhino()
16 | {
17 | Instance = this;
18 | }
19 |
20 | ///Gets the only instance of the MyRhinoPlugin1 plug-in.
21 | public static PluginRhino Instance { get; private set; }
22 |
23 | // You can override methods here to change the plug-in behavior on
24 | // loading and shut down, add options pages to the Rhino _Option command
25 | // and maintain plug-in wide options in a document.
26 | }
27 | }
--------------------------------------------------------------------------------
/BuildRhino7.bat:
--------------------------------------------------------------------------------
1 | call "CommonVariables.bat"
2 | call "%VsDevTools%"
3 |
4 | set Configuration=ReleaseR7
5 |
6 | REM prepare build Yak package
7 | set Stage=PrepareBuildYakPackage
8 | msbuild /t:%Stage% /p:Configuration=%Configuration% %Name%.sln || GOTO error
9 |
10 | REM build
11 | set Stage=restore
12 | msbuild /t:%Stage% /p:Configuration=%Configuration% %Name%.sln || GOTO error
13 | set Stage=build
14 | msbuild /t:%Stage% /p:Configuration=%Configuration% /p:TreatWarningsAsErrors=true %Name%.sln || GOTO error
15 |
16 | REM build Yak package
17 | set Stage=BuildYakPackage
18 | msbuild /t:%Stage% /p:Configuration=%Configuration% PluginGrasshopper\PluginGrasshopper.csproj || GOTO error
19 |
20 | :done
21 | if "%~1"=="" (
22 | set /p=Done. Hit ENTER to close...
23 | %SystemRoot%\explorer.exe %YakTargetDir%
24 | )
25 | exit /b 0
26 |
27 | :error
28 | if "%~1"=="" (
29 | if "%Stage%"=="" (
30 | set /p=An error happened. Hit ENTER to close...
31 | ) else (
32 | set /p=An error happened in stage %Stage%. Hit ENTER to close...
33 | )
34 | )
35 | exit /b 1
36 |
--------------------------------------------------------------------------------
/BuildRhino8.bat:
--------------------------------------------------------------------------------
1 | call "CommonVariables.bat"
2 | call "%VsDevTools%"
3 |
4 | set Configuration=ReleaseR8
5 |
6 | REM prepare build Yak package
7 | set Stage=PrepareBuildYakPackage
8 | msbuild /t:%Stage% /p:Configuration=%Configuration% %Name%.sln || GOTO error
9 |
10 | REM build
11 | set Stage=restore
12 | msbuild /t:%Stage% /p:Configuration=%Configuration% %Name%.sln || GOTO error
13 | set Stage=build
14 | msbuild /t:%Stage% /p:Configuration=%Configuration% /p:TreatWarningsAsErrors=true %Name%.sln || GOTO error
15 |
16 | REM build Yak package
17 | set Stage=BuildYakPackage
18 | msbuild /t:%Stage% /p:Configuration=%Configuration% PluginGrasshopper\PluginGrasshopper.csproj || GOTO error
19 |
20 | :done
21 | if "%~1"=="" (
22 | set /p=Done. Hit ENTER to close...
23 | %SystemRoot%\explorer.exe %YakTargetDir%
24 | )
25 | exit /b 0
26 |
27 | :error
28 | if "%~1"=="" (
29 | if "%Stage%"=="" (
30 | set /p=An error happened. Hit ENTER to close...
31 | ) else (
32 | set /p=An error happened in stage %Stage%. Hit ENTER to close...
33 | )
34 | )
35 | exit /b 1
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 ShapeDiver
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Directory.Packages.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
6 |
7 | true
8 |
9 | false
10 | true
11 |
12 |
15 |
16 |
19 |
20 |
23 |
24 |
--------------------------------------------------------------------------------
/CommonTasks.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/Shared/Shared.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | $(CommonNamespace).Shared
9 | $(CommonName).Shared
10 | Shared functionality not depending on Rhino
11 |
15 | true
16 | true
17 | true
18 | true
19 |
20 |
21 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/SharedRhino/SharedRhino.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | $(CommonNamespace).SharedRhino
10 | $(CommonName).SharedRhino
11 | Shared functionality depending on Rhino
12 |
16 | true
17 | true
18 | true
19 | true
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/TestShared/TestShared.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | $(CommonNamespace).Tests.Shared
10 | $(CommonName).Tests.Shared
11 | Tests for shared functionality not depending on Rhino
12 |
16 | true
17 | true
18 | true
19 | true
20 |
21 |
22 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/PluginGrasshopper/Properties/ResourceLoader.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Drawing;
4 | using System.IO;
5 | using System.Linq;
6 | using System.Text;
7 | using System.Threading.Tasks;
8 |
9 | namespace PluginTemplate.PluginGrasshopper
10 | {
11 | ///
12 | /// Load and convert embedded assembly resources
13 | ///
14 | internal static class ResourceLoader
15 | {
16 | static string GetResourcePath(string resourceName)
17 | {
18 | return $"{typeof(ResourceLoader).Namespace}.EmbeddedResources.{resourceName}";
19 | }
20 |
21 | public static Bitmap LoadBitmap(string resourceName)
22 | {
23 | var assembly = typeof(ResourceLoader).Assembly;
24 | using (var stream = assembly.GetManifestResourceStream(GetResourcePath(resourceName)))
25 | {
26 | if (stream == null)
27 | throw new Exception($"Failed to load resource {resourceName}");
28 | return new Bitmap(stream);
29 | }
30 | }
31 |
32 | public static Icon LoadIcon (string resourceName)
33 | {
34 | var assembly = typeof(ResourceLoader).Assembly;
35 | using (var stream = assembly.GetManifestResourceStream(GetResourcePath(resourceName)))
36 | {
37 | if (stream == null)
38 | throw new Exception($"Failed to load resource {resourceName}");
39 | return new Icon(stream);
40 | }
41 | }
42 |
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/TestSharedRhino/TestSharedRhino.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 | $(CommonNamespace).Tests.SharedRhino
11 | $(CommonName).Tests.SharedRhino
12 | Tests for shared functionality depending on Rhino
13 |
17 | true
18 | true
19 | true
20 | true
21 |
22 |
23 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/CommonReferencesRhino.csproj:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | $(ProgramW6432)\Rhino 7\System\Rhino.exe
13 |
14 |
15 | Program
16 | false
17 |
18 |
19 | $(DefineConstants),RHINOCOMMON_EQUAL_7
20 | $(DefineConstants),RHINOCOMMON_GREATER_EQUAL_7
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | $(ProgramW6432)\Rhino 8\System\Rhino.exe
29 |
30 |
31 | Program
32 | false
33 |
34 |
35 | $(DefineConstants),RHINOCOMMON_EQUAL_8
36 | $(DefineConstants),RHINOCOMMON_GREATER_EQUAL_7
37 | $(DefineConstants),RHINOCOMMON_GREATER_EQUAL_8
38 |
39 |
40 |
41 |
42 |
--------------------------------------------------------------------------------
/CommonReferencesSystemDrawing.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 |
11 |
12 |
17 |
18 |
19 | $(MSBuildThisFileDirectory)\References\MacOS\System.Drawing.Common.dll
20 | False
21 |
22 |
23 |
27 |
28 | $(DefineConstants),USING_MCNEEL_SYSTEM_DRAWING
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/TestShared/TestSharedExample.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | using PluginTemplate.Shared;
5 |
6 | namespace PluginTemplate.Tests.Shared
7 | {
8 | [TestClass]
9 | public class TestSharedExample
10 | {
11 | ///
12 | /// Test setup for complete class, will be called once for all tests contained herein
13 | /// Change signature to "async static Task" in case of async tests
14 | ///
15 | ///
16 | [ClassInitialize]
17 | public static void ClassInitialize(TestContext context)
18 | {
19 | // TODO
20 | }
21 |
22 | ///
23 | /// Test setup per test, will be called once for each test
24 | /// Change signature to "async Task" in case of async tests
25 | ///
26 | [TestInitialize]
27 | public void TestInitialize()
28 | {
29 | // TODO
30 | }
31 |
32 | ///
33 | /// Test method
34 | /// Change signature to "async Task" in case of async tests
35 | ///
36 | [TestMethod]
37 | public void Test_Add_00()
38 | {
39 | var sharedExample = new SharedExample();
40 | Assert.AreEqual(3, sharedExample.Add(1, 2));
41 | }
42 |
43 | ///
44 | /// Test cleanup per test, will be called once for each test
45 | /// Change signature to "async Task" in case of async tests
46 | ///
47 | [TestCleanup]
48 | public void TestCleanup()
49 | {
50 | // TODO
51 | }
52 |
53 | ///
54 | /// Test cleanup for complete class, will be called once for all tests contained herein
55 | /// Change signature to "async static Task" in case of async tests
56 | ///
57 | [ClassCleanup]
58 | public static void ClassCleanup()
59 | {
60 | // TODO
61 | }
62 | }
63 | }
--------------------------------------------------------------------------------
/PluginRhino/Commands/ExampleCommand.cs:
--------------------------------------------------------------------------------
1 | using Rhino;
2 | using Rhino.Commands;
3 | using Rhino.Geometry;
4 | using Rhino.Input;
5 | using Rhino.Input.Custom;
6 | using System;
7 | using System.Collections.Generic;
8 |
9 | namespace PluginTemplate.PluginRhino
10 | {
11 | public class ExampleCommand : Command
12 | {
13 | public ExampleCommand()
14 | {
15 | // Rhino only creates one instance of each command class defined in a
16 | // plug-in, so it is safe to store a refence in a static property.
17 | Instance = this;
18 | }
19 |
20 | ///The only instance of this command.
21 | public static ExampleCommand Instance { get; private set; }
22 |
23 | ///The command name as it appears on the Rhino command line.
24 | public override string EnglishName => "PluginTemplateExampleCommand";
25 |
26 | protected override Result RunCommand(RhinoDoc doc, RunMode mode)
27 | {
28 | /// The following code shows a possibility to differentiate between versions of RhinoCommon and .NET at compile time.
29 |
30 | /// The RHINOCOMMON_* constants are defined in "CommonReferencesRhino.csproj"
31 | #if RHINOCOMMON_EQUAL_7
32 | RhinoApp.WriteLine("RHINOCOMMON_EQUAL_7 is defined.");
33 | #endif
34 |
35 | #if RHINOCOMMON_EQUAL_8
36 | RhinoApp.WriteLine("RHINOCOMMON_EQUAL_8 is defined.");
37 | #endif
38 |
39 | #if RHINOCOMMON_GREATER_EQUAL_7
40 | RhinoApp.WriteLine("RHINOCOMMON_GREATER_EQUAL_7 is defined.");
41 | #endif
42 |
43 | #if RHINOCOMMON_GREATER_EQUAL_8
44 | RhinoApp.WriteLine("RHINOCOMMON_GREATER_EQUAL_8 is defined.");
45 | #endif
46 |
47 | /// see https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/preprocessor-directives
48 | #if NETFRAMEWORK
49 | RhinoApp.WriteLine("NETFRAMEWORK is defined.");
50 | #endif
51 |
52 | #if NET7_0_OR_GREATER
53 | RhinoApp.WriteLine("NET7_0_OR_GREATER is defined.");
54 | #endif
55 |
56 | return Result.Success;
57 | }
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/PluginRhino/PluginRhino.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | $(CommonNamespace).PluginRhino
10 | $(CommonName).PluginRhino
11 | $(CommonName)
12 | $(Product)
13 | .rhp
14 |
18 | true
19 | true
20 | true
21 | true
22 |
26 | true
27 |
28 |
29 |
34 |
35 |
36 |
37 |
38 |
39 |
43 |
44 | <_Parameter1>$(RhinoPluginGuid)
45 |
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/CommonVariables.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
13 |
14 | 0
15 | 1
16 | 0
17 |
20 | -alpha
21 |
22 |
25 |
26 | 00000000-0000-0000-0000-000000000000
27 | 00000000-0000-0000-0000-000000000000
28 |
29 |
33 |
34 | PluginTemplate
35 | PluginTemplate
36 |
37 |
40 |
41 | Alex Schiftner
42 | alex@shapediver.com
43 | ShapeDiver
44 | ShapeDiver GmbH 2024
45 | A template plug-in for Grasshopper and Rhino
46 | $(CommonName)
47 | $(CommonAuthors), $(CommonCompany)
48 | $(CommonProduct)
49 | https://github.com/shapediver/GrasshopperPluginTemplate
50 | $(MSBuildThisFileDirectory)/Artwork/PluginRhino_64.png
51 | - Rhino
52 | - Grasshopper
53 | - Template
54 |
55 |
56 |
--------------------------------------------------------------------------------
/TestSharedRhino/TestSharedRhinoExample.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using Microsoft.VisualStudio.TestTools.UnitTesting;
3 |
4 | using Rhino.Geometry;
5 | using PluginTemplate.SharedRhino;
6 |
7 | namespace PluginTemplate.Tests.SharedRhino
8 | {
9 | [TestClass]
10 | public class TestSharedRhinoExample
11 | {
12 | ///
13 | /// Test setup for complete class, will be called once for all tests contained herein
14 | /// Change signature to "async static Task" in case of async tests
15 | ///
16 | ///
17 | [ClassInitialize]
18 | public static void ClassInitialize(TestContext context)
19 | {
20 | // TODO
21 | }
22 |
23 | ///
24 | /// Test setup per test, will be called once for each test
25 | /// Change signature to "async Task" in case of async tests
26 | ///
27 | [TestInitialize]
28 | public void TestInitialize()
29 | {
30 | // TODO
31 | }
32 |
33 | ///
34 | /// Test method
35 | /// Change signature to "async Task" in case of async tests
36 | ///
37 | [TestMethod]
38 | public void Test_PlaneLineIntersection_00()
39 | {
40 | var sharedRhinoExample = new SharedRhinoExample();
41 | var point = sharedRhinoExample.PlaneLineIntersection(Plane.WorldXY, new Line(new Point3d(1,1,-1), new Point3d(1,1,1)));
42 | Assert.AreEqual(0, point.DistanceToSquared(new Point3d(1,1,0)));
43 | }
44 |
45 | ///
46 | /// Test cleanup per test, will be called once for each test
47 | /// Change signature to "async Task" in case of async tests
48 | ///
49 | [TestCleanup]
50 | public void TestCleanup()
51 | {
52 | // TODO
53 | }
54 |
55 | ///
56 | /// Test cleanup for complete class, will be called once for all tests contained herein
57 | /// Change signature to "async static Task" in case of async tests
58 | ///
59 | [ClassCleanup]
60 | public static void ClassCleanup()
61 | {
62 | // TODO
63 | }
64 | }
65 | }
--------------------------------------------------------------------------------
/PluginGrasshopper/PluginGrasshopper.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | $(CommonNamespace).PluginGrasshopper
12 | $(CommonName).PluginGrasshopper
13 | $(CommonName)
14 | $(Product)
15 | .gha
16 |
20 | true
21 | true
22 | true
23 | true
24 |
28 | true
29 |
30 |
31 |
36 |
37 |
38 |
39 |
40 |
41 |
45 |
46 | <_Parameter1>$(GrasshopperPluginGuid)
47 |
48 |
49 |
50 |
51 |
52 |
53 |
--------------------------------------------------------------------------------
/PluginGrasshopper/Components/ExampleComponent.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper;
2 | using Grasshopper.Kernel;
3 | using Rhino.Geometry;
4 | using System;
5 | using System.Collections.Generic;
6 |
7 | namespace PluginTemplate.PluginGrasshopper
8 | {
9 | public class ExampleComponent : GH_Component
10 | {
11 | ///
12 | /// Each implementation of GH_Component must provide a public
13 | /// constructor without any arguments.
14 | /// Category represents the Tab in which the component will appear,
15 | /// Subcategory the panel. If you use non-existing tab or panel names,
16 | /// new tabs/panels will automatically be created.
17 | ///
18 | public ExampleComponent()
19 | : base("ExampleComponent", "Nickname",
20 | "Description",
21 | "PluginTemplate", "Example")
22 | {
23 | }
24 |
25 | ///
26 | /// Registers all the input parameters for this component.
27 | ///
28 | protected override void RegisterInputParams(GH_Component.GH_InputParamManager pManager)
29 | {
30 | }
31 |
32 | ///
33 | /// Registers all the output parameters for this component.
34 | ///
35 | protected override void RegisterOutputParams(GH_Component.GH_OutputParamManager pManager)
36 | {
37 | }
38 |
39 | ///
40 | /// This is the method that actually does the work.
41 | ///
42 | /// The DA object can be used to retrieve data from input parameters and
43 | /// to store data in output parameters.
44 | protected override void SolveInstance(IGH_DataAccess DA)
45 | {
46 | }
47 |
48 | ///
49 | /// Provides an Icon for every component that will be visible in the User Interface.
50 | /// Icons need to be 24x24 pixels.
51 | /// You can add image files to your project resources and access them like this:
52 | /// return Resources.IconForThisComponent;
53 | ///
54 | protected override System.Drawing.Bitmap Icon => ResourceLoader.LoadBitmap("PluginGrasshopper_24.png");
55 |
56 | ///
57 | /// Each component must have a unique Guid to identify it.
58 | /// It is vital this Guid doesn't change otherwise old ghx files
59 | /// that use the old ID will partially fail during loading.
60 | ///
61 | public override Guid ComponentGuid => new Guid("69E66DAA-0427-4ABF-9CE9-277D645F4A7D");
62 | }
63 | }
--------------------------------------------------------------------------------
/CommonTargets.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 | $(OutputPath)/net48
9 |
10 |
11 | $(OutputPath)
12 |
13 |
14 | $(YakBuildPath)/manifest.yml
15 |
16 |
19 |
20 |
21 |
22 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/TestSharedRhino/RhinoInsideInit.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.VisualStudio.TestTools.UnitTesting;
2 | using Microsoft.Win32;
3 | using System;
4 | using System.IO;
5 | using System.Reflection;
6 |
7 | using RRT = Rhino.Runtime;
8 |
9 | namespace PluginTemplate.Tests.SharedRhino
10 | {
11 | ///
12 | /// Shared VS test assembly class using Rhino.Inside.
13 | /// Inspired by this repo: https://github.com/tmakin/RhinoCommonUnitTesting
14 | ///
15 | [TestClass]
16 | public static class RhinoInsideInit
17 | {
18 | private static bool initialized = false;
19 | private static string rhinoDir;
20 |
21 |
22 | [AssemblyInitialize]
23 | public static void AssemblyInitialize(TestContext context)
24 | {
25 | //get the correct rhino 7 installation directory
26 | #if RHINOCOMMON_GREATER_EQUAL_8
27 | rhinoDir = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\McNeel\Rhinoceros\8.0\Install", "Path", null) as string ?? string.Empty;
28 | #elif RHINOCOMMON_GREATER_EQUAL_7
29 | rhinoDir = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\McNeel\Rhinoceros\7.0\Install", "Path", null) as string ?? string.Empty;
30 | #endif
31 | Assert.IsTrue(System.IO.Directory.Exists(rhinoDir), "Rhino system dir not found: {0}", rhinoDir);
32 | context.WriteLine(" The current Rhino installation is " + rhinoDir);
33 |
34 | if (initialized)
35 | {
36 | throw new InvalidOperationException("Initialize Rhino.Inside once");
37 | }
38 | else
39 | {
40 | RhinoInside.Resolver.Initialize();
41 | initialized = true;
42 | context.WriteLine("Rhino.Inside init has started");
43 | }
44 |
45 | // Ensure we are running the tests in x64
46 | Assert.IsTrue(Environment.Is64BitProcess, "Tests must be run as x64");
47 |
48 | // Set path to rhino system directory
49 | string envPath = Environment.GetEnvironmentVariable("path");
50 | Environment.SetEnvironmentVariable("path", envPath + ";" + rhinoDir);
51 |
52 | // Start a headless rhino instance using Rhino.Inside
53 | StartRhino();
54 |
55 | // We have to load grasshopper.dll on the current AppDomain manually for some reason
56 | AppDomain.CurrentDomain.AssemblyResolve += ResolveGrasshopper;
57 | }
58 |
59 | ///
60 | /// Starting Rhino - loading the relevant libraries
61 | ///
62 | [STAThread]
63 | public static void StartRhino()
64 | {
65 | #if RHINOCOMMON_GREATER_EQUAL_7
66 | var _rhinoCore = new RRT.InProcess.RhinoCore(null, RRT.InProcess.WindowStyle.NoWindow);
67 | #endif
68 | }
69 |
70 |
71 | ///
72 | /// Add Grasshopper.dll to the current Appdomain
73 | ///
74 | private static Assembly ResolveGrasshopper(object sender, ResolveEventArgs args)
75 | {
76 | var name = args.Name;
77 |
78 | if (name.StartsWith("Grasshopper"))
79 | {
80 | var path = Path.Combine(Path.GetFullPath(Path.Combine(rhinoDir, @"..\")), "Plug-ins\\Grasshopper\\Grasshopper.dll");
81 | return Assembly.LoadFrom(path);
82 | }
83 | if (name.StartsWith("GH_IO"))
84 | {
85 | var path = Path.Combine(Path.GetFullPath(Path.Combine(rhinoDir, @"..\")), "Plug-ins\\Grasshopper\\GH_IO.dll");
86 | return Assembly.LoadFrom(path);
87 | }
88 | else
89 | {
90 | return null;
91 | }
92 |
93 |
94 |
95 | }
96 | }
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/PluginGrasshopper/PluginInfo.cs:
--------------------------------------------------------------------------------
1 | using Grasshopper;
2 | using Grasshopper.Kernel;
3 | using System;
4 | using System.Drawing;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 |
8 | namespace PluginTemplate.PluginGrasshopper
9 | {
10 | public class PluginInfo : GH_AssemblyInfo
11 | {
12 | public override string Name
13 | {
14 | get
15 | {
16 | return Assembly.GetExecutingAssembly().GetCustomAttribute().Title;
17 | }
18 | }
19 |
20 | public override Bitmap Icon => ResourceLoader.LoadBitmap("PluginGrasshopper_24.png");
21 |
22 | public override Bitmap AssemblyIcon => Icon;
23 |
24 | public override string Description
25 | {
26 | get
27 | {
28 | var description = Assembly.GetExecutingAssembly().GetCustomAttribute().Description;
29 | var configuration = Assembly.GetExecutingAssembly().GetCustomAttribute().Configuration;
30 | if (configuration.ToLowerInvariant().Contains("debug"))
31 | {
32 | description = $"{description}, {Version} ({configuration})";
33 | }
34 | return description;
35 | }
36 | }
37 |
38 | public override string AssemblyDescription => Description;
39 |
40 | public override Guid Id
41 | {
42 | get
43 | {
44 | return new Guid(Assembly.GetExecutingAssembly().GetCustomAttribute().Value);
45 | }
46 | }
47 |
48 | public override string AuthorName
49 | {
50 | get
51 | {
52 | var company = Assembly.GetExecutingAssembly().GetCustomAttribute().Company;
53 |
54 | var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes();
55 | if (attributes != null)
56 | {
57 | foreach (var attribute in attributes)
58 | {
59 | if (attribute.Key == "Authors")
60 | {
61 | return $"{attribute.Value}, {company}";
62 | }
63 | }
64 | }
65 |
66 | return company;
67 | }
68 | }
69 |
70 | public override string AuthorContact
71 | {
72 | get
73 | {
74 | var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes();
75 | if (attributes != null)
76 | {
77 | foreach (var attribute in attributes)
78 | {
79 | if (attribute.Key == "AuthorContact")
80 | {
81 | return attribute.Value;
82 | }
83 | }
84 | }
85 | return "";
86 | }
87 | }
88 |
89 | public override string Version
90 | {
91 | get
92 | {
93 | var version = Assembly.GetExecutingAssembly().GetCustomAttribute().InformationalVersion;
94 | return version.ToString();
95 | }
96 | }
97 |
98 | public override string AssemblyVersion
99 | {
100 | get
101 | {
102 | var version = Assembly.GetExecutingAssembly().GetCustomAttribute().InformationalVersion;
103 | return version.ToString();
104 | }
105 | }
106 | }
107 | }
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Grasshopper and Rhino Plug-in Template
2 | This repository contains a template for plug-ins to Grasshopper and [Rhino](https://www.rhino3d.com/).
3 | The template follows best practices we use at ShapeDiver.
4 |
5 | ## Features
6 |
7 | ### Centralized versioning and metadata
8 |
9 | see [CommonVariables.csproj](CommonVariables.csproj)
10 |
11 | The version of all assemblies built by the solution can be configured in a central place.
12 | The same principle is used for further metadata like plug-in authorship, and properties
13 | of the [Package Manifest](https://developer.rhino3d.com/guides/yak/the-package-manifest/)
14 | for the [Yak Package Manager](https://developer.rhino3d.com/guides/yak/).
15 |
16 |
17 | ### Centralized nuget package versioning
18 | see [Directory.Packages.props](Directory.Packages.props)
19 |
20 | Version of nuget packages are configured in a central place for all projects.
21 |
22 | ### Shared assembly between Grasshopper and Rhino plug-in
23 |
24 | The setup includes two shared assemblies:
25 |
26 | * [Shared](Shared) for shared code which does not depend on Rhino.
27 | * [SharedRhino](SharedRhino) for shared code depending on Rhino.
28 |
29 | ### Setup for unit tests, including tests using Rhino.Inside
30 |
31 | Two test projects are used for unit testing of the shared assemblies. Since [Rhino.Inside](https://github.com/mcneel/rhino.inside) this is very useful,
32 | because one can test and debug code depending on Rhino without starting Rhino.
33 |
34 | * [TestShared](TestShared) tests for the assembly [Shared](Shared)
35 | * [TestSharedRhino](TestSharedRhino) tests for the assembly [SharedRhino](SharedRhino)
36 |
37 | How to use this? Start the _Test Explorer_ in Visual Studio.
38 |
39 | ### Build scripts for Rhino 7 and 8, Windows and Mac
40 |
41 | The solution includes separate build configurations for Rhino 7 and Rhino 8. Rhino 6 can easily be added.
42 |
43 | The following batch scripts are available for building using a single click.
44 |
45 | * [BuildRhino7.bat](BuildRhino7.bat) build for Rhino 7 including yak package
46 | * [BuildRhino8.bat](BuildRhino8.bat) build for Rhino 8 including yak package
47 | * [BuildYakOnlyRhino7.bat](BuildYakOnlyRhino7.bat) build yak package for Rhino 7 (requires the plugins to be built separately beforehand)
48 | * [BuildYakOnlyRhino8.bat](BuildYakOnlyRhino8.bat) build yak package for Rhino 8 (requires the plugins to be built separately beforehand)
49 |
50 | ### Multi-targeting for Rhino 8
51 |
52 | The solution is configured to build a multi-targeted yak package in case of Rhino 8 (.NET Framework 4.8, .NET 7 for Windows and Mac).
53 |
54 | Note: There is still a [bug related to this](https://discourse.mcneel.com/t/net-multi-targeting-for-yak-packages/166183/10?u=snabela) in yak for Rhino 8 SR 4, this should be fixed soon.
55 |
56 |
57 | ## How to use this
58 |
59 | Download the code or fork the repository.
60 | Please open GitHub issues or submit a PR in case you find a problem or have suggestions for improvement.
61 |
62 | Building the solution is supposed work out of the box in Visual Studio 2022.
63 | We still need to test and add instructions for building using Visual Studio Code on Mac.
64 |
65 | The following steps are important when starting your own plug-in from this:
66 |
67 | * Review and adapt the variable values in [CommonVariables.csproj](CommonVariables.csproj).
68 | * Create a new Guid for the Grasshopper plug-in and replace `00000000-0000-0000-0000-000000000000`.
69 | * Create a new Guid for the Rhino plug-in and replace `00000000-0000-0000-0000-000000000000`.
70 | * Set your version number.
71 | * Adapt information about Author, Company, Copyright, Product
72 | * Review and adapt the variable values in [CommonVariables.bat](CommonVariables.bat).
73 | * Installation path of Visual Studio
74 | * Path to Yak package manager
75 | * In case you don't need a Rhino or Grasshopper plug-in, remove it from the solution.
76 | * Set Rhino plug-in metadata in [AssemblyInfo.cs](PluginRhino/Properties/AssemblyInfo.cs) (still need to implement to create this automatically).
77 | * Adapt the images in [PluginGrasshopper/EmbeddedResources](PluginGrasshopper/EmbeddedResources) and [PluginRhino/EmbeddedResources](PluginRhino/EmbeddedResources).
78 |
79 |
80 |
--------------------------------------------------------------------------------
/CommonSettings.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
7 |
8 |
11 |
12 |
13 |
16 |
17 | DebugR7
18 | DebugR7;DebugR8;ReleaseR7;ReleaseR8
19 | $(MSBuildThisFileDirectory)\bin\$(Configuration)\
20 |
21 |
22 |
26 |
27 | net48
28 |
29 |
30 | net48;net8.0-windows
31 |
32 |
33 | $(TargetFrameworks);net7.0-windows
34 |
35 |
36 |
39 |
40 |
44 | 7.3
45 |
49 | true
50 |
55 | True
56 | True
57 | $(DefaultItemExcludes);Windows\**\*
58 | $(DefaultItemExcludes);MacOS\**\*
59 |
60 |
61 |
65 |
71 |
72 |
75 |
76 | $([System.DateTime]::Now.ToString("o"))
77 |
78 |
79 |
82 |
83 | true
84 | full
85 | false
86 | $(DefineConstants),DEBUG,TRACE
87 | prompt
88 | 4
89 |
90 |
91 |
92 | pdbonly
93 | true
94 | $(DefineConstants)
95 | prompt
96 | 4
97 |
98 |
99 |
105 |
106 |
107 |
108 |
109 |
113 |
114 | true
115 | $(CommonVersionMajor).$(CommonVersionMinor).$(CommonVersionPatch)$(CommonVersionSuffix)
116 | $(CommonAuthors)
117 | $(CommonCompany)
118 | $(CommonCopyright)
119 | $(CommonProduct)
120 |
126 | false
127 |
128 |
129 |
130 |
135 |
136 | <_Parameter1>AuthorContact
137 | <_Parameter2>$(CommonAuthorContact)
138 |
139 |
140 | <_Parameter1>Authors
141 | <_Parameter2>$(CommonAuthors)
142 |
143 |
144 | <_Parameter1>BuildTimestamp
145 | <_Parameter2>$(BuildTimestamp)
146 |
147 |
148 |
149 |
150 |
153 |
154 |
155 |
158 |
159 |
160 |
161 |
--------------------------------------------------------------------------------
/PluginTemplate.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 17
4 | VisualStudioVersion = 17.8.34408.163
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Shared", "Shared\Shared.csproj", "{DE0D681B-7381-4C5A-8BC9-9468A49530DE}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SharedRhino", "SharedRhino\SharedRhino.csproj", "{979B3977-171C-4556-B258-67DCDB22EA50}"
9 | EndProject
10 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestShared", "TestShared\TestShared.csproj", "{8038AC47-3427-417F-B332-5C690A527EAC}"
11 | EndProject
12 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSharedRhino", "TestSharedRhino\TestSharedRhino.csproj", "{30CF2229-F954-42B2-A309-339276B7FAE5}"
13 | EndProject
14 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Shared", "Shared", "{FAB810F0-1304-456B-AED3-6130C47D9E9E}"
15 | EndProject
16 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{9A99AD89-394A-42BD-AE87-B50612D1F2DC}"
17 | EndProject
18 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Plugins", "Plugins", "{81FD4852-BD3E-4D54-85F4-1D38CBDB9EF5}"
19 | EndProject
20 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PluginGrasshopper", "PluginGrasshopper\PluginGrasshopper.csproj", "{72892D62-9108-4903-851F-2FD850096605}"
21 | EndProject
22 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "PluginRhino", "PluginRhino\PluginRhino.csproj", "{1868DD53-EF87-4564-A98B-C377DC38847B}"
23 | EndProject
24 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{BE2713C1-7811-4EE6-A885-7E3A904B43A7}"
25 | ProjectSection(SolutionItems) = preProject
26 | .gitignore = .gitignore
27 | BuildRhino7.bat = BuildRhino7.bat
28 | BuildRhino8.bat = BuildRhino8.bat
29 | BuildYakOnlyRhino7.bat = BuildYakOnlyRhino7.bat
30 | BuildYakOnlyRhino8.bat = BuildYakOnlyRhino8.bat
31 | CommonReferencesGrasshopper.csproj = CommonReferencesGrasshopper.csproj
32 | CommonReferencesRhino.csproj = CommonReferencesRhino.csproj
33 | CommonReferencesTests.csproj = CommonReferencesTests.csproj
34 | CommonSettings.csproj = CommonSettings.csproj
35 | CommonSettingsFinal.csproj = CommonSettingsFinal.csproj
36 | CommonVariables.bat = CommonVariables.bat
37 | CommonVariables.csproj = CommonVariables.csproj
38 | Directory.Packages.props = Directory.Packages.props
39 | Packages.props = Packages.props
40 | PackagesRhino7.props = PackagesRhino7.props
41 | PackagesRhino8.props = PackagesRhino8.props
42 | README.md = README.md
43 | test.DebugR7.runsettings = test.DebugR7.runsettings
44 | test.DebugR8.runsettings = test.DebugR8.runsettings
45 | TODO.md = TODO.md
46 | EndProjectSection
47 | EndProject
48 | Global
49 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
50 | DebugR7|Any CPU = DebugR7|Any CPU
51 | DebugR8|Any CPU = DebugR8|Any CPU
52 | ReleaseR7|Any CPU = ReleaseR7|Any CPU
53 | ReleaseR8|Any CPU = ReleaseR8|Any CPU
54 | EndGlobalSection
55 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
56 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.DebugR7|Any CPU.ActiveCfg = DebugR7|Any CPU
57 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.DebugR7|Any CPU.Build.0 = DebugR7|Any CPU
58 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.DebugR8|Any CPU.ActiveCfg = DebugR8|Any CPU
59 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.DebugR8|Any CPU.Build.0 = DebugR8|Any CPU
60 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.ReleaseR7|Any CPU.ActiveCfg = ReleaseR7|Any CPU
61 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.ReleaseR7|Any CPU.Build.0 = ReleaseR7|Any CPU
62 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.ReleaseR8|Any CPU.ActiveCfg = ReleaseR8|Any CPU
63 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE}.ReleaseR8|Any CPU.Build.0 = ReleaseR8|Any CPU
64 | {979B3977-171C-4556-B258-67DCDB22EA50}.DebugR7|Any CPU.ActiveCfg = DebugR7|Any CPU
65 | {979B3977-171C-4556-B258-67DCDB22EA50}.DebugR7|Any CPU.Build.0 = DebugR7|Any CPU
66 | {979B3977-171C-4556-B258-67DCDB22EA50}.DebugR8|Any CPU.ActiveCfg = DebugR8|Any CPU
67 | {979B3977-171C-4556-B258-67DCDB22EA50}.DebugR8|Any CPU.Build.0 = DebugR8|Any CPU
68 | {979B3977-171C-4556-B258-67DCDB22EA50}.ReleaseR7|Any CPU.ActiveCfg = ReleaseR7|Any CPU
69 | {979B3977-171C-4556-B258-67DCDB22EA50}.ReleaseR7|Any CPU.Build.0 = ReleaseR7|Any CPU
70 | {979B3977-171C-4556-B258-67DCDB22EA50}.ReleaseR8|Any CPU.ActiveCfg = ReleaseR8|Any CPU
71 | {979B3977-171C-4556-B258-67DCDB22EA50}.ReleaseR8|Any CPU.Build.0 = ReleaseR8|Any CPU
72 | {8038AC47-3427-417F-B332-5C690A527EAC}.DebugR7|Any CPU.ActiveCfg = DebugR7|Any CPU
73 | {8038AC47-3427-417F-B332-5C690A527EAC}.DebugR7|Any CPU.Build.0 = DebugR7|Any CPU
74 | {8038AC47-3427-417F-B332-5C690A527EAC}.DebugR8|Any CPU.ActiveCfg = DebugR8|Any CPU
75 | {8038AC47-3427-417F-B332-5C690A527EAC}.DebugR8|Any CPU.Build.0 = DebugR8|Any CPU
76 | {8038AC47-3427-417F-B332-5C690A527EAC}.ReleaseR7|Any CPU.ActiveCfg = ReleaseR7|Any CPU
77 | {8038AC47-3427-417F-B332-5C690A527EAC}.ReleaseR8|Any CPU.ActiveCfg = ReleaseR8|Any CPU
78 | {30CF2229-F954-42B2-A309-339276B7FAE5}.DebugR7|Any CPU.ActiveCfg = DebugR7|Any CPU
79 | {30CF2229-F954-42B2-A309-339276B7FAE5}.DebugR7|Any CPU.Build.0 = DebugR7|Any CPU
80 | {30CF2229-F954-42B2-A309-339276B7FAE5}.DebugR8|Any CPU.ActiveCfg = DebugR8|Any CPU
81 | {30CF2229-F954-42B2-A309-339276B7FAE5}.DebugR8|Any CPU.Build.0 = DebugR8|Any CPU
82 | {30CF2229-F954-42B2-A309-339276B7FAE5}.ReleaseR7|Any CPU.ActiveCfg = ReleaseR7|Any CPU
83 | {30CF2229-F954-42B2-A309-339276B7FAE5}.ReleaseR8|Any CPU.ActiveCfg = ReleaseR8|Any CPU
84 | {72892D62-9108-4903-851F-2FD850096605}.DebugR7|Any CPU.ActiveCfg = DebugR7|Any CPU
85 | {72892D62-9108-4903-851F-2FD850096605}.DebugR7|Any CPU.Build.0 = DebugR7|Any CPU
86 | {72892D62-9108-4903-851F-2FD850096605}.DebugR8|Any CPU.ActiveCfg = DebugR8|Any CPU
87 | {72892D62-9108-4903-851F-2FD850096605}.DebugR8|Any CPU.Build.0 = DebugR8|Any CPU
88 | {72892D62-9108-4903-851F-2FD850096605}.ReleaseR7|Any CPU.ActiveCfg = ReleaseR7|Any CPU
89 | {72892D62-9108-4903-851F-2FD850096605}.ReleaseR7|Any CPU.Build.0 = ReleaseR7|Any CPU
90 | {72892D62-9108-4903-851F-2FD850096605}.ReleaseR8|Any CPU.ActiveCfg = ReleaseR8|Any CPU
91 | {72892D62-9108-4903-851F-2FD850096605}.ReleaseR8|Any CPU.Build.0 = ReleaseR8|Any CPU
92 | {1868DD53-EF87-4564-A98B-C377DC38847B}.DebugR7|Any CPU.ActiveCfg = DebugR7|Any CPU
93 | {1868DD53-EF87-4564-A98B-C377DC38847B}.DebugR7|Any CPU.Build.0 = DebugR7|Any CPU
94 | {1868DD53-EF87-4564-A98B-C377DC38847B}.DebugR8|Any CPU.ActiveCfg = DebugR8|Any CPU
95 | {1868DD53-EF87-4564-A98B-C377DC38847B}.DebugR8|Any CPU.Build.0 = DebugR8|Any CPU
96 | {1868DD53-EF87-4564-A98B-C377DC38847B}.ReleaseR7|Any CPU.ActiveCfg = ReleaseR7|Any CPU
97 | {1868DD53-EF87-4564-A98B-C377DC38847B}.ReleaseR7|Any CPU.Build.0 = ReleaseR7|Any CPU
98 | {1868DD53-EF87-4564-A98B-C377DC38847B}.ReleaseR8|Any CPU.ActiveCfg = ReleaseR8|Any CPU
99 | {1868DD53-EF87-4564-A98B-C377DC38847B}.ReleaseR8|Any CPU.Build.0 = ReleaseR8|Any CPU
100 | EndGlobalSection
101 | GlobalSection(SolutionProperties) = preSolution
102 | HideSolutionNode = FALSE
103 | EndGlobalSection
104 | GlobalSection(NestedProjects) = preSolution
105 | {DE0D681B-7381-4C5A-8BC9-9468A49530DE} = {FAB810F0-1304-456B-AED3-6130C47D9E9E}
106 | {979B3977-171C-4556-B258-67DCDB22EA50} = {FAB810F0-1304-456B-AED3-6130C47D9E9E}
107 | {8038AC47-3427-417F-B332-5C690A527EAC} = {9A99AD89-394A-42BD-AE87-B50612D1F2DC}
108 | {30CF2229-F954-42B2-A309-339276B7FAE5} = {9A99AD89-394A-42BD-AE87-B50612D1F2DC}
109 | {72892D62-9108-4903-851F-2FD850096605} = {81FD4852-BD3E-4D54-85F4-1D38CBDB9EF5}
110 | {1868DD53-EF87-4564-A98B-C377DC38847B} = {81FD4852-BD3E-4D54-85F4-1D38CBDB9EF5}
111 | EndGlobalSection
112 | GlobalSection(ExtensibilityGlobals) = postSolution
113 | SolutionGuid = {19C0329D-CEE7-45E5-9852-A4F542A845CD}
114 | EndGlobalSection
115 | EndGlobal
116 |
--------------------------------------------------------------------------------