#ifdef _WIN32
#ifndef IPV6STRICT
#define IPV6STRICT
#endif
#include <winsock2.h>
#include <windows.h>
#include <XInput.h>
#pragma comment(lib, "XInput.lib")
#endif // _WIN32
#include <maya/MFnPlugin.h>
#include <maya/MTypeId.h>
#include <api_macros.h>
#include <maya/MIOStream.h>
#include <maya/MPlug.h>
#include <maya/MDataBlock.h>
#include <maya/MFnNumericAttribute.h>
#include <maya/MPxThreadedDeviceNode.h>
{
public:
gameInputDeviceNode();
virtual ~gameInputDeviceNode();
static void* creator();
public:
private:
};
MTypeId gameInputDeviceNode::id( 0x00081053 );
MObject gameInputDeviceNode::outputTranslate;
MObject gameInputDeviceNode::outputTranslateX;
MObject gameInputDeviceNode::outputTranslateY;
MObject gameInputDeviceNode::outputTranslateZ;
MObject gameInputDeviceNode::updateTranslateXZ;
gameInputDeviceNode::gameInputDeviceNode()
{}
gameInputDeviceNode::~gameInputDeviceNode()
{
destroyMemoryPools();
}
void gameInputDeviceNode::postConstructor()
{
attrArray.
append( gameInputDeviceNode::outputTranslate );
setRefreshOutputAttributes( attrArray );
createMemoryPools( 24, 3, sizeof(double));
}
#ifdef _WIN32
bool checkController(XINPUT_STATE& state)
{
DWORD dwResult;
ZeroMemory( &state, sizeof(XINPUT_STATE) );
dwResult = XInputGetState( 0, &state );
if( dwResult == ERROR_SUCCESS )
{
return true;
}
return false;
}
#endif
void gameInputDeviceNode::threadHandler()
{
#ifdef _WIN32
setDone( false );
while ( ! isDone() )
{
if ( ! isLive() )
continue;
status = acquireDataStorage(buffer);
if ( ! status )
continue;
XINPUT_STATE state;
if ( ! checkController( state ) )
{
releaseDataStorage(buffer);
continue;
}
beginThreadLoop();
{
float changeX = 0.0, changeY = 0.0;
float leftThumbX = state.Gamepad.sThumbLX;
float leftThumbY = state.Gamepad.sThumbLY;
if ( leftThumbX > +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) changeX = +1;
if ( leftThumbX < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) changeX = -1;
if ( leftThumbY > +XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) changeY = +1;
if ( leftThumbY < -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE ) changeY = -1;
double* doubleData =
reinterpret_cast<double*
>(buffer.
ptr());
doubleData[0] = changeX ; doubleData[1] = changeY; doubleData[2] = 0.0;
pushThreadData( buffer );
}
endThreadLoop();
}
#endif // _WIN32
setDone( true );
}
void gameInputDeviceNode::threadShutdownHandler()
{
setDone( true );
}
void* gameInputDeviceNode::creator()
{
return new gameInputDeviceNode;
}
MStatus gameInputDeviceNode::initialize()
{
MCHECKERROR(status, "create outputTranslateX");
MCHECKERROR(status, "create outputTranslateY");
MCHECKERROR(status, "create outputTranslateZ");
outputTranslate = numAttr.
create(
"outputTranslate",
"ot", outputTranslateX, outputTranslateY,
outputTranslateZ, &status);
MCHECKERROR(status, "create outputTranslate");
ADD_ATTRIBUTE(outputTranslate);
ADD_ATTRIBUTE(updateTranslateXZ);
ATTRIBUTE_AFFECTS( live, outputTranslate);
ATTRIBUTE_AFFECTS( frameRate, outputTranslate);
ATTRIBUTE_AFFECTS( updateTranslateXZ, outputTranslate);
}
{
if( plug == outputTranslate || plug == outputTranslateX ||
plug == outputTranslateY || plug == outputTranslateZ )
{
if ( popThreadData(buffer) )
{
double* doubleData =
reinterpret_cast<double*
>(buffer.
ptr());
MCHECKERROR(status, "Error in block.outputValue for outputTranslate");
double3& outputTranslate = outputTranslateHandle.
asDouble3();
if ( xzUpdate )
{
outputTranslate[0] += doubleData[0];
outputTranslate[1] += doubleData[2];
outputTranslate[2] -= doubleData[1];
}
else
{
outputTranslate[0] += doubleData[0];
outputTranslate[1] += doubleData[1];
outputTranslate[2] += doubleData[2];
}
releaseDataStorage(buffer);
}
else
{
}
}
}
{
MFnPlugin plugin(obj, PLUGIN_COMPANY,
"3.0",
"Any");
status = plugin.registerNode( "gameInputDevice",
gameInputDeviceNode::id,
gameInputDeviceNode::creator,
gameInputDeviceNode::initialize,
if( !status ) {
status.
perror(
"failed to registerNode gameInputDeviceNode");
}
return status;
}
{
status = plugin.deregisterNode( gameInputDeviceNode::id );
if( !status ) {
status.
perror(
"failed to deregisterNode gameInputDeviceNode");
}
return status;
}