[SlimDX] and Mono?

Started by
8 comments, last by Uda 13 years, 3 months ago
Hi, I need some force feedback action and I'm using Unity (which uses Mono). Unity seems to be having trouble. So I take it SlimDX doesn't support MONO?
Advertisement
Mono doesn't have the C++/CLI support required to run SlimDX. SlimDX v2 may address this, but we don't have a release window yet.

Even if it did work, it would unceremoniously fail on non-Windows platforms, so it doesn't strike me as a good solution anyhow.
damn, thanks. So is there any way to get force feedback while using Mono?
The problem is for some reason Unity doesn't support any.
Of course I might have to make a c++ wrapper myself :|
I've no idea -- you might try asking on the Unity forums.

Trying to roll your own C++/CLI wrapper will put you in the same position you're in now. Mono can't run them. You may be able to write a C DLL around whatever feedback API you want and then P/Invoke it -- mono supports that. But it seems like a lot of work.
Thanks for the suggestions, but mention force feedback and you get stoney silence from Unity.
Amazingly no-one seems to have ever used ff in Unity or Mono.. and getting SlimDX to even work with ff was a nightmare of no docs or examples. Of course someone made an XInput lib for Unity which works perfectly, but XInput doesn't support 'real' force feedback on joystick/wheels GAH!

Looks like I'm going to have to make my own interface :|
SlimDX just wraps DirectInput for force feedback. You can find plenty of documentation and examples via Google on DirectInput force feedback.
Quote:Original post by jpetrie
SlimDX just wraps DirectInput for force feedback. You can find plenty of documentation and examples via Google on DirectInput force feedback.


No you can't :) The examples are all different/old. I finally patched together the various bits of info from forums etc to get a working example. I'm amazed really.

For anyone in the same boat here is my modified SlimDX DirectInput force feedback demo

/** Copyright (c) 2007-2009 SlimDX Group* * Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated documentation files (the "Software"), to deal* in the Software without restriction, including without limitation the rights* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell* copies of the Software, and to permit persons to whom the Software is* furnished to do so, subject to the following conditions:* * The above copyright notice and this permission notice shall be included in* all copies or substantial portions of the Software.* * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN* THE SOFTWARE.*/using System;using System.Globalization;using System.Windows.Forms;using SlimDX;using SlimDX.DirectInput;namespace JoystickTest{	public partial class MainForm : Form	{		private int SliderCount;		private Effect effect;		private Joystick joystick;		private int numPOVs;		private JoystickState state = new JoystickState();		private void CreateDevice()		{			// make sure that DirectInput has been initialized			var dinput = new DirectInput();			// search for devices			foreach (DeviceInstance device in dinput.GetDevices(DeviceClass.GameController, DeviceEnumerationFlags.AttachedOnly))			{				// create the device				try				{					joystick = new Joystick(dinput, device.InstanceGuid);					joystick.SetCooperativeLevel(this, CooperativeLevel.Exclusive | CooperativeLevel.Foreground);					break;				}				catch (DirectInputException)				{				}			}			if (joystick == null)			{				MessageBox.Show("There are no joysticks attached to the system.");				return;			}			joystick.Properties.AxisMode = DeviceAxisMode.Absolute;			joystick.Properties.AutoCenter = false;			// acquire the device			joystick.Acquire();			// set the timer to go off 12 times a second to read input			// NOTE: Normally applications would read this much faster.			// This rate is for demonstration purposes only.			timer.Interval = 1000/12;			timer.Start();			Console.WriteLine(joystick.Properties.ProductName);            			int xAxisOffset = 0, yAxisOffset = 0;			int nextOffset = 0;			foreach (DeviceObjectInstance d in joystick.GetObjects())			{				if ((d.ObjectType & ObjectDeviceType.ForceFeedbackActuator) != 0)				{					// No idea what all the offset stuff is about..					if (nextOffset == 0)						xAxisOffset = d.Offset;					else						yAxisOffset = d.Offset;					nextOffset++;				}			}/* for joysticks with 2 axis. I just want to test a 1 axis wheel			int[] offsets = new int[2];			offsets[0] = xAxisOffset;			offsets[1] = yAxisOffset;*/			int[] offsets = new int[1];			offsets[0] = xAxisOffset;			Console.WriteLine("xAxisOffset = "+xAxisOffset);			// No idea what this does or why it's needed			int[] coords = { -1000, 1000 };			foreach (EffectInfo ei in joystick.GetEffects(EffectType.All))			{				if (ei.Name == "Constant") // hack string ==				{					Console.WriteLine("effect = " + ei.Name + " : " + ei.Type + " : " + EffectType.ConstantForce);					Guid forceFeedbackGuid = ei.Guid;					var typeSpec = new ConstantForce();					typeSpec.Magnitude = -50000; // *************** CHANGE/UPDATE THIS TO EFFECT THE DIRECTION/FORCE *******************					typeSpec.AsConstantForce();					EffectParameters parameters = new EffectParameters();					parameters.Flags = EffectFlags.ObjectOffsets | EffectFlags.Cartesian;					parameters.Duration = int.MaxValue;					parameters.SamplePeriod = joystick.Capabilities.ForceFeedbackSamplePeriod;					parameters.Gain = 5000;					parameters.TriggerButton = -1;//					parameters.TriggerRepeatInterval = 0;							parameters.SetAxes(offsets, coords);					parameters.Envelope = null;					parameters.Parameters = typeSpec;					parameters.StartDelay = 0;					effect = new Effect(joystick, forceFeedbackGuid);					effect.SetParameters(parameters);					effect.Download();					effect.Start(1, EffectPlayFlags.NoDownload);				}			}		}		private void ReadImmediateData()		{			if (joystick.Acquire().IsFailure)				return;			if (joystick.Poll().IsFailure)				return;			state = joystick.GetCurrentState();			if (Result.Last.IsFailure)				return;			UpdateUI();		}		private void ReleaseDevice()		{			timer.Stop();			if (joystick != null)			{				joystick.Unacquire();				joystick.Dispose();			}			joystick = null;		}		#region Boilerplate		public MainForm()		{			InitializeComponent();			UpdateUI();		}		private void timer_Tick(object sender, EventArgs e)		{			ReadImmediateData();		}		private void exitButton_Click(object sender, EventArgs e)		{			ReleaseDevice();			Close();		}		private void UpdateUI()		{			if (joystick == null)				createDeviceButton.Text = "Create Device";			else				createDeviceButton.Text = "Release Device";			string strText = null;			label_X.Text = state.X.ToString(CultureInfo.CurrentCulture);			label_Y.Text = state.Y.ToString(CultureInfo.CurrentCulture);			label_Z.Text = state.Z.ToString(CultureInfo.CurrentCulture);			label_XRot.Text = state.RotationX.ToString(CultureInfo.CurrentCulture);			label_YRot.Text = state.RotationY.ToString(CultureInfo.CurrentCulture);			label_ZRot.Text = state.RotationZ.ToString(CultureInfo.CurrentCulture);			int[] slider = state.GetSliders();			label_S0.Text = slider[0].ToString(CultureInfo.CurrentCulture);			label_S1.Text = slider[1].ToString(CultureInfo.CurrentCulture);			int[] pov = state.GetPointOfViewControllers();			label_P0.Text = pov[0].ToString(CultureInfo.CurrentCulture);			label_P1.Text = pov[1].ToString(CultureInfo.CurrentCulture);			label_P2.Text = pov[2].ToString(CultureInfo.CurrentCulture);			label_P3.Text = pov[3].ToString(CultureInfo.CurrentCulture);			bool[] buttons = state.GetButtons();			for (int b = 0; b < buttons.Length; b++)			{				if (buttons)					strText += b.ToString("00 ", CultureInfo.CurrentCulture);			}			label_ButtonList.Text = strText;		}		private void UpdateControl(DeviceObjectInstance d)		{			if (ObjectGuid.XAxis == d.ObjectTypeGuid)			{				label_XAxis.Enabled = true;				label_X.Enabled = true;			}			if (ObjectGuid.YAxis == d.ObjectTypeGuid)			{				label_YAxis.Enabled = true;				label_Y.Enabled = true;			}			if (ObjectGuid.ZAxis == d.ObjectTypeGuid)			{				label_ZAxis.Enabled = true;				label_Z.Enabled = true;			}			if (ObjectGuid.RotationalXAxis == d.ObjectTypeGuid)			{				label_XRotation.Enabled = true;				label_XRot.Enabled = true;			}			if (ObjectGuid.RotationalYAxis == d.ObjectTypeGuid)			{				label_YRotation.Enabled = true;				label_YRot.Enabled = true;			}			if (ObjectGuid.RotationalZAxis == d.ObjectTypeGuid)			{				label_ZRotation.Enabled = true;				label_ZRot.Enabled = true;			}			if (ObjectGuid.Slider == d.ObjectTypeGuid)			{				switch (SliderCount++)				{					case 0:						label_Slider0.Enabled = true;						label_S0.Enabled = true;						break;					case 1:						label_Slider1.Enabled = true;						label_S1.Enabled = true;						break;				}			}			if (ObjectGuid.PovController == d.ObjectTypeGuid)			{				switch (numPOVs++)				{					case 0:						label_POV0.Enabled = true;						label_P0.Enabled = true;						break;					case 1:						label_POV1.Enabled = true;						label_P1.Enabled = true;						break;					case 2:						label_POV2.Enabled = true;						label_P2.Enabled = true;						break;					case 3:						label_POV3.Enabled = true;						label_P3.Enabled = true;						break;				}			}		}		private void createDeviceButton_Click(object sender, EventArgs e)		{			if (joystick == null)				CreateDevice();			else				ReleaseDevice();			UpdateUI();		}		private void MainForm_FormClosed(object sender, FormClosedEventArgs e)		{			ReleaseDevice();		}		#endregion	}}
Quote:
No you can't :) The examples are all different/old.

Yes, you can. DirectInput is old, and no longer actively maintained, all the code you're going to find is thus old and the more different examples one finds, the better.
What I meant was none of the examples worked as is in SlimDX. Even some SlimDX specific examples. Lots of differently named classes/methods/vars or missing. Different ways of injecting parameters etc
Dear Octamed,
I succesfully compiled your example, but when I run it and press the button, I get this error:
E_INVALIDARG: An invalid parameter was passed to the returning function (-2147024809)

on line: effect.SetParameters(parameters); - in foreach where the effect is done.
I am using Logitech RumblePad 2 and Win 7-32bit. The gamepad works well e.g. with FFConst example from DirectX SDK.
Have you any idea what might be wrong? Thank you in advance! Ludek

This topic is closed to new replies.

Advertisement