diff --git a/WireEventImplementor/Properties/launchSettings.json b/WireEventImplementor/Properties/launchSettings.json new file mode 100644 index 0000000..ff47e2d --- /dev/null +++ b/WireEventImplementor/Properties/launchSettings.json @@ -0,0 +1,9 @@ +{ + "profiles": { + "WireEventImplementor": { + "commandName": "Executable", + "executablePath": "C:\\Program Files\\Rhino 7\\System\\Rhino.exe", + "commandLineArgs": "" + } + } +} \ No newline at end of file diff --git a/WireEventImplementor/WireEventImplementor.csproj b/WireEventImplementor/WireEventImplementor.csproj new file mode 100644 index 0000000..0047f87 --- /dev/null +++ b/WireEventImplementor/WireEventImplementor.csproj @@ -0,0 +1,19 @@ + + + + net48 + 1.0 + WireEventImplementor + Description of WireEventImplementor + .dll + + + + + + + + + + + \ No newline at end of file diff --git a/WireEventImplementor/WireInstances.cs b/WireEventImplementor/WireInstances.cs new file mode 100644 index 0000000..ebe1c5a --- /dev/null +++ b/WireEventImplementor/WireInstances.cs @@ -0,0 +1,79 @@ +using Grasshopper.GUI.Canvas; +using Grasshopper.GUI.Canvas.Interaction; +using Grasshopper.Kernel; +using System; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WireEventImplementor +{ + public static class WireInstances + { + + public delegate void PreWiredEventHandler(WireStatus wireStatus); + + public delegate void WiringEventHandler(WireStatus wireStatus); + + public delegate void PostWiredEventHandler(WireStatus wireStatus); + + /// + /// Invoked when your wiring cursor is floating. + /// + public static event WiringEventHandler Wiring; + + /// + /// Invoked when your wiring cursor is on the grip. + /// + public static event PreWiredEventHandler PreWired; + + /// + /// Invoked when your wire connects grips. + /// + public static event PostWiredEventHandler PostWired; + + private static TaskCompletionSource m_source = new TaskCompletionSource(); + + /// + /// Call when canvas created. + /// + /// Applied canvas. + public static void SetUp(GH_Canvas canvas) + { + canvas.MouseMove += Canvas_MouseMove; + canvas.MouseUp += Canvas_MouseUp; + } + + private static void Canvas_MouseMove(object sender, MouseEventArgs e) + { + if (sender is GH_Canvas canvas && canvas.ActiveInteraction is GH_WireInteraction wireInteraction) + { + wireInteraction.GetWireParameters(out WireStatus status); + + if (e.Button == MouseButtons.Left) + { + m_source = new TaskCompletionSource(); + + if (status.WireTarget == null) + Wiring?.Invoke(status); + else + { + PreWired?.Invoke(status); + m_source.SetResult(status); + } + } + + canvas.Refresh(); + } + } + + private static async void Canvas_MouseUp(object sender, MouseEventArgs e) + { + WireStatus status = await m_source.Task; + m_source = new TaskCompletionSource(); + + PostWired?.Invoke(status); + + (sender as GH_Canvas).Refresh(); + } + } +} diff --git a/WireEventImplementor/WireStatus.cs b/WireEventImplementor/WireStatus.cs new file mode 100644 index 0000000..e2ce356 --- /dev/null +++ b/WireEventImplementor/WireStatus.cs @@ -0,0 +1,31 @@ +using Grasshopper.Kernel; + +namespace WireEventImplementor +{ + public class WireStatus + { + public IGH_Param WireSource { get; } + + public IGH_Param WireTarget { get; } + + public LinkMode? LinkMode { get; } + + public bool? IsDragFromInput { get; } + + public IGH_Param PreviousSideParam => (bool)IsDragFromInput ? WireTarget : WireSource; + + public IGH_Param SubsequentSideParam => (bool)IsDragFromInput ? WireSource : WireTarget; + + private WireStatus() + { + } + + internal WireStatus(IGH_Param wireSource, IGH_Param wireTarget, LinkMode? linkMode, bool? isDragFromInput) + { + WireSource = wireSource; + WireTarget = wireTarget; + LinkMode = linkMode; + IsDragFromInput = isDragFromInput; + } + } +} diff --git a/WireEventImplementor/WireUtil.cs b/WireEventImplementor/WireUtil.cs new file mode 100644 index 0000000..59b768b --- /dev/null +++ b/WireEventImplementor/WireUtil.cs @@ -0,0 +1,29 @@ +using Grasshopper.GUI.Canvas.Interaction; +using Grasshopper.Kernel; +using System; +using System.Reflection; + +namespace WireEventImplementor +{ + public enum LinkMode + { + Replace, + Add, + Remove + } + + public static class WireUtil + { + internal static void GetWireParameters(this GH_WireInteraction self, out WireStatus wireStatus) + { + Func getPrivateParam = (name) => typeof(GH_WireInteraction).GetField(name, BindingFlags.NonPublic | BindingFlags.Instance).GetValue(self); + + IGH_Param source = getPrivateParam("m_source") as IGH_Param; + IGH_Param target = getPrivateParam("m_target") as IGH_Param; + LinkMode mode = (LinkMode)Enum.Parse(typeof(LinkMode), getPrivateParam("m_mode").ToString()); + bool dragFromInput = (bool)getPrivateParam("m_dragfrominput"); + + wireStatus = new WireStatus(source, target, mode, dragFromInput); + } + } +}