forked from dolphin-emu/dolphin
		
	
		
			
	
	
		
			97 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
		
		
			
		
	
	
			97 lines
		
	
	
		
			3.1 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| 
								 | 
							
								// Copyright 2017 Dolphin Emulator Project
							 | 
						||
| 
								 | 
							
								// Licensed under GPLv2+
							 | 
						||
| 
								 | 
							
								// Refer to the license.txt file included.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "InputCommon/ControllerEmu/ControlGroup/Tilt.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include <algorithm>
							 | 
						||
| 
								 | 
							
								#include <cmath>
							 | 
						||
| 
								 | 
							
								#include <memory>
							 | 
						||
| 
								 | 
							
								#include <string>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#include "Common/Common.h"
							 | 
						||
| 
								 | 
							
								#include "InputCommon/ControlReference/ControlReference.h"
							 | 
						||
| 
								 | 
							
								#include "InputCommon/ControllerEmu/Control/Control.h"
							 | 
						||
| 
								 | 
							
								#include "InputCommon/ControllerEmu/Control/Input.h"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								namespace ControllerEmu
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								Tilt::Tilt(const std::string& name_) : ControlGroup(name_, GROUP_TYPE_TILT)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  controls.emplace_back(std::make_unique<Input>("Forward"));
							 | 
						||
| 
								 | 
							
								  controls.emplace_back(std::make_unique<Input>("Backward"));
							 | 
						||
| 
								 | 
							
								  controls.emplace_back(std::make_unique<Input>("Left"));
							 | 
						||
| 
								 | 
							
								  controls.emplace_back(std::make_unique<Input>("Right"));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  controls.emplace_back(std::make_unique<Input>(_trans("Modifier")));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Dead Zone"), 0, 0, 50));
							 | 
						||
| 
								 | 
							
								  numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Circle Stick"), 0));
							 | 
						||
| 
								 | 
							
								  numeric_settings.emplace_back(std::make_unique<NumericSetting>(_trans("Angle"), 0.9, 0, 180));
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								void Tilt::GetState(ControlState* const x, ControlState* const y, const bool step)
							 | 
						||
| 
								 | 
							
								{
							 | 
						||
| 
								 | 
							
								  // this is all a mess
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
							 | 
						||
| 
								 | 
							
								  ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ControlState deadzone = numeric_settings[0]->GetValue();
							 | 
						||
| 
								 | 
							
								  ControlState circle = numeric_settings[1]->GetValue();
							 | 
						||
| 
								 | 
							
								  auto const angle = numeric_settings[2]->GetValue() / 1.8;
							 | 
						||
| 
								 | 
							
								  ControlState m = controls[4]->control_ref->State();
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // deadzone / circle stick code
							 | 
						||
| 
								 | 
							
								  // this section might be all wrong, but its working good enough, I think
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ControlState ang = atan2(yy, xx);
							 | 
						||
| 
								 | 
							
								  ControlState ang_sin = sin(ang);
							 | 
						||
| 
								 | 
							
								  ControlState ang_cos = cos(ang);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // the amt a full square stick would have at current angle
							 | 
						||
| 
								 | 
							
								  ControlState square_full =
							 | 
						||
| 
								 | 
							
								      std::min(ang_sin ? 1 / fabs(ang_sin) : 2, ang_cos ? 1 / fabs(ang_cos) : 2);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // the amt a full stick would have that was (user setting circular) at current angle
							 | 
						||
| 
								 | 
							
								  // I think this is more like a pointed circle rather than a rounded square like it should be
							 | 
						||
| 
								 | 
							
								  ControlState stick_full = (square_full * (1 - circle)) + (circle);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  ControlState dist = sqrt(xx * xx + yy * yy);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // dead zone code
							 | 
						||
| 
								 | 
							
								  dist = std::max(0.0, dist - deadzone * stick_full);
							 | 
						||
| 
								 | 
							
								  dist /= (1 - deadzone);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // circle stick code
							 | 
						||
| 
								 | 
							
								  ControlState amt = dist / stick_full;
							 | 
						||
| 
								 | 
							
								  dist += (square_full - 1) * amt * circle;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  if (m)
							 | 
						||
| 
								 | 
							
								    dist *= 0.5;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  yy = std::max(-1.0, std::min(1.0, ang_sin * dist));
							 | 
						||
| 
								 | 
							
								  xx = std::max(-1.0, std::min(1.0, ang_cos * dist));
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // this is kinda silly here
							 | 
						||
| 
								 | 
							
								  // gui being open will make this happen 2x as fast, o well
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  // silly
							 | 
						||
| 
								 | 
							
								  if (step)
							 | 
						||
| 
								 | 
							
								  {
							 | 
						||
| 
								 | 
							
								    if (xx > m_tilt[0])
							 | 
						||
| 
								 | 
							
								      m_tilt[0] = std::min(m_tilt[0] + 0.1, xx);
							 | 
						||
| 
								 | 
							
								    else if (xx < m_tilt[0])
							 | 
						||
| 
								 | 
							
								      m_tilt[0] = std::max(m_tilt[0] - 0.1, xx);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    if (yy > m_tilt[1])
							 | 
						||
| 
								 | 
							
								      m_tilt[1] = std::min(m_tilt[1] + 0.1, yy);
							 | 
						||
| 
								 | 
							
								    else if (yy < m_tilt[1])
							 | 
						||
| 
								 | 
							
								      m_tilt[1] = std::max(m_tilt[1] - 0.1, yy);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  *y = m_tilt[1] * angle;
							 | 
						||
| 
								 | 
							
								  *x = m_tilt[0] * angle;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								}  // namespace ControllerEmu
							 |