private static bool GetInputDigital (InputAction action, ButtonState buttonState,IDevice device)
				{

						return GetInputDigital (action.getCode(device), buttonState,device);

				}
				/// <summary>
				/// Check if InputActin happened( SINGLE,DOUBLE,LONG)
				/// </summary>
				/// <returns>true/false</returns>
				/// <param name="action">InputAction to be compared with input</param>
				internal static bool GetAction (InputAction action,IDevice device)
				{

						if (action.type == InputActionType.SINGLE) {
								if (InputEx.GetInputDigital (action, ButtonState.Down,device)) {
										Debug.Log ("Single <" + InputActionType.SINGLE);
										//action.startTime = Time.time;
										_lastCode = action.getCode(device);
										return true;
								}

								return false;
						}


						if (action.type == InputActionType.DOUBLE) {
								if (InputEx.GetInputDigital (action, ButtonState.Down,device)) {
										if (_lastCode != action.getCode(device)) {//first click

												_lastCode = action.getCode(device);
												action.startTime = Time.time;
												Debug.Log ("First Click" + Time.time + ":" + action.startTime + " going for " + InputActionType.DOUBLE);
												return false;
										} else {//InputEx.LastCode==_pointer.Current.code //second click
												//check time diffrence if less then
												if (Time.time - action.startTime < InputAction.DOUBLE_CLICK_SENSITIVITY) {

														_lastCode = 0;//???
														action.startTime = 0;
														Debug.Log ("Double " + Time.time + ":" + action.startTime + "<" + InputActionType.DOUBLE);

														return true;
												}

												// Debug.Log("Lost Double " + Time.time + ":" + action.startTime + "<" + InputActionType.DOUBLE);
										}
								}

								return false;
						}


						if (action.type == InputActionType.LONG) {
								if (InputEx.GetInputDigital (action, ButtonState.Hold,device)) {//if hold
										if (_lastCode != action.getCode(device)) {

												_lastCode = action.getCode(device);

												action.startTime = Time.time;

												return false;
										} else {//InputEx.LastCode==_pointer.Current.getCode(device) //hold
												//check time diffrence if less then
												if (Time.time - action.startTime >= InputAction.LONG_CLICK_SENSITIVITY) {

														_lastCode = 0;//KeyCode.None;
														action.startTime = 0;
														Debug.Log ("Long " + (Time.time - action.startTime) + " " + InputActionType.LONG);

														return true;
												}
										}
								}

								return false;

						}


						return false;


				}
				/// <summary>
				/// Gets the key up.
				/// </summary>
				/// <returns><c>true</c>, if key up was gotten, <c>false</c> otherwise.</returns>
				/// <param name="action">Action.</param>
				internal static bool GetInputUp (InputAction action,IDevice Device)
				{
					return GetInputDigital (action, ButtonState.Up,Device);
				}
				/// <summary>
				/// Gets the input down.
				/// </summary>
				/// <returns><c>true</c>, if input down was gotten, <c>false</c> otherwise.</returns>
				/// <param name="action">Action.</param>
				public static bool GetInputDown (InputAction action,IDevice Device)
				{
					return GetInputDigital ( action, ButtonState.Down,Device);
				}
				public InputExArgs (InputAction action)
				{

						this.action = action;

				}
				//!!! IMPORTANT: Input happen every frame. If there is no refresh from the hardware device 
				// Input give same values just states are refreshed from DOWN->HOLD (value=1 stay) and UP->NONE (value=0 stay)

				/// <summary>
				/// Gets the axis.
				/// </summary>
				/// <returns>The axis.</returns>
				/// <param name="action">Action.</param>
				public static float GetInputAnalog (InputAction action,IDevice device)
				{
						int code = action.getCode(device);
                       // action.getCode(_currentPlayer._Device.profile);


					
						
						lock (syncRoot) {
							
							
							if (device!=null) {
								
								
								return device.GetInputAnalog (code);
								
								
								
							} else {
								float axisValue=0f;

									foreach (IDevice dev in Devices)
										if((axisValue=dev.GetInputAnalog (code))!=0f)
										return axisValue;
										
								
									return 0f;		
					
							}
							
						}



		}
				public void Add (InputAction action)
				{
						_actionsList.Add (action);
						_combinationString = ToString (_actionsList);
						_actions = _actionsList.ToArray ();

					
				}
				/// <summary>
				/// Processes the input code into InputAction
				/// </summary>
				/// <returns>InputAction (single,double,long) or null.</returns>
				/// <param name="code">Code.</param>
				/// <param name="time">Time.</param>
				internal static InputAction processInputCode (int code, float time,IDevice device)
				{


						InputAction action = null;

						// Debug.Log ("process "+code);

						if (code != 0) {//=KeyCode.None 


								if (_lastCode == 0) {//=KeyCode.None
										//save key event and time needed for double check
										_lastCode = code;
										_lastCodeTime = time;

										Debug.Log ("Last code " + InputCode.toEnumString (_lastCode) + " at time:" + _lastCodeTime);
										//	Debug.Log("Take time "+_lastCodeTime);
								} else {
										//if new pressed key is different then the last
										if (_lastCode != code) {
												//consturct string from lastCode
												action = new InputAction (_lastCode, InputActionType.SINGLE,device);

												//take new pressed code as lastCode
												_lastCode = code;

												Debug.Log ("Single " + time + ":" + _lastCodeTime + " " + InputActionType.SINGLE);



										} else {


												if (time - _lastCodeTime < InputAction.DOUBLE_CLICK_SENSITIVITY) {
														action = new InputAction (_lastCode, InputActionType.DOUBLE,device);
														_lastCode = 0;//KeyCode.None;
														Debug.Log ("Double " + time + ":" + _lastCodeTime + "<" + InputActionType.DOUBLE);
												}


										}

								}

						} else {



								if (_lastCode != 0) {//=KeyCode.None
										//if key is still down and time longer then default long time click => display long click
										if (InputEx.GetInputHold (_lastCode,device) || (!Application.isPlaying && InputEx.GetKeyDown (_lastCode))) {
												if (time - _lastCodeTime >= InputAction.LONG_CLICK_SENSITIVITY) {
														action = new InputAction (_lastCode, InputActionType.LONG,device);
														_lastCode = 0;//KeyCode.None;
														Debug.Log ("Long " + (time - _lastCodeTime) + " <" + InputActionType.LONG);
												}
										} else {//time wating for double click activity passed => display last code
												if (time - _lastCodeTime >= InputAction.DOUBLE_CLICK_SENSITIVITY) {
														action = new InputAction (_lastCode, InputActionType.SINGLE,device);
														_lastCode = 0;//KeyCode.None;

														Debug.Log ("Single after wating Double time pass " + (time - _lastCodeTime) + " " + InputActionType.SINGLE);
												}

										}



								}

						}
						return action;
				}
 public void Add(InputAction action)
 {
     _actionsList.Add(action);
     _combinationString = ToString(_actionsList);
     _actions           = _actionsList.ToArray();
 }
				/// <summary>
				/// Update this instance.
				/// </summary>
				void Update ()
				{



						if (!Application.isPlaying && _profiles != null && !__wereDevicesEnumerated) {
								InputManager.hidInterface.SetProfiles (_profiles);
								InputManager.hidInterface.Enumerate ();
								__wereDevicesEnumerated = true;
							
						}

						InputAction actionCurrent;

						actionCurrent = InputManager.GetAction (_deviceSelected);
							
							
						if (actionCurrent != null && (actionCurrent.getCode (_deviceSelected) ^ (int)KeyCode.Escape) != 0 && (actionCurrent.getCode (_deviceSelected) ^ (int)KeyCode.Return) != 0) {
								
								
								
								if ((actionCurrent.getCode (_deviceSelected) ^ (int)KeyCode.Backspace) == 0) {
										_nameGiven = String.Empty;
									
								} else {
									
							
									
										actionCurrent.type = InputActionType.SINGLE;
									
										actionCurrent.setCode (InputCode.toCodeAnyDevice (actionCurrent.getCode (_deviceSelected)), null);
									
									
								
										actionCurrent.setCode (InputCode.toCodeAxisFull (actionCurrent.getCode (_deviceSelected)), null);
										
									
									
										_actionSelected = actionCurrent.Clone ();

										//Debug.Log ("Action:" + _actionSelected + " " + _actionSelected.getCode (_deviceSelected) + " type:" + _actionSelected.type);
										this.Repaint ();
										
								}
								
								
								
								//Debug.Log ("Action:" + _action + " " + _action.getCode(_deviceByProfile)+" type:"+_action.type);
						}


				}
				/// <summary>
				/// onGUI
				/// </summary>
				/////////////////    onGUI   ////////////
				void OnGUI ()
				{



						///////////////      DEVICES      ///////////////
						if (_profiles != null) {
								List<IDevice> devicesList = InputManager.GetDevices<IDevice> ();

                               

								if (devicesList.Count > 0) {
										_displayOptions = devicesList.Select (item => item.Name).ToArray ();

										_deviceDisplayIndex = EditorGUILayout.Popup ("Devices:", _deviceDisplayIndex, _displayOptions);

										_deviceSelected = devicesList [_deviceDisplayIndex];


                                        if (!String.IsNullOrEmpty(_profileNameSelected))
                                        {

                                            EditorGUILayout.BeginHorizontal();
                                            if (GUILayout.Button("Assign Profile"))
                                            {

                                                string pidVidKey = _deviceSelected.VID.ToString("X4") + "#" + _deviceSelected.PID.ToString("X4");
                                                _profiles.vidpidProfileNameDict[pidVidKey] = _profileNameSelected;

                                                EditorUtility.SetDirty(_profiles);
                                                AssetDatabase.SaveAssets();
                                            }

                                            if (GUILayout.Button("Remove From Profile"))
                                            {

                                                string pidVidKey = _deviceSelected.VID.ToString("X4") + "#" + _deviceSelected.PID.ToString("X4");

                                                _profiles.vidpidProfileNameDict.Remove(pidVidKey);

                                                EditorUtility.SetDirty(_profiles);
                                                AssetDatabase.SaveAssets();

                                            }

                                            EditorGUILayout.EndHorizontal();

                                        }

                                      
								} else {

										EditorGUILayout.LabelField ("Devices: No attached devices");
								}



                                if (_deviceCount != devicesList.Count)
                                    this.Repaint();

                                _deviceCount = devicesList.Count;
						}



                     


//				if(GUILayout.Button("Proifle2DeviceProfile")){
//						char splitChar = '|';
//
//						string fileBase;
//
//						foreach(var kvp in _profiles.runtimePlatformDeviceProfileDict){
//
//						fileBase=kvp.Key;
//
//						DeviceProfile profile;
//
//						profile=kvp.Value[RuntimePlatform.WindowsPlayer]=new DeviceProfile();
//						profile.Name=kvp.Key;
//						
//						using (StreamReader reader = new StreamReader(Path.Combine(Application.streamingAssetsPath, fileBase + "_win.txt")))
//						{
//							
//							if (!reader.EndOfStream)
//								profile.buttonNaming = reader.ReadLine().Split(splitChar);
//							
//							if (!reader.EndOfStream)
//								profile.axisNaming = reader.ReadLine().Split(splitChar);
//							
//							//rest in future
//							
//							
//							
//						}
//
//						profile=kvp.Value[RuntimePlatform.OSXPlayer]=new DeviceProfile();
//						profile.Name=kvp.Key;
//
//						using (StreamReader reader = new StreamReader(Path.Combine(Application.streamingAssetsPath, fileBase + "_osx.txt")))
//						{
//							
//							if (!reader.EndOfStream)
//								profile.buttonNaming = reader.ReadLine().Split(splitChar);
//							
//							if (!reader.EndOfStream)
//								profile.axisNaming = reader.ReadLine().Split(splitChar);
//							
//							//rest in future
//							
//							
//							
//						}
//
//
//					}
//
//					EditorUtility.SetDirty (_profiles);
//					AssetDatabase.SaveAssets ();
//
//				}


//								if (GUILayout.Button ("Profiles.txt2DeviceProfiles.asset")) {
//										string[] deviceNameProfilePair;
//										char splitChar = '|';
//
//										using (StreamReader reader = new StreamReader(Path.Combine(Application.streamingAssetsPath, "profiles.txt"))) {
//					
//					
//												while (!reader.EndOfStream) {
//						
//														deviceNameProfilePair = reader.ReadLine ().Split (splitChar);
//														if (!_profiles.vidpidProfileNameDict.ContainsKey (deviceNameProfilePair [0]))
//																_profiles.vidpidProfileNameDict [deviceNameProfilePair [0]] = deviceNameProfilePair [1];
//
//														if (!_profiles.runtimePlatformDeviceProfileDict.ContainsKey (deviceNameProfilePair [1])) {
//
//																_profiles.runtimePlatformDeviceProfileDict [deviceNameProfilePair [1]] = new Dictionary<RuntimePlatform, DeviceProfile> ();
//														}
//												}
//
//												EditorUtility.SetDirty (_profiles);
//												AssetDatabase.SaveAssets ();
//					
//										}
//								}

							
						
						

						EditorGUILayout.Separator ();



						///////////////  PROFILES /////////////

						_profiles = EditorGUILayout.ObjectField (_profiles, typeof(DeviceProfiles), false) as DeviceProfiles;

						if (_deviceSelected != null && _profiles != null) {
								

								_displayOptions = _profiles.runtimePlatformDeviceProfileDict.Keys.ToArray ();

								if (_displayOptions.Length > 0) {
										_profileIndexSelected = EditorGUILayout.Popup ("Profiles:", _profileIndexSelected, _displayOptions);
										_profileNameSelected = _displayOptions [_profileIndexSelected];
								}

								EditorGUILayout.BeginHorizontal ();

								_profileName = EditorGUILayout.TextField ("Name", _profileName);

								if (GUILayout.Button ("Add profile") && !String.IsNullOrEmpty (_profileName)) {
										

										if (!_profiles.runtimePlatformDeviceProfileDict.ContainsKey (_profileName)) {

											
												_profiles.runtimePlatformDeviceProfileDict [_profileName] = new Dictionary<RuntimePlatform, DeviceProfile> ();
										} else {

												Debug.LogWarning ("Already contain such profile");
										}

										_profileName = String.Empty;

										EditorUtility.SetDirty (_profiles);
										AssetDatabase.SaveAssets ();

								}


								


								EditorGUILayout.EndHorizontal ();

								EditorGUILayout.Separator ();
				

								///////////////// NAMING(buttons,axis..) //////////////
								string actionCodeString = "Click button or Move stick";
								DeviceProfile profile = null;
								JoystickAxis axis = JoystickAxis.None;
								string nameGivenCurrent = "No Name";
			
								if (!String.IsNullOrEmpty (_profileNameSelected)) {
										///// CURRENT ACTION /////
										/// 
										/// 
										EditorGUILayout.BeginHorizontal ();
										EditorGUILayout.LabelField ("GENERIC NAME:");

										

										if (_actionSelected != null) {


												actionCodeString = _actionSelected.codeString;
												//find axis button number
												axis = InputCode.toAxis (_actionSelected.getCode (_deviceSelected));

												_platform = Application.platform == RuntimePlatform.OSXEditor ? RuntimePlatform.OSXPlayer : RuntimePlatform.WindowsPlayer;
											
											
											
											
												if (_profiles.runtimePlatformDeviceProfileDict [_profileNameSelected].ContainsKey (_platform)) {
														profile = _profiles.runtimePlatformDeviceProfileDict [_profileNameSelected] [_platform];
												
												
												
												
														if (axis == JoystickAxis.None) {
																nameGivenCurrent = profile.buttonNaming [InputCode.toData (_actionSelected.getCode (_deviceSelected))];
														} else {
																nameGivenCurrent = profile.axisNaming [(int)axis];
														}
												}
										}

										EditorGUILayout.LabelField (actionCodeString);

										EditorGUILayout.EndHorizontal ();

										EditorGUILayout.Separator ();

										///// GIVE NAME ////			
										EditorGUILayout.BeginHorizontal ();



                                        if (String.IsNullOrEmpty(nameGivenCurrent))
                                        {
                                            nameGivenCurrent = "No Name [Click to Edit]";
                                            _nameGiven = String.Empty;
                                        }
                                        else
                                            _nameGiven = nameGivenCurrent;

										if (_actionSelected != null)
										if (!_nameGiveEdit
												&& GUILayout.Button (nameGivenCurrent))
												_nameGiveEdit = true;


										if (_nameGiveEdit) {
												_nameGiven = EditorGUILayout.TextField ("Name", _nameGiven);
				

									

												if (GUILayout.Button ("Give") || (Event.current.isKey && Event.current.keyCode == KeyCode.Return))
												if (!String.IsNullOrEmpty (_profileNameSelected) && !String.IsNullOrEmpty (_nameGiven)) {


									
							
									
														if (profile == null) {
																profile = new DeviceProfile ();
																profile.Name = _profileNameSelected;
																_profiles.runtimePlatformDeviceProfileDict [_profileNameSelected] [_platform] = profile;
										
														}

														if (axis == JoystickAxis.None) {
																profile.buttonNaming [InputCode.toData (_actionSelected.getCode (_deviceSelected))] = _nameGiven;
														} else {
																profile.axisNaming [(int)axis] = _nameGiven;
														}
											
									
														_actionSelected = null;
														_nameGiven = String.Empty;

														EditorUtility.SetDirty (_profiles);

														AssetDatabase.SaveAssets ();


														_nameGiveEdit = false;

														this.Repaint ();
										
												}



										}


										EditorGUILayout	.EndHorizontal ();
								}
						}
						

						///////////////         CREATE ASSET       ////////////////
						if (GUILayout.Button ("Create Assets/Resources/DeviceProfiles.asset")) {

								if (!Directory.Exists (Path.Combine (Application.dataPath, "Resources")))
										AssetDatabase.CreateFolder ("Assets", "Resources");
								
								if (File.Exists (Path.Combine (Path.Combine (Application.dataPath, "Resources"), "DeviceProfiles.asset"))) {
					
										if (EditorUtility.DisplayDialog ("DeviceProfiles Asset Exists!",
					                            "Are you sure you overwrite?", "Yes", "Cancel")) {
												AssetDatabase.CreateAsset (ScriptableObject.CreateInstance<DeviceProfiles> (), "Assets/Resources/DeviceProfiles.asset");
										}
								} else {
										AssetDatabase.CreateAsset (ScriptableObject.CreateInstance<DeviceProfiles> (), "Assets/Resources/DeviceProfiles.asset");
								}
				
				
						}






						//if event is of key or mouse
						if (Event.current.isKey) {
									
								if (Event.current.keyCode == KeyCode.Escape) {
										_nameGiveEdit = false;
										_instance.Repaint ();
								}		
						}
			
			
				}
				/////////////////////////                  UPDATE              /////////////////////////
				/// <summary>
				/// Update this instance.
				/// </summary>
				void Update ()
				{
						InputState state;


						if (!Application.isPlaying && !__wereDevicesEnumerated) {
								__wereDevicesEnumerated = true;
								InputManager.hidInterface.SetProfiles (AssetDatabase.LoadAssetAtPath ("Assets/Resources/DeviceProfiles.asset", typeof(DeviceProfiles)) as DeviceProfiles);

								InputManager.hidInterface.Enumerate ();

						}

						if (!Application.isPlaying && _selectedStateHash != 0) {

							

									
								_action = InputManager.GetAction (_deviceByProfile);
				

								if (_action != null && (_action.getCode (_deviceByProfile) ^ (int)KeyCode.Escape) != 0 && (_action.getCode (_deviceByProfile) ^ (int)KeyCode.Return) != 0) {



										if ((_action.getCode (_deviceByProfile) ^ (int)KeyCode.Backspace) == 0) {
												state = _stateInputCombinations [_selectedStateHash];
												state.combinations [_isPrimary].Clear ();
												state.combinations [_isPrimary].Add (new InputAction (KeyCode.None));

										} else {

												
						                        


												if (!_isComplexActionTypesAllowed)
														_action.type = InputActionType.SINGLE;

												_action.setCode (InputCode.toCodeAnyDevice (_action.getCode (_deviceByProfile)), _deviceByProfile);
					

												if (_isDeviceAxisPositionFull) {
														_action.setCode (InputCode.toCodeAxisFull (_action.getCode (_deviceByProfile)), _deviceByProfile);
                                                       
												}

												toInputCombination (_stateInputCombinations [_selectedStateHash].combinations [_isPrimary], _action);
										}



										//Debug.Log ("Action:" + _action + " " + _action.getCode(_deviceByProfile)+" type:"+_action.type);
								}


								//Debug.Log ("Action:"+action);
						}
               

				

				}
				/// <summary>
				/// Resolves empty or None input or restricts input to max num of combinaition(maxCombosNum)
				/// </summary>
				/// <param name="combos">Combos. ex. w+Mouse1(x2)+Joystick1Button3(-)</param>
				/// <param name="input">Input.</param>
				void toInputCombination (InputCombination combos, InputAction input)
				{
				
						if (combos.numActions + 1 > maxCombosNum || (combos.numActions == 1 && combos.GetActionAt (0).getCode (_deviceByProfile) == 0))
								combos.Clear ();
				
						combos.Add (input);

						//Debug.Log(input);

				}