mcneel / rhino.inside

Sample Projects for Rhino.Inside
MIT License
384 stars 168 forks source link

Reference Grasshopper related dlls in Unity and resolve dependencies. #121

Closed fraguada closed 5 years ago

fraguada commented 5 years ago

Targeting the Grasshopper api requires several dependencies. What is the appropriate way to reference these? I've copied Grasshopper.dll and GH_IO.dll to the Sample1\Assets\Standard Assets\RhinoInside directory.

Assembly 'Assets/Standard Assets/RhinoInside/Grasshopper.dll' will not be loaded due to errors:
Unable to resolve reference 'Microsoft.VisualBasic'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'Eto'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'Mono.Cecil'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'GH_Util'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'QWhale.Editor'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'QWhale.Syntax.Parsers'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'Yak'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'Eto.Wpf'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'Rhino.UI'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'QWhale.Common'. Is the assembly missing or incompatible with the current platform?
Unable to resolve reference 'QWhale.Syntax'. Is the assembly missing or incompatible with the current platform?
fraguada commented 5 years ago

More or less what I'm trying to do: https://github.com/mcneel/rhino.inside/commit/8fd531d2128a9ab17aae0c558545b17e2d31a885

Maybe you have some idea @kike-garbo?

pearswj commented 5 years ago

@fraguada could an assembly resolver help?

https://github.com/mcneel/rhino.inside/blob/cef14b3c13e8c41e5386161863563bd644541b7f/Autodesk/Revit/src/RhinoInside.Revit/Addin.cs#L33

fraguada commented 5 years ago

@pearswj Tried that, as I did here. https://github.com/mcneel/rhino.inside/blob/node.js/Node.js/Sample-4/InsideNode/RhinoInsideTaskManager.cs#L43-L73 Loading Grasshopper.dll isn't the problem, it is ensuring that the other dependencies (listed above) are also resolved.

fraguada commented 5 years ago

After looking at this with @kike-garbo it is a bit clearer why we are seeing this behavior. It remains to be tested, but it seems a very likely candidate. Since Unity uses the Mono Runtime, any assembly copied to the Unity project Asset folder should be compatible with that. When Rhino is run inside of Unity, it loads all of the assemblies it depends on in the .Net runtime. One can see this by looking at the modules loaded by Unity (Visual Studio allows you to attach to the Unity debugger). Even though Rhino and Grasshopper might be loaded and visible, the only DLL that one can see via the runtime used by Unity is RhinoCommon.dll. If one attaches the .Net debugger to Unity, one will see Rhino and all of the assemblies needed for it to run. As I understand it, the only reason the Sample 1 works to create a loft surface is because there is native code being called to create the surface which can be loaded by both Mono and the .Net Runtime, and RhinoCommon has few dependencies.

In conclusion, there would be a few solutions to this (there might be others):

  1. Make Rhino for Windows run with the Mono runtime (😱)
  2. Instead of targeting Windows, run this from macOS / Rhino for Mac. This would require Rhino.Inside to work on Rhino for Mac WIP 7, and that the Mono runtimes between both Unity and Rhino are compatible.
  3. Create a Rhino Plugin with the desired functionality from Grasshopper (subscribing to events, etc) and a C/C++ plugin that references this. The Unity project could reference that C/C++ dll or perhaps have C# dll that is referenced by the Unity project.

@kike-garbo is this accurate?

Finally, one of the benefits of Rhino.Inside is to have both Rhino and Host Application APIs side by side. By employing any of the solutions above, one is effectively circumventing this benefit. Hence, Rhino.Inside.Unity is probably not a good use case for Rhino.Inside. In the past, there have been examples of using UDP, sockets, or other networking technology to pass data from Rhino to Unity. There is a Speckle Client for Unity, and there are examples of using Rhino.Compute / RESTHopper with Unity . This still might be the best way to interoperate in 'Real-Time' with Rhino and Unity.