InputImpl.cpp

//@STATE=作成中 //@DESCRIPTION --------------------------------------------------------------- // InputImpl 抽象クラスの具象(実装)クラス // サンプルからパクリまくってます。 // 履歴: // $Log: InputImpl.cpp,v $ // Revision 1.5 2001/07/09 20:30:08 fujiwara // 例外処理の組み込み // // Revision 1.4 2001/07/01 21:30:34 fujiwara // メモリリークチェック見直し // // Revision 1.3 2001/07/01 01:03:44 fujiwara // const の見直し // 配置エディタは途中経過 // // Revision 1.2 2001/05/29 01:12:45 fujiwara // 雑魚キャラ(飛行物)の作成。配置エディタのバグ修正 // // Revision 1.1 2001/05/12 01:07:33 fujiwara // CVSを導入し、ログ表示を追加 // // 2001/01/29 メモリーリーク検出用ライブラリの追加 //@DESCRIPTION_END ----------------------------------------------------------- //@AUTHOR=S.F. // Copyright (C) 2000 Satoshi Fujiwara. All Rights Reserved. /////////////////////////////////////////////////////////////////////////////// #pragma warning( disable : 4786 ) //STLの警告外し // メモリーリーク検出用 #include "sfdebug.h" #define WIN32_LEAN_AND_MEAN #define _WIN32_WINNT 0x0400 #include "math.h" #include <list> #include <queue> #include <memory> #include <map> #include "windows.h" #include "windowsx.h" #include "d3d8.h" #include "d3dx8.h" #include "dmusici.h" #include "dinput.h" #include "dxerr8sf.h" // PROJECT INCLUDES // #include "exception.h" #include "resource.h" #include "System.h" #include "Console.h" #include "Obj.h" #include "singleton.h" #include "AbstractSprite.h" #include "ConsoleImpl.h" #include "SoundImpl.h" #ifdef _DEBUG #define new DEBUG_NEW #endif #include "InputImpl.h" #include "Scene.h" #include "MainApp.h" #include "SystemImpl.h" ////////////////////////////////////////////////////////////////////// // 構築/消滅 ////////////////////////////////////////////////////////////////////// using namespace sf::system::input; // デフォルトコンストラクタ --------------------------------------------------- InputImpl::InputImpl() { } // コンストラクタ ------------------------------------------------------------- InputImpl::InputImpl(HWND hwnd) { mHWND = hwnd; // initialize(); } // デストラクタ --------------------------------------------------------------- InputImpl::~InputImpl() { uninitialize(); }// ~InputImpl() // 初期化 --------------------------------------------------------------------- void InputImpl::initialize(void) { mpDI = NULL; mpJoystick = NULL; mpKeyboard = NULL; mbEnabled = false; mbLeft = false; mbRight = false; mbUp = false; mbDown = false; mbButtonA = false; mbButtonB = false; mbButtonC = false; mbButtonD = false; mbStart = false; mbExit = false; mbBeforeLeft = false; mbBeforeRight = false; mbBeforeUp = false; mbBeforeDown = false; mbBeforeButtonA = false; mbBeforeButtonB = false; mbBeforeButtonC = false; mbBeforeButtonD = false; mbBeforeStart = false; mbBeforeExit = false; // uninitialize(); mbEnabled = false; mbMouseCursor = false; HRESULT hr; // DirectInput オブジェクトの生成 if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, IID_IDirectInput8, (VOID**)&mpDI, NULL ) ) ) { std::string tmp("DirectInput8Create() Error : "); tmp += DXGetErrorString8(hr); tmp += " "; throw FatalErrorException(tmp,__FILE__,__LINE__); } // Joystickの初期化 try { initJoystick(); } catch (RecoverbleErrorException e) { if(mpJoystick != NULL){ mpJoystick->Release(); mpJoystick = NULL; } } catch (...){ throw; } // KeyBoardの初期化 try { initKeyboard(); } catch (RecoverbleErrorException e) { if(mpKeyboard != NULL) { mpKeyboard->Release(); mpKeyboard = NULL; } } catch (...){ throw; } // 入力デバイスが存在しない場合は、エラーで終了する。 if(NULL == mpJoystick && NULL == mpKeyboard) { throw FatalErrorException("InputImpl Device Not Found\r\n",__FILE__,__LINE__); }; addWindowMessageMap(); mbEnabled = true; }// intialize() // 終了 ----------------------------------------------------------------------- void InputImpl::uninitialize(void) { KeyboardListenerList::iterator it = mKeyboardListenerList.begin(); while(it != mKeyboardListenerList.end()) { if(*it != NULL){ (*it)->keyboardTalkerIsDeleted(); // ++it; } it = mKeyboardListenerList.erase(it); } it = mKeyboardListenerQ.begin(); while(it != mKeyboardListenerQ.end()) { if(*it != NULL){ (*it)->keyboardTalkerIsDeleted(); } it = mKeyboardListenerQ.erase(it); } MouseListenerList::iterator itm = mMouseListenerList.begin(); while(itm != mMouseListenerList.end()) { if(*itm != NULL){ (*itm)->mouseTalkerIsDeleted(); // ++itm; } itm = mMouseListenerList.erase(itm); } itm = mMouseListenerQ.begin(); while(itm != mMouseListenerQ.end()) { if(*itm != NULL){ (*itm)->mouseTalkerIsDeleted(); // ++itm; } itm = mMouseListenerQ.erase(itm); } if(mpJoystick){ mpJoystick->Release(); mpJoystick = NULL; } if(mpKeyboard){ mpKeyboard->Release(); mpKeyboard = NULL; } if(mpDI){ mpDI->Release(); mpDI = NULL; } }// uninitialize() // ジョイスティックデバイス列挙用コールバック --------------------------------- BOOL InputImpl::enumJoysticksCallback(const DIDEVICEINSTANCE *pdidInstance) { HRESULT hr; // Obtain an interface to the enumerated joystick. hr = mpDI->CreateDevice( pdidInstance->guidInstance, &mpJoystick, NULL ); // If it failed, then we can't use this joystick. (Maybe the user unplugged // it while we were in the middle of enumerating it.) if( FAILED(hr) ) return DIENUM_CONTINUE; // Stop enumeration. Note: we're just taking the first joystick we get. You // could store all the enumerated joysticks and let the user pick. return DIENUM_STOP; } // ジョイスティックの初期化 --------------------------------------------------- void InputImpl::initJoystick(void) { HRESULT hr = E_FAIL; // DirectInputデバイスの列挙 if( FAILED(hr = mpDI->EnumDevices( DI8DEVCLASS_GAMECTRL, enumJoysticksCallback, (VOID*)this, DIEDFL_ATTACHEDONLY ) ) ) { throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__); } // Make sure we got a joystick if( NULL == mpJoystick ) { throw RecoverbleErrorException(" NULL == mpJoystick",__FILE__,__LINE__);} if( FAILED(mpJoystick->SetDataFormat( &c_dfDIJoystick2 ) ) ) { throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__); } // Set the cooperative level to let DInputImpl know how this device should // interact with the system and with other DInputImpl applications. if( FAILED(mpJoystick->SetCooperativeLevel( mHWND, DISCL_EXCLUSIVE | DISCL_FOREGROUND ) ) ) { throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__);} // Determine how many axis the joystick has (so we don't error out setting // properties for unavailable axis) mDIJoystickDevCaps.dwSize = sizeof(DIDEVCAPS); if ( FAILED(mpJoystick->GetCapabilities(&mDIJoystickDevCaps) ) ) { throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__); } // Enumerate the axes of the joyctick and set the range of each axis. Note: // we could just use the defaults, but we're just trying to show an example // of enumerating device objects (axes, buttons, etc.). if ( FAILED(mpJoystick->EnumObjects( enumAxesCallback, (VOID*)this, DIDFT_AXIS ) ) ) { throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__); } }// InitJoystick() // ジョイスティックの設定コールバック ------------------------------------------------- BOOL InputImpl::enumAxesCallback( const DIDEVICEOBJECTINSTANCE* pdidoi) { DIPROPRANGE diprg; diprg.diph.dwSize = sizeof(DIPROPRANGE); diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); diprg.diph.dwHow = DIPH_BYID; diprg.diph.dwObj = pdidoi->dwType; // Specify the enumerated axis diprg.lMin = -1000; diprg.lMax = +1000; // Set the range for the axis if( FAILED( mpJoystick->SetProperty( DIPROP_RANGE, &diprg.diph ) ) ) { return DIENUM_STOP; } return DIENUM_CONTINUE; }// enumAxesCallback // キーボードデバイスの初期化 ------------------------------------------------- void InputImpl::initKeyboard(void) { HRESULT hr = E_FAIL; // キーボードデバイスの作成 if( FAILED( hr = mpDI->CreateDevice( GUID_SysKeyboard, &mpKeyboard, NULL ) ) ) { //system::Factory::getInstance()->outputError(DXGetErrorString8(hr)); throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__); } if( FAILED( hr = mpKeyboard->SetDataFormat( &c_dfDIKeyboard ) ) ) { //system::Factory::getInstance()->outputError(DXGetErrorString8(hr)); throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__); } // 協調レベルの設定 if(FAILED(mpKeyboard->SetCooperativeLevel( mHWND, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND ))) { throw RecoverbleErrorException(DXGetErrorString8(hr),__FILE__,__LINE__); } // Acquire the newly created device mpKeyboard->Acquire(); }// initKeyboard // キーボード・ジョイスティックの現在の状態を取得 ----------------------------- void InputImpl::update(void) { HRESULT hr = E_FAIL; bool b_joystick = false; bool b_keyboard = false; // ジョイスティックの現在状態を取得 // if(mpJoystick){ mpJoystick->Poll(); hr = mpJoystick->GetDeviceState(sizeof(DIJOYSTATE2),(LPVOID)&mDIJoyState); if(FAILED(hr)){ mpJoystick->Acquire(); while( hr == DIERR_INPUTLOST ) hr = mpJoystick->Acquire(); } else { b_joystick = true; } } // キーボードの現在状態を取得 // if(mpKeyboard){ // ZeroMemory( &mDIKeys, sizeof(mDIKeys) ); hr = mpKeyboard->GetDeviceState(sizeof(mDIKeys),(LPVOID)&mDIKeys); if(FAILED(hr)){ #ifdef _DEBUG OutputDebugString(DXGetErrorString8(hr)); #endif mpKeyboard->Acquire(); while( hr == DIERR_INPUTLOST ) hr = mpKeyboard->Acquire(); } else { b_keyboard = true; } } // mbBeforeLeft = mbLeft; mbBeforeRight = mbRight; mbBeforeUp = mbUp; mbBeforeDown = mbDown; mbBeforeButtonA = mbButtonA; mbBeforeButtonB = mbButtonB; mbBeforeButtonC = mbButtonC; mbBeforeButtonD = mbButtonD; mbBeforeStart = mbStart; mbBeforeExit = mbExit; mbLeft = mbRight = mbUp = mbDown = false; mbButtonA = mbButtonB = mbButtonC = mbButtonD = false; mbStart = mbExit = false; if(b_joystick){ if(mDIJoyState.lX > 300){ mbRight = true; } else { if(mDIJoyState.lX < -300) { mbLeft = true; } } if(mDIJoyState.lY > 300) mbDown = true; else if(mDIJoyState.lY < -300) mbUp = true; if(mDIJoyState.rgbButtons[0]) { mbButtonA = true; mbStart = true; } if(mDIJoyState.rgbButtons[1]) mbButtonB = true; if(mDIJoyState.rgbButtons[2]) mbButtonC = true; if(mDIJoyState.rgbButtons[3]) mbButtonD = true; } if(b_keyboard){ if(mDIKeys[DIK_LEFT] & 0x80) mbLeft = true; if(mDIKeys[DIK_RIGHT] & 0x80) mbRight = true; if(mDIKeys[DIK_UP] & 0x80) mbUp = true; if(mDIKeys[DIK_DOWN] & 0x80) mbDown = true; if(mDIKeys[DIK_Z] & 0x80) mbButtonA = true; if(mDIKeys[DIK_X] & 0x80) mbButtonB = true; if(mDIKeys[DIK_C] & 0x80) mbButtonC = true; if(mDIKeys[DIK_V] & 0x80) mbButtonD = true; if(mDIKeys[DIK_SPACE] & 0x80) mbStart = true; if(mDIKeys[DIK_ESCAPE] & 0x80) mbExit = true; } // イベントリスナーQ→イベントリスナーリストへ // MouseListenerList::iterator it = mMouseListenerQ.begin(); while(it != mMouseListenerQ.end()) { if(*it != NULL){ mMouseListenerList.push_back(*it); } it = mMouseListenerQ.erase(it); } KeyboardListenerList::iterator itk = mKeyboardListenerQ.begin(); while(itk != mKeyboardListenerQ.end()) { if(*itk != NULL){ mKeyboardListenerList.push_back(*itk); } itk = mKeyboardListenerQ.erase(itk); } }// update() LRESULT InputImpl::onSetCursor(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { if(system::Factory::getInstance()->isActive() && !mouseCursorVisibility()) { SetCursor(NULL);//マウスカーソルを消す。 return 0; } return DefWindowProc (hwnd, WM_SETCURSOR,wParam, lParam); }// onSetCursor() // マウスの左ボタンが押された −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onLButtonDown(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::leftButtonDown); }// onLButtonDown() // マウスの左ボタンが離された −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onLButtonUp(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::leftButtonUp); }// onLButtonUp() // マウスの左ボタンがダブルクリックされた −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onLButtonDoubleClick(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::leftButtonDoubleClick); }// onLButtonDoubleClick() // マウスの右ボタンが離された −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onRButtonDown(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::rightButtonDown); }// onRButtonDown() // マウスの右ボタンが押された −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onRButtonUp(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::rightButtonUp); }// onRButtonUp() // マウスの右ボタンがダブルクリックされた −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onRButtonDoubleClick(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::rightButtonDoubleClick); }// onRButtonDoubleClick() // マウスが動いた −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onMouseMove(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::mouseMove); }// onMouseMove() // ホイールが動いた −−−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::onMouseWheel(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return callMouseListenerMethod(hwnd,wParam,lParam,input::mouse::Listener::mouseWheel); }// onMouseWheel() // MouseListenerのメソッドを呼び出す −−−−−−−−−−−−−−−−−−−−−− LRESULT InputImpl::callMouseListenerMethod(const HWND hwnd, const WPARAM wParam, const LPARAM lParam,void(mouse::Listener::* pMethod)(const int,const int,const DWORD)) { using namespace sf::system::input; if(mMouseListenerList.size() == 0) return 0; POINT pt; pt.x = LOWORD(lParam); pt.y = HIWORD(lParam); ClientToScreen(hwnd,&pt); DWORD mkey = 0; if(MK_CONTROL & wParam) mkey |= mouse::MKEY_CONTROL; if(MK_SHIFT & wParam) mkey |= mouse::MKEY_SHIFT; mkey |= (wParam & 0xffff0000); MouseListenerList::iterator it = mMouseListenerList.begin(); while(it != mMouseListenerList.end()) { if(*it == NULL){ it = mMouseListenerList.erase(it); } else { if((*it)->isListeningMouse()){ ((*it)->*pMethod)(pt.x,pt.y,mkey); } ++it; } } return 0; }// callListener // キー押下時の処理 ----------------------------------------------------------- LRESULT InputImpl::onKeyDown(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { DWORD extKey = 0; // とりあえず、ESCキーが押されたら終了するようにしている switch(wParam) { case 'Q': PostMessage( hwnd, WM_CLOSE, 0, 0L ); break; default: if(GetAsyncKeyState(VK_SHIFT)) extKey |= keyboard::SHIFT; if(GetAsyncKeyState(VK_CONTROL)) extKey |= keyboard::CONTROL; KeyboardListenerList::iterator it = mKeyboardListenerList.begin(); while(it != mKeyboardListenerList.end()) { if(*it == NULL){ it = mKeyboardListenerList.erase(it); } else { if((*it)->isListeningKeyboard()){ (*it)->keyDown(wParam,extKey); } ++it; } } } return 0; // WM_KEYDOWN }// onKeyDown // キーが離された時の処理 ----------------------------------------------------------- LRESULT InputImpl::onKeyUp(const HWND hwnd, const WPARAM wParam, const LPARAM lParam) { return 0; }// onKeyUp // ウィンドウメッセージハンドラをSystemImplに登録 −−−−−−−− void InputImpl::addWindowMessageMap() { SystemImpl *pSys = dynamic_cast<SystemImpl *>(system::Factory::getInstance()); pSys->addWindowMessage(WM_SETCURSOR, new WindowMessageImpl<InputImpl>(this,&InputImpl::onSetCursor)); pSys->addWindowMessage(WM_LBUTTONDOWN,new WindowMessageImpl<InputImpl>(this,&InputImpl::onLButtonDown)); pSys->addWindowMessage(WM_LBUTTONUP,new WindowMessageImpl<InputImpl>(this,&InputImpl::onLButtonUp)); pSys->addWindowMessage(WM_LBUTTONDBLCLK,new WindowMessageImpl<InputImpl>(this,&InputImpl::onLButtonDoubleClick)); pSys->addWindowMessage(WM_RBUTTONDOWN,new WindowMessageImpl<InputImpl>(this,&InputImpl::onRButtonDown)); pSys->addWindowMessage(WM_RBUTTONUP,new WindowMessageImpl<InputImpl>(this,&InputImpl::onRButtonUp)); pSys->addWindowMessage(WM_RBUTTONDBLCLK,new WindowMessageImpl<InputImpl>(this,&InputImpl::onRButtonDoubleClick)); pSys->addWindowMessage(WM_MOUSEMOVE,new WindowMessageImpl<InputImpl>(this,&InputImpl::onMouseMove)); pSys->addWindowMessage(WM_MOUSEWHEEL,new WindowMessageImpl<InputImpl>(this,&InputImpl::onMouseWheel)); pSys->addWindowMessage(WM_KEYDOWN,new WindowMessageImpl<InputImpl>(this,&InputImpl::onKeyDown)); pSys->addWindowMessage(WM_KEYUP,new WindowMessageImpl<InputImpl>(this,&InputImpl::onKeyUp)); }