diff --git a/Rhino.Templates/content/CSGrasshopper2/.template.config/dotnetcli.host.json b/Rhino.Templates/content/CSGrasshopper2/.template.config/dotnetcli.host.json new file mode 100755 index 0000000..7301b0a --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/.template.config/dotnetcli.host.json @@ -0,0 +1,52 @@ +{ + "$schema": "http://json.schemastore.org/dotnetcli.host", + "symbolInfo": { + "IncludeSample": { + "longName": "include-sample", + "shortName": "sample" + }, + "RhinoVersion": { + "longName": "version", + "shortName": "v" + }, + "PlugInDisplayName": { + "longName": "plugin-display-name", + "shortName": "plugin-name" + }, + "ComponentClassName": { + "longName": "component-class", + "shortName": "component" + }, + "ComponentName": { + "longName": "component-name", + "shortName": "cname" + }, + "ComponentInfo": { + "shortName": "info" + }, + "ComponentChapter": { + "longName": "chapter", + "shortName": "ch" + }, + "ComponentSection": { + "longName": "section", + "shortName": "sec" + }, + "UseWpf": { + "longName": "include-wpf", + "shortName": "wpf" + }, + "UseWinForms": { + "longName": "include-winforms", + "shortName": "wf" + }, + "BuildYak": { + "longName": "build-yak", + "shortName": "yak" + }, + "IncludeVSCode": { + "longName": "include-vscode-launch", + "shortName": "vscode" + } + } +} \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/.template.config/ide.host.json b/Rhino.Templates/content/CSGrasshopper2/.template.config/ide.host.json new file mode 100755 index 0000000..fb277c7 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/.template.config/ide.host.json @@ -0,0 +1,8 @@ +{ + "$schema": "http://json.schemastore.org/vs-2017.3.host", + "unsupportedHosts": [ + { + "id": "vs" + } + ] +} \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/.template.config/template.json b/Rhino.Templates/content/CSGrasshopper2/.template.config/template.json new file mode 100755 index 0000000..9fa9008 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/.template.config/template.json @@ -0,0 +1,159 @@ +{ + "$schema": "http://json.schemastore.org/template", + "author": "McNeel", + "classifications": [ + "Rhino", + "Grasshopper2", + "GH2" + ], + "name": "Grasshopper2 PlugIn (WIP)", + "description": "Build Grasshopper2 components for Rhino 3D in C#", + "identity": "Grasshopper2.Component.CS", + "groupIdentity": "Grasshopper2.PlugIn", + "precedence": 100, + "defaultName": "MyGrasshopper2Components", + "shortName": "gh2", + "tags": { + "language": "C#", + "type": "project" + }, + "sourceName": "MyGrasshopper.1", + "preferNameDirectory": true, + "symbols": { + "IncludeSample": { + "type": "parameter", + "description": "Include code sample.", + "dataType": "bool", + "defaultValue": "false" + }, + "RhinoVersion": { + "type": "parameter", + "description": "Version of Rhino", + "datatype": "choice", + "defaultValue": "8", + "choices": [ + { + "choice": "8", + "description": "Version 8" + } + ] + }, + "BuildYak": { + "type": "parameter", + "description": "Include target to build yak package(s) for your plugin", + "datatype": "bool", + "defaultValue": "false" + }, + "IncludeVSCode": { + "type": "parameter", + "description": "Include tasks.json and launch.json to build/debug in VS Code", + "datatype": "bool", + "defaultValue": "true" + }, + "PlugInDisplayName": { + "type": "parameter", + "description": "Display name of your Grasshopper2 plug-in", + "datatype": "text", + "replaces": "MyGrasshopper.1 Info" + }, + "ComponentClassName": { + "type": "parameter", + "description": "Name of the component class", + "datatype": "text", + "replaces": "MyGrasshopper__1Component", + "fileRename": "MyGrasshopper__1Component" + }, + "ComponentName": { + "type": "parameter", + "description": "Display name of the component", + "datatype": "text", + "replaces": "MyGrasshopper.1 Component" + }, + "ComponentInfo": { + "type": "parameter", + "description": "Description of the component", + "replaces": "ComponentInfo", + "defaultValue": "Description of component" + }, + "ComponentChapter": { + "type": "parameter", + "description": "Chapter of the component", + "replaces": "ComponentChapter", + "defaultValue": "Chapter" + }, + "ComponentSection": { + "type": "parameter", + "description": "Section of the component", + "replaces": "ComponentSection", + "defaultValue": "Section" + }, + + "UseWpf": { + "type": "parameter", + "description": "Enable to use WPF (Windows only)", + "datatype": "bool", + "defaultValue": "false" + }, + "UseWinForms": { + "type": "parameter", + "description": "Enable the use of Windows Forms", + "datatype": "bool", + "defaultValue": "false" + }, + "UseWindowsDesktop": { + "type": "computed", + "value": "UseWpf || UseWinForms" + }, + + "HostIdentifier": { + "type": "bind", + "binding": "HostIdentifier" + } + }, + "forms": { + "JsonStringEncode": { + "identifier": "replace", + "pattern": "\\\\", + "replacement": "\\\\" + } + }, + "sources": [ + { + "modifiers": [ + { + "condition": "!IncludeVSCode", + "exclude": [ ".vscode/*.*" ] + }, + { + "condition": "ComponentClassName == 'MyGrasshopper__1Component'", + "rename": { + "MyGrasshopper__1Component.cs": "MyGrasshopper.1Component.cs", + "MyGrasshopper__1Component.3dm": "MyGrasshopper.1Component.3dm", + "MyGrasshopper__1Component.ghicon": "MyGrasshopper.1Component.ghicon" + } + } + ] + } + ], + "primaryOutputs": [ + { "path": "MyGrasshopper.1.csproj" }, + { "path": "MyGrasshopper__1Component.cs" } + ], + "guids": [ + "ee4e2b39-d96b-4e4c-8f9d-9b6561e61b64", + "e79cd2b5-cb9c-4d08-93ec-446cc1f6d923", + "cd826b9b-8dbe-4c31-aac1-6fc7ea2bcfb7" + ], + "postActions": [ + { + "condition": "(HostIdentifier != \"dotnetcli\" && HostIdentifier != \"dotnetcli-preview\")", + "description": "Opens the command in the editor", + "manualInstructions": [], + "actionId": "84C0DA21-51C8-4541-9940-6CA19AF04EE6", + "args": { + "files": "1" + }, + "continueOnError": true + } + ] +} \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/.vscode/launch.json b/Rhino.Templates/content/CSGrasshopper2/.vscode/launch.json new file mode 100644 index 0000000..6d3f097 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/.vscode/launch.json @@ -0,0 +1,47 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Rhino 8 - netcore", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + "program": "", + "osx": { + "program": "/Applications/Rhino 8.app/Contents/MacOS/Rhinoceros", + "args": [ + "-runscript=_G2" + ] + }, + "windows": { + "program": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe", + "targetArchitecture": "x86_64", + "args": "/netcore /runscript=\"_G2\"" + }, + "env": { + "RHINO_PACKAGE_DIRS": "${workspaceFolder}/bin/Debug" + }, + "cwd": "${workspaceFolder}", + "stopAtEntry": false, + "console": "internalConsole" + }, + { + "name": "Rhino 8 Windows - netfx", + "type": "clr", + "request": "launch", + "preLaunchTask": "build", + "windows": { + "program": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe", + "targetArchitecture": "x86_64", + "args": "/netfx /runscript=\"_G2\"" + }, + "env": { + "RHINO_PACKAGE_DIRS": "${workspaceFolder}/bin/Debug" + }, + "cwd": "${workspaceFolder}", + "stopAtEntry": false, + "console": "internalConsole" + }, + ], + "compounds": [] +} \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/.vscode/tasks.json b/Rhino.Templates/content/CSGrasshopper2/.vscode/tasks.json new file mode 100644 index 0000000..20c5e62 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/.vscode/tasks.json @@ -0,0 +1,21 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "shell", + "args": [ + "build", + "-clp:NoSummary", + "${workspaceFolder}/MyGrasshopper.1.csproj" + ], + "problemMatcher": "$msCompile", + "presentation": { + "reveal": "always", + "clear": true + }, + "group": "build" + } + ] +} \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper.1Plugin.3dm b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper.1Plugin.3dm new file mode 100644 index 0000000..114cfcf Binary files /dev/null and b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper.1Plugin.3dm differ diff --git a/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper.1Plugin.ghicon b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper.1Plugin.ghicon new file mode 100644 index 0000000..26fcfab Binary files /dev/null and b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper.1Plugin.ghicon differ diff --git a/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper__1Component.3dm b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper__1Component.3dm new file mode 100644 index 0000000..cf0f299 Binary files /dev/null and b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper__1Component.3dm differ diff --git a/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper__1Component.ghicon b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper__1Component.ghicon new file mode 100644 index 0000000..e3f0e3c Binary files /dev/null and b/Rhino.Templates/content/CSGrasshopper2/Icons/MyGrasshopper__1Component.ghicon differ diff --git a/Rhino.Templates/content/CSGrasshopper2/Icons/plugin.ico b/Rhino.Templates/content/CSGrasshopper2/Icons/plugin.ico new file mode 100644 index 0000000..022d1f7 Binary files /dev/null and b/Rhino.Templates/content/CSGrasshopper2/Icons/plugin.ico differ diff --git a/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1.csproj b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1.csproj new file mode 100755 index 0000000..f0bfde0 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1.csproj @@ -0,0 +1,89 @@ + + + + + + net7.0-windows;net48 + + net7.0-windows;net7.0;net48 + + net7.0;net48 + + true + .rhp + + NU1701;NETSDK1086 + + NU1701 + + true + + + + + 1.0 + MyGrasshopper.1 + MyGrasshopper.1 Authors + Description of MyGrasshopper.1 + + + + + + + + + + + true + + + true + + + + + + + + + + + + + + + + + + + + + + + + + + C:\Program Files\Rhino 8\System\Yak.exe + /Applications/Rhino 8.app/Contents/Resources/bin/yak + + True + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1Plugin.cs b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1Plugin.cs new file mode 100644 index 0000000..f54028a --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1Plugin.cs @@ -0,0 +1,28 @@ +using System; +using Rhino; + +namespace MyGrasshopper._1 +{ + /// + /// Every RhinoCommon .rhp assembly must have one and only one PlugIn-derived + /// class. DO NOT create instances of this class yourself. It is the + /// responsibility of Rhino to create an instance of this class. + /// To complete plug-in information, please also see all PlugInDescription + /// attributes in AssemblyInfo.cs (you might need to click "Project" -> + /// "Show All Files" to see it in the "Solution Explorer" window). + /// + public class MyGrasshopper__1Plugin : Rhino.PlugIns.PlugIn + { + public MyGrasshopper__1Plugin() + { + Instance = this; + } + + ///Gets the only instance of the MyRhino__1Plugin plug-in. + public static MyGrasshopper__1Plugin Instance { get; private set; } + + // You can override methods here to change the plug-in behavior on + // loading and shut down, add options pages to the Rhino _Option command + // and maintain plug-in wide options in a document. + } +} \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1PluginInfo.cs b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1PluginInfo.cs new file mode 100644 index 0000000..0d53186 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper.1PluginInfo.cs @@ -0,0 +1,35 @@ +using System; +using System.Reflection; +using Grasshopper.UI; +using Grasshopper.UI.Icon; + +namespace MyGrasshopper._1 +{ + public sealed class MyGrasshopper__1PluginInfo : Grasshopper.Framework.Plugin + { + static T GetAttribute() where T : Attribute => typeof(MyGrasshopper__1PluginInfo).Assembly.GetCustomAttribute(); + + public MyGrasshopper__1PluginInfo() + : base(new Guid("cd826b9b-8dbe-4c31-aac1-6fc7ea2bcfb7"), + new Nomen( + GetAttribute()?.Title, + GetAttribute()?.Description), + typeof(MyGrasshopper__1PluginInfo).Assembly.GetName().Version) + { + Icon = AbstractIcon.FromResource("MyGrasshopper.1Plugin", typeof(MyGrasshopper__1PluginInfo)); + } + + public override string Author => GetAttribute()?.Company; + + public override sealed IIcon Icon { get; } + + public override sealed string Copyright => GetAttribute()?.Copyright ?? base.Copyright; + + // public override sealed string Website => "https://mywebsite.example.com"; + + // public override sealed string Contact => "myemail@example.com"; + + // public override sealed string LicenceAgreement => "license or URL"; + + } +} \ No newline at end of file diff --git a/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper__1Component.cs b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper__1Component.cs new file mode 100644 index 0000000..b98d9b9 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/MyGrasshopper__1Component.cs @@ -0,0 +1,134 @@ +using System; +using Rhino.Geometry; +using GrasshopperIO; +using Grasshopper.UI; +using Grasshopper.Components; + +namespace MyGrasshopper._1 +{ + [IoId("e79cd2b5-cb9c-4d08-93ec-446cc1f6d923")] + public sealed class MyGrasshopper__1Component : Component + { + public MyGrasshopper__1Component() : base(new Nomen( + "MyGrasshopper.1 Component", + "ComponentInfo", + "ComponentChapter", + "ComponentSection")) + { + + } + + public MyGrasshopper__1Component(IReader reader) : base(reader) { } + +#if IncludeSample + /// + /// Registers all the input parameters for this component. + /// + protected override void AddInputs(InputAdder inputs) + { + inputs.AddPlane("Plane", "P", "Base plane for spiral").Set(Plane.WorldXY); + inputs.AddNumber("Inner Radius", "R0", "Inner radius for spiral").Set(1.0); + inputs.AddNumber("Outer Radius", "R1", "Outer radius for spiral").Set(10.0); + inputs.AddInteger("Turns", "T", "Number of turns between radii").Set(10); + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void AddOutputs(OutputAdder outputs) + { + outputs.AddCurve("Spiral", "S", "Spiral curve"); + } + + /// + /// This is the method that actually does the work. + /// + /// The IDataAccess object can be used to retrieve data from input parameters and + /// to store data in output parameters. + protected override void Process(IDataAccess access) + { + // First, we need to retrieve all data from the input parameters. + // When data cannot be extracted from a parameter, we should abort this method. + if (!access.GetItem(0, out Plane plane)) return; + if (!access.GetItem(1, out double radius0)) return; + if (!access.GetItem(2, out double radius1)) return; + if (!access.GetItem(3, out int turns)) return; + + // We should now validate the data and warn the user if invalid data is supplied. + if (radius0 < 0.0) + { + access.AddError("Inner radius must be bigger than or equal to zero", ""); + return; + } + if (radius1 <= radius0) + { + access.AddError("Outer radius must be bigger than the inner radius", ""); + return; + } + if (turns <= 0) + { + access.AddError("Spiral turn count must be bigger than or equal to one", ""); + return; + } + + // We're set to create the spiral now. To keep the size of the SolveInstance() method small, + // The actual functionality will be in a different method: + Curve spiral = CreateSpiral(plane, radius0, radius1, turns); + + // Finally assign the spiral to the output parameter. + access.SetItem(0, spiral); + } + + Curve CreateSpiral(Plane plane, double r0, double r1, Int32 turns) + { + Line l0 = new Line(plane.Origin + r0 * plane.XAxis, plane.Origin + r1 * plane.XAxis); + Line l1 = new Line(plane.Origin - r0 * plane.XAxis, plane.Origin - r1 * plane.XAxis); + + Point3d[] p0; + Point3d[] p1; + + l0.ToNurbsCurve().DivideByCount(turns, true, out p0); + l1.ToNurbsCurve().DivideByCount(turns, true, out p1); + + PolyCurve spiral = new PolyCurve(); + + for (int i = 0; i < p0.Length - 1; i++) + { + Arc arc0 = new Arc(p0[i], plane.YAxis, p1[i + 1]); + Arc arc1 = new Arc(p1[i + 1], -plane.YAxis, p0[i + 1]); + + spiral.Append(arc0); + spiral.Append(arc1); + } + + return spiral; + } +#else + /// + /// Registers all the input parameters for this component. + /// + protected override void AddInputs(InputAdder inputs) + { + + } + + /// + /// Registers all the output parameters for this component. + /// + protected override void AddOutputs(OutputAdder outputs) + { + + } + + /// + /// This is the method that actually does the work. + /// + /// The IDataAccess object can be used to retrieve data from input parameters and + /// to store data in output parameters. + protected override void Process(IDataAccess access) + { + + } +#endif + } +} diff --git a/Rhino.Templates/content/CSGrasshopper2/Properties/AssemblyInfo.cs b/Rhino.Templates/content/CSGrasshopper2/Properties/AssemblyInfo.cs new file mode 100755 index 0000000..e76b049 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/Properties/AssemblyInfo.cs @@ -0,0 +1,22 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Rhino.PlugIns; + +// Plug-in Description Attributes - all of these are optional. +// These will show in Rhino's option dialog, in the tab Plug-ins. +[assembly: PlugInDescription(DescriptionType.Address, "")] +[assembly: PlugInDescription(DescriptionType.Country, "")] +[assembly: PlugInDescription(DescriptionType.Email, "")] +[assembly: PlugInDescription(DescriptionType.Phone, "")] +[assembly: PlugInDescription(DescriptionType.Fax, "")] +[assembly: PlugInDescription(DescriptionType.Organization, "")] +[assembly: PlugInDescription(DescriptionType.UpdateUrl, "")] +[assembly: PlugInDescription(DescriptionType.WebSite, "")] + +// Icons should be Windows .ico files and contain 32-bit images in the following sizes: 16, 24, 32, 48, and 256. +[assembly: PlugInDescription(DescriptionType.Icon, "MyGrasshopper._1.Icons.plugin.ico")] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +// This will also be the Guid of the Rhino plug-in +[assembly: Guid("ee4e2b39-d96b-4e4c-8f9d-9b6561e61b64")] diff --git a/Rhino.Templates/content/CSGrasshopper2/Properties/launchSettings.json b/Rhino.Templates/content/CSGrasshopper2/Properties/launchSettings.json new file mode 100644 index 0000000..e30f217 --- /dev/null +++ b/Rhino.Templates/content/CSGrasshopper2/Properties/launchSettings.json @@ -0,0 +1,20 @@ +{ + "profiles": { + "Rhino 8 - netcore": { + "commandName": "Executable", + "executablePath": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe", + "commandLineArgs": "/netcore /runscript=\"_G2\"", + "environmentVariables": { + "RHINO_PACKAGE_DIRS": "$(ProjectDir)$(OutputPath)\\" + } + }, + "Rhino 8 - netfx": { + "commandName": "Executable", + "executablePath": "C:\\Program Files\\Rhino 8\\System\\Rhino.exe", + "commandLineArgs": "/netfx /runscript=\"_G2\"", + "environmentVariables": { + "RHINO_PACKAGE_DIRS": "$(ProjectDir)$(OutputPath)\\" + } + }, + } +} \ No newline at end of file diff --git a/Rhino.VisualStudio.Windows/Rhino.VisualStudio.Windows.csproj b/Rhino.VisualStudio.Windows/Rhino.VisualStudio.Windows.csproj index 4f0465f..5fb0500 100755 --- a/Rhino.VisualStudio.Windows/Rhino.VisualStudio.Windows.csproj +++ b/Rhino.VisualStudio.Windows/Rhino.VisualStudio.Windows.csproj @@ -94,6 +94,8 @@ + + @@ -214,6 +216,7 @@ + diff --git a/Rhino.VisualStudio.Windows/Templates/CSGrasshopper2/grasshopper2.vstemplate b/Rhino.VisualStudio.Windows/Templates/CSGrasshopper2/grasshopper2.vstemplate new file mode 100755 index 0000000..f9d7d5f --- /dev/null +++ b/Rhino.VisualStudio.Windows/Templates/CSGrasshopper2/grasshopper2.vstemplate @@ -0,0 +1,43 @@ + + + + Grasshopper2 Plug-In for Rhino 3D (C#) + Build Grasshopper2 components for Rhino 3D in C# + 1 + + 20 + + Grasshopper2.Component.CS + CSharp + Windows + macOS + Desktop + Rhino + CSharp + icon.ico + MyGrasshopper2PlugIn + + true + true + Enabled + true + + + + + + + + + + + + + Rhino.VisualStudio.Windows, Version=8.15.0.0, Culture=neutral, PublicKeyToken=null + Rhino.VisualStudio.Windows.Wizard.Grasshopper2Wizard + + + Microsoft.VisualStudio.TemplateEngine.Wizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + Microsoft.VisualStudio.TemplateEngine.Wizard.TemplateEngineWizard + + \ No newline at end of file diff --git a/Rhino.VisualStudio.Windows/Templates/CSGrasshopper2/icon.ico b/Rhino.VisualStudio.Windows/Templates/CSGrasshopper2/icon.ico new file mode 100755 index 0000000..dc15579 Binary files /dev/null and b/Rhino.VisualStudio.Windows/Templates/CSGrasshopper2/icon.ico differ diff --git a/Rhino.VisualStudio.Windows/Wizard/Grasshopper2Wizard.cs b/Rhino.VisualStudio.Windows/Wizard/Grasshopper2Wizard.cs new file mode 100755 index 0000000..b4b9046 --- /dev/null +++ b/Rhino.VisualStudio.Windows/Wizard/Grasshopper2Wizard.cs @@ -0,0 +1,11 @@ +using Eto.Forms; + +namespace Rhino.VisualStudio.Windows.Wizard +{ + public class Grasshopper2Wizard : EtoWizard + { + protected override Control CreatePanel() => new Grasshopper2OptionsPanel(false); + + protected override BaseWizardViewModel CreateViewModel() => new Grasshopper2OptionsViewModel(); + } +} \ No newline at end of file diff --git a/Rhino.VisualStudio/Grasshopper2OptionsPanel.cs b/Rhino.VisualStudio/Grasshopper2OptionsPanel.cs new file mode 100755 index 0000000..bdb2bdb --- /dev/null +++ b/Rhino.VisualStudio/Grasshopper2OptionsPanel.cs @@ -0,0 +1,110 @@ +using Eto.Forms; +using Eto.Drawing; +using System; +using Rhino.VisualStudio.Controls; + +namespace Rhino.VisualStudio +{ + public class Grasshopper2OptionsPanel : BaseRhinoPageView + { + public Grasshopper2OptionsPanel(bool showProjectName) + { + var spacing = new Size(6, 6); + var padding = new Padding(8); + + var projectNameTextBox = new TextBox(); + projectNameTextBox.TextBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.ProjectName); + + var nameValid = new Label { TextColor = Global.Theme.ErrorForeground }; + nameValid.BindDataContext(c => c.Visible, (Grasshopper2OptionsViewModel m) => m.IsProjectNameInvalid); + nameValid.BindDataContext(c => c.Text, (Grasshopper2OptionsViewModel m) => m.ProjectNameValidationText); + + var pluginDisplayNameTextBox = new TextBox(); + pluginDisplayNameTextBox.TextBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.PlugInDisplayName); + + var componentClassNameTextBox = new TextBox(); + componentClassNameTextBox.TextBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.ComponentClassName); + + var provideCommandSampleCheckBox = new CheckBox { Text = "Provide sample code", ToolTip = "Check to provide a sample implementation for the component" }; + provideCommandSampleCheckBox.CheckedBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.IncludeSample); + + + var componentNameTextBox = new TextBox(); + componentNameTextBox.TextBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.ComponentName); + + var componentChapterTextBox = new TextBox(); + componentChapterTextBox.TextBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.ComponentChapter); + + var componentSectionTextBox = new TextBox(); + componentSectionTextBox.TextBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.ComponentSection); + + var componentInfoTextBox = new TextBox(); + componentInfoTextBox.TextBinding.BindDataContext((Grasshopper2OptionsViewModel m) => m.ComponentInfo); + + // rhino location + var rhinoLocation = new FilePicker(); + rhinoLocation.Filters.Add(new FileFilter("Rhino.exe", "Rhino.exe")); + rhinoLocation.BindDataContext(c => c.FilePath, (BaseLocationWizardViewModel m) => m.ExecutableLocation); + + var rhinoLocationInvalid = new Label { Text = "Could not find Rhino.exe at the specified location.", TextColor = Global.Theme.ErrorForeground }; + rhinoLocationInvalid.BindDataContext(c => c.Visible, (BaseLocationWizardViewModel m) => m.IsLocationInvalid); + + + // styles + Styles.Add(null, g => g.Padding = padding); + + // layout + var layout = new DynamicLayout { DefaultSpacing = spacing, Padding = padding }; + + layout.AddCentered("Adds the first component that has an icon to the toolbar."); + // top + layout.BeginVertical(); + if (showProjectName) + { + layout.AddRow("Project name", new TableLayout(projectNameTextBox, nameValid)); + } + layout.AddRow("Plug-In display name", pluginDisplayNameTextBox); + layout.AddRow("Component class name", componentClassNameTextBox); + layout.EndVertical(); + + // type group + layout.BeginVertical(); + layout.Add(new PanelSeparator("First component"));; + layout.AddRow("Name", componentNameTextBox); + layout.BeginHorizontal(); + layout.Add("Chapter"); + layout.BeginVertical(); + layout.BeginHorizontal(); + layout.Add(componentChapterTextBox, xscale: true); + layout.Add("Section"); + layout.Add(componentSectionTextBox, xscale: true); + layout.EndHorizontal(); + layout.EndVertical(); + layout.AddRow("Description", componentInfoTextBox); + + layout.EndVertical(); + + layout.BeginVertical(); + layout.Add(new PanelSeparator("Options")); + AddRhinoVersion(layout); + AddBuildYakPackage(layout); + AddIncludeVSCode(layout); + layout.Add(provideCommandSampleCheckBox); + layout.EndVertical(); + + AddWindowsUI(layout); + + // AddRhinoLocation(layout); + + Content = layout; + + var information = new DynamicLayout(); + information.AddSpace(); + AddRhinoDownloadInfo(information); + information.AddSpace(); + + Information = information; + + } + } +} \ No newline at end of file diff --git a/Rhino.VisualStudio/Grasshopper2OptionsViewModel.cs b/Rhino.VisualStudio/Grasshopper2OptionsViewModel.cs new file mode 100755 index 0000000..9fb503a --- /dev/null +++ b/Rhino.VisualStudio/Grasshopper2OptionsViewModel.cs @@ -0,0 +1,136 @@ +using Eto.Forms; +using System.Collections.Generic; +using System.Linq; + +namespace Rhino.VisualStudio +{ + public class Grasshopper2OptionsViewModel : BaseDesktopWizardViewModel + { + string _componentClassName; + + public override string ProjectTitle => "New Grasshopper2 Plug-In"; + + public string ComponentClassName + { + get => _componentClassName ?? Utility.GetSafeName(ProjectName, "Component", "Component", "Components", "Plugin", "Addin"); + set + { + if (Set(ref _componentClassName, value)) + { + OnPropertyChanged(nameof(IsValid)); + } + } + } + + string _componentName; + public string ComponentName + { + get => _componentName ?? ComponentClassName; + set => Set(ref _componentName, value); + } + + string _componentChapter; + public string ComponentChapter + { + get => _componentChapter; + set => Set(ref _componentChapter, value); + } + + string _componentSection; + public string ComponentSection + { + get => _componentSection; + set => Set(ref _componentSection, value); + } + + string _componentInfo; + public string ComponentInfo + { + get => _componentInfo; + set => Set(ref _componentInfo, value); + } + + string _projectName; + public override string ProjectName + { + get => _projectName ?? string.Empty; + set + { + if (Set(ref _projectName, value)) + { + OnPropertyChanged(nameof(PlugInDisplayName)); + OnPropertyChanged(nameof(ComponentClassName)); + OnPropertyChanged(nameof(ComponentName)); + OnPropertyChanged(nameof(IsValid)); + OnPropertyChanged(nameof(IsProjectNameInvalid)); + } + } + } + + string _plugInDisplayName; + public string PlugInDisplayName + { + get => _plugInDisplayName ?? ProjectName; + set + { + if (Set(ref _plugInDisplayName, value)) + { + OnPropertyChanged(nameof(IsValid)); + } + } + } + + bool _includeSample; + public bool IncludeSample + { + get => _includeSample; + set + { + if (Set(ref _includeSample, value)) + { + if (value) + { + ComponentChapter = "Curve"; + ComponentSection = "Primitive"; + ComponentInfo = "Construct an Archimedean, or arithmetic, spiral given its radii and number of turns."; + } + } + } + } + + protected override string FindLocation(int version) => Global.Helpers.FindRhino(version); + + public Grasshopper2OptionsViewModel() + { + SetDefaults(); + } + + public override bool IsValid => + !IsProjectNameInvalid + && Utility.IsValidIdentifier(ComponentClassName); + + void SetDefaults() + { + ComponentChapter = "Chapter"; + ComponentSection = "Section"; + + ComponentInfo = "Description"; + } + + public override void Finish() + { + base.Finish(); + if (Host == null) + return; + + Host.SetParameter("ComponentClassName", ComponentClassName); + Host.SetParameter("AddonDisplayName", PlugInDisplayName); + Host.SetParameter("IncludeSample", IncludeSample.ToString()); + Host.SetParameter("ComponentName", ComponentName); + Host.SetParameter("ComponentChapter", ComponentChapter); + Host.SetParameter("ComponentSsection", ComponentSection); + Host.SetParameter("ComponentInfo", ComponentInfo); + } + + } +} \ No newline at end of file diff --git a/build/GenerateTemplates.proj b/build/GenerateTemplates.proj index ac66868..ba208bb 100644 --- a/build/GenerateTemplates.proj +++ b/build/GenerateTemplates.proj @@ -69,7 +69,7 @@ Condition="!Exists($(MyTextFile))" /> - + @@ -200,6 +200,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + +