Sign in to follow this  
Octamed

[SlimDX] and Mono?

Recommended Posts

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.

Share this post


Link to post
Share on other sites
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 :|

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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 :|

Share this post


Link to post
Share on other sites
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[b])
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
}
}

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this