Xbox Controller bridge - Overview

Platform: 3ds Max 2010 (MAXScript) - 32 bit ONLY
Status: Released - V1.0
Address: www.GeoffSamuel.com/Scrip_Files.php?proj=3


This script is half based in C# and half in MAXScript and allows for the use of a connect Xbox 360 controller within 3ds Max as an input device. The example with this script shows it being used to move the virtual controller.

Although this is called the Xbox controller, it is more of a generic controller into 3ds max. It is limited in what xbox buttons can be used, and tehre will be another script to fill this gap in the near feature.

The .Net DLL is pre-compilled, source code is given, but requires visual studio 2008, .Net v3 or greater and the latest version of the DirectX SDK.

Code - MAXScript

------------------------------------------------------
--           Generic Joystick Plugin           --
--         Created by Geoffrey Samuel          --
--        Email: Geoff@geoffsamuel.com        --
--       Website: www.geoffsamuel.com     --
--                  (Version 1.0)                  --
------------------------------------------------------
------------------------------------------------------
------------------------------------------------------
/* LEGAL AND COPYRIGHT  INFO
------------------------------------------------------
Copyright (c) 2010, Geoff Samuel
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

------------------------------------------------------
/* OTHER  INFO
------------------------------------------------------

It would be appreciate if the author could be informed to the use of the plugin/tool/code as to promote the usage of the plugin/tool/code.
Any modifications done to the plugin/tool/code for improved functionality or stability would be welcome as keep building off a single plugin/tool/code allowing for more people to benefit,
although this is not mandatory.

Bugs and feature requests to: Support@GeoffSamuel.com

------------------------------------------------------
/* BUILD AND VERSION INFO
------------------------------------------------------
Build date: 7/3/2009


Further features to be implemented: (build version 0.5)
*

Version History: (build version 0.1)
* PROJECT STARTED.


*/
--Loads in the required DLL for connection and call it.
dotnet.loadAssembly ((GetDir #maxroot + "Scripts")+"\\Generic_Controller_bridge.dll")

testobj = dotnetobject "Xbox_Controller_bridge.Controller"

--Basic setup retuine, get the connect devices, the number of devices, sets the device to the default of 1 and preforms a test manual poll
testobj.GetDevices()
testobj.GetNumDevices()
testobj.SetDevices(1)
testobj.Manual_Poll()



-----------------------------------------EXAMPLE OF HOW TO USE: #1 Joystick Camera control
/*
Ry = Right control stick Y axis value
Rx = Right control stick X axis value
Z = trigger value
Y = Left control stick Y axis value
X = Left control stick X axis value
*/


--Calibrate for deadzone and set center points:
testobj.Manual_Poll()
old_Ry = testobj.Public_State.Ry/100
old_Rx = testobj.Public_State.Rx/100
old_Z = testobj.Public_State.Z/100
old_Y = testobj.Public_State.Y/100
old_X = testobj.Public_State.X/100

--Create and aligin test camera
Joystick_Cam = freecamera()
rotate Joystick_Cam (angleaxis 90 [1,0,0])

--function to be run at every tick of the timer
fn Manual_Poll = (
    --Poll the controller for the most uptodate stats
    testobj.Manual_Poll()
    --if the value isnt the same as the old one, i.e. its moved, do something
    if(testobj.Public_State.X/100 != old_X)do(
        Joystick_Cam.pos.X = old_X - (testobj.Public_State.X/100)
    )
    --and set the old value to the current value for next time
    old_X = testobj.Public_State.X/100
   
   
   
    --if the value isnt the same as the old one, i.e. its moved, do something
    if(testobj.Public_State.Y/100 != old_Y)do(
        Joystick_Cam.pos.Y = old_Y - (testobj.Public_State.Y/100)
    )
    --and set the old value to the current value for next time
    old_Y = testobj.Public_State.Y/100
   
   
   
    --if the value isnt the same as the old one, i.e. its moved, do something
    if(testobj.Public_State.Z/100 != old_Z)do(
        Joystick_Cam.Fov = old_Z - (testobj.Public_State.Z/100)
    )
    --and set the old value to the current value for next time
    old_Y = testobj.Public_State.Z/100
   
)
--create a Timer
theControllerTimer = dotNetObject "System.Windows.Forms.Timer"
--add ON TICK event hander to call the function
dotnet.addEventHandler theControllerTimer "tick" Manual_Poll
--set the tick interval 20 milliseconds
theControllerTimer.interval = 20




rollout test "test" width:162 height:68
(
    label lbl1 "Camera Joystick Example #1" pos:[9,6] width:144 height:16
    button btn1 "Start" pos:[24,30] width:113 height:18
    on btn1 pressed  do(
        if(btn1.text != "Stop")then(
        theControllerTimer.start()
        btn1.text = "Stop"
        )else(
            theControllerTimer.stop()
            DestroyDialog test
        )
    )
)

createdialog test

Script Download

The script can be downloaded here

Code - C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Microsoft.DirectX;
using Microsoft.DirectX.DirectInput;

namespace Xbox_Controller_bridge
{
public class Controller
{

private Device joystickDevice;
private JoystickState state;
public JoystickState Public_State;
private DeviceList gameControllerList;
public int timer = 100;
private Timer ticker;
private bool polling = false;
private bool got_Controllers = false;
private bool set_Controller = false;
public bool Poll_Change = false;


public void GetDevices()
{
gameControllerList = Manager.GetDevices(DeviceClass.GameControl, EnumDevicesFlags.AttachedOnly);
if (gameControllerList.Count == 0)
{
MessageBox.Show("No controllers", "Xbox Controller Bridge");
return;
}
got_Controllers = true;
return;
}

public int GetNumDevices()
{
if (got_Controllers == false)
{
MessageBox.Show("Devices not set", "Xbox Controller Bridge");
return 0;
}
return gameControllerList.Count;
}

public void SetDevices(int Num)
{
if (got_Controllers == false)
{
MessageBox.Show("Devices not set", "Xbox Controller Bridge");
return;
}
for (int i = 0; i < Num; i++)
{
gameControllerList.MoveNext();
}
DeviceInstance deviceInstance = (DeviceInstance)
gameControllerList.Current;

// create a device from this controller.

joystickDevice = new Device(deviceInstance.InstanceGuid);
//joystickDevice.SetCooperativeLevel(, CooperativeLevelFlags.Background | CooperativeLevelFlags.NonExclusive);

joystickDevice.SetDataFormat(DeviceDataFormat.Joystick);
// Finally, acquire the device.

joystickDevice.Acquire();
set_Controller = true;
}

private void Poll()
{
JoystickState temp = state;
joystickDevice.Poll();
state = Public_State = joystickDevice.CurrentJoystickState;
if (temp.Equals(state))
{
Poll_Change = true;
}
else
{
Poll_Change = false;
}
}

public void Manual_Poll()
{
if (set_Controller == false)
{
MessageBox.Show("Devices not set", "Xbox Controller Bridge");
return;
}
Poll();
}

private void Start()
{
ticker = new Timer();
ticker.Interval = timer;
ticker.Tick += new EventHandler(ticker_Tick);
ticker.Start();
}

void ticker_Tick(object sender, EventArgs e)
{
Poll();
}

private void Stop()
{
ticker.Stop();
}

public void Start_Stop()
{
if (set_Controller == false)
{
MessageBox.Show("Devices not set", "Xbox Controller Bridge");
return;
}
if (polling)
{
Start();
polling = true;
return;
}
else
{
Stop();
polling = false;
return;
}
}


}
}

DLL Download

The compiled DLL can be downloaded here