forked from eden-emu/eden
		
	
		
			
				
	
	
		
			216 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
	
		
			6 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
 | |
| // SPDX-License-Identifier: GPL-2.0-or-later
 | |
| 
 | |
| #include "common/settings.h"
 | |
| #include "input_common/input_engine.h"
 | |
| #include "input_common/input_mapping.h"
 | |
| 
 | |
| namespace InputCommon {
 | |
| 
 | |
| MappingFactory::MappingFactory() = default;
 | |
| 
 | |
| void MappingFactory::BeginMapping(Polling::InputType type) {
 | |
|     is_enabled = true;
 | |
|     input_type = type;
 | |
|     input_queue.Clear();
 | |
|     first_axis = -1;
 | |
|     second_axis = -1;
 | |
| }
 | |
| 
 | |
| Common::ParamPackage MappingFactory::GetNextInput() {
 | |
|     Common::ParamPackage input;
 | |
|     input_queue.Pop(input);
 | |
|     return input;
 | |
| }
 | |
| 
 | |
| void MappingFactory::RegisterInput(const MappingData& data) {
 | |
|     if (!is_enabled) {
 | |
|         return;
 | |
|     }
 | |
|     if (!IsDriverValid(data)) {
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (input_type) {
 | |
|     case Polling::InputType::Button:
 | |
|         RegisterButton(data);
 | |
|         return;
 | |
|     case Polling::InputType::Stick:
 | |
|         RegisterStick(data);
 | |
|         return;
 | |
|     case Polling::InputType::Motion:
 | |
|         RegisterMotion(data);
 | |
|         return;
 | |
|     default:
 | |
|         return;
 | |
|     }
 | |
| }
 | |
| 
 | |
| void MappingFactory::StopMapping() {
 | |
|     is_enabled = false;
 | |
|     input_type = Polling::InputType::None;
 | |
|     input_queue.Clear();
 | |
| }
 | |
| 
 | |
| void MappingFactory::RegisterButton(const MappingData& data) {
 | |
|     Common::ParamPackage new_input;
 | |
|     new_input.Set("engine", data.engine);
 | |
|     if (data.pad.guid.IsValid()) {
 | |
|         new_input.Set("guid", data.pad.guid.RawString());
 | |
|     }
 | |
|     new_input.Set("port", static_cast<int>(data.pad.port));
 | |
|     new_input.Set("pad", static_cast<int>(data.pad.pad));
 | |
| 
 | |
|     switch (data.type) {
 | |
|     case EngineInputType::Button:
 | |
|         // Workaround for old compatibility
 | |
|         if (data.engine == "keyboard") {
 | |
|             new_input.Set("code", data.index);
 | |
|             break;
 | |
|         }
 | |
|         new_input.Set("button", data.index);
 | |
|         break;
 | |
|     case EngineInputType::HatButton:
 | |
|         new_input.Set("hat", data.index);
 | |
|         new_input.Set("direction", data.hat_name);
 | |
|         break;
 | |
|     case EngineInputType::Analog:
 | |
|         // Ignore mouse axis when mapping buttons
 | |
|         if (data.engine == "mouse" && data.index != 4) {
 | |
|             return;
 | |
|         }
 | |
|         new_input.Set("axis", data.index);
 | |
|         new_input.Set("threshold", 0.5f);
 | |
|         break;
 | |
|     case EngineInputType::Motion:
 | |
|         new_input.Set("motion", data.index);
 | |
|         break;
 | |
|     default:
 | |
|         return;
 | |
|     }
 | |
|     input_queue.Push(new_input);
 | |
| }
 | |
| 
 | |
| void MappingFactory::RegisterStick(const MappingData& data) {
 | |
|     Common::ParamPackage new_input;
 | |
|     new_input.Set("engine", data.engine);
 | |
|     if (data.pad.guid.IsValid()) {
 | |
|         new_input.Set("guid", data.pad.guid.RawString());
 | |
|     }
 | |
|     new_input.Set("port", static_cast<int>(data.pad.port));
 | |
|     new_input.Set("pad", static_cast<int>(data.pad.pad));
 | |
| 
 | |
|     // If engine is mouse map the mouse position as a joystick
 | |
|     if (data.engine == "mouse") {
 | |
|         new_input.Set("axis_x", 0);
 | |
|         new_input.Set("axis_y", 1);
 | |
|         new_input.Set("threshold", 0.5f);
 | |
|         new_input.Set("range", 1.0f);
 | |
|         new_input.Set("deadzone", 0.0f);
 | |
|         input_queue.Push(new_input);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (data.type) {
 | |
|     case EngineInputType::Button:
 | |
|     case EngineInputType::HatButton:
 | |
|         RegisterButton(data);
 | |
|         return;
 | |
|     case EngineInputType::Analog:
 | |
|         if (first_axis == data.index) {
 | |
|             return;
 | |
|         }
 | |
|         if (first_axis == -1) {
 | |
|             first_axis = data.index;
 | |
|             return;
 | |
|         }
 | |
|         new_input.Set("axis_x", first_axis);
 | |
|         new_input.Set("axis_y", data.index);
 | |
|         new_input.Set("threshold", 0.5f);
 | |
|         new_input.Set("range", 0.95f);
 | |
|         new_input.Set("deadzone", 0.15f);
 | |
|         break;
 | |
|     default:
 | |
|         return;
 | |
|     }
 | |
|     input_queue.Push(new_input);
 | |
| }
 | |
| 
 | |
| void MappingFactory::RegisterMotion(const MappingData& data) {
 | |
|     Common::ParamPackage new_input;
 | |
|     new_input.Set("engine", data.engine);
 | |
|     if (data.pad.guid.IsValid()) {
 | |
|         new_input.Set("guid", data.pad.guid.RawString());
 | |
|     }
 | |
|     new_input.Set("port", static_cast<int>(data.pad.port));
 | |
|     new_input.Set("pad", static_cast<int>(data.pad.pad));
 | |
| 
 | |
|     // If engine is mouse map it automatically to mouse motion
 | |
|     if (data.engine == "mouse") {
 | |
|         new_input.Set("motion", 0);
 | |
|         new_input.Set("pad", 1);
 | |
|         new_input.Set("threshold", 0.001f);
 | |
|         input_queue.Push(new_input);
 | |
|         return;
 | |
|     }
 | |
| 
 | |
|     switch (data.type) {
 | |
|     case EngineInputType::Button:
 | |
|     case EngineInputType::HatButton:
 | |
|         RegisterButton(data);
 | |
|         return;
 | |
|     case EngineInputType::Analog:
 | |
|         if (first_axis == data.index) {
 | |
|             return;
 | |
|         }
 | |
|         if (second_axis == data.index) {
 | |
|             return;
 | |
|         }
 | |
|         if (first_axis == -1) {
 | |
|             first_axis = data.index;
 | |
|             return;
 | |
|         }
 | |
|         if (second_axis == -1) {
 | |
|             second_axis = data.index;
 | |
|             return;
 | |
|         }
 | |
|         new_input.Set("axis_x", first_axis);
 | |
|         new_input.Set("axis_y", second_axis);
 | |
|         new_input.Set("axis_z", data.index);
 | |
|         new_input.Set("range", 1.0f);
 | |
|         new_input.Set("deadzone", 0.20f);
 | |
|         break;
 | |
|     case EngineInputType::Motion:
 | |
|         new_input.Set("motion", data.index);
 | |
|         break;
 | |
|     default:
 | |
|         return;
 | |
|     }
 | |
|     input_queue.Push(new_input);
 | |
| }
 | |
| 
 | |
| bool MappingFactory::IsDriverValid(const MappingData& data) const {
 | |
|     // Only port 0 can be mapped on the keyboard
 | |
|     if (data.engine == "keyboard" && data.pad.port != 0) {
 | |
|         return false;
 | |
|     }
 | |
|     // Only port 0 can be mapped on the mouse
 | |
|     if (data.engine == "mouse" && data.pad.port != 0) {
 | |
|         return false;
 | |
|     }
 | |
|     // To prevent mapping with two devices we disable any UDP except motion
 | |
|     if (!Settings::values.enable_udp_controller && data.engine == "cemuhookudp" &&
 | |
|         data.type != EngineInputType::Motion) {
 | |
|         return false;
 | |
|     }
 | |
|     // The following drivers don't need to be mapped
 | |
|     if (data.engine == "touch_from_button") {
 | |
|         return false;
 | |
|     }
 | |
|     if (data.engine == "analog_from_button") {
 | |
|         return false;
 | |
|     }
 | |
|     return true;
 | |
| }
 | |
| 
 | |
| } // namespace InputCommon
 | 
