Beispiel #1
0
        public void SetIsAxisEnabled(Axis axis, bool isEnabled)
        {
            AxisData axisData = axes[axis];

            axisData.IsEnabled = isEnabled;
            axes[axis]         = axisData;
        }
Beispiel #2
0
        public void UpdateAxes()
        {
            foreach (Axis axis in (Axis[])Enum.GetValues(typeof(Axis)))
            {
                AxisData axisData = axes[axis];

                if (!axisData.IsOverriden)
                {
                    Quaternion angle = Quaternion.LookRotation(Vector3.forward);
                    switch (axis)
                    {
                    case Axis.RIGHT:
                        angle = Quaternion.LookRotation(transform.rotation * Vector3.right);
                        break;

                    case Axis.UP:
                        angle = Quaternion.LookRotation(transform.rotation * Vector3.up);
                        break;

                    case Axis.FORWARD:
                        angle = Quaternion.LookRotation(transform.rotation * Vector3.forward);
                        break;
                    }

                    AxisData modifiedAxis = axisData;
                    modifiedAxis.orientation = angle;

                    axes[axis] = modifiedAxis;
                }
            }
        }
Beispiel #3
0
        protected void AddAxisToContribution(AxisData axis, ref Vector3 contribution, float magnitude)
        {
            if (referenceCamera != null)
            {
                bool shouldContribute = true;

                // zoom doesn't work via translation in orthographic mode
                if (axis.key == Axis.FORWARD)
                {
                    if (referenceCamera.orthographic)
                    {
                        referenceCamera.orthographicSize -= magnitude;
                        referenceCamera.orthographicSize  = Mathf.Clamp(referenceCamera.orthographicSize, minViewPortSize, maxViewPortSize);
                        // Debug.Log(referenceCamera.orthographicSize);
                        shouldContribute = false;
                    }
                    else
                    {
                        if (focusTarget != null)
                        {
                            Vector3 potentialPosition = referenceCamera.transform.position + axis.orientation * Vector3.forward * magnitude * Time.deltaTime;

                            float dotProduct = GetForwardDotToFocusTarget();

                            if (GetForwardDotToFocusTarget(potentialPosition) > 0 && dotProduct <= 0)
                            {
                                // the proposed translation will overshoot the target (aka clip through the floor)
                                // so shorten it

                                shouldContribute = false;

                                // Debug.Log("adjusted position");

                                Vector3 dir1   = GetCrossVector();
                                Vector3 dir2   = axes[Axis.FORWARD].orientation * Vector3.forward;
                                float   cosine = Mathf.Cos(Vector3.Angle(dir1, dir2) * Mathf.Deg2Rad);

                                float newMagnitude = dotProduct / cosine - minForwardDistanceFromFocusTarget - referenceCamera.nearClipPlane;

                                Vector3 translation = axis.orientation * Vector3.forward * newMagnitude;

                                // only add to the contribution if it's a non-zero change
                                if (referenceCamera.transform.position + translation != referenceCamera.transform.position)
                                {
                                    contribution += translation;
                                }
                            }
                            else if (dotProduct > 0)
                            {
                                // if we're already overshot, need to clamp
                                // Debug.Log("overshot, clamping");

                                shouldContribute = false;
                                ClampPerspectiveClose();
                            }

                            // zoomed in sufficiently, switch to FOV change
                            if (Mathf.Abs(dotProduct) <= minForwardDistanceFromFocusTarget)
                            {
                                referenceCamera.fieldOfView = Mathf.Clamp(referenceCamera.fieldOfView - magnitude, minFieldOfView, maxFieldOfView);

                                if (referenceCamera.fieldOfView < maxFieldOfView)
                                {
                                    shouldContribute = false;
                                }
                            }
                            else if (referenceCamera.fieldOfView < maxFieldOfView)
                            {
                                referenceCamera.fieldOfView = Mathf.Lerp(referenceCamera.fieldOfView, maxFieldOfView, 0.3f);
                            }
                        }
                    }
                }

                if (shouldContribute)
                {
                    contribution += axis.orientation * Vector3.forward * magnitude;
                }
            }
        }
        public void OnSceneGUI()
        {
            PanZoomBehavior panZoom = (PanZoomBehavior)target;

            panZoom.UpdateAxes();
            panZoom.DrawDebugRays();

            // edit individual axes orientations visually
            if (isEditingAxes)
            {
                serializedObject.Update();

                // update list of axes being targeted
                for (int i = 0; i < axesValues.arraySize; i++)
                {
                    SerializedProperty sp = axesValues.GetArrayElementAtIndex(i);

                    AxisData tempData = new AxisData
                    {
                        key         = (Axis)sp.FindPropertyRelative("key").enumValueIndex,
                        orientation = sp.FindPropertyRelative("orientation").quaternionValue,
                        IsOverriden = sp.FindPropertyRelative("IsOverriden").boolValue,
                        IsEnabled   = sp.FindPropertyRelative("IsEnabled").boolValue,
                        inputMethod = (InputMethod)sp.FindPropertyRelative("inputMethod").enumValueIndex
                    };

                    if (tempData.IsEnabled && tempData.IsOverriden)
                    {
                        if (!axisProfilesMap.ContainsKey(tempData.key))
                        {
                            // Debug.Log("added property");
                            axisProfilesMap.Add(tempData.key, new AxisProfile {
                                data = tempData, isBeingEdited = false
                            });
                        }
                        else
                        {
                            // update orientation of old entry,
                            // but preserve isBeingEdited
                            axisProfilesMap[tempData.key] = new AxisProfile {
                                data = tempData, isBeingEdited = axisProfilesMap[tempData.key].isBeingEdited
                            };
                        }
                    }
                    else if (axisProfilesMap.ContainsKey(tempData.key))
                    {
                        axisProfilesMap.Remove(tempData.key);
                    }
                }



                // window with axis selection
                // see https://forum.unity.com/threads/unexplained-guilayout-mismatched-issue-is-it-a-unity-bug-or-a-miss-understanding.158375/
                //if (Event.current.type == EventType.Layout)
                //{ ^^ seems to block drawing UI in OnSceneGUI
                Handles.BeginGUI();

                GUILayout.BeginVertical("Box", GUILayout.MaxWidth(Screen.width / 3));

                GUILayout.Label("Axes to edit");

                if (axisProfilesMap.Count > 0)
                {
                    // deep copy of keys to keep dictionary in sync
                    List <Axis> keysDeepCopy = new List <Axis>();
                    foreach (Axis key in axisProfilesMap.Keys)
                    {
                        keysDeepCopy.Add(key);
                    }

                    foreach (var key in keysDeepCopy)
                    {
                        GUILayout.BeginHorizontal();
                        bool flag = GUILayout.Toggle(axisProfilesMap[key].isBeingEdited, "Axis " + axisProfilesMap[key].data.key.ToString());
                        GUILayout.Label(axisProfilesMap[key].data.orientation.eulerAngles.ToString());
                        GUILayout.EndHorizontal();

                        axisProfilesMap[key] = new AxisProfile {
                            data = axisProfilesMap[key].data, isBeingEdited = flag
                        };
                    }
                }
                else
                {
                    GUILayout.Label("Override an enabled axis in the inspector to edit here.");
                }

                if (GUILayout.Button("Close <esc>") || Event.current.keyCode == KeyCode.Escape)
                {
                    isEditingAxes = false;
                }

                GUILayout.EndVertical();

                Handles.EndGUI();

                // handle actual rotation

                Vector3 pos = HandleUtility.GUIPointToWorldRay(new Vector2(Screen.width * 0.25f, Screen.height * 0.67f)).GetPoint(1f);

                // get any value from the dictionary
                var e = axisProfilesMap.GetEnumerator();
                e.MoveNext();
                var orientation = e.Current.Value.data.orientation;

                EditorGUI.BeginChangeCheck();
                Quaternion rot = Handles.RotationHandle(orientation, pos);
                if (EditorGUI.EndChangeCheck())
                {
                    // see https://stackoverflow.com/questions/22157435/difference-between-the-two-quaternions
                    // take the rotation delta and apply to all active axes

                    Quaternion diff = rot * Quaternion.Inverse(orientation);

                    foreach (var kvp in axisProfilesMap)
                    {
                        if (kvp.Value.isBeingEdited)
                        {
                            for (int i = 0; i < axesValues.arraySize; i++)
                            {
                                SerializedProperty sp = axesValues.GetArrayElementAtIndex(i);

                                if ((Axis)sp.FindPropertyRelative("key").enumValueIndex == kvp.Key)
                                {
                                    sp.FindPropertyRelative("orientation").quaternionValue = diff * kvp.Value.data.orientation;
                                }
                            }
                        }
                    }
                }
            }

            serializedObject.ApplyModifiedProperties();
        }
        public override void OnInspectorGUI()
        {
            // Update the serializedProperty - always do this in the beginning of OnInspectorGUI.
            serializedObject.Update();

            EditorGUILayout.Space();

            // Show the custom GUI controls.
            EditorGUILayout.PropertyField(mouseButton, new GUIContent("Mouse Button", "Button that triggers pointer drag"));
            EditorGUILayout.PropertyField(precision, new GUIContent("Mouse Precision", "Minimum distance for user to drag pointer for pan to be noticeable"));

            EditorGUILayout.Space();

            EditorGUILayout.PropertyField(referenceCamera, new GUIContent("Reference Camera", "Defaults to attached Camera component or Camera.main if left null. Camera used to convert screen space to world space."));
            EditorGUILayout.PropertyField(focusTarget, new GUIContent("Focus Target", "Object you want to move at a magnitude equal to the pan amount"));
            EditorGUILayout.PropertyField(minDistFromTarget, new GUIContent("Min Distance From Focus", "Used for zoom clamping"));
            EditorGUILayout.PropertyField(isContributionProportionalToDistFromTarget, new GUIContent("Proportional Move Speed", "Speed along axes will be greater when distance from focus is greater if enabled"));

            EditorGUILayout.Space();

            EditorGUILayout.PropertyField(triggerBoundaryObject, new GUIContent("Boundary Object", "Object with attached trigger collider that constrains camera position"));
            EditorGUILayout.PropertyField(triggerBoundaryLayerName, new GUIContent("Boundary Layer Name", "Optional--if left blank behavior will raycast against all colliders in scene to check for boundary."));

            EditorGUILayout.Space();

            EditorGUILayout.LabelField("Orthographic Settings", EditorStyles.boldLabel);
            EditorGUILayout.PropertyField(minViewPortSize, new GUIContent("Min Viewport Size"));
            EditorGUILayout.PropertyField(maxViewPortSize, new GUIContent("Max Viewport Size"));

            PanZoomBehavior panZoom = (PanZoomBehavior)target;

            EditorGUILayout.Space();

            areMultipliersShown = EditorGUILayout.Foldout(areMultipliersShown, areMultipliersShown ? "Input Axis Multipliers" : "Show Input Multipliers");

            if (areMultipliersShown)
            {
                EditorGUILayout.LabelField(new GUIContent("[Hover here for note]", "Note that multipliers configured for a perspective camera may need to be reconfigured for use with an orthographic camera."));

                for (int i = 0; i < inputMultiplierKeys.arraySize; i++)
                {
                    InputMethod method     = (InputMethod)inputMultiplierKeys.GetArrayElementAtIndex(i).enumValueIndex;
                    float       floatValue = inputMultiplierValues.GetArrayElementAtIndex(i).floatValue;
                    inputMultiplierValues.GetArrayElementAtIndex(i).floatValue = EditorGUILayout.FloatField(new GUIContent(method.ToString()), floatValue);
                }
            }

            EditorGUILayout.Space();

            if (GUILayout.Button("Edit Overriden Axes"))
            {
                isEditingAxes = true;
                SceneView.RepaintAll();
            }

            EditorGUILayout.Space();

            areAxesShown = EditorGUILayout.Foldout(areAxesShown, areAxesShown ? "Configure Axes" : "Show Axes");

            if (areAxesShown)
            {
                for (int i = 0; i < axesValues.arraySize; i++)
                {
                    SerializedProperty sp = axesValues.GetArrayElementAtIndex(i);

                    AxisData tempData = new AxisData {
                        key                        = (Axis)sp.FindPropertyRelative("key").enumValueIndex,
                        orientation                = sp.FindPropertyRelative("orientation").quaternionValue,
                        IsOverriden                = sp.FindPropertyRelative("IsOverriden").boolValue,
                        IsEnabled                  = sp.FindPropertyRelative("IsEnabled").boolValue,
                        inputMethod                = (InputMethod)sp.FindPropertyRelative("inputMethod").enumValueIndex,
                        secondaryInputMethod       = (InputMethod)sp.FindPropertyRelative("secondaryInputMethod").enumValueIndex,
                        IsSecondaryInputEnabled    = sp.FindPropertyRelative("IsSecondaryInputEnabled").boolValue,
                        DoesSecondaryNeedTrigger   = sp.FindPropertyRelative("DoesSecondaryNeedTrigger").boolValue,
                        secondaryInputTrigger      = sp.FindPropertyRelative("secondaryInputTrigger").stringValue,
                        customInputMethod          = sp.FindPropertyRelative("customInputMethod").stringValue,
                        customSecondaryInputMethod = sp.FindPropertyRelative("customSecondaryInputMethod").stringValue
                    };

                    EditorGUILayout.Space();

                    GUILayout.Label("Axis " + tempData.key.ToString(), EditorStyles.boldLabel);

                    tempData.IsEnabled = GUILayout.Toggle(tempData.IsEnabled, new GUIContent("Enabled?"));

                    if (tempData.IsEnabled)
                    {
                        tempData.IsOverriden = GUILayout.Toggle(tempData.IsOverriden, new GUIContent("Override axis value?"));
                        if (tempData.IsOverriden)
                        {
                            tempData.orientation = Quaternion.Euler(EditorGUILayout.Vector3Field(new GUIContent("Orientation"), tempData.orientation.eulerAngles));
                        }

                        tempData.inputMethod = (InputMethod)EditorGUILayout.EnumPopup(new GUIContent("Input Method"), tempData.inputMethod);

                        if (tempData.inputMethod == InputMethod.CustomAxis)
                        {
                            tempData.customInputMethod = EditorGUILayout.TextField(new GUIContent("Custom Axis Name"), tempData.customInputMethod);
                        }

                        tempData.IsSecondaryInputEnabled = GUILayout.Toggle(tempData.IsSecondaryInputEnabled, new GUIContent("Enable secondary input?"));

                        if (tempData.IsSecondaryInputEnabled)
                        {
                            tempData.secondaryInputMethod = (InputMethod)EditorGUILayout.EnumPopup(new GUIContent("Secondary Input Method"), tempData.secondaryInputMethod);

                            if (tempData.secondaryInputMethod == InputMethod.CustomAxis)
                            {
                                tempData.customSecondaryInputMethod = EditorGUILayout.TextField(new GUIContent("Custom Axis Name"), tempData.customSecondaryInputMethod);
                            }

                            tempData.DoesSecondaryNeedTrigger = GUILayout.Toggle(tempData.DoesSecondaryNeedTrigger, new GUIContent("Is secondary triggered by button?"));

                            if (tempData.DoesSecondaryNeedTrigger)
                            {
                                tempData.secondaryInputTrigger = EditorGUILayout.TextField(new GUIContent("Trigger Button Name"), tempData.secondaryInputTrigger);
                            }
                        }
                    }

                    sp.FindPropertyRelative("IsEnabled").boolValue                    = tempData.IsEnabled;
                    sp.FindPropertyRelative("IsOverriden").boolValue                  = tempData.IsOverriden;
                    sp.FindPropertyRelative("orientation").quaternionValue            = tempData.orientation;
                    sp.FindPropertyRelative("inputMethod").enumValueIndex             = (int)tempData.inputMethod;
                    sp.FindPropertyRelative("secondaryInputMethod").enumValueIndex    = (int)tempData.secondaryInputMethod;
                    sp.FindPropertyRelative("IsSecondaryInputEnabled").boolValue      = tempData.IsSecondaryInputEnabled;
                    sp.FindPropertyRelative("DoesSecondaryNeedTrigger").boolValue     = tempData.DoesSecondaryNeedTrigger;
                    sp.FindPropertyRelative("secondaryInputTrigger").stringValue      = tempData.secondaryInputTrigger;
                    sp.FindPropertyRelative("customInputMethod").stringValue          = tempData.customInputMethod;
                    sp.FindPropertyRelative("customSecondaryInputMethod").stringValue = tempData.customSecondaryInputMethod;
                }

                EditorGUILayout.Space();
            }

            // Apply changes to the serializedProperty - always do this in the end of OnInspectorGUI.
            serializedObject.ApplyModifiedProperties();
        }