// // Lol Engine // // Copyright © 2010—2015 Benjamin Litzelmann // © 2017—2018 Sam Hocevar // // Lol Engine is free software. It comes without any warranty, to // the extent permitted by applicable law. You can redistribute it // and/or modify it under the terms of the Do What the Fuck You Want // to Public License, Version 2, as published by the WTFPL Task Force. // See http://www.wtfpl.net/ for more details. // #include #include namespace lol { /////////////////////////////////////////////////////////////////////////////// // KeyBinding void KeyBinding::Bind(const std::string& device_name, const std::string& key_name) { const InputDevice* device = InputDevice::Get(device_name); if (!device) { msg::warn("trying to bind key to nonexistent input device %s\n", device_name.c_str()); return; } int keyindex = device->GetKeyIndex(key_name); if (keyindex < 0) { msg::warn("trying to bind nonexistent key %s.%s\n", device_name.c_str(), key_name.c_str()); return; } m_keybindings.push(device, keyindex); } bool KeyBinding::Unbind(const std::string& device_name, const std::string& key_name) { for (int i = 0; i < m_keybindings.count(); ++i) { if (m_keybindings[i].m1->GetName() == device_name) { if (m_keybindings[i].m2 == m_keybindings[i].m1->GetKeyIndex(key_name)) { m_keybindings.remove(i); return true; } } } return false; } void KeyBinding::ClearBindings() { m_keybindings.clear(); } /////////////////////////////////////////////////////////////////////////////// // AxisBinding void AxisBinding::Bind(const std::string& device_name, const std::string& axis_name) { const InputDevice* device = InputDevice::Get(device_name); if (!device) { msg::warn("trying to bind axis to nonexistent input device %s\n", device_name.c_str()); return; } int axisindex = device->GetAxisIndex(axis_name); if (axisindex < 0) { msg::warn("trying to bind nonexistent axis %s.%s\n", device_name.c_str(), axis_name.c_str()); return; } m_axisbindings.push(device, axisindex); } void AxisBinding::BindKey(const std::string& device_name, const std::string& key_name) { const InputDevice* device = InputDevice::Get(device_name); if (!device) { msg::warn("trying to bind axis key to nonexistent input device %s\n", device_name.c_str()); return; } int keyindex = device->GetKeyIndex(key_name); if (keyindex < 0) { msg::warn("trying to bind nonexistent axis key %s.%s\n", device_name.c_str(), key_name.c_str()); return; } m_keybindings.push(device, -1, keyindex); } void AxisBinding::BindKeys(const std::string& device_name, const std::string& min_key_name, const std::string& max_key_name) { const InputDevice* device = InputDevice::Get(device_name); if (!device) { msg::warn("trying to bind axis keys to nonexistent input device %s\n", device_name.c_str()); return; } int minkeyindex = device->GetKeyIndex(min_key_name); if (minkeyindex < 0) { msg::warn("trying to bind nonexistent axis key %s.%s\n", device_name.c_str(), min_key_name.c_str()); return; } int maxkeyindex = device->GetKeyIndex(max_key_name); if (maxkeyindex < 0) { msg::warn("trying to bind nonexistent axis key %s.%s\n", device_name.c_str(), max_key_name.c_str()); return; } m_keybindings.push(device, minkeyindex, maxkeyindex); } bool AxisBinding::Unbind(const std::string& device_name, const std::string& axis_name) { for (int i = 0; i < m_keybindings.count(); ++i) { if (m_axisbindings[i].m1->GetName() == device_name) { if (m_axisbindings[i].m2 == m_axisbindings[i].m1->GetAxisIndex(axis_name)) { m_axisbindings.remove(i); return true; } } } return false; } bool AxisBinding::UnbindKey(const std::string& device_name, const std::string& key_name) { for (int i = 0; i < m_keybindings.count(); ++i) { if (m_keybindings[i].m1->GetName() == device_name) { if (m_keybindings[i].m2 == -1 && m_keybindings[i].m3 == m_keybindings[i].m1->GetKeyIndex(key_name)) { m_keybindings.remove(i); return true; } } } return false; } bool AxisBinding::UnbindKeys(const std::string& device_name, const std::string& min_key_name, const std::string& max_key_name) { for (int i = 0; i < m_keybindings.count(); ++i) { if (m_keybindings[i].m1->GetName() == device_name) { if (m_keybindings[i].m2 == m_keybindings[i].m1->GetKeyIndex(min_key_name) && m_keybindings[i].m3 == m_keybindings[i].m1->GetKeyIndex(max_key_name)) { m_keybindings.remove(i); return true; } } } return false; } void AxisBinding::ClearBindings() { m_axisbindings.clear(); m_keybindings.clear(); } float AxisBinding::RetrieveCurrentValue() { float max_positive = 0.0f; float max_negative = 0.0f; for (int i = 0; i < m_axisbindings.count(); ++i) { float value = m_axisbindings[i].m1->GetAxis(m_axisbindings[i].m2); if (value > max_positive) max_positive = value; if (value < max_negative) max_negative = value; } for (int i = 0; i < m_keybindings.count(); ++i) { float value = 0.0f; m_keybindings[i].m1->GetKey(m_keybindings[i].m2); value += m_keybindings[i].m1->GetKey(m_keybindings[i].m3) ? 1.0f : 0.0f; if (m_keybindings[i].m2 != -1) value += m_keybindings[i].m1->GetKey(m_keybindings[i].m2) ? -1.0f : 0.0f; if (value > max_positive) max_positive = value; if (value < max_negative) max_negative = value; } return max_negative + max_positive; } /////////////////////////////////////////////////////////////////////////////// // Controller array Controller::controllers; uint32_t Controller::m_active_layer = ~((uint32_t)0); //----------------------------------------------------------------------------- Controller::Controller(std::string const &name) { m_gamegroup = GAMEGROUP_INPUT; m_name = name; m_activate_nextframe = true; m_deactivate_nextframe = false; m_active = false; if (Get(name) != nullptr) { msg::warn("controller “%s” has already been registered\n", name.c_str()); } controllers.push(this); } Controller::Controller(std::string const &name, InputProfile const& profile) : Controller(name) { Init(profile); } Controller::~Controller() { ClearProfile(); for (int i = 0; i < controllers.count(); ++i) { if (controllers[i] == this) { controllers.remove(i); break; } } } //Init mode 1: Input profile system ------------------------------------------- void Controller::Init(InputProfile const& profile) { UnbindProfile(); BindProfile(profile); } void Controller::ClearProfile() { UnbindProfile(); } //Init mode 2: By hand, key/axis by key/axis ---------------------------------- void Controller::SetInputCount(int nb_keys, int nb_axis) { m_keys.resize(nb_keys); m_axis.resize(nb_axis); } //Layer mask stuff ------------------------------------------------------------ void Controller::SetLayerMask(uint32_t layer_mask) { m_layer_mask = layer_mask; } uint32_t Controller::GetLayerMask() { return m_layer_mask; } bool Controller::IsLayerActive() { return !!(m_layer_mask & m_active_layer); } //GetKeys/Axis stuff ---------------------------------------------------------- KeyBinding& Controller::GetKey(int index) { return m_keys[index]; } KeyBinding const& Controller::GetKey(int index) const { return m_keys[index]; } AxisBinding& Controller::GetAxis(int index) { return m_axis[index]; } AxisBinding const& Controller::GetAxis(int index) const { return m_axis[index]; } //Key methods: should not go directly to binding ------------------------------ bool Controller::IsKeyPressed(int index) const { //#error do something better IsLayerActive() return GetKey(index).IsPressed(); } bool Controller::IsKeyReleased(int index) const { return GetKey(index).IsReleased(); } bool Controller::WasKeyPressedThisFrame(int index) const { return GetKey(index).WasPressedThisFrame(); } bool Controller::WasKeyReleasedThisFrame(int index) const { return GetKey(index).WasReleasedThisFrame(); } //Axis methods: should not go directly to binding ----------------------------- float Controller::GetAxisValue(int index) const { return GetAxis(index).GetValue(); } float Controller::GetAxisDelta(int index) const { return GetAxis(index).GetDelta(); } //----------------------------------------------------------------------------- Controller* Controller::Get(std::string const &name) { for (auto controller : controllers) if (controller->m_name == name) return controller; return nullptr; } //Input profile system -------------------------------------------------------- void Controller::UnbindProfile() { if (m_profile.IsEmpty()) return; m_mutex.lock(); //Keyboard if (m_keyboard) { for (InputProfile::Keyboard& key : m_profile.m_keys) GetKey(key.m_idx).UnbindKeyboard(key.m_name); m_keyboard = nullptr; } //Mouse if (m_mouse) { for (InputProfile::MouseKey& key : m_profile.m_mouse_keys) GetKey(key.m_idx).UnbindMouse(key.m_name); for (InputProfile::MouseAxis& axis : m_profile.m_mouse_axis) GetAxis(axis.m_idx).UnbindMouse(axis.m_name); m_mouse = nullptr; } //Joystick for (InputProfile::JoystickKey& key : m_profile.m_joystick_keys) { if (m_joystick_idx.find(key.m_joy) != INDEX_NONE) GetKey(key.m_idx).UnbindJoystick(key.m_joy, key.m_name); } for (InputProfile::JoystickAxis& axis : m_profile.m_joystick_axis) { if (m_joystick_idx.find(axis.m_joy) != INDEX_NONE) GetAxis(axis.m_idx).UnbindJoystick(axis.m_joy, axis.m_name); } m_joystick.clear(); m_joystick_idx.clear(); m_mutex.unlock(); } //Input profile system -------------------------------------------------------- void Controller::BindProfile(InputProfile const& setup) { ASSERT(!setup.IsEmpty()); m_mutex.lock(); m_profile = setup; m_keys.resize(m_profile.GetKeyCount()); m_axis.resize(m_profile.GetAxisCount()); //Keyboard m_keyboard = InputDevice::GetKeyboard(); if (m_keyboard) { for (InputProfile::Keyboard& key : m_profile.m_keys) GetKey(key.m_idx).BindKeyboard(key.m_name); } //Mouse m_mouse = InputDevice::GetMouse(); if (m_mouse) { for (InputProfile::MouseKey& key : m_profile.m_mouse_keys) GetKey(key.m_idx).BindMouse(key.m_name); for (InputProfile::MouseAxis& axis : m_profile.m_mouse_axis) GetAxis(axis.m_idx).BindMouse(axis.m_name); } //Joystick for (uint64_t joy_idx : m_profile.m_joystick) { class InputDevice* joystick = InputDevice::GetJoystick(joy_idx); if (joystick) { m_joystick << joystick; m_joystick_idx << joy_idx; } } for (InputProfile::JoystickKey& key : m_profile.m_joystick_keys) { if (m_joystick_idx.find(key.m_joy) != INDEX_NONE) GetKey(key.m_idx).BindJoystick(key.m_joy, key.m_name); } for (InputProfile::JoystickAxis& axis : m_profile.m_joystick_axis) { if (m_joystick_idx.find(axis.m_joy) != INDEX_NONE) GetAxis(axis.m_idx).BindJoystick(axis.m_joy, axis.m_name); } m_mutex.unlock(); } //----------------------------------------------------------------------------- void Controller::tick_game(float seconds) { Entity::tick_game(seconds); if (m_active) { for (int i = 0; i < m_keys.count(); ++i) m_keys[i].Update(); for (int i = 0; i < m_axis.count(); ++i) m_axis[i].Update(); } if (m_activate_nextframe) m_active = true; if (m_deactivate_nextframe) m_active = false; m_activate_nextframe = false; m_deactivate_nextframe = false; } //----------------------------------------------------------------------------- void Controller::Activate() { m_activate_nextframe = true; m_deactivate_nextframe = false; } void Controller::Deactivate() { m_deactivate_nextframe = true; m_activate_nextframe = false; } //----------------------------------------------------------------------------- array Controller::DeactivateAll() { array result; for (int i = 0; i < controllers.count(); ++i) { if (controllers[i]->m_active || controllers[i]->m_activate_nextframe) { result.push(controllers[i]); controllers[i]->Deactivate(); } } return result; } } /* namespace lol */