GameController Component for GrassHopper/Kangaroo

OK, so who’s going to make a component that gives GameControllers access to Rhino objects, probably via GrassHopper / Kangaroo components?

With the option to “Record” whatever signals that were sent, so as to be able to repeat the manually controlled sequence.

Or does it already exist? Anything in this direction exist?

// Rolf

Hi Rolf,

I’m not aware of anything available right now for this, but I did see this example, so it seems it is possible.

I saw also that there are some nice xbox samples on msdn, and I have a controller lying around somewhere, so I’ll give this a try at some point, though no promises when that will be.

Hi Daniel,
After some research I found some libraries to try. SlimDX or SharpDX seems easy to get to work but their .dlls needs to be on the runtime machine.

I’m complete newbie on .NET so I don’t know if it’s possible to compile the used parts of the dlls as “static” as to avoid runtime dlls.


Then there’s Brandon Potters XBoxController

But since I don’t like the idea of having those extra dlls hanging around, I will evaluate also the package “Xbox Controller SDK 1.0.0” which is said to have no dependencies:

Well, this is what I found after a day’s search.

I already started trying out SharpDX, and it seems simple enough, except for the need to place the dll.s in the same .gha library (unless there’s a solution for this). SharpDX seems to cover most drivers so I will try to make something to work.

For a “jump start” with SharpDX I just got the following to work (no loop for continual reading of XInput values included). Can GH’s time component be accessed from code like in this case, somehow? As an old Delphi guy I find VB.NET convenient enough :

Imports System.Collections.Generic

Imports Grasshopper.Kernel
Imports Rhino.Geometry
Imports SharpDX.XInput

Public Class XBoxOneControlComponent
    Inherits GH_Component

    Public Const GC_Output_Debug = 0
    Public Const GC_Output_Running = 1
    Public Const GC_Output_RightThumbX = 2
    Public Const GC_Output_RightThumbY = 3

    Public M_DEBUG_DA As IGH_DataAccess

    '// --------------------------------------------------------
    Public Sub New()
        '| Abbreviation (Name)
        '| Description
        '| Category              ; Main TAB
        '| SubCategory           ; Group within TAB
        MyBase.New("XBox One Game Control", "XBoxOne",
                "Reads input from XBox One Game Controller.",
                "UI", "Game")
    End Sub


    '// --------------------------------------------------------
    ''' <summary>
    ''' INPUT - parameters for this component.
    ''' </summary>
    Protected Overrides Sub RegisterInputParams(ByVal pManager As GH_Component.GH_InputParamManager)
        pManager.AddBooleanParameter("Scan", "S", "Scans the XBox Controller for signals", 0)
    End Sub


    '// --------------------------------------------------------
    ''' <summary>
    ''' OUTPUT - parameters for this component.
    ''' </summary>
    Protected Overrides Sub RegisterOutputParams(ByVal pManager As GH_Component.GH_OutputParamManager)
        pManager.AddTextParameter("Debug", "Debug", "Debug channel for development only.", GH_ParamAccess.item)
        pManager.AddBooleanParameter("Running", "R", "The XBox Controller Is scanned for input", GH_ParamAccess.item)
        pManager.AddNumberParameter("RightThumbX", "RTX", "Right Thumb X", GH_ParamAccess.item)
        pManager.AddNumberParameter("RightThumbY", "RTY", "Right Thumb Y", GH_ParamAccess.item)
    End Sub


    '// --------------------------------------------------------
    ''' <summary>
    ''' USed only during development to log code progress/success in the Debug output of the component
    ''' </summary>
    Protected Sub DebugMsg(msg As String)
        M_DEBUG_DA.SetData(GC_Output_Debug, New String(msg))
    End Sub

    '// --------------------------------------------------------
    Protected Overrides Sub SolveInstance(DA As IGH_DataAccess)
        '// --------------------------------------------------------
        '// Example of Dead zones sensitivity
        '// --------------------------------------------------------

        'Dim LStick_DeadZone As Integer = 7849
        'Dim RStick_DeadZone As Integer = 8689
        'Dim LTrigger_Threshold As Integer = 30
        'Dim RTrigger_Threshold As Integer = 30

        '// --------------------------------------------------------
        '// Enable the Sub DebugMsg to use DA parameter for output
        '// --------------------------------------------------------

        M_DEBUG_DA = DA

        '// Variable activating this GH component to read the XBox Controller (once).
        '// 
        '// TODO: Loop to read values. What about GH's Timer component?
        '// 

        Dim DoScan As Boolean = False

        '// --------------------------------------------------------
        '// Use the DA object to retrieve the data inside the first input parameter.
        '// If the retieval fails (for example if there is no data) we need to abort.
        '// --------------------------------------------------------

        If (Not DA.GetData(0, DoScan)) Then Return

        '// --------------------------------------------------------
        '// Set Chained Output
        '// --------------------------------------------------------

        DA.SetData(GC_Output_Running, DoScan)

        '// --------------------------------------------------------
        '// GAME CONTROLLER 
        '// --------------------------------------------------------
        If Not DoScan Then
            DA.SetData(GC_Output_RightThumbX, 0)
            DA.SetData(GC_Output_RightThumbY, 0)
            DebugMsg("No DoScan")
        Else
            DebugMsg("OK, Scanning...")

            '//------------------------------------------------------
            '// Type: SharpDX.XInput.Controller
            '//------------------------------------------------------

            Dim controllers As New List(Of Controller)
            Dim gc As Controller = Nothing
            gc = New Controller(UserIndex.One)
            controllers.Add(gc)

            '// Disabled (for now) the other three controllers that can potentially 
            '// be active simultaneously            

            'controllers.Add(New Controller(UserIndex.Two))
            'controllers.Add(New Controller(UserIndex.Three))
            'controllers.Add(New Controller(UserIndex.Four))

            '//------------------------------------------------------
            '// Pick (first) Game Controller (gc)
            '//------------------------------------------------------
            For Each selectController In controllers
                If selectController.IsConnected Then
                    gc = selectController
                    DebugMsg("One Controller found.")
                    Exit For
                End If
                DebugMsg("No Controller found! :( ")
            Next


            '//------------------------------------------------------
            '// OUTPUT GamePad values, if connected
            '//------------------------------------------------------
            If gc IsNot Nothing AndAlso gc.IsConnected Then
                Dim g_state = gc.GetState()
                DA.SetData(GC_Output_RightThumbX, g_state.Gamepad.RightThumbX)
                DA.SetData(GC_Output_RightThumbY, g_state.Gamepad.RightThumbY)
                    '// ...
                    '// aso
                    '// ...
            Else
                DA.SetData(GC_Output_RightThumbX, 0)
                DA.SetData(GC_Output_RightThumbY, 0)
                    '// ...
                    '// aso
                    '// ...
            End If

        End If

    End Sub '// SolveInstance


    '// --------------------------------------------------------
    Protected Overrides ReadOnly Property Icon() As System.Drawing.Bitmap
        Get
            Return Nothing
        End Get
    End Property


    '// --------------------------------------------------------
    Public Overrides ReadOnly Property ComponentGuid() As Guid
        Get
            Return New Guid(" .... your guid ... ")
        End Get
    End Property
End Class

// Rolf