Пример #1
0
	public void Start ()
    {
		// Try to find RUISTracker that uses Razer Hydra in some way
		RUISTracker[] trackers = Object.FindObjectsOfType(typeof(RUISTracker)) as RUISTracker[];
		for(int i = 0; i < trackers.Length; ++i)
		{
			// Below complicated clauses make sure that this is a properly configured Razer Hydra tracker
			if(		trackers[i].headPositionInput == RUISTracker.HeadPositionSource.RazerHydra
				||	(	trackers[i].headRotationInput == RUISTracker.HeadRotationSource.RazerHydra
					 &&	!trackers[i].useOculusRiftRotation)
				||	(	trackers[i].compass == RUISTracker.CompassSource.RazerHydra
					 && trackers[i].externalDriftCorrection
					 && (	trackers[i].useOculusRiftRotation 
						 || trackers[i].headRotationInput == RUISTracker.HeadRotationSource.InputTransform )))
				if(trackers[i].isRazerBaseMobile) // Found a Razer Hydra tracker that claims to have mobile base
					headTracker = trackers[i];
		}
	}
Пример #2
0
 public void Start()
 {
     // Try to find RUISTracker that uses Razer Hydra in some way
     RUISTracker[] trackers = Object.FindObjectsOfType(typeof(RUISTracker)) as RUISTracker[];
     for (int i = 0; i < trackers.Length; ++i)
     {
         // Below complicated clauses make sure that this is a properly configured Razer Hydra tracker
         if (trackers[i].headPositionInput == RUISTracker.HeadPositionSource.RazerHydra ||
             (trackers[i].headRotationInput == RUISTracker.HeadRotationSource.RazerHydra &&
              !trackers[i].useOculusRiftRotation) ||
             (trackers[i].compass == RUISTracker.CompassSource.RazerHydra &&
              trackers[i].externalDriftCorrection &&
              (trackers[i].useOculusRiftRotation ||
               trackers[i].headRotationInput == RUISTracker.HeadRotationSource.InputTransform)))
         {
             if (trackers[i].isRazerBaseMobile)                // Found a Razer Hydra tracker that claims to have mobile base
             {
                 headTracker = trackers[i];
             }
         }
     }
 }
Пример #3
0
    void Awake()
    {
        if (!scriptEnabled)
        {
            return;
        }

        inputManager = FindObjectOfType(typeof(RUISInputManager)) as RUISInputManager;

        bool kinect2   = false;
        bool kinect    = false;
        bool psmove    = false;
        bool razer     = false;
        bool oculusDK2 = false;

        bool isRiftConnected = false;

        //#if UNITY_EDITOR
        //if(UnityEditorInternal.InternalEditorUtility.HasPro())
        //#endif
        {
            try
            {
                // Find out if an Oculus HMD is connected
                if (OVRManager.display != null)
                {
                    isRiftConnected = OVRManager.display.isPresent;
                }

                // Find out the Oculus HMD version
                if (OVRManager.capiHmd != null)
                {
                    ovrHmdVersion = OVRManager.capiHmd.GetDesc().Type;
                }
            }
            catch (UnityException e)
            {
                Debug.LogError(e);
            }
        }

        if (inputManager)
        {
            if (isRiftConnected && (ovrHmdVersion == Ovr.HmdType.DK2 || ovrHmdVersion == Ovr.HmdType.Other))
            {
                oculusDK2 = true;
            }

            kinect2 = inputManager.enableKinect2;
            kinect  = inputManager.enableKinect;
            psmove  = inputManager.enablePSMove;
            razer   = inputManager.enableRazerHydra;

            int         trackerCount      = 0;
            RUISTracker closestMatch      = null;
            int         currentMatchScore = 0;

            RUISHeadTrackerAssigner[] assigners = FindObjectsOfType(typeof(RUISHeadTrackerAssigner)) as RUISHeadTrackerAssigner[];
            if (!allowMultipleAssigners && assigners.Length > 1)
            {
                Debug.LogError("Multiple active RUISHeadTrackerAssigner scripts found while 'Allow Multiple Assigners' is false: "
                               + "Disabling all headtrackers and their child objects that are listed in the RUISHeadTrackerAssigner "
                               + "component of '" + gameObject.name + "' object.");

                for (int i = 0; i < headTrackers.Capacity; ++i)
                {
                    if (headTrackers[i] && headTrackers[i].gameObject.activeInHierarchy)
                    {
                        headTrackers[i].gameObject.SetActive(false);
                    }
                }
                return;
            }

            foreach (RUISTracker trackerScript in headTrackers)
            {
                if (trackerScript && trackerScript.gameObject.activeInHierarchy)
                {
                    ++trackerCount;
                    int foundTrackerScore = 0;

                    // Give score to found head trackers
                    if (oculusDK2 && trackerScript.headPositionInput == RUISTracker.HeadPositionSource.OculusDK2)
                    {
                        foundTrackerScore = 7;
                        print(trackerScript);
                    }
                    else if (psmove && trackerScript.headPositionInput == RUISTracker.HeadPositionSource.PSMove)
                    {
                        foundTrackerScore = 6;
                    }
                    else if (razer && trackerScript.isRazerBaseMobile &&                         // Legacy: Mobile Hydra Base (custom tracker)
                             trackerScript.headPositionInput == RUISTracker.HeadPositionSource.RazerHydra &&
                             trackerScript.mobileRazerBase == RUISTracker.RazerHydraBase.InputTransform)
                    {
                        foundTrackerScore = 5;
                    }
                    else if (kinect2 && trackerScript.headPositionInput == RUISTracker.HeadPositionSource.Kinect2)
                    {
                        foundTrackerScore = 4;
                    }
                    else if (kinect && razer && trackerScript.isRazerBaseMobile &&                         // Legacy: Mobile Hydra Base (Kinect)
                             trackerScript.headPositionInput == RUISTracker.HeadPositionSource.RazerHydra &&
                             trackerScript.mobileRazerBase == RUISTracker.RazerHydraBase.Kinect1)
                    {
                        foundTrackerScore = 3;
                    }
                    else if (kinect && trackerScript.headPositionInput == RUISTracker.HeadPositionSource.Kinect1)
                    {
                        foundTrackerScore = 2;
                    }
                    else if (razer && trackerScript.headPositionInput == RUISTracker.HeadPositionSource.RazerHydra &&                         // Plain ol' Razer Hydra
                             !trackerScript.isRazerBaseMobile)
                    {
                        foundTrackerScore = 1;
                    }

                    // Assign new best head tracker candidate if it is better than the previously found
                    if (currentMatchScore < foundTrackerScore)
                    {
                        closestMatch      = trackerScript;
                        currentMatchScore = foundTrackerScore;
                    }
                }
            }

            if (trackerCount == 0 && Application.isEditor)
            {
                Debug.LogError("No active GameObjects with RUISTracker script found from headTrackers list!");
            }

            string     positionTracker = "<None>";
            string     logString       = "";
            string     names           = "";
            RUISCamera ruisCamera      = null;

            if (closestMatch == null)
            {
                // Disable all but the first active head tracker from the headTrackers list
                logString = "Could not find a suitable head tracker with regard to "
                            + "enabled devices in RUISInputManager!";

                bool disabling        = false;
                int  leftEnabledIndex = -1;
                for (int i = 0; i < headTrackers.Capacity; ++i)
                {
                    if (headTrackers[i] && headTrackers[i].gameObject.activeInHierarchy)
                    {
                        if (disabling)
                        {
                            if (names.Length > 0)
                            {
                                names = names + ", ";
                            }
                            names = names + headTrackers[i].gameObject.name;
                            headTrackers[i].gameObject.SetActive(false);
                        }
                        else
                        {
                            leftEnabledIndex = i;
                            closestMatch     = headTrackers[leftEnabledIndex];
                            positionTracker  = headTrackers[leftEnabledIndex].gameObject.name;
                            disabling        = true;
                        }
                    }
                }
                if (leftEnabledIndex >= 0)
                {
                    logString = logString + " Choosing the first head tracker in the list. Using "
                                + positionTracker + " for tracking head position";
                    if (names.Length > 0)
                    {
                        logString = logString + ", and disabling the following: " + names;
                    }
                    logString = logString + ". This choice was made using a pre-selected list of "
                                + "head trackers.";

                    ruisCamera = headTrackers[leftEnabledIndex].gameObject.GetComponentInChildren <RUISCamera>();
                }
                Debug.LogError(logString);
            }
            else
            {
                // Disable all but the closest match head tracker from the headTrackers list
                for (int i = 0; i < headTrackers.Capacity; ++i)
                {
                    if (headTrackers[i] && headTrackers[i].gameObject.activeInHierarchy)
                    {
                        if (headTrackers[i] != closestMatch)
                        {
                            if (names.Length > 0)
                            {
                                names = names + ", ";
                            }
                            names = names + headTrackers[i].gameObject.name;
                            headTrackers[i].gameObject.SetActive(false);
                        }
                        else
                        {
                            positionTracker = headTrackers[i].gameObject.name;
                        }
                    }
                }
                logString = "Found the best head tracker with regard to enabled devices in "
                            + "RUISInputManager! Using " + positionTracker + " for tracking head position";
                if (names.Length > 0)
                {
                    logString = logString + ", and disabling the following: " + names;
                }
                Debug.Log(logString + ". This choice was made using a pre-selected list of head trackers.");

                ruisCamera = closestMatch.gameObject.GetComponentInChildren <RUISCamera>();

                if (changePivotIfNoKinect && psmove && !kinect && !kinect2 &&
                    closestMatch.headPositionInput == RUISTracker.HeadPositionSource.PSMove)
                {
                    RUISCharacterController characterController = gameObject.GetComponentInChildren <RUISCharacterController>();
                    if (characterController != null &&
                        characterController.characterPivotType != RUISCharacterController.CharacterPivotType.MoveController)
                    {
                        characterController.characterPivotType = RUISCharacterController.CharacterPivotType.MoveController;
                        characterController.moveControllerId   = closestMatch.positionPSMoveID;
                        Debug.Log("PS Move enabled and Kinect disabled. Setting " + characterController.name
                                  + "'s CharacterCamera Pivot as PS Move controller #" + closestMatch.positionPSMoveID
                                  + ". PS Move position offset for this pivot is " + characterController.psmoveOffset);
                    }
                }
            }


            if (ruisCamera)
            {
                if (display == null)
                {
                    Debug.LogWarning("No RUISDisplay attached to the RUISHeadTrackerAssigner script!");
                    RUISDisplay[] displays = FindObjectsOfType(typeof(RUISDisplay)) as RUISDisplay[];
                    for (int i = 0; i < displays.Length; ++i)
                    {
                        if (displays[i].linkedCamera == null)
                        {
                            Debug.LogWarning("Assigned RUISCamera component from the child of " + positionTracker
                                             + " to render on " + displays[i].gameObject.name + " because that "
                                             + "RUISDisplay component's RUISCamera field was empty.");
                            displays[i].linkedCamera = ruisCamera;
                            break;
                        }
                    }
                }
                else
                {
                    if (display.linkedCamera == null)
                    {
                        Debug.Log("Assigned RUISCamera component from the child of " + positionTracker
                                  + " to render on " + display.gameObject.name);
                        display.linkedCamera = ruisCamera;
                    }
                    else
                    {
                        Debug.LogWarning("RUISDisplay " + display.gameObject.name + " is already connected with a "
                                         + "RUISCamera object! Leave the RUISCamera field empty in your RUISDisplay "
                                         + "component if you want RUISHeadTrackerAssigner script to automatically "
                                         + "assign a RUISCamera to your RUISDisplay.");
                    }
                }
            }
            else
            {
                if (closestMatch)
                {
                    Debug.LogError(positionTracker + " did not have a child with RUISCamera component, "
                                   + "and therefore it is not used to draw on any of the displays in "
                                   + "DisplayManager.");
                }
            }

            // If we are using Razer with a static base for head tracking, then apply onlyRazerOffset
            // on the parent objects of the Razer head tracker and the hand-held Razer
            if (closestMatch != null && razer &&
                closestMatch.headPositionInput == RUISTracker.HeadPositionSource.RazerHydra &&
                !closestMatch.isRazerBaseMobile)
            {
                // The parent object of the Razer head tracker must not have RUISCharacterConroller,
                // because that script will modify the object's position
                if (closestMatch.transform.parent != null &&
                    closestMatch.transform.parent.GetComponent <RUISCharacterController>() == null &&
                    (onlyRazerOffset.x != 0 || onlyRazerOffset.y != 0 || onlyRazerOffset.z != 0))
                {
                    string razerWandOffsetInfo = "";
                    closestMatch.transform.parent.localPosition += onlyRazerOffset;
                    if (razerWandParent != null)
                    {
                        razerWandParent.localPosition += onlyRazerOffset;
                        razerWandOffsetInfo            = " and " + razerWandParent.gameObject.name + " (parent of hand-held Razer "
                                                         + "Hydra)";
                    }
                    Debug.Log("Applying offset of " + onlyRazerOffset + " to "
                              + closestMatch.transform.parent.gameObject.name + " (parent of Razer Hydra head tracker)"
                              + razerWandOffsetInfo + ".");
                }
            }

            // If no Razer, Kinect, or PS Move is available, then apply onlyMouseOffset
            // on the parent object of the head tracker that is left enabled
//			if(		closestMatch != null && !razer && !kinect && !psmove)
//			{
//				// The parent object of the Razer head tracker must not have RUISCharacterConroller,
//				// because that script will modify the object's position
//				if(		closestMatch.transform.parent != null
//					&&	closestMatch.transform.parent.GetComponent<RUISCharacterController>() == null
//					&& (onlyMouseOffset.x != 0 || onlyMouseOffset.y != 0 || onlyMouseOffset.z != 0)  )
//				{
//					closestMatch.transform.parent.localPosition += onlyMouseOffset;
//					Debug.Log(  "Applying offset of " + onlyMouseOffset + " to "
//							   + closestMatch.transform.parent.gameObject.name + " (parent of assigned head tracker).");
//				}
//			}

            // *** TODO: Below is slightly hacky
            // Read inputConfig.xml to see if Kinect yaw drift correction for Oculus Rift should be enabled
            if (closestMatch != null &&
                closestMatch.useOculusRiftRotation && applyKinectDriftCorrectionPreference)
            {
                if (inputManager.kinectDriftCorrectionPreferred)
                {
                    // Preference is to use Kinect for drift correction (if PS Move is not used for head tracking)
                    switch (closestMatch.headPositionInput)
                    {
                    case RUISTracker.HeadPositionSource.Kinect1:
                        if (!psmove && kinect)
                        {
                            closestMatch.externalDriftCorrection = true;
                            closestMatch.compass = RUISTracker.CompassSource.Kinect1;
                        }
                        break;

                    case RUISTracker.HeadPositionSource.RazerHydra:
                        if (!psmove && kinect && razer)
                        {
                            if (closestMatch.isRazerBaseMobile)
                            {
                                closestMatch.externalDriftCorrection = true;
                                closestMatch.compass = RUISTracker.CompassSource.Kinect1;
                            }
                        }
                        break;
                    }
                }
                else
                {
                    // Preference is NOT to use Kinect for drift correction
                    if (closestMatch.headPositionInput == RUISTracker.HeadPositionSource.Kinect1 &&
                        !psmove && kinect)
                    {
                        closestMatch.externalDriftCorrection = false;
                    }
                }
            }
        }
    }
    public override void OnInspectorGUI()
    {
        serializedObject.Update();

        EditorGUILayout.PropertyField(defaultPosition, new GUIContent("Default Position (meters)", "Head position before tracking starts"));
        //EditorGUILayout.PropertyField(skeletonManager, new GUIContent("skeletonManager", "Can be None"));

		if(serializedObject.targetObject is RUISTracker)
		{
			trackerScript = (RUISTracker) serializedObject.targetObject;
			if(trackerScript)
				ovrCameraRig = trackerScript.gameObject.GetComponentInChildren<OVRCameraRig>();
			if(ovrCameraRig)
			{
				riftFound = true;
			}
			else
			{
				riftFound = false;
			}
		}
		
		if(!riftFound)
		{
			EditorGUILayout.PropertyField(pickRotationSource, new GUIContent( "Pick Rotation Source", "If disabled, then the Rotation "
																			+ "Tracker is same as Position Tracker"));
		}
		
        EditorGUILayout.Space();
        EditorGUILayout.PropertyField(headPositionInput, new GUIContent("Position Tracker", "Device that tracks the head position"));
		
        EditorGUI.indentLevel += 2;
        switch (headPositionInput.enumValueIndex)
        {
			case (int)RUISTracker.HeadPositionSource.OculusDK2:
				EditorGUILayout.PropertyField(positionOffsetOculus, new GUIContent("Position Offset (meters)", "Adds an position offset to Oculus Rift's "
				                                                                   + "tracked position. This should be zero when using Oculus Rift positional "
				                                                                   + "tracking together with Kinect skeleton tracking."));

				break;
            case (int)RUISTracker.HeadPositionSource.Kinect1:
			case (int)RUISTracker.HeadPositionSource.Kinect2:
				positionPlayerID.intValue = Mathf.Clamp(positionPlayerID.intValue, 0, maxKinectSkeletons - 1);
				if(positionNoiseCovarianceKinect.floatValue < minNoiseCovariance)
					positionNoiseCovarianceKinect.floatValue = minNoiseCovariance;
                EditorGUILayout.PropertyField(positionPlayerID, new GUIContent("Kinect Player Id", "Between 0 and 3"));

                EditorGUILayout.PropertyField(positionJoint, new GUIContent("Joint", "Head is the best joint for tracking head position"));
                EditorGUILayout.PropertyField(positionOffsetKinect, new GUIContent("Position Offset (meters)", "Kinect joint's position in "
                															+ "the tracked object's local coordinate system. Set these values "
																			+ "according to the joint's offset from the tracked object's "
																			+ "origin (head etc.). When using Kinect for head tracking, then zero " 
																			+ "vector is the best choice if head is the position Joint."));
		        EditorGUILayout.PropertyField(filterPositionKinect, new GUIContent("Filter Position", "Enables simple Kalman filtering for position "
																			+ "tracking. Recommended for Kinect."));
				if(filterPositionKinect.boolValue)
			        EditorGUILayout.PropertyField(positionNoiseCovarianceKinect, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
																			+ "a bigger value means smoother results but a slower "
																			+ "response to changes."));
                break;
            case (int)RUISTracker.HeadPositionSource.PSMove:
				positionPSMoveID.intValue = Mathf.Clamp(positionPSMoveID.intValue, 0, maxPSMoveControllers - 1);
				if(positionNoiseCovariancePSMove.floatValue < minNoiseCovariance)
					positionNoiseCovariancePSMove.floatValue = minNoiseCovariance;
                EditorGUILayout.PropertyField(positionPSMoveID, new GUIContent("PS Move ID", "Between 0 and 3"));
                EditorGUILayout.PropertyField(positionOffsetPSMove, new GUIContent("Position Offset (meters)", "PS Move controller's position in "
                															+ "the tracked object's local coordinate system. Set these values "
																			+ "according to the controller's offset from the tracked object's "
																			+ "origin (head etc.)."));
		        EditorGUILayout.PropertyField(filterPositionPSMove, new GUIContent("Filter Position", "Enables simple Kalman filtering for position "
																			+ "tracking. Best left disabled for PS Move."));
				if(filterPositionPSMove.boolValue)
			        EditorGUILayout.PropertyField(positionNoiseCovariancePSMove, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
																			+ "a bigger value means smoother results but a slower "
																			+ "response to changes."));
                break;
            case (int)RUISTracker.HeadPositionSource.RazerHydra:
				if(positionNoiseCovarianceHydra.floatValue < minNoiseCovariance)
					positionNoiseCovarianceHydra.floatValue = minNoiseCovariance;
			
		        EditorGUILayout.PropertyField(isRazerBaseMobile, new GUIContent("Moving Base Station", "Enable this if the Razer Hydra base station is "
																			+ "attached to something that is moving (e.g. Kinect tracked player's belt)"));
				
			    EditorGUILayout.PropertyField(positionRazerID, new GUIContent("Razer Hydra ID", "Either LEFT or RIGHT"));
                EditorGUILayout.PropertyField(positionOffsetHydra, new GUIContent("Position Offset (meters)", "Razer Hydra controller's position in "
                															+ "the tracked object's local coordinate system. Set these values "
																			+ "according to the controller's offset from the tracked object's "
																			+ "origin (head etc.)."));
		        EditorGUILayout.PropertyField(filterPositionHydra, new GUIContent("Filter Position", "Enables simple Kalman filtering for position "
																			+ "tracking. Best left disabled for Razer Hydra."));
				if(filterPositionHydra.boolValue)
			        EditorGUILayout.PropertyField(positionNoiseCovarianceHydra, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
																			+ "a bigger value means smoother results but a slower "
																			+ "response to changes."));
				break;
            case (int)RUISTracker.HeadPositionSource.InputTransform:
				if(positionNoiseCovarianceTransform.floatValue < minNoiseCovariance)
					positionNoiseCovarianceTransform.floatValue = minNoiseCovariance;
                EditorGUILayout.PropertyField(positionInput, new GUIContent("Input Transform", "All other position trackers are supported "
																			+ "through this transform. Drag and drop here a transform "
																			+ "whose position is controlled by a tracking device."));
		        EditorGUILayout.PropertyField(filterPositionTransform, new GUIContent("Filter Position", "Enables simple Kalman filtering for position "
																			+ "tracking."));
				if(filterPositionTransform.boolValue)
			        EditorGUILayout.PropertyField(positionNoiseCovarianceTransform, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
																			+ "a bigger value means smoother results but a slower "
																			+ "response to changes."));
				break;
        }
		
//		if(headPositionInput.enumValueIndex != (int)RUISTracker.HeadPositionSource.None)
//		{
//	        EditorGUILayout.PropertyField(filterPosition, new GUIContent("Filter Position", "Enables simple Kalman filtering for position "
//																					+ "tracking. Only recommended for Kinect."));
//	        EditorGUILayout.PropertyField(positionNoiseCovariance, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
//																					+ "a bigger value means smoother results but a slower "
//																					+ "response to changes."));
//		}
				
        EditorGUI.indentLevel -= 2;

		
        EditorGUILayout.Space();
		
		if(riftFound)
		{
			
			EditorGUILayout.LabelField("Rotation Tracker:    Oculus Rift", EditorStyles.boldLabel);
        	EditorGUI.indentLevel += 2;
			
        	EditorGUILayout.PropertyField(oculusID, new GUIContent("Oculus Rift ID", "Choose which Rift is the source of the head tracking. "
																	+ "Leave this to 0 (multiple Rifts are not supported yet)."));
			
			
			EditorStyles.textField.wordWrap = true;
			EditorGUILayout.TextArea(typeof(OVRCameraRig) + " script detected in a child object of this " + trackerScript.gameObject.name
										+ ". Assuming that you want to use rotation from Oculus Rift. Disabling other Rotation Tracker "
										+ "options. You can access other rotation trackers when you remove or disable the child object "
			                         + "that has the " + typeof(OVRCameraRig) + " component.", GUILayout.Height(120));
			
			EditorGUILayout.LabelField( new GUIContent("Reset Orientation Button(s):", "The button(s) that reset Oculus Rift's yaw "
										+ "rotation to zero."), 
										EditorStyles.boldLabel);
        	EditorGUI.indentLevel += 1;
			EditorGUILayout.PropertyField(resetKey, new GUIContent("KeyCode", "The button that resets Oculus Rift's yaw rotation to zero."));
			
			if(externalDriftCorrection.boolValue && compass.enumValueIndex == (int)RUISTracker.CompassSource.RazerHydra)
				EditorGUILayout.LabelField(new GUIContent(("BUMPER+START Razer Hydra " + compassRazerID.enumNames[compassRazerID.enumValueIndex]),
										   "BUMPER and START of the Razer Hydra controller that you use for Yaw Drift Correction."),
										   EditorStyles.label);
			else if(headPositionInput.enumValueIndex == (int)RUISTracker.HeadPositionSource.RazerHydra)
				EditorGUILayout.LabelField(new GUIContent(("BUMPER+START Razer Hydra " + positionRazerID.enumNames[positionRazerID.enumValueIndex]),
										   "BUMPER and START of the Razer Hydra controller that you use for position tracking."),
										   EditorStyles.label);
			if(externalDriftCorrection.boolValue && compass.enumValueIndex == (int)RUISTracker.CompassSource.PSMove)
				EditorGUILayout.LabelField(new GUIContent(("MOVE button on PS Move #" + compassPSMoveID.intValue),
										   "MOVE button of the PS Move controller that you use for Yaw Drift Correction."),
										   EditorStyles.label);
			else if(headPositionInput.enumValueIndex == (int)RUISTracker.HeadPositionSource.PSMove)
				EditorGUILayout.LabelField(new GUIContent(("MOVE button on PS Move #" + positionPSMoveID.intValue),
										   "MOVE button of the PS Move controller that you use for position tracking."),
										   EditorStyles.label);
        	EditorGUI.indentLevel -= 1;
		}
		else
		{
			if(!pickRotationSource.boolValue)
			{
				switch (headPositionInput.enumValueIndex)
        		{	
					case (int)RUISTracker.HeadPositionSource.Kinect1:
					{
						headRotationInput.enumValueIndex = (int)RUISTracker.HeadRotationSource.Kinect1;
						rotationPlayerID.intValue = positionPlayerID.intValue;
						rotationJoint.enumValueIndex = positionJoint.enumValueIndex;
						break;
					}
					case (int)RUISTracker.HeadPositionSource.Kinect2:
					{
						headRotationInput.enumValueIndex = (int)RUISTracker.HeadRotationSource.Kinect2;
						rotationPlayerID.intValue = positionPlayerID.intValue;
						rotationJoint.enumValueIndex = positionJoint.enumValueIndex;
						break;
					}
					case (int)RUISTracker.HeadPositionSource.PSMove:
					{
						headRotationInput.enumValueIndex = (int)RUISTracker.HeadRotationSource.PSMove;
						rotationPSMoveID.intValue = positionPSMoveID.intValue;
						break;
					}
					case (int)RUISTracker.HeadPositionSource.RazerHydra:
					{
						headRotationInput.enumValueIndex = (int)RUISTracker.HeadRotationSource.RazerHydra;
						rotationRazerID.intValue = positionRazerID.intValue;
						break;
					}
					case (int)RUISTracker.HeadPositionSource.InputTransform:
					{
						headRotationInput.enumValueIndex = (int)RUISTracker.HeadRotationSource.InputTransform;
						rotationInput.objectReferenceValue = positionInput.objectReferenceValue;
						break;
					}
					case (int)RUISTracker.HeadPositionSource.None:
					{
						headRotationInput.enumValueIndex = (int)RUISTracker.HeadRotationSource.None;
						break;
					}
				}
			}
			
			EditorGUI.BeginDisabledGroup(!pickRotationSource.boolValue);
        	EditorGUILayout.PropertyField(headRotationInput, new GUIContent("Rotation Tracker", "Device that tracks the head rotation"));
			EditorGUI.EndDisabledGroup();
			
        	EditorGUI.indentLevel += 2;
			
	        switch (headRotationInput.enumValueIndex)
	        {
	            case (int)RUISTracker.HeadRotationSource.Kinect1:
				case (int)RUISTracker.HeadRotationSource.Kinect2:
					rotationPlayerID.intValue = Mathf.Clamp(rotationPlayerID.intValue, 0, maxKinectSkeletons - 1);
					if(rotationNoiseCovarianceKinect.floatValue < minNoiseCovariance)
						rotationNoiseCovarianceKinect.floatValue = minNoiseCovariance;
					EditorGUI.BeginDisabledGroup(!pickRotationSource.boolValue);
	                EditorGUILayout.PropertyField(rotationPlayerID, new GUIContent("Kinect Player ID", "Between 0 and 3"));
	                EditorGUILayout.PropertyField(rotationJoint, new GUIContent("Joint", "ATTENTION: Torso has most stable joint rotation "
																				+ "for head tracking! Currently OpenNI's head joint rotation "
																				+ "is always the same as torso rotation, except its tracking "
																				+ "fails more often."));
					EditorGUI.EndDisabledGroup();
	                EditorGUILayout.PropertyField(rotationOffsetKinect, new GUIContent("Rotation Offset", "Tracked joint's rotation in tracked "
																				+ "object's local coordinate system. If using Kinect for head "
																				+ "tracking, then zero vector is usually the best choice if "
																				+ "torso or head is the Rotation Joint."));
			        EditorGUILayout.PropertyField(filterRotationKinect, new GUIContent("Filter Rotation", "Enables simple Kalman filtering for rotation "
																				+ "tracking. Recommended for Kinect."));
					if(filterRotationKinect.boolValue)
				        EditorGUILayout.PropertyField(rotationNoiseCovarianceKinect, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
																				+ "a bigger value means smoother results but a slower "
																				+ "response to changes."));
	                break;
	            case (int)RUISTracker.HeadRotationSource.PSMove:
					rotationPSMoveID.intValue = Mathf.Clamp(rotationPSMoveID.intValue, 0, maxPSMoveControllers - 1);
					if(rotationNoiseCovariancePSMove.floatValue < minNoiseCovariance)
						rotationNoiseCovariancePSMove.floatValue = minNoiseCovariance;
					EditorGUI.BeginDisabledGroup(!pickRotationSource.boolValue);
	                EditorGUILayout.PropertyField(rotationPSMoveID, new GUIContent("PS Move ID", "Between 0 and 3"));
					EditorGUI.EndDisabledGroup();
	                EditorGUILayout.PropertyField(rotationOffsetPSMove, new GUIContent("Rotation Offset", "Tracked PS Move controller's "
																				+ "rotation in tracked object's local coordinate system. "
																				+ "Set these euler angles according to the orientation in "
																				+ "which Move is attached to the tracked object (head etc.)."));
			        EditorGUILayout.PropertyField(filterRotationPSMove, new GUIContent("Filter Rotation", "Enables simple Kalman filtering for rotation "
																				+ "tracking. Best left disabled for PS Move."));
					if(filterRotationPSMove.boolValue)
				        EditorGUILayout.PropertyField(rotationNoiseCovariancePSMove, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
																				+ "a bigger value means smoother results but a slower "
																				+ "response to changes."));
	                break;
	            case (int)RUISTracker.HeadRotationSource.RazerHydra:
					if(rotationNoiseCovarianceHydra.floatValue < minNoiseCovariance)
						rotationNoiseCovarianceHydra.floatValue = minNoiseCovariance;
					
					EditorGUI.BeginDisabledGroup(!pickRotationSource.boolValue);
			        EditorGUILayout.PropertyField(isRazerBaseMobile, new GUIContent("Moving Base Station", "Enable this if the Razer Hydra base station is "
																				+ "attached to something that is moving (e.g. Kinect tracked player's "
																				+ "belt)"));
	                EditorGUILayout.PropertyField(rotationRazerID, new GUIContent("Razer Hydra ID", "Either LEFT or RIGHT"));
					EditorGUI.EndDisabledGroup();
	                EditorGUILayout.PropertyField(rotationOffsetHydra, new GUIContent("Rotation Offset", "Tracked Razer Hydra controller's "
																				+ "rotation in tracked object's local coordinate system. "
																				+ "Set these euler angles according to the orientation in which "
																				+ "the Razer Hydra is attached to the tracked object (head etc.)."));
			        EditorGUILayout.PropertyField(filterRotationHydra, new GUIContent("Filter Rotation", "Enables simple Kalman filtering for rotation "
																				+ "tracking. Best left disabled for Razer Hydra."));
					if(filterRotationHydra.boolValue)
				        EditorGUILayout.PropertyField(rotationNoiseCovarianceHydra, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
																				+ "a bigger value means smoother results but a slower "
																				+ "response to changes."));
					break;
	            case (int)RUISTracker.HeadRotationSource.InputTransform:
					if(rotationNoiseCovarianceTransform.floatValue < minNoiseCovariance)
						rotationNoiseCovarianceTransform.floatValue = minNoiseCovariance;
					EditorGUI.BeginDisabledGroup(!pickRotationSource.boolValue);
	                EditorGUILayout.PropertyField(rotationInput, new GUIContent("Input Transform", "All other rotation trackers are supported "
																				+ "through this transform. Drag and drop here a transform "
																				+ "whose rotation is controlled by a tracking device."));
					EditorGUI.EndDisabledGroup();
			        EditorGUILayout.PropertyField(filterRotationTransform, new GUIContent("Filter Rotation", "Enables simple Kalman filtering "
																				+ "for rotation tracking."));
					if(filterRotationTransform.boolValue)
				        EditorGUILayout.PropertyField(rotationNoiseCovarianceTransform, new GUIContent("Filter Strength", "Noise covariance of Kalman " 
																				+ "filtering: a bigger value means smoother results but a slower "
																				+ "response to changes."));
					break;
	        }
			
//			if(headRotationInput.enumValueIndex != (int)RUISTracker.HeadRotationSource.None)
//			{
//		        EditorGUILayout.PropertyField(filterRotation, new GUIContent("Filter Rotation", "Enables simple Kalman filtering for rotation "
//																			+ "tracking. Only recommended for Kinect."));
//		        EditorGUILayout.PropertyField(rotationNoiseCovariance, new GUIContent("Filter Strength", "Noise covariance of Kalman filtering: " 
//																			+ "a bigger value means smoother results but a slower "
//																			+ "response to changes."));
//			}
		}
		
        EditorGUI.indentLevel -= 2;
				
        EditorGUILayout.Space();

		
		if(!riftFound && headRotationInput.enumValueIndex != (int)RUISTracker.HeadRotationSource.InputTransform)
		{
			EditorGUI.BeginDisabledGroup(true);
	        EditorGUILayout.PropertyField(externalDriftCorrection, new GUIContent("Yaw Drift Correction", "Enables external yaw drift correction "
																		+ "using Kinect, PS Move, or some other device"));
			if(	  headRotationInput.enumValueIndex == (int)RUISTracker.HeadRotationSource.Kinect1
			   || headRotationInput.enumValueIndex == (int)RUISTracker.HeadRotationSource.Kinect2)
				EditorGUILayout.LabelField("Kinect joints don't need drift correction");
			if(headRotationInput.enumValueIndex == (int)RUISTracker.HeadRotationSource.PSMove)
				EditorGUILayout.LabelField("PS Move doesn't need drift correction");
			if(headRotationInput.enumValueIndex == (int)RUISTracker.HeadRotationSource.RazerHydra)
				EditorGUILayout.LabelField("Razer Hydra doesn't need drift correction");
			if(headRotationInput.enumValueIndex == (int)RUISTracker.HeadRotationSource.None)
				EditorGUILayout.LabelField("No Rotation Tracker: Drift correction disabled");
			EditorGUI.EndDisabledGroup();
		}
		else
		{
	        EditorGUILayout.PropertyField(externalDriftCorrection, new GUIContent("Yaw Drift Correction", "Enables external yaw drift correction "
																				+ "using Kinect, PS Move, or some other device"));
			if(externalDriftCorrection.boolValue)
			{
			
		        EditorGUI.indentLevel += 2;
				
				EditorGUILayout.PropertyField(compassIsPositionTracker, new GUIContent("Use Position Tracker", "If enabled, rotation from the "
																					+ "above Position Tracker will act as a compass that "
																					+ "corrects yaw drift of the Rotation Tracker"));
				
				if(compassIsPositionTracker.boolValue)
				{
					switch(headPositionInput.enumValueIndex)
					{
						case (int)RUISTracker.HeadPositionSource.Kinect1:
						{
							compass.enumValueIndex = (int)RUISTracker.CompassSource.Kinect1;
							compassPlayerID.intValue = positionPlayerID.intValue;
							compassJoint.enumValueIndex = positionJoint.enumValueIndex;
							break;
						}
						case (int)RUISTracker.HeadPositionSource.Kinect2:
						{
							compass.enumValueIndex = (int)RUISTracker.CompassSource.Kinect2;
							compassPlayerID.intValue = positionPlayerID.intValue;
							compassJoint.enumValueIndex = positionJoint.enumValueIndex;
							break;
						}
						case (int)RUISTracker.HeadPositionSource.PSMove:
						{
							compass.enumValueIndex = (int)RUISTracker.CompassSource.PSMove;
							compassPSMoveID.intValue = positionPSMoveID.intValue;
							break;
						}
						case (int)RUISTracker.HeadPositionSource.RazerHydra:
						{
							compass.enumValueIndex = (int)RUISTracker.CompassSource.RazerHydra;
							compassRazerID.enumValueIndex = positionRazerID.enumValueIndex;
							break;
						}
						case (int)RUISTracker.HeadPositionSource.InputTransform:
						{
							compass.enumValueIndex = (int)RUISTracker.CompassSource.InputTransform;
							compassTransform.objectReferenceValue = positionInput.objectReferenceValue;
							break;
						}
						case (int)RUISTracker.HeadPositionSource.None:
						{
							compass.enumValueIndex = (int)RUISTracker.CompassSource.None;
							break;
						}
					}
				}
				
				
				EditorGUI.BeginDisabledGroup(compassIsPositionTracker.boolValue);
		        EditorGUILayout.PropertyField(compass, new GUIContent("Compass Tracker", "Tracker that will be used to correct the yaw drift of "
																	+ "Rotation Tracker"));
				EditorGUI.EndDisabledGroup();
				
				if(compassIsPositionTracker.boolValue && headPositionInput.enumValueIndex == (int)RUISTracker.HeadPositionSource.None)
					EditorGUILayout.LabelField("Position Tracker is set to None!");
				else
			        switch (compass.enumValueIndex)
			        {
						case (int)RUISTracker.CompassSource.Kinect1:
						case (int)RUISTracker.CompassSource.Kinect2:
							compassPlayerID.intValue = Mathf.Clamp(compassPlayerID.intValue, 0, maxKinectSkeletons - 1);
							driftCorrectionRateKinect.floatValue = Mathf.Clamp(driftCorrectionRateKinect.floatValue, minDriftCorrectionRate, 
																													 maxDriftCorrectionRate );
							EditorGUI.BeginDisabledGroup(compassIsPositionTracker.boolValue);
			                EditorGUILayout.PropertyField(compassPlayerID, new GUIContent("Kinect Player ID", "Between 0 and 3"));
			                EditorGUILayout.PropertyField(compassJoint, new GUIContent("Compass Joint", "ATTENTION: Torso has most stable "
																				+ "joint rotation for drift correction! Currently OpenNI's "
																				+ "head joint rotation is always the same as torso rotation, "
																				+ "except its tracking fails more often."));
							EditorGUI.EndDisabledGroup();
			                EditorGUILayout.PropertyField(compassRotationOffsetKinect, new GUIContent("Compass Rotation Offset", "Kinect joint's "
																				+ "rotation in tracked object's local coordinate system. If using "
																				+ "Kinect for head tracking yaw drif correction, then zero vector is "
																				+ "usually the best choice if torso or head is the Compass Joint. "
																				+ "IT IS IMPORTANT THAT THIS PARAMETER IS CORRECT."
																				+ "Use 'Optional visualizers' to help finding the right values."));
			                EditorGUILayout.PropertyField(correctOnlyWhenFacingForward, new GUIContent("Only Forward Corrections", "Allows drift "
																				+ "correction to occur only when the player is detected as "
																				+ "standing towards Kinect (+-90 degrees). This is useful when "
																				+ "you know that the players will be mostly facing towards Kinect "
																				+ "and you want to improve drift correction by ignoring OpenNI's "
																				+ "tracking errors where the player is detected falsely "
																				+ "standing backwards (happens often)."));
					        EditorGUILayout.PropertyField(driftCorrectionRateKinect, new GUIContent("Correction Rate", "Positive values only. How fast "
																				+ "the drifting rotation is shifted towards the compass' "
																				+ "rotation. Kinect tracked skeleton is quite inaccurate as a " 
																				+ "compass, and the default 0.08 might be good. You might want "
																				+ "to adjust this to suit your liking."));
			                break;
			            case (int)RUISTracker.CompassSource.PSMove:
							compassPSMoveID.intValue = Mathf.Clamp(compassPSMoveID.intValue, 0, maxPSMoveControllers - 1);
							driftCorrectionRatePSMove.floatValue = Mathf.Clamp(driftCorrectionRatePSMove.floatValue, minDriftCorrectionRate, 
																													 maxDriftCorrectionRate );
							EditorGUI.BeginDisabledGroup(compassIsPositionTracker.boolValue);
		                	EditorGUILayout.PropertyField(compassPSMoveID, new GUIContent("PS Move ID", "Between 0 and 3"));
							EditorGUI.EndDisabledGroup();
			                EditorGUILayout.PropertyField(compassRotationOffsetPSMove, new GUIContent("Compass Rotation Offset", "Tracked PS Move "
																				+ "controller's rotation in tracked object's local coordinate "
																				+ "system. Set these euler angles according to the orientation "
																				+ "in which Move Compass is attached to your tracked object "
																				+ "(head etc.). IT IS IMPORTANT THAT THIS PARAMETER IS CORRECT. "
																				+ "Use 'Optional visualizers' to help finding the right values."));
					        EditorGUILayout.PropertyField(driftCorrectionRatePSMove, new GUIContent("Correction Rate", "Positive values only. How fast "
																				+ "the drifting rotation is shifted towards the compass' "
																				+ "rotation. Default of 0.1 is good."));
			                break;
			            case (int)RUISTracker.CompassSource.RazerHydra:
							driftCorrectionRateHydra.floatValue = Mathf.Clamp(driftCorrectionRateHydra.floatValue,  minDriftCorrectionRate, 
																													maxDriftCorrectionRate );

							EditorGUI.BeginDisabledGroup(compassIsPositionTracker.boolValue);
					        EditorGUILayout.PropertyField(isRazerBaseMobile, new GUIContent("Moving Base Station", "Enable this if the Razer Hydra "
																				+ "base station is attached to something that is "
																				+ "moving (e.g. Kinect tracked player's belt)"));
			
			                EditorGUILayout.PropertyField(compassRazerID, new GUIContent("Razer Hydra ID", "Either LEFT or RIGHT"));
							EditorGUI.EndDisabledGroup();
			                EditorGUILayout.PropertyField(compassRotationOffsetHydra, new GUIContent("Compass Rotation Offset", "Tracked Razer Hydra "
																				+ "controller's rotation in tracked object's local "
																				+ "coordinate system.  Set these euler angles according "
																				+ "to the orientation in which the Razer Hydra is "
																				+ "attached to your tracked object (head etc.). "
																				+ "IT IS IMPORTANT THAT THIS PARAMETER IS CORRECT."
																				+ "Use 'Optional visualizers' to help finding the right values."));
					        EditorGUILayout.PropertyField(driftCorrectionRateHydra, new GUIContent("Correction Rate", "Positive values only. How fast "
																				+ "the drifting rotation is shifted towards the compass' "
																				+ "rotation. Default of 0.1 is good."));
			                break;
			            case (int)RUISTracker.CompassSource.InputTransform:
							driftCorrectionRateTransform.floatValue = Mathf.Clamp(driftCorrectionRateTransform.floatValue,  minDriftCorrectionRate, 
																															maxDriftCorrectionRate );
						
							EditorGUI.BeginDisabledGroup(compassIsPositionTracker.boolValue);
			                EditorGUILayout.PropertyField(compassTransform, new GUIContent("Input Transform", "Drift correction via all other "
																				+ "trackers is supported through this transform. Drag "
																				+ "and drop here a transform whose rotation cannot drift."));
							EditorGUI.EndDisabledGroup();
					        EditorGUILayout.PropertyField(driftCorrectionRateTransform, new GUIContent("Correction Rate", "Positive values only. "
																				+ "How fast the drifting rotation is shifted towards the "
																				+ "compass' rotation."));
							break;
			        }
				
	       		EditorGUILayout.Space();
				EditorGUILayout.LabelField("Optional visualizers:");
		        EditorGUILayout.PropertyField(enableVisualizers, new GUIContent("Enable Visualizers", "Below visualizers are optional and meant to"
																	+ "illustrate the performance of the drift correction."));
				if(enableVisualizers.boolValue)
				{
					
		        	EditorGUI.indentLevel += 1;
			        EditorGUILayout.PropertyField(driftingDirectionVisualizer, new GUIContent("Drifter Rotation Visualizer", "Drag and drop a Game "
																		+ "Object here to visualize rotation from Rotation Tracker"));
			        EditorGUILayout.PropertyField(compassDirectionVisualizer, new GUIContent("Compass Yaw Visualizer", "Drag and drop a Game Object "
																		+ "here to visualize yaw rotation from Compass Tracker"));
			        EditorGUILayout.PropertyField(correctedDirectionVisualizer, new GUIContent("Corrected Rotation Visualizer", "Drag and drop a Game "
																		+ "Object here to visualize the final, corrected rotation"));
			        EditorGUILayout.PropertyField(driftVisualizerPosition, new GUIContent("Visualizer Position", "Drag and drop a Transform here "
																		+ "that defines the position where the above three "
																		+ "visualizers will appear"));
	        		EditorGUI.indentLevel -= 1;
				}
				
	        	EditorGUI.indentLevel -= 2;
			}
		
		}
		
		if(isRazerBaseMobile.boolValue)
		{
			if(headPositionInput.enumValueIndex == (int)RUISTracker.HeadPositionSource.RazerHydra)
				movingBaseAnnouncement = "Razer Hydra base station set as moving in Position Tracker";
			else if(headRotationInput.enumValueIndex == (int)RUISTracker.HeadRotationSource.RazerHydra && !riftFound)
				movingBaseAnnouncement = "Razer Hydra base station set as moving in Rotation Tracker";
			else if(	compass.enumValueIndex == (int)RUISTracker.CompassSource.RazerHydra && externalDriftCorrection.boolValue
					&&	(riftFound || headRotationInput.enumValueIndex == (int)RUISTracker.HeadRotationSource.InputTransform)	)
				movingBaseAnnouncement = "Razer Hydra base station set as moving in Yaw Drift Correction";
			else
			{
				movingBaseAnnouncement = "";
				isRazerBaseMobile.boolValue = false; // When all the ifs fail, we can set isRazerBaseMobile to false
			}
		}
		
		if(isRazerBaseMobile.boolValue)
		{
			
    		EditorGUILayout.PropertyField(mobileRazerBase, new GUIContent("Razer Base Tracker", "The tracker onto which the Razer Hydra "
																		+ "base station is attached to"));
			EditorGUI.indentLevel += 2;
			
			if(movingBaseAnnouncement.Length > 0)
			{
				EditorStyles.textField.wordWrap = true;
				EditorGUILayout.TextArea(movingBaseAnnouncement, GUILayout.Height(30));
			}
			switch(mobileRazerBase.enumValueIndex)
			{
				case (int) RUISTracker.RazerHydraBase.Kinect1:
					hydraBaseKinectPlayerID.intValue = Mathf.Clamp(hydraBaseKinectPlayerID.intValue, 0, maxKinectSkeletons - 1);
					if(hydraBasePositionCovarianceKinect.floatValue < minNoiseCovariance)
						hydraBasePositionCovarianceKinect.floatValue = minNoiseCovariance;
					if(hydraBaseRotationCovarianceKinect.floatValue < minNoiseCovariance)
						hydraBaseRotationCovarianceKinect.floatValue = minNoiseCovariance;
					EditorGUILayout.PropertyField(hydraBaseKinectPlayerID, new GUIContent("Kinect Player Id", "Between 0 and 3"));
					EditorGUILayout.PropertyField(hydraBaseJoint, new GUIContent("Joint", "Kinect joint onto which Razer Hydra base station "
																		+ "is attached to"));
			        EditorGUILayout.PropertyField(hydraBasePositionOffsetKinect, new GUIContent("Base Position Offset (meters)", "Razer Hydra "
            															+ "base station's position in the tracked joint's local coordinate "
																		+ "system. Set these values according to the base station's position "
																		+ "offset from the tracked joint's origin."));
			        EditorGUILayout.PropertyField(hydraBaseRotationOffsetKinect, new GUIContent("Base Rotation Offset", "Razer Hydra "
																		+ "base station's rotation in the tracked joint's local coordinate "
																		+ "system. Set these euler angles according to the orientation in which "
																		+ "Razer Hydra base station is attached to the tracked joint. "
																		+ "IT IS IMPORTANT THAT THIS PARAMETER IS CORRECT."));
					EditorGUILayout.PropertyField(inferBaseRotationFromRotationTrackerKinect, new GUIContent("Use Rotation Tracker", "If the "
																		+ "above Position Tracker or Compass Razer Hydra is attached to the "
																		+ "Rotation Tracker (e.g. Oculus Rift), then use them together to "
																		+ "calculate the base station's rotation. Recommended for "
																		+ "Kinect."));
					if(inferBaseRotationFromRotationTrackerKinect.boolValue)
					{
						EditorGUI.indentLevel += 1;
						EditorGUILayout.PropertyField(hydraAtRotationTrackerOffset, new GUIContent("Razer Hydra Rotation Offset", "Tracked "
																		+ "Razer Hydra controller's rotation in tracked object's local coordinate "
																		+ "system. Set these euler angles according to the orientation in which "
																		+ "the Razer Hydra is attached to the tracked object (head etc.). "
																		+ "IT IS IMPORTANT THAT THIS PARAMETER IS CORRECT."));
						EditorGUI.indentLevel -= 1;
					
					}
					EditorGUILayout.PropertyField(filterHydraBasePoseKinect, new GUIContent("Filter Tracking", "Enables simple "
																		+ "Kalman filtering for position and rotation tracking of the Razer "
																		+ "Hydra base station. Recommended for Kinect."));
					if(filterHydraBasePoseKinect.boolValue)
					{
						EditorGUILayout.PropertyField(hydraBasePositionCovarianceKinect, new GUIContent("Filter Position Strength", "Position " 
																		+ "noise covariance of Kalman filtering: a bigger value means "
																		+ "smoother results but a slower response to changes."));
						EditorGUILayout.PropertyField(hydraBaseRotationCovarianceKinect, new GUIContent("Filter Rotation Strength", "Rotation " 
																		+ "noise covariance of Kalman filtering: a bigger value means "
																		+ "smoother results but a slower response to changes."));
					}
				break;
			
				case (int) RUISTracker.RazerHydraBase.InputTransform:
					if(hydraBasePositionCovarianceTransform.floatValue < minNoiseCovariance)
						hydraBasePositionCovarianceTransform.floatValue = minNoiseCovariance;
					if(hydraBaseRotationCovarianceTransform.floatValue < minNoiseCovariance)
						hydraBaseRotationCovarianceTransform.floatValue = minNoiseCovariance;
					EditorGUILayout.PropertyField(hydraBaseInput, new GUIContent("Input Transform", "All other trackers are supported "
																		+ "through this transform. Drag and drop here a transform "
																		+ "whose position and rotation is controlled by a tracking device."));
				
					EditorGUILayout.PropertyField(inferBaseRotationFromRotationTrackerTransform, new GUIContent("Use Rotation Tracker", "If the "
																		+ "above Position Tracker or Compass Razer Hydra is attached to the "
																		+ "Rotation Tracker (e.g. Oculus Rift), then use them together to "
																		+ "calculate the base station's rotation."));
					if(inferBaseRotationFromRotationTrackerTransform.boolValue)
					{
						EditorGUI.indentLevel += 1;
						EditorGUILayout.PropertyField(hydraAtRotationTrackerOffset, new GUIContent("Razer Hydra Rotation Offset", "Tracked "
																		+ "Razer Hydra controller's rotation in tracked object's local coordinate "
																		+ "system. Set these euler angles according to the orientation in which "
																		+ "the Razer Hydra is attached to the tracked object (head etc.). "
																		+ "IT IS IMPORTANT THAT THIS PARAMETER IS CORRECT."));
						EditorGUI.indentLevel -= 1;
					
					}
					EditorGUILayout.PropertyField(filterHydraBasePoseTransform, new GUIContent("Filter Tracking", "Enables simple "
																		+ "Kalman filtering for position and rotation tracking of the Razer "
																		+ "Hydra base station."));
					if(filterHydraBasePoseTransform.boolValue)
					{
						EditorGUILayout.PropertyField(hydraBasePositionCovarianceTransform, new GUIContent("Filter Position Strength", "Position " 
																		+ "noise covariance of Kalman filtering: a bigger value means "
																		+ "smoother results but a slower response to changes."));
						EditorGUILayout.PropertyField(hydraBaseRotationCovarianceTransform, new GUIContent("Filter Rotation Strength", "Rotation " 
																		+ "noise covariance of Kalman filtering: a bigger value means "
																		+ "smoother results but a slower response to changes."));
					}
				break;
			}
			EditorGUI.indentLevel -= 2;
			
		}
		
		
        serializedObject.ApplyModifiedProperties();
    }