示例#1
0
        private void HandleSelectedSegmentModifications()
        {
            if (selectedSegmentIndex < 0 || selectedSegmentIndex >= water.Spline.Segments.Count)
            {
                return;
            }
            if (!water.Spline.IsSegmentValid(selectedSegmentIndex))
            {
                return;
            }
            PSplineSegment segment     = water.Spline.Segments[selectedSegmentIndex];
            PSplineAnchor  startAnchor = water.Spline.Anchors[segment.StartIndex];
            PSplineAnchor  endAnchor   = water.Spline.Anchors[segment.EndIndex];

            Vector3 worldStartPosition = water.transform.TransformPoint(startAnchor.Position);
            Vector3 worldEndPosition   = water.transform.TransformPoint(endAnchor.Position);
            Vector3 worldStartTangent  = water.transform.TransformPoint(segment.StartTangent);
            Vector3 worldEndTangent    = water.transform.TransformPoint(segment.EndTangent);

            EditorGUI.BeginChangeCheck();
            Handles.zTest     = UnityEngine.Rendering.CompareFunction.Always;
            worldStartTangent = Handles.PositionHandle(worldStartTangent, Quaternion.identity);
            worldEndTangent   = Handles.PositionHandle(worldEndTangent, Quaternion.identity);

            segment.StartTangent = water.transform.InverseTransformPoint(worldStartTangent);
            segment.EndTangent   = water.transform.InverseTransformPoint(worldEndTangent);
            if (EditorGUI.EndChangeCheck())
            {
                water.GenerateSplineMeshAtSegment(selectedSegmentIndex);
            }

            Handles.color = Color.white;
            Handles.DrawLine(worldStartPosition, worldStartTangent);
            Handles.DrawLine(worldEndPosition, worldEndTangent);
        }
示例#2
0
        public void RemoveAnchor(int index)
        {
            PSplineAnchor a = Anchors[index];
            List <int>    segmentIndices = FindSegments(index);

            for (int i = 0; i < segmentIndices.Count; ++i)
            {
                int sIndex = segmentIndices[i];
                Segments[sIndex].Dispose();
            }

            Segments.RemoveAll(s => s.StartIndex == index || s.EndIndex == index);
            Segments.ForEach(s =>
            {
                if (s.StartIndex > index)
                {
                    s.StartIndex -= 1;
                }
                if (s.EndIndex > index)
                {
                    s.EndIndex -= 1;
                }
            });
            Anchors.RemoveAt(index);
        }
示例#3
0
        public Vector3 EvaluateScale(int segmentIndex, float t)
        {
            PSplineSegment s           = Segments[segmentIndex];
            PSplineAnchor  startAnchor = Anchors[s.StartIndex];
            PSplineAnchor  endAnchor   = Anchors[s.EndIndex];

            return(Vector3.Lerp(startAnchor.Scale, endAnchor.Scale, t));
        }
示例#4
0
        public Quaternion EvaluateRotation(int segmentIndex, float t)
        {
            PSplineSegment s           = Segments[segmentIndex];
            PSplineAnchor  startAnchor = Anchors[s.StartIndex];
            PSplineAnchor  endAnchor   = Anchors[s.EndIndex];

            return(Quaternion.Lerp(startAnchor.Rotation, endAnchor.Rotation, t));
        }
示例#5
0
        private void HandleAddAnchor()
        {
            bool isLeftMouseUp = Event.current.type == EventType.MouseUp && Event.current.button == 0;
            bool isShift       = Event.current.shift;

            if (!isLeftMouseUp)
            {
                return;
            }
            int        raycastLayer = PSplineToolConfig.Instance.RaycastLayer;
            Ray        r            = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
            RaycastHit hit;

            if (Physics.Raycast(r, out hit, 10000, LayerMask.GetMask(LayerMask.LayerToName(raycastLayer))))
            {
                if (!isShift)
                {
                    selectedAnchorIndex = -1;
                    return;
                }
                Vector3       offset   = Vector3.up * PSplineToolConfig.Instance.YOffset;
                Vector3       worldPos = hit.point + offset;
                Vector3       localPos = water.transform.InverseTransformPoint(worldPos);
                PSplineAnchor a        = new PSplineAnchor(localPos);
                water.Spline.AddAnchor(a);

                if (selectedAnchorIndex >= 0 && selectedAnchorIndex < water.Spline.Anchors.Count - 1)
                {
                    water.Spline.AddSegment(selectedAnchorIndex, water.Spline.Anchors.Count - 1);
                    if (PSplineToolConfig.Instance.AutoTangent)
                    {
                        int[] segmentIndices = water.Spline.SmoothTangents(selectedAnchorIndex, water.Spline.Anchors.Count - 1);
                        water.GenerateSplineMeshAtSegments(segmentIndices);
                    }
                    else
                    {
                        water.GenerateSplineMeshAtSegment(water.Spline.Segments.Count - 1);
                    }
                }

                selectedAnchorIndex = water.Spline.Anchors.Count - 1;
                Event.current.Use();
            }
            else
            {
                selectedAnchorIndex = -1;
            }
        }
示例#6
0
        public Vector3 EvaluatePosition(int segmentIndex, float t)
        {
            PSplineSegment s           = Segments[segmentIndex];
            PSplineAnchor  startAnchor = Anchors[s.StartIndex];
            PSplineAnchor  endAnchor   = Anchors[s.EndIndex];

            Vector3 p0 = startAnchor.Position;
            Vector3 p1 = s.StartTangent;
            Vector3 p2 = s.EndTangent;
            Vector3 p3 = endAnchor.Position;

            t = Mathf.Clamp01(t);
            float   oneMinusT = 1 - t;
            Vector3 p         =
                oneMinusT * oneMinusT * oneMinusT * p0 +
                3 * oneMinusT * oneMinusT * t * p1 +
                3 * oneMinusT * t * t * p2 +
                t * t * t * p3;

            return(p);
        }
示例#7
0
        public override void Apply()
        {
            if (SplineCreator == null && Water == null)
            {
                return;
            }
            if (Water.MeshType != PWaterMeshType.Spline)
            {
                return;
            }

            GSpline gSpline = SplineCreator.Spline;
            PSpline pSpline = Water.Spline;

            pSpline.Dispose();
            pSpline.Anchors.Clear();
            pSpline.Segments.Clear();

            for (int i = 0; i < gSpline.Anchors.Count; ++i)
            {
                PSplineAnchor a = (PSplineAnchor)gSpline.Anchors[i];
                a.Position += Vector3.up * HeightOffset;
                pSpline.Anchors.Add(a);
            }

            for (int i = 0; i < gSpline.Segments.Count; ++i)
            {
                PSplineSegment s = (PSplineSegment)gSpline.Segments[i];
                s.StartTangent += Vector3.up * HeightOffset;
                s.EndTangent   += Vector3.up * HeightOffset;
                pSpline.Segments.Add(s);
            }

            Water.transform.position   = transform.position;
            Water.transform.rotation   = transform.rotation;
            Water.transform.localScale = transform.localScale;
            Water.SplineWidth          = SplineCreator.Width + SplineCreator.FalloffWidth * 2;
            Water.GenerateSplineMesh();
            Water.ReCalculateBounds();
        }
示例#8
0
        private void DrawSelectedAnchorGUI()
        {
            int anchorIndex = splineEditingGUIDrawer.selectedAnchorIndex;

            if (anchorIndex < 0 ||
                anchorIndex >= water.Spline.Anchors.Count)
            {
                return;
            }
            string label = "Selected Anchor";
            string id    = "poseidon-selected-anchor";

            PEditorCommon.Foldout(label, true, id, () =>
            {
                EditorGUI.indentLevel -= 1;
                PSplineAnchor a        = water.Spline.Anchors[anchorIndex];
                EditorGUI.BeginChangeCheck();
                a.Position = PEditorCommon.InlineVector3Field("Position", a.Position);
                a.Rotation = Quaternion.Euler(PEditorCommon.InlineVector3Field("Rotation", a.Rotation.eulerAngles));
                a.Scale    = PEditorCommon.InlineVector3Field("Scale", a.Scale);
                water.Spline.Anchors[anchorIndex] = a;
                if (EditorGUI.EndChangeCheck())
                {
                    if (PSplineToolConfig.Instance.AutoTangent)
                    {
                        int[] segmentIndices = water.Spline.SmoothTangents(anchorIndex);
                        water.GenerateSplineMeshAtSegments(segmentIndices);
                    }
                    else
                    {
                        List <int> segmentIndices = water.Spline.FindSegments(anchorIndex);
                        water.GenerateSplineMeshAtSegments(segmentIndices);
                    }
                }
                EditorGUI.indentLevel += 1;
            });
        }
示例#9
0
        public PSplineSegment AddSegment(int startIndex, int endIndex)
        {
            PSplineSegment s = Segments.Find(s0 =>
                                             (s0.StartIndex == startIndex && s0.EndIndex == endIndex) ||
                                             (s0.StartIndex == endIndex && s0.EndIndex == startIndex));

            if (s != null)
            {
                return(s);
            }
            PSplineSegment newSegment = new PSplineSegment();

            newSegment.StartIndex = startIndex;
            newSegment.EndIndex   = endIndex;
            Segments.Add(newSegment);
            PSplineAnchor startAnchor = Anchors[newSegment.StartIndex];
            PSplineAnchor endAnchor   = Anchors[newSegment.EndIndex];
            Vector3       direction   = (endAnchor.Position - startAnchor.Position).normalized;
            float         length      = (endAnchor.Position - startAnchor.Position).magnitude / 3;

            newSegment.StartTangent = startAnchor.Position + direction * length;
            newSegment.EndTangent   = endAnchor.Position - direction * length;
            return(newSegment);
        }
示例#10
0
        private void HandleSelectTransformRemoveAnchor()
        {
            List <PSplineAnchor> anchors = water.Spline.Anchors;

            for (int i = 0; i < anchors.Count; ++i)
            {
                PSplineAnchor a          = anchors[i];
                Vector3       localPos   = a.Position;
                Vector3       worldPos   = water.transform.TransformPoint(localPos);
                float         handleSize = HandleUtility.GetHandleSize(worldPos) * 0.2f;
                if (i == selectedAnchorIndex)
                {
                    Handles.color = Handles.selectedColor;
                    Handles.SphereHandleCap(0, worldPos, Quaternion.identity, handleSize, EventType.Repaint);
                    bool isGlobalRotation = Tools.pivotRotation == PivotRotation.Global;

                    EditorGUI.BeginChangeCheck();
                    if (Tools.current == Tool.Move)
                    {
                        worldPos   = Handles.PositionHandle(worldPos, isGlobalRotation ? Quaternion.identity : a.Rotation);
                        localPos   = water.transform.InverseTransformPoint(worldPos);
                        a.Position = localPos;
                    }
                    else if (Tools.current == Tool.Rotate && !PSplineToolConfig.Instance.AutoTangent)
                    {
                        a.Rotation = Handles.RotationHandle(a.Rotation, worldPos);
                    }
                    else if (Tools.current == Tool.Scale)
                    {
                        a.Scale = Handles.ScaleHandle(a.Scale, worldPos, isGlobalRotation ? Quaternion.identity : a.Rotation, HandleUtility.GetHandleSize(worldPos));
                    }
                    anchors[i] = a;
                    if (EditorGUI.EndChangeCheck())
                    {
                        if (PSplineToolConfig.Instance.AutoTangent)
                        {
                            water.Spline.SmoothTangents(selectedAnchorIndex);
                        }
                        List <int> segmentIndices = water.Spline.FindSegments(selectedAnchorIndex);
                        water.GenerateSplineMeshAtSegments(segmentIndices);
                    }
                }
                else
                {
                    Handles.color = Color.cyan;
                    if (Handles.Button(worldPos, Quaternion.identity, handleSize, handleSize * 0.5f, Handles.SphereHandleCap))
                    {
                        if (Event.current.control)
                        {
                            selectedAnchorIndex  = -1;
                            selectedSegmentIndex = -1;
                            water.Spline.RemoveAnchor(i);
                        }
                        else if (Event.current.shift)
                        {
                            if (selectedAnchorIndex != i &&
                                selectedAnchorIndex >= 0 &&
                                selectedAnchorIndex < anchors.Count)
                            {
                                water.Spline.AddSegment(selectedAnchorIndex, i);
                                if (PSplineToolConfig.Instance.AutoTangent)
                                {
                                    int[] segmentsIndices = water.Spline.SmoothTangents(selectedAnchorIndex, i);
                                    water.GenerateSplineMeshAtSegments(segmentsIndices);
                                }
                                else
                                {
                                    water.GenerateSplineMeshAtSegment(water.Spline.Segments.Count - 1);
                                }
                                selectedAnchorIndex  = i;
                                selectedSegmentIndex = -1;
                            }
                        }
                        else
                        {
                            selectedAnchorIndex  = i;
                            selectedSegmentIndex = -1;
                        }
                        Event.current.Use();
                    }
                }
            }
        }
示例#11
0
        private void HandleSelectTransformRemoveSegment()
        {
            List <PSplineSegment> segments = water.Spline.Segments;
            List <PSplineAnchor>  anchors  = water.Spline.Anchors;

            for (int i = 0; i < segments.Count; ++i)
            {
                if (!water.Spline.IsSegmentValid(i))
                {
                    continue;
                }
                if (i == selectedSegmentIndex && !PSplineToolConfig.Instance.AutoTangent)
                {
                    HandleSelectedSegmentModifications();
                }
                int           i0            = segments[i].StartIndex;
                int           i1            = segments[i].EndIndex;
                PSplineAnchor a0            = anchors[i0];
                PSplineAnchor a1            = anchors[i1];
                Vector3       startPosition = water.transform.TransformPoint(a0.Position);
                Vector3       endPosition   = water.transform.TransformPoint(a1.Position);
                Vector3       startTangent  = water.transform.TransformPoint(segments[i].StartTangent);
                Vector3       endTangent    = water.transform.TransformPoint(segments[i].EndTangent);
                Color         color         = (i == selectedSegmentIndex) ?
                                              Handles.selectedColor :
                                              Color.white;
                Color colorFade = new Color(color.r, color.g, color.b, color.a * 0.1f);

                Vector3[] bezierPoints = Handles.MakeBezierPoints(startPosition, endPosition, startTangent, endTangent, 11);
                Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
                Handles.color = color;
                Handles.DrawAAPolyLine(BEZIER_WIDTH, bezierPoints);
                Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
                Handles.color = colorFade;
                Handles.DrawAAPolyLine(BEZIER_WIDTH, bezierPoints);

                Matrix4x4 localToWorld  = water.transform.localToWorldMatrix;
                Matrix4x4 splineToLocal = water.Spline.TRS(i, 0.5f);
                Matrix4x4 splineToWorld = localToWorld * splineToLocal;
                Vector3   arrow0        = splineToWorld.MultiplyPoint(Vector3.zero);
                splineToLocal = water.Spline.TRS(i, 0.45f);
                splineToWorld = localToWorld * splineToLocal;
                Vector3 arrow1 = splineToWorld.MultiplyPoint(Vector3.left * 0.5f);
                Vector3 arrow2 = splineToWorld.MultiplyPoint(Vector3.right * 0.5f);
                Handles.zTest = UnityEngine.Rendering.CompareFunction.LessEqual;
                Handles.color = color;
                Handles.DrawAAPolyLine(BEZIER_WIDTH, arrow1, arrow0, arrow2);
                Handles.zTest = UnityEngine.Rendering.CompareFunction.Greater;
                Handles.color = colorFade;
                Handles.DrawAAPolyLine(BEZIER_WIDTH, arrow1, arrow0, arrow2);

                if (Event.current.type == EventType.MouseUp && Event.current.button == 0)
                {
                    float d0 = DistanceMouseToSpline(Event.current.mousePosition, bezierPoints);
                    float d1 = DistanceMouseToPoint(Event.current.mousePosition, bezierPoints[0]);
                    float d2 = DistanceMouseToPoint(Event.current.mousePosition, bezierPoints[bezierPoints.Length - 1]);
                    if (d0 <= BEZIER_SELECT_DISTANCE &&
                        d1 > BEZIER_SELECT_DISTANCE &&
                        d2 > BEZIER_SELECT_DISTANCE)
                    {
                        selectedSegmentIndex = i;
                        if (Event.current.control)
                        {
                            water.Spline.RemoveSegment(selectedSegmentIndex);
                            selectedSegmentIndex = -1;
                            GUI.changed          = true;
                        }
                        //don't Use() the event here
                    }
                    else
                    {
                        if (selectedSegmentIndex == i)
                        {
                            selectedSegmentIndex = -1;
                        }
                    }
                }
            }
            Handles.zTest = UnityEngine.Rendering.CompareFunction.Always;
        }
示例#12
0
 public void AddAnchor(PSplineAnchor a)
 {
     Anchors.Add(a);
 }
示例#13
0
        public int[] SmoothTangents(params int[] anchorIndices)
        {
            int[]     anchorRanks    = new int[Anchors.Count];
            Vector3[] directions     = new Vector3[Anchors.Count];
            float[]   segmentLengths = new float[Segments.Count];

            for (int i = 0; i < Segments.Count; ++i)
            {
                PSplineSegment s = Segments[i];
                anchorRanks[s.StartIndex] += 1;
                anchorRanks[s.EndIndex]   += 1;

                PSplineAnchor aStart = Anchors[s.StartIndex];
                PSplineAnchor aEnd   = Anchors[s.EndIndex];

                Vector3 startToEnd = aEnd.Position - aStart.Position;
                Vector3 d          = Vector3.Normalize(startToEnd);
                directions[s.StartIndex] += d;
                directions[s.EndIndex]   += d;

                segmentLengths[i] = startToEnd.magnitude;
            }

            for (int i = 0; i < directions.Length; ++i)
            {
                if (anchorRanks[i] == 0)
                {
                    continue;
                }
                directions[i] = Vector3.Normalize(directions[i] / anchorRanks[i]);
            }

            if (anchorIndices == null || anchorIndices.Length == 0)
            {
                anchorIndices = PUtilities.GetIndicesArray(Anchors.Count);
            }

            for (int i = 0; i < anchorIndices.Length; ++i)
            {
                int index = anchorIndices[i];
                if (anchorRanks[index] > 0)
                {
                    Quaternion rot = Quaternion.LookRotation(directions[index], Vector3.up);
                    Anchors[index].Rotation = rot;
                }
            }

            List <int> segmentIndices = new List <int>();

            for (int i = 0; i < Segments.Count; ++i)
            {
                PSplineSegment s = Segments[i];
                for (int j = 0; j < anchorIndices.Length; ++j)
                {
                    int anchorIndex = anchorIndices[j];
                    if (s.StartIndex == anchorIndex || s.EndIndex == anchorIndex)
                    {
                        segmentIndices.Add(i);
                    }
                }
            }

            for (int i = 0; i < segmentIndices.Count; ++i)
            {
                int            index  = segmentIndices[i];
                PSplineSegment s      = Segments[index];
                PSplineAnchor  aStart = Anchors[s.StartIndex];
                PSplineAnchor  aEnd   = Anchors[s.EndIndex];

                float   sLength       = segmentLengths[index];
                float   tangentLength = sLength * 0.33f;
                Vector3 dirStart      = directions[s.StartIndex];
                Vector3 dirEnd        = directions[s.EndIndex];
                s.StartTangent = aStart.Position + dirStart * tangentLength;
                s.EndTangent   = aEnd.Position - dirEnd * tangentLength;
            }
            return(segmentIndices.ToArray());
        }