//----------------------------------------------------------------------------------- // // Torque Network Library - ZAP example multiplayer vector graphics space game // Copyright (C) 2004 GarageGames.com, Inc. // For more information see http://www.opentnl.org // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation; either version 2 of the License, or // (at your option) any later version. // // For use in products that are not compatible with the terms of the GNU // General Public License, alternative licensing options are available // from GarageGames.com. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //------------------------------------------------------------------------------------ #define STRICT #define DIRECTINPUT_VERSION 0x0800 #include #include #include "gameConnection.h" #include "point.h" #include "UI.h" #include "input.h" namespace Zap { extern const char *gWindowTitle; void getModifierState( bool &shiftDown, bool &controlDown, bool &altDown ) { shiftDown = ( GetKeyState( VK_SHIFT ) & 0xFF00 ) != 0; controlDown = ( GetKeyState( VK_CONTROL ) & 0xFF00 ) != 0; altDown = ( GetKeyState( VK_MENU ) & 0xFF00 ) != 0; } void checkMousePos(S32 maxdx, S32 maxdy) { char windowName[256]; HWND theWindow = GetForegroundWindow(); GetWindowText(theWindow, windowName, sizeof(windowName)); if(strcmp(windowName, gWindowTitle)) return; RECT r; GetWindowRect(theWindow, &r); POINT cp; GetCursorPos(&cp); // Check our position in the window; if we're close to the top (within 32px) then ignore // same if we're within 5px of the edges. That way we can avoid going crazy when // people try to resize/drag the window. if(cp.x - r.top < 32) return; if(cp.y - r.left < 5) return; if(r.right - cp.y < 5) return; if(r.bottom - cp.x < 5) return; S32 centerX = (r.right + r.left) >> 1; S32 centerY = (r.bottom + r.top) >> 1; cp.x -= centerX; cp.y -= centerY; if(cp.x > maxdx) cp.x = maxdx; if(cp.y > maxdy) cp.y = maxdy; if(cp.x < -maxdx) cp.x = -maxdx; if(cp.y < -maxdy) cp.y = -maxdy; SetCursorPos(int(centerX + cp.x), int(centerY + cp.y)); } BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ); LPDIRECTINPUT8 gDirectInput = NULL; LPDIRECTINPUTDEVICE8 gJoystick = NULL; char gJoystickName[MAX_PATH] = ""; void InitJoystick() { if(FAILED(DirectInput8Create ( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&gDirectInput, NULL ) ) ) return; if(FAILED(gDirectInput->EnumDevices( DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ATTACHEDONLY ) ) ) return; if(!gJoystick) return; if( FAILED(gJoystick->SetDataFormat( &c_dfDIJoystick2 ) ) ) return; } const char *GetJoystickName() { return gJoystickName; } BOOL CALLBACK EnumJoysticksCallback( const DIDEVICEINSTANCE* pdidInstance, VOID* pContext ) { // Obtain an interface to the enumerated joystick. if(FAILED(gDirectInput->CreateDevice( pdidInstance->guidInstance, &gJoystick, NULL ))) return DIENUM_CONTINUE; strcpy(gJoystickName, pdidInstance->tszProductName); logprintf("Joystick found: %s", gJoystickName); return DIENUM_STOP; } bool ReadJoystick(F32 axes[MaxJoystickAxes], U32 &buttonMask, U32 &hatMask) { // mark: it's ok // mark: it's called "winJoystick" // mark: it's supposed to be gross. DIJOYSTATE2 js; // DInput joystick state if(!gJoystick) return false; if(FAILED(gJoystick->Poll() ) ) { HRESULT hr; hr = gJoystick->Acquire(); while( hr == DIERR_INPUTLOST ) hr = gJoystick->Acquire(); return false; } // Get the input's device state if(FAILED(gJoystick->GetDeviceState( sizeof(DIJOYSTATE2), &js ) ) ) return false; // The device should have been acquired during the Poll() F32 scale = 1 / 32768.0f; axes[0] = (F32(js.lX) - 32768.0f) * scale; axes[1] = (F32(js.lY) - 32768.0f) * scale; axes[2] = (F32(js.lZ) - 32768.0f) * scale; axes[3] = (F32(js.lRx) - 32768.0f) * scale; axes[4] = (F32(js.lRy) - 32768.0f) * scale; axes[5] = (F32(js.lRz) - 32768.0f) * scale; axes[6] = (F32(js.rglSlider[0]) - 32768.0f) * scale; axes[7] = (F32(js.rglSlider[1]) - 32768.0f) * scale; axes[8] = 0; axes[9] = 0; axes[10] = 0; axes[11] = 0; // check the state of the buttons: buttonMask = 0; U32 pov = js.rgdwPOV[0]; for( U32 i = 0; i < 12; i++ ) if((js.rgbButtons[i] & 0x80) != 0) buttonMask |= BIT(i); switch(pov) { case 0: hatMask |= ControllerButtonDPadUp; break; case 4500: hatMask |= ControllerButtonDPadUp | ControllerButtonDPadRight; break; case 9000: hatMask |= ControllerButtonDPadRight; break; case 13500: hatMask |= ControllerButtonDPadRight | ControllerButtonDPadDown; break; case 18000: hatMask |= ControllerButtonDPadDown; break; case 22500: hatMask |= ControllerButtonDPadDown | ControllerButtonDPadLeft; break; case 27000: hatMask |= ControllerButtonDPadLeft; break; case 31500: hatMask |= ControllerButtonDPadLeft | ControllerButtonDPadUp; break; } return true; } void ShutdownJoystick() { // Unacquire the device one last time just in case // the app tried to exit while the device is still acquired. if( gJoystick ) gJoystick->Unacquire(); // Release any DirectInput objects. if(gJoystick) gJoystick->Release(); if(gDirectInput) gDirectInput->Release(); } };