Rewrite event system using delegates and threads
This commit is contained in:
		
							
								
								
									
										35
									
								
								Program.cs
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								Program.cs
									
									
									
									
									
								
							@@ -1,20 +1,41 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using spnavwrapper;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace spnavcsharpwrapper
 | 
					namespace SpaceNavWrapper
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	class Program
 | 
						class Program
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		static void Main(string[] args)
 | 
							static void Main(string[] args)
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			SpaceNav.Instance.Threshold = 5;
 | 
								//spnavwrapper.SpaceNav.Instance.Threshold = 5;
 | 
				
			||||||
			SpaceNav.Instance.Sensitivity = 0.1;
 | 
								//spnavwrapper.SpaceNav.Instance.Sensitivity = 0.1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								//for (; ; )
 | 
				
			||||||
 | 
								//{
 | 
				
			||||||
 | 
								//	var ev = spnavwrapper.SpaceNav.Instance.WaitEvent(100);
 | 
				
			||||||
 | 
								//	Console.WriteLine(ev);
 | 
				
			||||||
 | 
								//}
 | 
				
			||||||
 | 
								SpaceNavDriver navDriver = new SpaceNavDriver();
 | 
				
			||||||
 | 
								navDriver.InitDevice();
 | 
				
			||||||
 | 
								navDriver.Button += OnButton;
 | 
				
			||||||
 | 
								navDriver.Motion += OnMotion;
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            Console.CancelKeyPress += delegate {
 | 
				
			||||||
 | 
									navDriver.Dispose();
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			for (; ; )
 | 
								for (; ; )
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				var ev = SpaceNav.Instance.WaitEvent(100);
 | 
								}
 | 
				
			||||||
				Console.WriteLine(ev);
 | 
							}
 | 
				
			||||||
			}
 | 
					
 | 
				
			||||||
 | 
							private static void OnMotion(object sender, MotionEventArgs e)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Console.WriteLine(e);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private static void OnButton(object sender, EventArgs e)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Console.WriteLine("Button pressed");
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										143
									
								
								SpaceNav.cs
									
									
									
									
									
								
							
							
						
						
									
										143
									
								
								SpaceNav.cs
									
									
									
									
									
								
							@@ -1,10 +1,12 @@
 | 
				
			|||||||
using System;
 | 
					using System;
 | 
				
			||||||
using System.Runtime.InteropServices;
 | 
					using System.Runtime.InteropServices;
 | 
				
			||||||
 | 
					using System.Threading;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace spnavwrapper
 | 
					namespace SpaceNavWrapper
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	public sealed class SpaceNav : IDisposable
 | 
						public class SpaceNavDriver : IDisposable
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const string DLL_NAME = "spnavhdi";
 | 
							const string DLL_NAME = "spnavhdi";
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        #region Constants
 | 
					        #region Constants
 | 
				
			||||||
@@ -14,9 +16,14 @@ namespace spnavwrapper
 | 
				
			|||||||
        private const ushort SPNAV_PRODUCT_ID = 0x0c627;
 | 
					        private const ushort SPNAV_PRODUCT_ID = 0x0c627;
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							public event EventHandler<MotionEventArgs> Motion;
 | 
				
			||||||
 | 
							public event EventHandler<EventArgs> Button;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
							private Thread eventThread;
 | 
				
			||||||
 | 
					        private bool deviceReady;
 | 
				
			||||||
        private double _sensitivity = 1.0;
 | 
					        private double _sensitivity = 1.0;
 | 
				
			||||||
        private int _threshold = 5;
 | 
					        private int _threshold = 5;
 | 
				
			||||||
		private static SpaceNav instance;
 | 
							private bool isDisposed;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		#region Structures
 | 
							#region Structures
 | 
				
			||||||
		private struct SpNavEventMotion
 | 
							private struct SpNavEventMotion
 | 
				
			||||||
@@ -59,118 +66,82 @@ namespace spnavwrapper
 | 
				
			|||||||
        private static extern int spnav_deadzone(int threshold);
 | 
					        private static extern int spnav_deadzone(int threshold);
 | 
				
			||||||
        #endregion
 | 
					        #endregion
 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
		private SpaceNav()
 | 
					        public SpaceNavDriver()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
								eventThread = new Thread(HandleEvents)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									IsBackground = true,
 | 
				
			||||||
 | 
									Name = "3Dconnexion-Event-Dispatcher"
 | 
				
			||||||
 | 
								};
 | 
				
			||||||
 | 
								eventThread.Start();
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        public void InitDevice()
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
			// TODO : handle retcode
 | 
					 | 
				
			||||||
			spnav_open(SPNAV_VENDOR_ID, SPNAV_PRODUCT_ID);
 | 
								spnav_open(SPNAV_VENDOR_ID, SPNAV_PRODUCT_ID);
 | 
				
			||||||
 | 
								spnav_deadzone(5);
 | 
				
			||||||
 | 
								deviceReady = true;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		#region IDisposable Support
 | 
							private void HandleEvents(object obj)
 | 
				
			||||||
		private bool disposedValue = false; // To detect redundant calls
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		private void Dispose(bool disposing)
 | 
					 | 
				
			||||||
		{        
 | 
							{        
 | 
				
			||||||
			if (!disposedValue)
 | 
					            // Block while the device isn't ready
 | 
				
			||||||
			{
 | 
					            while (!deviceReady) {}
 | 
				
			||||||
				// Free unmanaged resources
 | 
					            Console.WriteLine("Device ready !");
 | 
				
			||||||
				spnav_close();
 | 
								while (!isDisposed)
 | 
				
			||||||
				disposedValue = true;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		~SpaceNav()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
 | 
					 | 
				
			||||||
			Dispose(false);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		// This code added to correctly implement the disposable pattern.
 | 
					 | 
				
			||||||
		public void Dispose()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			Dispose(true);
 | 
					 | 
				
			||||||
			GC.SuppressFinalize(this);
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		#endregion
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		#region Methods
 | 
					 | 
				
			||||||
		public static SpaceNav Instance
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			get
 | 
					 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				if (instance == null)
 | 
					 | 
				
			||||||
				{
 | 
					 | 
				
			||||||
					instance = new SpaceNav();
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
				return instance;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public void CloseDevice()
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			spnav_close();
 | 
					 | 
				
			||||||
			instance = null;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public SpaceNavEvent WaitEvent()
 | 
					 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
                SpNavEvent sev = new SpNavEvent();
 | 
					                SpNavEvent sev = new SpNavEvent();
 | 
				
			||||||
			spnav_wait_event(ref sev);
 | 
									int ev_type = spnav_wait_event(ref sev);
 | 
				
			||||||
			switch (sev.type)
 | 
									Console.WriteLine("Event type : {0}", sev.type);
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				case SPNAV_EVENT_BUTTON:
 | 
					 | 
				
			||||||
					return new SpaceNavButtonEvent(Convert.ToBoolean(sev.button.press), sev.button.bnum);
 | 
					 | 
				
			||||||
				case SPNAV_EVENT_MOTION:
 | 
					 | 
				
			||||||
					var ev = sev.motion;
 | 
					 | 
				
			||||||
					return new SpaceNavMotionEvent(ev.x, ev.y, ev.z, ev.rx, ev.ry, ev.rz);
 | 
					 | 
				
			||||||
				default:
 | 
					 | 
				
			||||||
					return null;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		public SpaceNavEvent WaitEvent(int milliseconds)
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			SpNavEvent sev = new SpNavEvent();
 | 
					 | 
				
			||||||
			int ev_type = spnav_wait_event_timeout(ref sev, milliseconds);
 | 
					 | 
				
			||||||
                switch (ev_type)
 | 
					                switch (ev_type)
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
                    case SPNAV_EVENT_BUTTON:
 | 
					                    case SPNAV_EVENT_BUTTON:
 | 
				
			||||||
					return new SpaceNavButtonEvent(Convert.ToBoolean(sev.button.press), sev.button.bnum);
 | 
											//return new SpaceNavButtonEvent(Convert.ToBoolean(sev.button.press), sev.button.bnum);
 | 
				
			||||||
 | 
											Button(this, new EventArgs());
 | 
				
			||||||
 | 
											break;
 | 
				
			||||||
                    case SPNAV_EVENT_MOTION:
 | 
					                    case SPNAV_EVENT_MOTION:
 | 
				
			||||||
						var ev = sev.motion;
 | 
											var ev = sev.motion;
 | 
				
			||||||
					return new SpaceNavMotionEvent(ev.x, ev.y, ev.z, ev.rx, ev.ry, ev.rz);
 | 
					                        Motion(this, new MotionEventArgs(ev.x, ev.y, ev.z, ev.rx, ev.ry, ev.rz));
 | 
				
			||||||
				default:
 | 
											break;
 | 
				
			||||||
					return null;
 | 
					                }
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public double Sensitivity
 | 
							public double Sensitivity
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			get
 | 
								get => _sensitivity;
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				return _sensitivity;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			set
 | 
								set
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				// TODO : handle retcode
 | 
					 | 
				
			||||||
				spnav_sensitivity(value);
 | 
					 | 
				
			||||||
				_sensitivity = value;
 | 
									_sensitivity = value;
 | 
				
			||||||
 | 
									spnav_sensitivity(value);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		public int Threshold
 | 
							public int Threshold
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			get
 | 
								get => _threshold;
 | 
				
			||||||
			{
 | 
					 | 
				
			||||||
				return _threshold;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			set
 | 
								set
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				// TODO : handle retcode
 | 
					 | 
				
			||||||
				spnav_deadzone(value);
 | 
					 | 
				
			||||||
				_threshold = value;
 | 
									_threshold = value;
 | 
				
			||||||
 | 
									spnav_deadzone(value);
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		#endregion
 | 
					        
 | 
				
			||||||
 | 
					        public void Dispose()
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					            if (!isDisposed)
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                CloseDevice();
 | 
				
			||||||
 | 
					                Button = null;
 | 
				
			||||||
 | 
					                Motion = null;
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            isDisposed = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							private void CloseDevice()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// TODO : handle retcode and errors
 | 
				
			||||||
 | 
								spnav_close();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,36 +1,13 @@
 | 
				
			|||||||
namespace spnavwrapper
 | 
					using System;
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    public abstract class SpaceNavEvent
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    public class SpaceNavButtonEvent : SpaceNavEvent
 | 
					namespace SpaceNavWrapper
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
        public bool Pressed { get; }
 | 
					    public class MotionEventArgs : EventArgs 
 | 
				
			||||||
        public int Button { get; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public SpaceNavButtonEvent(bool pressed, int button)
 | 
					 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
            Pressed = pressed;
 | 
					        public readonly int X, Y, Z;
 | 
				
			||||||
            Button = button;
 | 
					        public readonly int Rx, Ry, Rz;
 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
        
 | 
					        
 | 
				
			||||||
        public override string ToString()
 | 
					        public MotionEventArgs(int x, int y, int z, int rx, int ry, int rz)
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
            return "pressed=" + Pressed + " button=" + Button;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    public class SpaceNavMotionEvent : SpaceNavEvent
 | 
					 | 
				
			||||||
    {
 | 
					 | 
				
			||||||
        public int X { get; }
 | 
					 | 
				
			||||||
        public int Y { get; }
 | 
					 | 
				
			||||||
        public int Z { get; }
 | 
					 | 
				
			||||||
        public int Rx { get; }
 | 
					 | 
				
			||||||
        public int Ry { get; }
 | 
					 | 
				
			||||||
        public int Rz { get; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        public SpaceNavMotionEvent(int x, int y, int z, int rx, int ry, int rz)
 | 
					 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
			X = x;
 | 
								X = x;
 | 
				
			||||||
			Y = y;
 | 
								Y = y;
 | 
				
			||||||
@@ -46,4 +23,15 @@
 | 
				
			|||||||
                " rx=" + Rz + " ry=" + Ry + " rz=" + Rz;
 | 
					                " rx=" + Rz + " ry=" + Ry + " rz=" + Rz;
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						public class ButtonEventArgs : EventArgs
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
							public readonly int button;
 | 
				
			||||||
 | 
							public readonly bool pressed;
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        public override string ToString()
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return string.Format("[ButtonEventArgs: button={0}, pressed={1}]", button, pressed);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user