void SdlManager::SdlController::RunHapticLeftRight(float left, float right) { CriticalCode criticalCode(criticalSection); if(!haptic) return; hapticEffect.leftright.length = SDL_HAPTIC_INFINITY; hapticEffect.leftright.large_magnitude = uint16_t(left * 0xffff); hapticEffect.leftright.small_magnitude = uint16_t(right * 0xffff); if(hapticEffectIndex >= 0 && hapticEffect.type == SDL_HAPTIC_LEFTRIGHT) { SDL_HapticStopEffect(haptic, hapticEffectIndex); SDL_HapticUpdateEffect(haptic, hapticEffectIndex, &hapticEffect); } else { if(hapticEffectIndex >= 0) { SDL_HapticStopEffect(haptic, hapticEffectIndex); SDL_HapticDestroyEffect(haptic, hapticEffectIndex); } hapticEffect.type = SDL_HAPTIC_LEFTRIGHT; hapticEffectIndex = SDL_HapticNewEffect(haptic, &hapticEffect); } SDL_HapticRunEffect(haptic, hapticEffectIndex, 1); }
void SdlManager::SdlController::StopHaptic() { CriticalCode criticalCode(criticalSection); if(hapticEffectIndex >= 0) { SDL_HapticStopEffect(haptic, hapticEffectIndex); } }
void Manager::AddEvent(const Event& e) { CriticalCode criticalCode(criticalSection); // skip text input events if text input is disabled if(e.device == Event::deviceKeyboard && e.keyboard.type == Event::Keyboard::typeCharacter && !textInputEnabled) return; internalFrame->AddEvent(e); }
ptr<Controller> SdlManager::TryGetController(int controllerId) { CriticalCode criticalCode(criticalSection); decltype(controllers)::const_iterator i = controllers.find(controllerId); if(i != controllers.end()) return i->second; return nullptr; }
void Manager::Update() { CriticalCode criticalCode(criticalSection); // switch frames std::swap(currentFrame, internalFrame); // old internal frame (new current frame) // should be copied to new internal frame, // and state is rewinded forward currentFrame->CopyTo(internalFrame); internalFrame->ForwardEvents(); internalFrame->Reset(); // add release events to internal frame if needed if(releaseButtonsOnUpdate) { releaseButtonsOnUpdate = false; const State& state = internalFrame->GetCurrentState(); for(size_t i = 0; i < sizeof(state.keyboard) / sizeof(state.keyboard[0]); ++i) if(state.keyboard[i]) { Event e; e.device = Event::deviceKeyboard; e.keyboard.type = Event::Keyboard::typeKeyUp; e.keyboard.key = Key(i); internalFrame->AddEvent(e); } for(size_t i = 0; i < sizeof(state.mouseButtons) / sizeof(state.mouseButtons[0]); ++i) if(state.mouseButtons[i]) { Event e; e.device = Event::deviceMouse; e.mouse.type = Event::Mouse::typeButtonUp; e.mouse.button = Event::Mouse::Button(i); internalFrame->AddEvent(e); } } }
void SdlManager::SdlController::Close() { CriticalCode criticalCode(criticalSection); if(hapticEffectIndex >= 0) { SDL_HapticStopEffect(haptic, hapticEffectIndex); SDL_HapticDestroyEffect(haptic, hapticEffectIndex); hapticEffectIndex = -1; } if(haptic) { SDL_HapticClose(haptic); haptic = nullptr; } if(controller) { SDL_GameControllerClose(controller); controller = nullptr; } }
bool SdlManager::SdlController::IsActive() const { CriticalCode criticalCode(criticalSection); return controller; }
void SdlManager::ProcessEvent(const SDL_Event& event) { switch(event.type) { case SDL_KEYDOWN: case SDL_KEYUP: { Event e; e.device = Event::deviceKeyboard; e.keyboard.type = event.type == SDL_KEYDOWN ? Event::Keyboard::typeKeyDown : Event::Keyboard::typeKeyUp; e.keyboard.key = ConvertKey(event.key.keysym.sym); AddEvent(e); } break; case SDL_TEXTINPUT: for(auto i = utf8::unchecked::iterator<const char*>(event.text.text); *i.base(); ++i) { Event e; e.device = Event::deviceKeyboard; e.keyboard.type = Event::Keyboard::typeCharacter; e.keyboard.character = *i; AddEvent(e); } break; case SDL_MOUSEMOTION: // raw move event { Event e; e.device = Event::deviceMouse; e.mouse.type = Event::Mouse::typeRawMove; e.mouse.rawMoveX = event.motion.xrel; e.mouse.rawMoveY = event.motion.yrel; e.mouse.rawMoveZ = 0; AddEvent(e); } // cursor move event { Event e; e.device = Event::deviceMouse; e.mouse.type = Event::Mouse::typeCursorMove; e.mouse.cursorX = (int)(event.motion.x * widthScale); e.mouse.cursorY = (int)(event.motion.y * heightScale); AddEvent(e); } break; case SDL_MOUSEBUTTONDOWN: case SDL_MOUSEBUTTONUP: { Event e; e.device = Event::deviceMouse; e.mouse.type = event.type == SDL_MOUSEBUTTONDOWN ? Event::Mouse::typeButtonDown : Event::Mouse::typeButtonUp; bool ok = true; switch(event.button.button) { case SDL_BUTTON_LEFT: e.mouse.button = Event::Mouse::buttonLeft; break; case SDL_BUTTON_MIDDLE: e.mouse.button = Event::Mouse::buttonMiddle; break; case SDL_BUTTON_RIGHT: e.mouse.button = Event::Mouse::buttonRight; break; default: ok = false; break; } if(ok) AddEvent(e); } break; case SDL_CONTROLLERDEVICEADDED: // device added event { // open controller SDL_GameController* sdlController = SDL_GameControllerOpen(event.cdevice.which); if(sdlController) { ptr<SdlController> controller = NEW(SdlController(sdlController)); { CriticalCode criticalCode(criticalSection); controllers[controller->GetControllerId()] = controller; } Event e; e.device = Event::deviceController; e.controller.type = Event::Controller::typeDeviceAdded; e.controller.device = controller->GetControllerId(); AddEvent(e); } } break; case SDL_CONTROLLERDEVICEREMOVED: // device removed event { // try to find controller by id, and remove it from map ptr<SdlController> controller; { CriticalCode criticalCode(criticalSection); decltype(controllers)::const_iterator i = controllers.find(event.cdevice.which); if(i != controllers.end()) { controller = i->second; controllers.erase(i); } } // if it's found if(controller) { // close controller controller->Close(); controller = nullptr; // emit event Event e; e.device = Event::deviceController; e.controller.type = Event::Controller::typeDeviceRemoved; e.controller.device = event.cdevice.which; AddEvent(e); } } break; case SDL_CONTROLLERBUTTONDOWN: case SDL_CONTROLLERBUTTONUP: // controller button down/up event { Event::Controller::Button button; bool ok = true; switch(event.cbutton.button) { #define B(a, b) case SDL_CONTROLLER_BUTTON_##a: button = Event::Controller::button##b; break B(A, A); B(B, B); B(X, X); B(Y, Y); B(BACK, Back); B(GUIDE, Guide); B(START, Start); B(LEFTSTICK, LeftStick); B(RIGHTSTICK, RightStick); B(LEFTSHOULDER, LeftShoulder); B(RIGHTSHOULDER, RightShoulder); B(DPAD_UP, DPadUp); B(DPAD_DOWN, DPadDown); B(DPAD_LEFT, DPadLeft); B(DPAD_RIGHT, DPadRight); #undef B default: ok = false; break; } if(ok) { Event e; e.device = Event::deviceController; e.controller.type = event.type == SDL_CONTROLLERBUTTONDOWN ? Event::Controller::typeButtonDown : Event::Controller::typeButtonUp; e.controller.device = event.cbutton.which; e.controller.button = button; AddEvent(e); } } break; case SDL_CONTROLLERAXISMOTION: // controller axis motion event { Event::Controller::Axis axis; bool ok = true; switch(event.caxis.axis) { #define A(a, b) case SDL_CONTROLLER_AXIS_##a: axis = Event::Controller::axis##b; break A(LEFTX, LeftX); A(LEFTY, LeftY); A(RIGHTX, RightX); A(RIGHTY, RightY); A(TRIGGERLEFT, TriggerLeft); A(TRIGGERRIGHT, TriggerRight); #undef A default: ok = false; break; } if(ok) { Event e; e.device = Event::deviceController; e.controller.type = Event::Controller::typeAxisMotion; e.controller.device = event.caxis.which; e.controller.axis = axis; e.controller.axisValue = event.caxis.value; AddEvent(e); } } break; } }
void Manager::StopTextInput() { CriticalCode criticalCode(criticalSection); textInputEnabled = false; }
void Manager::StartTextInput() { CriticalCode criticalCode(criticalSection); textInputEnabled = true; }
void Manager::ReleaseButtonsOnUpdate() { CriticalCode criticalCode(criticalSection); releaseButtonsOnUpdate = true; }