| 
									
										
										
										
											2010-06-12 17:15:16 +00:00
										 |  |  | // Copyright (C) 2010 Dolphin Project.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | #ifndef _CONTROLLEREMU_H_
 | 
					
						
							|  |  |  | #define _CONTROLLEREMU_H_
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // windows crap
 | 
					
						
							|  |  |  | #define NOMINMAX
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-13 09:26:00 +00:00
										 |  |  | #include <cmath>
 | 
					
						
							|  |  |  | #include <vector>
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							|  |  |  | #include <algorithm>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "GCPadStatus.h"
 | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-12 17:39:33 +00:00
										 |  |  | #include "ControllerInterface/ControllerInterface.h"
 | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | #include "IniFile.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #define sign(x) ((x)?(x)<0?-1:1:0)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | enum | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	GROUP_TYPE_OTHER, | 
					
						
							|  |  |  | 	GROUP_TYPE_STICK, | 
					
						
							|  |  |  | 	GROUP_TYPE_MIXED_TRIGGERS, | 
					
						
							|  |  |  | 	GROUP_TYPE_BUTTONS, | 
					
						
							|  |  |  | 	GROUP_TYPE_FORCE, | 
					
						
							|  |  |  | 	GROUP_TYPE_EXTENSION, | 
					
						
							|  |  |  | 	GROUP_TYPE_TILT, | 
					
						
							|  |  |  | 	GROUP_TYPE_CURSOR, | 
					
						
							|  |  |  | 	GROUP_TYPE_TRIGGERS, | 
					
						
							| 
									
										
										
										
											2010-10-05 21:43:51 +00:00
										 |  |  | 	GROUP_TYPE_UDPWII, | 
					
						
							|  |  |  | 	GROUP_TYPE_SLIDER, | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const char * const named_directions[] =  | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	"Up", | 
					
						
							|  |  |  | 	"Down", | 
					
						
							|  |  |  | 	"Left", | 
					
						
							|  |  |  | 	"Right" | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ControllerEmu | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		class Control | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		protected: | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			Control(ControllerInterface::ControlReference* const _ref, const char * const _name) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				: control_ref(_ref), name(_name){} | 
					
						
							|  |  |  | 		public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			virtual ~Control(); | 
					
						
							|  |  |  | 			ControllerInterface::ControlReference*		const control_ref; | 
					
						
							|  |  |  | 			const char * const		name; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		class Input : public Control | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		public: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			Input(const char * const _name) | 
					
						
							|  |  |  | 				: Control(new ControllerInterface::InputReference, _name) {} | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		class Output : public Control | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		public: | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			Output(const char * const _name) | 
					
						
							|  |  |  | 				: Control(new ControllerInterface::OutputReference, _name) {} | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		class Setting | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 		public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			Setting(const char* const _name, const ControlState def_value | 
					
						
							| 
									
										
										
										
											2010-06-05 05:30:23 +00:00
										 |  |  | 				, const unsigned int _low = 0, const unsigned int _high = 100 ) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				: name(_name) | 
					
						
							|  |  |  | 				, value(def_value) | 
					
						
							|  |  |  | 				, default_value(def_value) | 
					
						
							|  |  |  | 				, low(_low) | 
					
						
							|  |  |  | 				, high(_high){} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			const char* const	name; | 
					
						
							|  |  |  | 			ControlState		value; | 
					
						
							|  |  |  | 			const ControlState	default_value; | 
					
						
							|  |  |  | 			const unsigned int	low, high; | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		ControlGroup(const char* const _name, const unsigned int _type = GROUP_TYPE_OTHER) : name(_name), type(_type) {} | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		virtual ~ControlGroup(); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2010-07-05 10:46:32 +00:00
										 |  |  | 		virtual void LoadConfig(IniFile::Section *sec, const std::string& defdev = "", const std::string& base = "" ); | 
					
						
							|  |  |  | 		virtual void SaveConfig(IniFile::Section *sec, const std::string& defdev = "", const std::string& base = "" ); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		const char* const			name; | 
					
						
							|  |  |  | 		const unsigned int			type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		std::vector< Control* >		controls; | 
					
						
							|  |  |  | 		std::vector< Setting* >		settings; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class AnalogStick : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		template <typename C> | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		void GetState(C* const x, C* const y, const unsigned int base, const unsigned int range) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			// 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 = settings[0]->value; | 
					
						
							|  |  |  | 			ControlState square = settings[1]->value; | 
					
						
							|  |  |  | 			ControlState m = controls[4]->control_ref->State(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// modifier code
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			if (m) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2010-07-23 23:48:04 +00:00
										 |  |  | 				yy = (fabsf(yy)>deadzone) * sign(yy) * (m + deadzone/2); | 
					
						
							|  |  |  | 				xx = (fabsf(xx)>deadzone) * sign(xx) * (m + deadzone/2); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// deadzone / square stick code
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			if (deadzone || square) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				// this section might be all wrong, but its working good enough, i think
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				ControlState ang = atan2(yy, xx);  | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				ControlState ang_sin = sin(ang); | 
					
						
							|  |  |  | 				ControlState ang_cos = cos(ang); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// the amt a full square stick would have at current angle
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				ControlState square_full = std::min(ang_sin ? 1/fabsf(ang_sin) : 2, ang_cos ? 1/fabsf(ang_cos) : 2); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// the amt a full stick would have that was ( user setting squareness) at current angle
 | 
					
						
							|  |  |  | 				// i think this is more like a pointed circle rather than a rounded square like it should be
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				ControlState stick_full = (1 + (square_full - 1) * square); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				ControlState dist = sqrt(xx*xx + yy*yy); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// dead zone code
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				dist = std::max(0.0f, dist - deadzone * stick_full); | 
					
						
							|  |  |  | 				dist /= (1 - deadzone); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// square stick code
 | 
					
						
							|  |  |  | 				ControlState amt = dist / stick_full; | 
					
						
							|  |  |  | 				dist -= ((square_full - 1) * amt * square); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				yy = std::max(-1.0f, std::min(1.0f, ang_sin * dist)); | 
					
						
							|  |  |  | 				xx = std::max(-1.0f, std::min(1.0f, ang_cos * dist)); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			*y = C(yy * range + base); | 
					
						
							|  |  |  | 			*x = C(xx * range + base); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		AnalogStick(const char* const _name); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class Buttons : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		Buttons(const char* const _name); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		template <typename C> | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		void GetState(C* const buttons, const C* bitmasks) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			std::vector<Control*>::iterator i = controls.begin(), | 
					
						
							|  |  |  | 				e = controls.end(); | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			for (; i!=e; ++i, ++bitmasks) | 
					
						
							|  |  |  | 				if ((*i)->control_ref->State() > settings[0]->value) // threshold
 | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 					*buttons |= *bitmasks; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class MixedTriggers : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		template <typename C, typename S> | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		void GetState(C* const digital, const C* bitmasks, S* analog, const unsigned int range) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			const unsigned int trig_count = ((unsigned int) (controls.size() / 2)); | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			for (unsigned int i=0; i<trig_count; ++i,++bitmasks,++analog) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				if (controls[i]->control_ref->State() > settings[0]->value) //threshold
 | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				{ | 
					
						
							|  |  |  | 					*analog = range; | 
					
						
							|  |  |  | 					*digital |= *bitmasks; | 
					
						
							|  |  |  | 				} | 
					
						
							|  |  |  | 				else | 
					
						
							|  |  |  | 					*analog = S(controls[i+trig_count]->control_ref->State() * range); | 
					
						
							|  |  |  | 					 | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		MixedTriggers(const char* const _name); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class Triggers : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		template <typename S> | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		void GetState(S* analog, const unsigned int range) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			const unsigned int trig_count = ((unsigned int) (controls.size())); | 
					
						
							|  |  |  | 			const ControlState deadzone = settings[0]->value; | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			for (unsigned int i=0; i<trig_count; ++i,++analog) | 
					
						
							|  |  |  | 				*analog = S(std::max(controls[i]->control_ref->State() - deadzone, 0.0f) / (1 - deadzone) * range); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		Triggers(const char* const _name); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-05 21:43:51 +00:00
										 |  |  | 	class Slider : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		template <typename S> | 
					
						
							|  |  |  | 		void GetState(S* const slider, const unsigned int range, const unsigned int base = 0) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			const float deadzone = settings[0]->value; | 
					
						
							|  |  |  | 			const float state = controls[1]->control_ref->State() - controls[0]->control_ref->State(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (fabsf(state) > deadzone) | 
					
						
							|  |  |  | 				*slider = (S)((state - (deadzone * sign(state))) / (1 - deadzone) * range + base); | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 				*slider = 0; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Slider(const char* const _name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 	class Force : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		Force(const char* const _name); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		template <typename C, typename R> | 
					
						
							| 
									
										
										
										
											2010-07-26 05:30:50 +00:00
										 |  |  | 		void GetState(C* axis, const u8 base, const R range) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			const float deadzone = settings[0]->value; | 
					
						
							| 
									
										
										
										
											2010-07-26 05:30:50 +00:00
										 |  |  | 			for (unsigned int i=0; i<6; i+=2) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2010-07-26 05:30:50 +00:00
										 |  |  | 				float tmpf = 0; | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				const float state = controls[i+1]->control_ref->State() - controls[i]->control_ref->State(); | 
					
						
							| 
									
										
										
										
											2010-07-23 23:48:04 +00:00
										 |  |  | 				if (fabsf(state) > deadzone) | 
					
						
							| 
									
										
										
										
											2010-07-26 05:30:50 +00:00
										 |  |  | 					tmpf = ((state - (deadzone * sign(state))) / (1 - deadzone)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				float &ax = m_swing[i >> 1]; | 
					
						
							| 
									
										
										
										
											2010-10-03 04:29:34 +00:00
										 |  |  | 				*axis++	= (C)((tmpf - ax) * range + base); | 
					
						
							|  |  |  | 				ax = tmpf; | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-07-26 05:30:50 +00:00
										 |  |  | 	private: | 
					
						
							|  |  |  | 		float	m_swing[3]; | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class Tilt : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		Tilt(const char* const _name); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		template <typename C, typename R> | 
					
						
							| 
									
										
										
										
											2010-07-10 06:48:24 +00:00
										 |  |  | 		void GetState(C* const x, C* const y, const unsigned int base, const R range, const bool step = true) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		{ | 
					
						
							|  |  |  | 			// 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 = settings[0]->value; | 
					
						
							|  |  |  | 			ControlState circle = settings[1]->value; | 
					
						
							|  |  |  | 			ControlState m = controls[4]->control_ref->State(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// modifier code
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			if (m) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2010-07-23 23:48:04 +00:00
										 |  |  | 				yy = (fabsf(yy)>deadzone) * sign(yy) * (m + deadzone/2); | 
					
						
							|  |  |  | 				xx = (fabsf(xx)>deadzone) * sign(xx) * (m + deadzone/2); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// deadzone / circle stick code
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			if (deadzone || circle) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			{ | 
					
						
							|  |  |  | 				// this section might be all wrong, but its working good enough, i think
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				ControlState ang = atan2(yy, xx);  | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				ControlState ang_sin = sin(ang); | 
					
						
							|  |  |  | 				ControlState ang_cos = cos(ang); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// the amt a full square stick would have at current angle
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				ControlState square_full = std::min(ang_sin ? 1/fabsf(ang_sin) : 2, ang_cos ? 1/fabsf(ang_cos) : 2); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				// the amt a full stick would have that was (user setting circular) at current angle
 | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				// 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
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				dist = std::max(0.0f, dist - deadzone * stick_full); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				dist /= (1 - deadzone); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				// circle stick code
 | 
					
						
							|  |  |  | 				ControlState amt = dist / stick_full; | 
					
						
							|  |  |  | 				dist += (square_full - 1) * amt * circle; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 				yy = std::max(-1.0f, std::min(1.0f, ang_sin * dist)); | 
					
						
							|  |  |  | 				xx = std::max(-1.0f, std::min(1.0f, ang_cos * dist)); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-12 02:08:01 +00:00
										 |  |  | 			// this is kinda silly here
 | 
					
						
							|  |  |  | 			// gui being open will make this happen 2x as fast, o well
 | 
					
						
							| 
									
										
										
										
											2010-07-10 06:48:24 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			// silly
 | 
					
						
							|  |  |  | 			if (step) | 
					
						
							|  |  |  | 			{ | 
					
						
							|  |  |  | 				if (xx > m_tilt[0]) | 
					
						
							|  |  |  | 					m_tilt[0] = std::min(m_tilt[0] + 0.1f, xx); | 
					
						
							|  |  |  | 				else if (xx < m_tilt[0]) | 
					
						
							|  |  |  | 					m_tilt[0] = std::max(m_tilt[0] - 0.1f, xx); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				if (yy > m_tilt[1]) | 
					
						
							|  |  |  | 					m_tilt[1] = std::min(m_tilt[1] + 0.1f, yy); | 
					
						
							|  |  |  | 				else if (yy < m_tilt[1]) | 
					
						
							|  |  |  | 					m_tilt[1] = std::max(m_tilt[1] - 0.1f, yy); | 
					
						
							|  |  |  | 			} | 
					
						
							| 
									
										
										
										
											2010-06-12 02:08:01 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 			*y = C(m_tilt[1] * range + base); | 
					
						
							|  |  |  | 			*x = C(m_tilt[0] * range + base); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-06-12 02:08:01 +00:00
										 |  |  | 	private: | 
					
						
							|  |  |  | 		float	m_tilt[2]; | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class Cursor : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							| 
									
										
										
										
											2010-10-12 19:42:29 +00:00
										 |  |  | 		Cursor(const char* const _name); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		template <typename C> | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		void GetState(C* const x, C* const y, C* const z, const bool adjusted = false) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2010-06-12 02:08:01 +00:00
										 |  |  | 			const float zz = controls[4]->control_ref->State() - controls[5]->control_ref->State(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// silly being here
 | 
					
						
							|  |  |  | 			if (zz > m_z) | 
					
						
							|  |  |  | 				m_z = std::min(m_z + 0.1f, zz); | 
					
						
							|  |  |  | 			else if (zz < m_z) | 
					
						
							|  |  |  | 				m_z = std::max(m_z - 0.1f, zz); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			*z = m_z; | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			 | 
					
						
							|  |  |  | 			// hide
 | 
					
						
							| 
									
										
										
										
											2010-06-12 02:08:01 +00:00
										 |  |  | 			if (controls[6]->control_ref->State() > 0.5f) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2010-06-12 02:08:01 +00:00
										 |  |  | 				*x = 10000; *y = 0; | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			else | 
					
						
							|  |  |  | 			{ | 
					
						
							| 
									
										
										
										
											2010-07-16 03:43:11 +00:00
										 |  |  | 				float yy = controls[0]->control_ref->State() - controls[1]->control_ref->State(); | 
					
						
							|  |  |  | 				float xx = controls[3]->control_ref->State() - controls[2]->control_ref->State(); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 				// adjust cursor according to settings
 | 
					
						
							|  |  |  | 				if (adjusted) | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 					xx *= (settings[1]->value * 2); | 
					
						
							|  |  |  | 					yy *= (settings[2]->value * 2); | 
					
						
							|  |  |  | 					yy += (settings[0]->value - 0.5f); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 				} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				*x = xx; | 
					
						
							|  |  |  | 				*y = yy; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-12 02:08:01 +00:00
										 |  |  | 		float	m_z; | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	class Extension : public ControlGroup | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 	public: | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		Extension(const char* const _name) | 
					
						
							|  |  |  | 			: ControlGroup(_name, GROUP_TYPE_EXTENSION) | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 			, switch_extension(0) | 
					
						
							|  |  |  | 			, active_extension(0) {} | 
					
						
							|  |  |  | 		~Extension(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 		void GetState(u8* const data, const bool focus = true); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		std::vector<ControllerEmu*>		attachments; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int	switch_extension; | 
					
						
							|  |  |  | 		int	active_extension; | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	virtual ~ControllerEmu(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	virtual std::string GetName() const = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-10 06:48:24 +00:00
										 |  |  | 	virtual void LoadDefaults(const ControllerInterface& ciface); | 
					
						
							| 
									
										
										
										
											2010-06-12 12:57:28 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-05 10:46:32 +00:00
										 |  |  | 	virtual void LoadConfig(IniFile::Section *sec, const std::string& base = ""); | 
					
						
							|  |  |  | 	virtual void SaveConfig(IniFile::Section *sec, const std::string& base = ""); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 	void UpdateDefaultDevice(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-01-14 03:05:02 +00:00
										 |  |  | 	void UpdateReferences(ControllerInterface& devi); | 
					
						
							| 
									
										
										
										
											2010-06-03 18:05:08 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	std::vector< ControlGroup* >		groups; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ControllerInterface::DeviceQualifier	default_device; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #endif
 |