diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..a33f42807
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1 @@
+src/RhinoInside.Revit.GH/Scripting/Refs/Rhino.Runtime.Code.dll filter=lfs diff=lfs merge=lfs -text
diff --git a/src/RhinoInside.Revit.GH/Properties/AssemblyInfo.cs b/src/RhinoInside.Revit.GH/Properties/AssemblyInfo.cs
index 9e07ea8cc..300558ca3 100755
--- a/src/RhinoInside.Revit.GH/Properties/AssemblyInfo.cs
+++ b/src/RhinoInside.Revit.GH/Properties/AssemblyInfo.cs
@@ -54,6 +54,8 @@ public override GH_LoadingInstruction PriorityLoad()
var types = Assembly.GetExecutingAssembly().GetTypes().Where(x => x.IsDefined(typeof(AssemblyPriorityAttribute), false));
foreach (var type in types)
System.Runtime.CompilerServices.RuntimeHelpers.RunClassConstructor(type.TypeHandle);
+
+ Rhino.Runtime.Code.RhinoCode.Platforms.TryRegister(Scripting.RhinoInsideRevitPlatform.Instance);
}
catch { return GH_LoadingInstruction.Abort; }
diff --git a/src/RhinoInside.Revit.GH/RhinoInside.Revit.GH.csproj b/src/RhinoInside.Revit.GH/RhinoInside.Revit.GH.csproj
index 9bb82e99c..1692e65db 100644
--- a/src/RhinoInside.Revit.GH/RhinoInside.Revit.GH.csproj
+++ b/src/RhinoInside.Revit.GH/RhinoInside.Revit.GH.csproj
@@ -14,6 +14,10 @@
+
+
+
+
$(RevitAddinsPath)RhinoInside.Revit\R$(RhinoVersion)\
diff --git a/src/RhinoInside.Revit.GH/Scripting/Converters/ElementIdConverter.cs b/src/RhinoInside.Revit.GH/Scripting/Converters/ElementIdConverter.cs
new file mode 100644
index 000000000..4e869ae87
--- /dev/null
+++ b/src/RhinoInside.Revit.GH/Scripting/Converters/ElementIdConverter.cs
@@ -0,0 +1,35 @@
+using System;
+
+using Rhino.Runtime.Code;
+using Rhino.Runtime.Code.Execution;
+
+namespace RhinoInside.Revit.GH.Scripting.Converters
+{
+ public sealed class ElementIdConverter : ParamValueConverter
+ {
+ public static ParamConverterIdentity Identity { get; }
+ = new ParamConverterIdentity(new Guid("5716bd31-2735-4be5-88ac-bcc0304be776"), "ElementId", "mcneel.rhino3dinrevit.rhino");
+
+ public ElementIdConverter()
+ : base(Identity, new ParamType(typeof(Autodesk.Revit.DB.ElementId)))
+ {
+ Image = default;
+ Category = "Revit";
+ Description = "Converts DB.Element to DB.ElementId";
+ }
+
+ public override bool Cast(ConvertDirection direction, object data, out object target)
+ {
+ target = default;
+
+ if (ConvertDirection.Incoming == direction
+ && data is Autodesk.Revit.DB.Element element)
+ {
+ target = element.Id;
+ return true;
+ }
+
+ return false;
+ }
+ }
+}
diff --git a/src/RhinoInside.Revit.GH/Scripting/Refs/Rhino.Runtime.Code.dll b/src/RhinoInside.Revit.GH/Scripting/Refs/Rhino.Runtime.Code.dll
new file mode 100644
index 000000000..63d6f32ad
--- /dev/null
+++ b/src/RhinoInside.Revit.GH/Scripting/Refs/Rhino.Runtime.Code.dll
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6484c7e62593d1044be43dc0fcad6a91bbc74138f61d7696d1d056699b8e7436
+size 372736
diff --git a/src/RhinoInside.Revit.GH/Scripting/RhinoInsideRevitPlatform.cs b/src/RhinoInside.Revit.GH/Scripting/RhinoInsideRevitPlatform.cs
new file mode 100644
index 000000000..17b8db793
--- /dev/null
+++ b/src/RhinoInside.Revit.GH/Scripting/RhinoInsideRevitPlatform.cs
@@ -0,0 +1,161 @@
+#if RHINO_8
+using System;
+using System.Linq;
+using System.Collections.Generic;
+
+using Rhino;
+
+using Rhino.Runtime.Code;
+using Rhino.Runtime.Code.Editing;
+using Rhino.Runtime.Code.Environments;
+using Rhino.Runtime.Code.Execution;
+using Rhino.Runtime.Code.Execution.Debugging;
+using Rhino.Runtime.Code.Platform;
+using Rhino.Runtime.Code.Storage;
+
+namespace RhinoInside.Revit.GH.Scripting
+{
+ public sealed class RhinoInsideRevitPlatform : Platform
+ {
+ public static IPlatform Instance { get; } = new RhinoInsideRevitPlatform();
+
+ #region Converters
+ public static IParamValueConverter ElementIdConverter { get; } = new Converters.ElementIdConverter();
+ #endregion
+
+ #region Platform
+ public override PlatformIdentity Id { get; } = new PlatformIdentity(
+ name: "Rhino.Inside.Revit",
+ shortName: "RIR",
+ description: "Rhino.Inside.Revit platform",
+ domain: "rhino3dinrevit",
+ taxonomy: "mcneel.rhino3dinrevit.rhino",
+ RhinoApp.Version
+ );
+
+ public override IPlatformDocument ActiveDocument { get; } = default;
+
+ public override IEnumerable References
+ {
+ get
+ {
+ yield return CompileReference.FromAssembly(typeof(Autodesk.Revit.DB.IExternalDBApplication).Assembly);
+ yield return CompileReference.FromAssembly(typeof(Autodesk.Revit.UI.IExternalApplication).Assembly);
+ yield return CompileReference.FromAssembly(typeof(Autodesk.Windows.IRibbonPopup).Assembly);
+ }
+ }
+
+ public override IEnumerable ReferenceFilters
+ {
+ get
+ {
+ // TODO:
+ // return extension filters for platfrom plugin file exts
+ yield break;
+ }
+ }
+
+ public override IEnumerable EditorLibraries
+ {
+ get
+ {
+ var revitVersion = new Version(Revit.ActiveDBApplication.SubVersionNumber);
+ var nugetSpec = new PackageSpec($"Autodesk.Revit.SDK.refs.{revitVersion.Major}");
+ var nugetPackage = NuGetEnvirons.User.AddPackage(nugetSpec);
+ var refsDir = revitVersion.Major >= 2025 ? "ref/net8.0" : "ref/net48";
+ foreach (string revitSDK in nugetPackage.GetFiles(refsDir)
+ .Where(l => l.EndsWith("RevitAPI.dll") || l.EndsWith("RevitAPIUI.dll")))
+ {
+ AssemblyEditorLibrary revitSDKLib = default;
+ try
+ {
+ // TODO:
+ // implement url builder for https://www.revitapidocs.com/ maybe?
+ revitSDKLib = new AssemblyEditorLibrary(revitSDK);
+ }
+ catch (Exception ex)
+ {
+ RhinoCode.Logger.Warn($"Error generating docs for Autodesk.Revit {revitVersion.Major} libraries | {ex.Message}");
+ }
+
+ if (revitSDKLib is AssemblyEditorLibrary)
+ yield return revitSDKLib;
+ }
+ }
+ }
+
+ public override IEnumerable Converters
+ {
+ get
+ {
+ // TODO:
+ // add more converters
+ yield return ElementIdConverter;
+ }
+ }
+
+ public override IEnumerable GetCompileGuards(BuildKind buildKind)
+ {
+ const int FIRST_RHINOCODE_SUPPORTED_REVIT = 2018;
+ var revitVersion = new Version(Revit.ActiveDBApplication.SubVersionNumber);
+
+ // this creates 'flexible' guards for major versions starting from Revit FIRST_RHINOCODE_SUPPORTED_REVIT
+ // Example: REVIT_2018_OR_GREATER, REVIT_2019_OR_GREATER
+ foreach (int nextMajor in Enumerable.Range(FIRST_RHINOCODE_SUPPORTED_REVIT,
+ revitVersion.Major + 1 - FIRST_RHINOCODE_SUPPORTED_REVIT))
+ {
+ yield return new CompileGuard($"REVIT_{nextMajor}_OR_GREATER", true);
+ }
+
+ // this creates 'specific' guards that are only available on this Revit version
+ // Example: REVIT_2025_1, REVIT_2025
+ yield return new CompileGuard($"REVIT_{revitVersion.Major}_{revitVersion.Minor}", true);
+ yield return new CompileGuard($"REVIT_{revitVersion.Major}", true);
+ }
+
+ public override IDebugControls CreateDebugControls()
+ {
+ // This is not used for now.
+ // ScriptEditor uses debug controls provided by Rhino3d platform
+ throw new NotImplementedException();
+ }
+
+ public override void Pause(PauseContext context)
+ {
+ // TODO:
+ // implement a way to pause/disable Revit UI
+ // this is called when editor debugger is pausing on a breakpoint
+ // and wants to deactivate the platform functions to disallow
+ // changing document state
+ }
+
+ public override void Resume()
+ {
+ // TODO:
+ // unpause from paused/disabled state
+ }
+
+ public override bool TryGetAssemblyPath(string name, out string path)
+ {
+ // TODO:
+ // not necessary at this point
+
+ path = default;
+ return false;
+ }
+
+ public override void Write(string text)
+ {
+ // TODO:
+ // not necessary at this point
+ }
+
+ public override void WriteError(string text)
+ {
+ // TODO:
+ // not necessary at this point
+ }
+ #endregion
+ }
+}
+#endif