public FerrTerrainBuilder(List<Polygon2D> polygons, Ferr2D_Path ferrPathPrototype, float cellWidth, float cellHeight)
        {
            this.polygons = polygons;
            this.ferrPathPrototype = ferrPathPrototype;

            this.cellWidth = cellWidth;
            this.cellHeight = cellHeight;
        }
        public FerrTerrainBuilder(List<Polygon2D> polygons, Ferr2D_Path ferrPathPrototype, Vector2 entranceCell, Vector2 exitCell, float cellWidth, float cellHeight, bool randomizeVertexColor = false)
        {
            this.polygons = polygons;
            this.ferrPathPrototype = ferrPathPrototype;

            this.cellWidth = cellWidth;
            this.cellHeight = cellHeight;

            this.entrancePoint.x = cellWidth * entranceCell.x;
            this.entrancePoint.y = cellHeight * entranceCell.y;

            this.exitPoint.x = cellWidth * exitCell.x;
            this.exitPoint.y = cellHeight * exitCell.y;

            this.randomizeVertexColor = randomizeVertexColor;
        }
    private void OnSceneGUI()
    {
        if (!Ferr2DT_PathTerrain.showGUI)
        {
            return;
        }

        Ferr2D_Path         path      = (Ferr2D_Path)target;
        Ferr2DT_PathTerrain terrain   = path.GetComponent <Ferr2DT_PathTerrain>();
        GUIStyle            iconStyle = new GUIStyle();

        iconStyle.alignment = TextAnchor.MiddleCenter;
        snap = new Vector3(EditorPrefs.GetFloat("MoveSnapX", 1), EditorPrefs.GetFloat("MoveSnapY", 1), EditorPrefs.GetFloat("MoveSnapZ", 1));

        // setup undoing things
        Undo.RecordObject(target, "Modified Path");

        if (Event.current.type == EventType.Repaint && terrain != null)
        {
            Ferr2DT_PathTerrainEditor.DrawColliderEdge(terrain);
        }

        // draw the path line
        if (Event.current.type == EventType.Repaint)
        {
            DoPath(path);
        }

        // Check for drag-selecting multiple points
        DragSelect(path);

        // do adding verts in when the shift key is down!
        if (Event.current.shift && !Event.current.control)
        {
            DoShiftAdd(path, iconStyle);
        }

        // draw and interact with all the path handles
        DoHandles(path, iconStyle);

        // if this was an undo, refresh stuff too
        if (Event.current.type == EventType.ValidateCommand)
        {
            switch (Event.current.commandName)
            {
            case "UndoRedoPerformed":
                // Only rebuild this from an undo if the inspector is not visible.
                UnityEngine.Object[] objs = Resources.FindObjectsOfTypeAll(Type.GetType("UnityEditor.InspectorWindow, UnityEditor, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null", true));
                if (objs == null || objs.Length == 0)
                {
                    path.UpdateDependants(true);
                    if (OnChanged != null)
                    {
                        OnChanged();
                    }
                }
                break;
            }
        }

        // update everything that relies on this path, if the GUI changed
        if (GUI.changed)
        {
            if (PrefabUtility.GetCorrespondingObjectFromSource(target) != null)
            {
                NudgeArray(pathVerts);
                serializedObject.ApplyModifiedProperties();
            }

            UpdateDependentsSmart(path, false, false);
            EditorUtility.SetDirty(target);
            prevChanged = true;
        }
        else if (Event.current.type == EventType.Used)
        {
            if (prevChanged == true)
            {
                UpdateDependentsSmart(path, false, true);
            }
            prevChanged = false;
        }
    }
    private void DoNormalModeHandles(Ferr2D_Path path, Ferr2DT_PathTerrain terrain, int i, Matrix4x4 mat, Matrix4x4 invMat, Transform camTransform)
    {
        int     nextId     = i == path.Count - 1?(path.closed?0:i - 1):i + 1;
        Vector3 pos        = mat.MultiplyPoint3x4(path.pathVerts[i]);
        Vector3 posNext    = mat.MultiplyPoint3x4(path.pathVerts[nextId]);
        Vector3 normal     = -(Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed);
        bool    isSelected = false;

        if (selectedPoints != null)
        {
            isSelected = selectedPoints.Contains(i);
        }

        // check for moving the point
        CapFunction cap = CapDot;

        if (Event.current.control)
        {
            cap = isSelected ? (CapFunction)CapDotSelectedSnap : (CapFunction)CapDotSnap;
        }
        else
        {
            cap = isSelected ? (CapFunction)CapDotSelected     : (CapFunction)CapDot;
        }

        Vector3 result = Handles.FreeMoveHandle(pos, camTransform.rotation, HandleScale(pos) * Ferr2D_Visual.HandleSize, snap, cap);

        if (result != pos)
        {
            EnsureVertSelected(i, ref isSelected);

            Vector2 relative = GetRelativeMovementWithSnap(result, invMat, i, path);

            for (int s = 0; s < selectedPoints.Count; s++)
            {
                path.pathVerts[selectedPoints[s]] += relative;
            }
        }

        if (Ferr2DT_SceneOverlay.showIndices)
        {
            Vector3 labelPos = pos + normal;
            Handles.color = Ferr2D_Visual.IndicesColor;
            Handles.Label(labelPos, "" + i);
            Handles.color = Ferr2D_Visual.HandleColor;
        }

        if (!Ferr2DT_SceneOverlay.segmentLockMode)
        {
            float   scale      = HandleScale(pos) * Ferr2D_Visual.SmallHandleSize;
            Vector3 displayPos = pos;

            if (path.closed || i + 1 < path.pathVerts.Count)
            {
                displayPos = GetOverridePos(i, path, mat, pos, posNext);

                if (IsVisible(displayPos) && terrain.directionOverrides != null)
                {
                    cap = Event.current.alt ? (CapFunction)CapDotReset : GetDirIcon(terrain.directionOverrides[i]);
                    if (Handles.Button(displayPos, camTransform.rotation, scale, scale, cap))
                    {
                        EnsureVertSelected(i, ref isSelected);

                        Undo.RecordObject(terrain, "Override Vert Direction");

                        Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]);
                        for (int s = 0; s < selectedPoints.Count; s++)
                        {
                            terrain.directionOverrides[selectedPoints[s]] = dir;
                        }
                        EditorUtility.SetDirty(terrain);
                        GUI.changed = true;
                    }
                }
            }

            displayPos = pos + normal * terrain.vertScales[i] * 2 * Ferr2DT_Menu.PathScale;
            if (IsVisible(displayPos))
            {
                cap = Event.current.alt ? (CapFunction)CapDotReset : (CapFunction)CapDotScale;

                Vector3 scaleMove = Handles.FreeMoveHandle(displayPos, camTransform.rotation, scale, Vector3.zero, cap);
                float   scaleAmt  = Vector3.Distance(displayPos, scaleMove);
                if (Mathf.Abs(scaleAmt) > 0.01f)
                {
                    EnsureVertSelected(i, ref isSelected);

                    Undo.RecordObject(terrain, "Scale Path Vert");

                    float vertScale = Vector3.Distance(scaleMove, pos) / 2 / Ferr2DT_Menu.PathScale;
                    vertScale = Mathf.Clamp(vertScale, 0.2f, 3f);
                    for (int s = 0; s < selectedPoints.Count; s++)
                    {
                        terrain.vertScales[selectedPoints[s]] = vertScale;
                    }
                    EditorUtility.SetDirty(terrain);
                    GUI.changed = true;
                }
            }

            // make sure we can add new point at the midpoints!
            if (i + 1 < path.pathVerts.Count || path.closed == true)
            {
                Vector3 mid         = (pos + posNext) / 2;
                float   handleScale = HandleScale(mid) * Ferr2D_Visual.HandleSize;

                if (Handles.Button(mid, camTransform.rotation, handleScale, handleScale, CapDotPlus))
                {
                    Vector2 pt = invMat.MultiplyPoint3x4(mid);

                    terrain.AddPoint(pt, nextId);
                    EditorUtility.SetDirty(terrain);
                    GUI.changed = true;
                }
            }
        }
    }
Exemple #5
0
    private void DoHandles(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Handles.color = new Color(1, 1, 1, 0);
        for (int i = 0; i < path.pathVerts.Count; i++)
        {
            Vector3 pos = path.transform.position + new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0);

            // check if we want to remove points
            if (Event.current.control)
            {
                if (Handles.Button(pos + offset, Quaternion.identity, 0.6f, 0.6f, Handles.CircleCap))
                {
                    path.pathVerts.RemoveAt(i);
                    i--;
                    GUI.changed = true;
                }
                if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texMinus), iconStyle);
            }
            else
            {
                // check for moving the point
                if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texDot), iconStyle);
                Vector3 result = Handles.FreeMoveHandle(
                    pos + offset,
                    Quaternion.identity,
                    0.6f,
                    Vector3.zero, Handles.CircleCap);

                path.pathVerts[i] = new Vector2(
                    result.x - path.transform.position.x,
                    result.y - path.transform.position.y);

                // make sure we can add new point at the midpoints!
                if (i + 1 < path.pathVerts.Count || path.closed == true)
                {
                    int index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                    Vector3 pos2 = path.transform.position + new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0);
                    Vector3 mid = (pos + pos2) / 2;

                    if (Handles.Button(mid + offset, Quaternion.identity, 0.4f, 0.4f, Handles.CircleCap))
                    {
                        path.pathVerts.Insert(index, new Vector2(mid.x - path.transform.position.x, mid.y - path.transform.position.y));
                    }
                    if (SetScale(mid + offset, texDotPlus, ref iconStyle)) Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle);
                }
            }
        }
    }
Exemple #6
0
    private void DoHandles(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>();

        if (terrain)
        {
            terrain.MatchOverrides();
        }
        Quaternion inv = Quaternion.Inverse(path.transform.rotation);

        Handles.color = new Color(1, 1, 1, 0);
        for (int i = 0; i < path.pathVerts.Count; i++)
        {
            Vector3 pos        = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0), path.transform.localScale);
            Vector3 posOff     = pos + offset;
            bool    isSelected = false;
            if (selectedPoints != null)
            {
                isSelected = selectedPoints.Contains(i);
            }

            // check if we want to remove points
            if (Event.current.alt)
            {
                float handleScale = HandleScale(posOff);
                if (IsVisible(posOff))
                {
                    SetScale(posOff, texMinus, ref iconStyle);
                    //Handles.Label(posOff, new GUIContent((isSelected || selectedPoints.Count <= 0) ? texMinusSelected : texMinus), iconStyle);
                }

                if (Handles.Button(posOff, SceneView.lastActiveSceneView.camera.transform.rotation, handleScale, handleScale, Handles.CircleCap))
                {
                    if (!isSelected && selectedPoints != null)
                    {
                        selectedPoints.Clear();
                        selectedPoints.Add(i);
                    }
                    if (selectedPoints != null)
                    {
                        for (int s = 0; s < selectedPoints.Count; s++)
                        {
                            if (terrain)
                            {
                                terrain.RemovePoint(selectedPoints[s]);
                            }
                            else
                            {
                                path.pathVerts.RemoveAt(selectedPoints[s]);
                            }
                            if (selectedPoints[s] <= i)
                            {
                                i--;
                            }

                            for (int u = 0; u < selectedPoints.Count; u++)
                            {
                                if (selectedPoints[u] > selectedPoints[s])
                                {
                                    selectedPoints[u] -= 1;
                                }
                            }
                        }
                    }
                    if (selectedPoints != null)
                    {
                        selectedPoints.Clear();
                    }
                    GUI.changed = true;
                }
                else if (Ferr2DT_SceneOverlay.editMode != Ferr2DT_EditMode.None)
                {
                    if (terrain && i + 1 < path.pathVerts.Count)
                    {
                        float   scale     = handleScale * 0.5f;
                        Vector3 dirOff    = GetTickerOffset(path, pos, i);
                        Vector3 posDirOff = posOff + dirOff;

                        if (IsVisible(posDirOff))
                        {
                            Texture2D icon = null;
                            if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override)
                            {
                                icon = GetDirIcon(terrain.directionOverrides[i]);
                            }
                            else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
                            {
                                icon = texScale;
                            }
                            if (Event.current.alt)
                            {
                                icon = texReset;
                            }

                            SetScale(posDirOff, icon, ref iconStyle, 0.5f);
                            Handles.Label(posDirOff, new GUIContent(icon), iconStyle);

                            if (Handles.Button(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, scale, Handles.CircleCap) && selectedPoints != null)
                            {
                                if (selectedPoints.Count < 2 || isSelected == false)
                                {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                for (int s = 0; s < selectedPoints.Count; s++)
                                {
                                    if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override)
                                    {
                                        terrain.directionOverrides[selectedPoints[s]] = Ferr2DT_TerrainDirection.None;
                                    }
                                    else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
                                    {
                                        terrain.vertScales[selectedPoints[s]] = 1;
                                    }
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                }
            }
            else
            {
                // check for moving the point
                Texture2D tex = null;
                if (Event.current.control)
                {
                    tex = isSelected ? texDotSelectedSnap : texDotSnap;
                }
                else
                {
                    tex = isSelected ? texDotSelected : texDot;
                }

                if (IsVisible(posOff))
                {
                    SetScale(posOff, texMinus, ref iconStyle);
                    Handles.Label(posOff, new GUIContent(tex), iconStyle);
                }
                Vector3 snap   = Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapRelative ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero;
                Vector3 result = Handles.FreeMoveHandle(
                    posOff,
                    SceneView.lastActiveSceneView.camera.transform.rotation,
                    HandleScale(pos + offset),
                    snap,
                    Handles.CircleCap);

                if (result != posOff)
                {
                    if (selectedPoints != null)
                    {
                        if (selectedPoints.Count < 2 || isSelected == false)
                        {
                            selectedPoints.Clear();
                            selectedPoints.Add(i);
                            isSelected = true;
                        }
                    }

                    if (!(Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapRelative))
                    {
                        result = GetRealPoint(result, path.transform.position.z);
                    }
                    Vector3 global = (result - offset);
                    if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapGlobal)
                    {
                        global = SnapVector(global);
                    }
                    Vector3 local = inv * (global - path.transform.position);
                    if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapLocal)
                    {
                        local = SnapVector(local);
                    }
                    if (!Event.current.control && Ferr2DT_SceneOverlay.smartSnap && selectedPoints != null)
                    {
                        local = SmartSnap(local, path.pathVerts, selectedPoints, Ferr_Menu.SmartSnapDist);
                    }

                    Vector2 relative = new Vector2(
                        local.x / path.transform.localScale.x,
                        local.y / path.transform.localScale.y) - path.pathVerts[i];
                    if (selectedPoints != null)
                    {
                        for (int s = 0; s < selectedPoints.Count; s++)
                        {
                            path.pathVerts[selectedPoints[s]] += relative;
                        }
                    }
                }

                // if using terrain, check to see for any edge overrides
                if (Ferr2DT_SceneOverlay.showIndices)
                {
                    Vector3 labelPos = posOff + (Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed);
                    Handles.color = Color.white;
                    Handles.Label(labelPos, "" + i);
                    Handles.color = new Color(1, 1, 1, 0);
                }

                if (terrain)
                {// && i+1 < path.pathVerts.Count) {
                    float   scale     = HandleScale(pos + offset) * 0.5f;
                    Vector3 dirOff    = GetTickerOffset(path, pos, i);
                    Vector3 posDirOff = posOff + dirOff;

                    if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override && i + 1 < path.pathVerts.Count)
                    {
                        if (IsVisible(posDirOff))
                        {
                            SetScale(posDirOff, texMinus, ref iconStyle, 0.5f);
                            Handles.Label(posDirOff, new GUIContent(Event.current.alt ? texReset : GetDirIcon(terrain.directionOverrides[i])), iconStyle);

                            if (Handles.Button(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, scale, Handles.CircleCap) && selectedPoints != null)
                            {
                                if (selectedPoints.Count < 2 || isSelected == false)
                                {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]);
                                for (int s = 0; s < selectedPoints.Count; s++)
                                {
                                    terrain.directionOverrides[selectedPoints[s]] = dir;
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                    else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
                    {
                        if (IsVisible(posDirOff))
                        {
                            SetScale(posDirOff, texMinus, ref iconStyle, 0.5f);
                            Handles.Label(posDirOff, new GUIContent(Event.current.alt ? texReset : texScale), iconStyle);

                            Vector3 scaleMove = Handles.FreeMoveHandle(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, Vector3.zero, Handles.CircleCap);
                            float   scaleAmt  = scaleMove.y - posDirOff.y;
                            if (Mathf.Abs(scaleAmt) > 0.01f)
                            {
                                if (selectedPoints != null && selectedPoints.Count < 2 || isSelected == false)
                                {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                float vertScale = terrain.vertScales[i] - Event.current.delta.y / 100f;
                                vertScale = Mathf.Clamp(vertScale, 0.2f, 3f);
                                if (selectedPoints != null)
                                {
                                    for (int s = 0; s < selectedPoints.Count; s++)
                                    {
                                        terrain.vertScales[selectedPoints[s]] = vertScale;
                                    }
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                }

                // make sure we can add new point at the midpoints!
                if (i + 1 < path.pathVerts.Count || path.closed == true)
                {
                    int     index       = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                    Vector3 pos2        = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0), path.transform.localScale);
                    Vector3 mid         = (pos + pos2) / 2;
                    float   handleScale = HandleScale(mid + offset);

                    if (Handles.Button(mid + offset, SceneView.lastActiveSceneView.camera.transform.rotation, handleScale, handleScale, Handles.CircleCap))
                    {
                        Vector2 pt = inv * new Vector2((mid.x - path.transform.position.x) / path.transform.localScale.x, (mid.y - path.transform.position.y) / path.transform.localScale.y);
                        if (terrain)
                        {
                            terrain.AddPoint(pt, index);
                        }
                        else
                        {
                            path.pathVerts.Insert(index, pt);
                        }
                    }
                    if (IsVisible(mid + offset))
                    {
                        SetScale(mid + offset, texDotPlus, ref iconStyle);
                        Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle);
                    }
                }
            }
        }

        if (selectedPoints != null && Event.current.type == EventType.keyDown && Event.current.keyCode == KeyCode.Delete && selectedPoints.Count > 0)
        {
            for (int s = 0; s < selectedPoints.Count; s++)
            {
                if (terrain)
                {
                    terrain.RemovePoint(selectedPoints[s]);
                }
                else
                {
                    path.pathVerts.RemoveAt(selectedPoints[s]);
                }

                for (int u = 0; u < selectedPoints.Count; u++)
                {
                    if (selectedPoints[u] > selectedPoints[s])
                    {
                        selectedPoints[u] -= 1;
                    }
                }
            }
            selectedPoints.Clear();
            GUI.changed = true;
            Event.current.Use();
        }
    }
	private void    UpdateDependentsSmart(Ferr2D_Path aPath, bool aForce, bool aFullUpdate) {
		if (aForce || Ferr2DT_Menu.UpdateTerrainSkipFrames == 0 || updateCount % Ferr2DT_Menu.UpdateTerrainSkipFrames == 0) {
			aPath.UpdateDependants(aFullUpdate);
			if (Application.isPlaying) aPath.UpdateColliders();
			if (OnChanged != null) OnChanged();
		}
		updateCount += 1;
	}
	private void    DoShiftAdd           (Ferr2D_Path path, GUIStyle iconStyle)
	{
        Vector3             snap      = Event.current.control ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero;
		Ferr2DT_PathTerrain terrain   = path.gameObject.GetComponent<Ferr2DT_PathTerrain>();
        Transform           transform = path.transform;
        Transform           camTransform = SceneView.lastActiveSceneView.camera.transform;
		Vector3             pos       = transform.InverseTransformPoint( GetMousePos(Event.current.mousePosition, transform) );
		bool                hasDummy  = path.pathVerts.Count <= 0;
		
		if (hasDummy) path.pathVerts.Add(Vector2.zero);
		
		int   closestID  = path.GetClosestSeg(pos);
		int   secondID   = closestID + 1 >= path.Count ? 0 : closestID + 1;
		
		float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
		float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);
		
		Vector3 local  = pos;
		if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal ) local  = SnapVector(local,  snap);
		Vector3 global = transform.TransformPoint(pos);
		if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal) global = SnapVector(global, snap);
		
		Handles.color = Color.white;
		if (!(secondID == 0 && !path.closed && firstDist > secondDist))
		{
			Handles.DrawLine( global, transform.TransformPoint(path.pathVerts[closestID]));
		}
		if (!(secondID == 0 && !path.closed && firstDist < secondDist))
		{
			Handles.DrawLine( global, transform.TransformPoint(path.pathVerts[secondID]));
		}
		Handles.color = new Color(1, 1, 1, 1);
		
		Vector3 handlePos = transform.TransformPoint(pos);
        float   scale     = HandleScale(handlePos);
		if (Handles.Button(handlePos, camTransform.rotation, scale, scale, CapDotPlus))
		{
			Vector3 finalPos = transform.InverseTransformPoint(global);
			if (secondID == 0) {
				if (firstDist < secondDist) {
					if (terrain)
						terrain.AddPoint(finalPos);
					else
						path.pathVerts.Add(finalPos);
				} else {
					if (terrain)
						terrain.AddPoint(finalPos, 0);
					else
						path.pathVerts.Insert(0, finalPos);
				}
			} else {
				if (terrain)
					terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID));
				else
					path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos);
			}
			selectedPoints.Clear();
			GUI.changed = true;
		}
		
		if (hasDummy) path.pathVerts.RemoveAt(0);
	}
Exemple #9
0
 private void DoPath    (Ferr2D_Path path)
 {
     Handles.color = Color.white;
     Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>();
     List<Vector2> verts = terrain == null ? path.GetVertsRaw() : path.GetVerts(false, 2, terrain.splitCorners);
     for (int i = 0; i < verts.Count - 1; i++)
     {
         Vector3 pos  = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i    ].x, verts[i    ].y, 0), path.transform.localScale);
         Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i + 1].x, verts[i + 1].y, 0), path.transform.localScale);
         Handles.DrawLine(pos + offset, pos2 + offset);
     }
     if (path.closed)
     {
         Vector3 pos  = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[0              ].x, verts[0              ].y, 0), path.transform.localScale);
         Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[verts.Count - 1].x, verts[verts.Count - 1].y, 0), path.transform.localScale);
         Handles.DrawLine(pos + offset, pos2 + offset);
     }
 }
    private void    DoHandles(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Vector3             snap         = Event.current.control ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero;
        Transform           transform    = path.transform;
        Matrix4x4           mat          = transform.localToWorldMatrix;
        Matrix4x4           invMat       = transform.worldToLocalMatrix;
        Transform           camTransform = SceneView.lastActiveSceneView.camera.transform;
        Ferr2DT_PathTerrain terrain      = path.GetComponent <Ferr2DT_PathTerrain>();

        if (terrain)
        {
            terrain.MatchOverrides();
        }

        Handles.color = new Color(1, 1, 1, 1);
        for (int i = 0; i < path.pathVerts.Count; i++)
        {
            Vector3 pos        = mat.MultiplyPoint3x4(path.pathVerts[i]);
            Vector3 posStart   = pos;
            bool    isSelected = false;
            if (selectedPoints != null)
            {
                isSelected = selectedPoints.Contains(i);
            }

            // check if we want to remove points
            if (Event.current.alt)
            {
                float handleScale           = HandleScale(posStart);
                Handles.DrawCapFunction cap = (isSelected || selectedPoints.Count <= 0) ? (Handles.DrawCapFunction)CapDotMinusSelected : (Handles.DrawCapFunction)CapDotMinus;
                if (Handles.Button(posStart, camTransform.rotation, handleScale, handleScale, cap))
                {
                    if (!isSelected)
                    {
                        selectedPoints.Clear();
                        selectedPoints.Add(i);
                    }
                    for (int s = 0; s < selectedPoints.Count; s++)
                    {
                        if (terrain)
                        {
                            terrain.RemovePoint(selectedPoints[s]);
                        }
                        else
                        {
                            path.pathVerts.RemoveAt(selectedPoints[s]);
                        }
                        if (selectedPoints[s] <= i)
                        {
                            i--;
                        }

                        for (int u = 0; u < selectedPoints.Count; u++)
                        {
                            if (selectedPoints[u] > selectedPoints[s])
                            {
                                selectedPoints[u] -= 1;
                            }
                        }
                    }
                    selectedPoints.Clear();
                    GUI.changed = true;
                }
                else if (Ferr2DT_SceneOverlay.editMode != Ferr2DT_EditMode.None)
                {
                    if (terrain && i + 1 < path.pathVerts.Count)
                    {
                        float   scale     = handleScale * 0.5f;
                        Vector3 dirOff    = GetTickerOffset(path, pos, i);
                        Vector3 posDirOff = posStart + dirOff;

                        if (IsVisible(posDirOff))
                        {
                            cap = null;
                            if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override)
                            {
                                cap = GetDirIcon(terrain.directionOverrides[i]);
                            }
                            else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
                            {
                                cap = CapDotScale;
                            }
                            if (Event.current.alt)
                            {
                                cap = CapDotReset;
                            }

                            if (Handles.Button(posDirOff, camTransform.rotation, scale, scale, cap))
                            {
                                if (selectedPoints.Count < 2 || isSelected == false)
                                {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                for (int s = 0; s < selectedPoints.Count; s++)
                                {
                                    if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override)
                                    {
                                        terrain.directionOverrides[selectedPoints[s]] = Ferr2DT_TerrainDirection.None;
                                    }
                                    else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
                                    {
                                        terrain.vertScales        [selectedPoints[s]] = 1;
                                    }
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                }
            }
            else
            {
                // check for moving the point
                Handles.DrawCapFunction cap = CapDot;
                if (Event.current.control)
                {
                    cap = isSelected ? (Handles.DrawCapFunction)CapDotSelectedSnap : (Handles.DrawCapFunction)CapDotSnap;
                }
                else
                {
                    cap = isSelected ? (Handles.DrawCapFunction)CapDotSelected     : (Handles.DrawCapFunction)CapDot;
                }

                Vector3 result = Handles.FreeMoveHandle(
                    posStart,
                    camTransform.rotation,
                    HandleScale(pos),
                    snap,
                    cap);

                if (result != posStart)
                {
                    if (selectedPoints.Count < 2 || isSelected == false)
                    {
                        selectedPoints.Clear();
                        selectedPoints.Add(i);
                        isSelected = true;
                    }

                    if (!(Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapRelative))
                    {
                        result = GetRealPoint(result, transform);
                    }

                    Vector3 global = result;
                    if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal)
                    {
                        global = SnapVector(global, snap);
                    }
                    Vector3 local = invMat.MultiplyPoint3x4(global);
                    if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal)
                    {
                        local = SnapVector(local, snap);
                    }
                    if (!Event.current.control && Ferr2DT_SceneOverlay.smartSnap)
                    {
                        local = SmartSnap(local, path.pathVerts, selectedPoints, Ferr2DT_Menu.SmartSnapDist);
                    }

                    Vector2 relative = new Vector2(local.x, local.y) - path.pathVerts[i];

                    for (int s = 0; s < selectedPoints.Count; s++)
                    {
                        path.pathVerts[selectedPoints[s]] += relative;
                    }
                }

                // if using terrain, check to see for any edge overrides
                if (Ferr2DT_SceneOverlay.showIndices)
                {
                    Vector3 labelPos = posStart + (Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed);
                    Handles.color = Color.white;
                    Handles.Label(labelPos, "" + i);
                    Handles.color = new Color(1, 1, 1, 0);
                }

                if (terrain)
                {
                    float   scale     = HandleScale(pos) * 0.5f;
                    Vector3 dirOff    = GetTickerOffset(path, pos, i);
                    Vector3 posDirOff = posStart + dirOff;

                    if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override && i + 1 < path.pathVerts.Count)
                    {
                        if (IsVisible(posDirOff) && terrain.directionOverrides != null)
                        {
                            cap = Event.current.alt ? (Handles.DrawCapFunction)CapDotReset : GetDirIcon(terrain.directionOverrides[i]);
                            if (Handles.Button(posDirOff, camTransform.rotation, scale, scale, cap))
                            {
                                if (selectedPoints.Count < 2 || isSelected == false)
                                {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]);
                                for (int s = 0; s < selectedPoints.Count; s++)
                                {
                                    terrain.directionOverrides[selectedPoints[s]] = dir;
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                    else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
                    {
                        if (IsVisible(posDirOff))
                        {
                            cap = Event.current.alt ? (Handles.DrawCapFunction)CapDotReset : (Handles.DrawCapFunction)CapDotScale;

                            Vector3 scaleMove = Handles.FreeMoveHandle(posDirOff, camTransform.rotation, scale, Vector3.zero, cap);
                            float   scaleAmt  = scaleMove.y - posDirOff.y;
                            if (Mathf.Abs(scaleAmt) > 0.01f)
                            {
                                if (selectedPoints.Count < 2 || isSelected == false)
                                {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                float vertScale = terrain.vertScales[i] - Event.current.delta.y / 100f;
                                vertScale = Mathf.Clamp(vertScale, 0.2f, 3f);
                                for (int s = 0; s < selectedPoints.Count; s++)
                                {
                                    terrain.vertScales[selectedPoints[s]] = vertScale;
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                }

                // make sure we can add new point at the midpoints!
                if (i + 1 < path.pathVerts.Count || path.closed == true)
                {
                    int     index       = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                    Vector3 pos2        = mat.MultiplyPoint3x4(path.pathVerts[index]);
                    Vector3 mid         = (pos + pos2) / 2;
                    float   handleScale = HandleScale(mid);

                    if (Handles.Button(mid, camTransform.rotation, handleScale, handleScale, CapDotPlus))
                    {
                        Vector2 pt = invMat.MultiplyPoint3x4(mid);
                        if (terrain)
                        {
                            terrain.AddPoint(pt, index);
                        }
                        else
                        {
                            path.pathVerts.Insert(index, pt);
                        }
                    }
                }
            }
        }

        if (Event.current.type == EventType.KeyDown && Event.current.keyCode == KeyCode.Delete && selectedPoints.Count > 0)
        {
            for (int s = 0; s < selectedPoints.Count; s++)
            {
                if (terrain)
                {
                    terrain.RemovePoint(selectedPoints[s]);
                }
                else
                {
                    path.pathVerts.RemoveAt(selectedPoints[s]);
                }

                for (int u = 0; u < selectedPoints.Count; u++)
                {
                    if (selectedPoints[u] > selectedPoints[s])
                    {
                        selectedPoints[u] -= 1;
                    }
                }
            }
            selectedPoints.Clear();
            GUI.changed = true;
            Event.current.Use();
        }
    }
Exemple #11
0
    private void DoHandles(Ferr2D_Path path, GUIStyle iconStyle)
    {
#if FERR2D_TERRAIN
        Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>();
        if (terrain)
        {
            terrain.MatchOverrides();
        }
#endif

        Handles.color = new Color(1, 1, 1, 0);
        for (int i = 0; i < path.pathVerts.Count; i++)
        {
            Vector3 pos = path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0), path.transform.localScale);

            // check if we want to remove points
            if (Event.current.control)
            {
                if (Handles.Button(pos + offset, Quaternion.identity, HandleScale(pos + offset), HandleScale(pos + offset), Handles.CircleCap))
                {
                    path.pathVerts.RemoveAt(i);
#if FERR2D_TERRAIN
                    if (terrain)
                    {
                        terrain.directionOverrides.RemoveAt(i);
                    }
#endif
                    i--;
                    GUI.changed = true;
                }
                if (SetScale(pos + offset, texMinus, ref iconStyle))
                {
                    Handles.Label(pos + offset, new GUIContent(texMinus), iconStyle);
                }
            }
            else
            {
                // check for moving the point
                if (SetScale(pos + offset, texMinus, ref iconStyle))
                {
                    Handles.Label(pos + offset, new GUIContent(texDot), iconStyle);
                }
                Vector3 result = Handles.FreeMoveHandle(
                    pos + offset,
                    Quaternion.identity,
                    HandleScale(pos + offset),
                    Vector3.zero, Handles.CircleCap);

                path.pathVerts[i] = new Vector2(
                    (result.x - path.transform.position.x) / path.transform.localScale.x,
                    (result.y - path.transform.position.y) / path.transform.localScale.y);

                // if using terrain, check to see for any edge overrides
#if FERR2D_TERRAIN
                if (terrain && i + 1 < path.pathVerts.Count)
                {
                    float   scale  = HandleScale(pos + offset) * 0.5f;
                    Vector3 dirOff = Vector3.zero;
                    if (i + 1 < path.pathVerts.Count || path.closed == true)
                    {
                        int     index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                        Vector3 delta = path.pathVerts[index] - path.pathVerts[i];
                        delta.Normalize();
                        Vector3 norm = new Vector3(-delta.y, delta.x, 0);
                        dirOff = delta * scale * 3 + new Vector3(norm.x, norm.y, 0) * scale * 2;
                    }

                    if (SetScale(pos + offset + dirOff, texMinus, ref iconStyle, 0.5f))
                    {
                        Handles.Label(pos + offset + dirOff, new GUIContent(GetDirIcon(terrain.directionOverrides[i])), iconStyle);
                    }
                    if (Handles.Button(pos + offset + dirOff, Quaternion.identity, scale, scale, Handles.CircleCap))
                    {
                        terrain.directionOverrides[i] = NextDir(terrain.directionOverrides[i]);
                        GUI.changed = true;
                    }
                }
#endif

                // make sure we can add new point at the midpoints!
                if (i + 1 < path.pathVerts.Count || path.closed == true)
                {
                    int     index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                    Vector3 pos2  = path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0), path.transform.localScale);
                    Vector3 mid   = (pos + pos2) / 2;

                    if (Handles.Button(mid + offset, Quaternion.identity, HandleScale(mid + offset), HandleScale(mid + offset), Handles.CircleCap))
                    {
                        path.pathVerts.Insert(index, new Vector2((mid.x - path.transform.position.x) / path.transform.localScale.x, (mid.y - path.transform.position.y) / path.transform.localScale.y));
#if FERR2D_TERRAIN
                        if (terrain)
                        {
                            terrain.directionOverrides.Insert(index, Ferr2DT_TerrainDirection.None);
                        }
#endif
                    }
                    if (SetScale(mid + offset, texDotPlus, ref iconStyle))
                    {
                        Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle);
                    }
                }
            }
        }
    }
Exemple #12
0
    private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle)
    {
#if FERR2D_TERRAIN
        Ferr2DT_PathTerrain terrain  = path.gameObject.GetComponent<Ferr2DT_PathTerrain>();
#endif
        Quaternion          inv      = Quaternion.Inverse(path.transform.rotation);
        Vector2             pos      = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y);
        bool                hasDummy = path.pathVerts.Count <= 0;

        if (hasDummy) path.pathVerts.Add(Vector2.zero);

        int   closestID  = path.GetClosestSeg(inv * new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
        int   secondID   = closestID + 1 >= path.Count ? 0 : closestID + 1;

        float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
        float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);

        Vector3 local  = pos;
        if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Local ) local  = SnapVector(local );
        Vector3 global = path.transform.position + local;
        if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Global) global = SnapVector(global);

        Handles.color = Color.white;
        if (!(secondID == 0 && !path.closed && firstDist > secondDist))
        {
            Handles.DrawLine(
                global,
                path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale));
        }
        if (!(secondID == 0 && !path.closed && firstDist < secondDist))
        {
            Handles.DrawLine(
                global,
                path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale));
        }
        Handles.color = new Color(1, 1, 1, 0);

        Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset;
        if (Handles.Button(handlePos, Quaternion.identity, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap))
        {
            Vector3    finalPos = inv * (new Vector3(global.x / path.transform.localScale.x, global.y / path.transform.localScale.y, 0) - path.transform.position);
            if (secondID == 0)
            {
                if (firstDist < secondDist)
                {
                    path.pathVerts.Add(finalPos);
#if FERR2D_TERRAIN
                    if (terrain)
                        terrain.directionOverrides.Add(Ferr2DT_TerrainDirection.None);
#endif
                }
                else
                {
                    path.pathVerts.Insert(0, finalPos);
#if FERR2D_TERRAIN
                    if (terrain)
                        terrain.directionOverrides.Insert(0, Ferr2DT_TerrainDirection.None);
#endif
                }
            }
            else
            {
                path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos);
#if FERR2D_TERRAIN
                if (terrain)
                    terrain.directionOverrides.Insert(Mathf.Max(closestID, secondID), Ferr2DT_TerrainDirection.None);
#endif
            }
            GUI.changed = true;
        }
        if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle)) Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle);

        if (hasDummy) path.pathVerts.RemoveAt(0);
    }
Exemple #13
0
    private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle)
    {
#if FERR2D_TERRAIN
        Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>();
#endif

        Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y);

        int closestID = path.GetClosestSeg(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
        int secondID  = closestID + 1 >= path.Count ? 0 : closestID + 1;

        float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
        float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);

        Handles.color = Color.white;
        if (!(secondID == 0 && !path.closed && firstDist > secondDist))
        {
            Handles.DrawLine(
                path.transform.position + new Vector3(pos.x, pos.y, 0),
                path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale));
        }
        if (!(secondID == 0 && !path.closed && firstDist < secondDist))
        {
            Handles.DrawLine(
                path.transform.position + new Vector3(pos.x, pos.y, 0),
                path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale));
        }
        Handles.color = new Color(1, 1, 1, 0);

        Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset;
        if (Handles.Button(handlePos, Quaternion.identity, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap))
        {
            if (secondID == 0)
            {
                if (firstDist < secondDist)
                {
                    path.pathVerts.Add(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
#if FERR2D_TERRAIN
                    if (terrain)
                    {
                        terrain.directionOverrides.Add(Ferr2DT_TerrainDirection.None);
                    }
#endif
                }
                else
                {
                    path.pathVerts.Insert(0, new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
#if FERR2D_TERRAIN
                    if (terrain)
                    {
                        terrain.directionOverrides.Insert(0, Ferr2DT_TerrainDirection.None);
                    }
#endif
                }
            }
            else
            {
                path.pathVerts.Insert(Mathf.Max(closestID, secondID), new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
#if FERR2D_TERRAIN
                if (terrain)
                {
                    terrain.directionOverrides.Insert(Mathf.Max(closestID, secondID), Ferr2DT_TerrainDirection.None);
                }
#endif
            }
            GUI.changed = true;
        }
        if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle))
        {
            Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle);
        }
    }
Exemple #14
0
    private void AddEdge()
    {
        // split the path into segments based on the split angle
        List <List <int>               > segments = new List <List <int>               >();
        List <Ferr2DT_TerrainDirection>  dirs     = new List <Ferr2DT_TerrainDirection>();
        List <int> order = new List <int>();

        segments = GetSegments(Path.GetVertsRaw(), out dirs);
        if (dirs.Count < segments.Count)
        {
            dirs.Add(directionOverrides[directionOverrides.Count - 1]);
        }
        for (int i = 0; i < segments.Count; i++)
        {
            order.Add(i);
        }

        order.Sort(
            new Ferr_LambdaComparer <int>(
                (x, y) => {
            Ferr2DT_TerrainDirection dirx = dirs[x] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[x], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[x];
            Ferr2DT_TerrainDirection diry = dirs[y] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[y], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[y];
            return(terrainMaterial.GetDescriptor(diry).zOffset.CompareTo(terrainMaterial.GetDescriptor(dirx).zOffset));
        }
                ));

        // process the segments into meshes
        for (int i = 0; i < order.Count; i++)
        {
            AddSegment(Ferr2D_Path.IndicesToPath(Path.pathVerts, segments[order[i]]), GetScalesFromIndices(segments[order[i]]), order.Count <= 1 && Path.closed, smoothPath, dirs[order[i]]);
        }
    }
Exemple #15
0
    private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y);

        int closestID = path.GetClosestSeg(pos);
        int secondID  = closestID + 1 >= path.Count ? 0 : closestID + 1;

        float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
        float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);

        Handles.color = Color.white;
        if (!(secondID == 0 && !path.closed && firstDist > secondDist))
        {
            Handles.DrawLine(
                path.transform.position + new Vector3(pos.x, pos.y, 0),
                path.transform.position + new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0));
        }
        if (!(secondID == 0 && !path.closed && firstDist < secondDist))
        {
            Handles.DrawLine(
                path.transform.position + new Vector3(pos.x, pos.y, 0),
                path.transform.position + new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0));
        }
        Handles.color = new Color(1, 1, 1, 0);

        if (Handles.Button(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, Quaternion.identity, 0.4f, 0.4f, Handles.CircleCap))
        {
            if (secondID == 0)
            {
                if (firstDist < secondDist)
                {
                    path.pathVerts.Add(new Vector2(pos.x, pos.y));
                }
                else
                {
                    path.pathVerts.Insert(0, new Vector2(pos.x, pos.y));
                }
            }
            else
            {
                path.pathVerts.Insert(Mathf.Max(closestID, secondID), new Vector2(pos.x, pos.y));
            }
            GUI.changed = true;
        }
        if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle)) Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle);
    }
    private Vector3 GetRelativeMovementWithSnap(Vector3 aHandlePos, Matrix4x4 aInvMat, int i, Ferr2D_Path aPath)
    {
        if (!(Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapRelative))
        {
            aHandlePos = GetRealPoint(aHandlePos, aPath.transform);
        }

        Vector3 global = aHandlePos;

        if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal)
        {
            global = SnapVector(global, snap);
        }
        Vector3 local = aInvMat.MultiplyPoint3x4(global);

        if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal)
        {
            local = SnapVector(local, snap);
        }
        if (!Event.current.control && Ferr2DT_Menu.SmartSnap)
        {
            local = SmartSnap(local, aPath.pathVerts, selectedPoints, Ferr2DT_Menu.SmartSnapDist);
        }

        return(new Vector2(local.x, local.y) - aPath.pathVerts[i]);
    }
Exemple #17
0
 private void UpdateDependentsSmart(Ferr2D_Path aPath, bool aForce) {
     if (aForce || Ferr_Menu.UpdateTerrainSkipFrames == 0 || updateCount % Ferr_Menu.UpdateTerrainSkipFrames == 0) {
         aPath.UpdateDependants();
     }
     updateCount += 1;
 }
    public override void OnInspectorGUI()
    {
        Undo.RecordObject(target, "Modified Path");

        Ferr2D_Path path = (Ferr2D_Path)target;

        // if this was an undo, refresh stuff too
        if (Event.current.type == EventType.ValidateCommand)
        {
            switch (Event.current.commandName)
            {
            case "UndoRedoPerformed":

                path.UpdateDependants(true);
                if (OnChanged != null)
                {
                    OnChanged();
                }
                return;
            }
        }

        path.closed = EditorGUILayout.Toggle("Closed", path.closed);
        if (path)
        {
            // display the path verts list info
            showVerts = EditorGUILayout.Foldout(showVerts, "Path Vertices");
        }
        EditorGUI.indentLevel = 2;
        if (showVerts)
        {
            int size = EditorGUILayout.IntField("Count: ", path.pathVerts.Count);
            while (path.pathVerts.Count > size)
            {
                path.pathVerts.RemoveAt(path.pathVerts.Count - 1);
            }
            while (path.pathVerts.Count < size)
            {
                path.pathVerts.Add(new Vector2(0, 0));
            }
        }
        // draw all the verts! Long list~
        for (int i = 0; showVerts && i < path.pathVerts.Count; i++)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("#" + i, GUILayout.Width(60));
            path.pathVerts[i] = new Vector2(
                EditorGUILayout.FloatField(path.pathVerts[i].x),
                EditorGUILayout.FloatField(path.pathVerts[i].y));
            EditorGUILayout.EndHorizontal();
        }

        // button for updating the origin of the object
        if (GUILayout.Button("Center Position"))
        {
            path.ReCenter();
        }

        bool updateClosed           = false;
        Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>();

        if (!path.closed && terrain != null && (terrain.fill == Ferr2DT_FillMode.Closed || terrain.fill == Ferr2DT_FillMode.InvertedClosed || terrain.fill == Ferr2DT_FillMode.FillOnlyClosed))
        {
            path.closed  = true;
            updateClosed = true;
        }
        if (terrain != null && path.closed && (terrain.fill == Ferr2DT_FillMode.FillOnlySkirt || terrain.fill == Ferr2DT_FillMode.Skirt))
        {
            path.closed  = false;
            updateClosed = true;
        }

        // update dependants when it changes
        if (GUI.changed || updateClosed)
        {
            path.UpdateDependants(false);
            EditorUtility.SetDirty(target);
        }
    }
Exemple #19
0
    private void DoHandles (Ferr2D_Path path, GUIStyle iconStyle)
    {
#if FERR2D_TERRAIN
        Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>();
        if (terrain) terrain.MatchOverrides();
#endif
        Quaternion inv = Quaternion.Inverse(path.transform.rotation);

        Handles.color = new Color(1, 1, 1, 0);
        for (int i = 0; i < path.pathVerts.Count; i++)
        {
            Vector3 pos = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0), path.transform.localScale);

            // check if we want to remove points
            if (Event.current.control)
            {
                if (Handles.Button(pos + offset, Quaternion.identity, HandleScale(pos+offset), HandleScale(pos+offset), Handles.CircleCap))
                {
                    path.pathVerts.RemoveAt(i);
#if FERR2D_TERRAIN
                    if (terrain)
                        terrain.directionOverrides.RemoveAt(i);
#endif
                    i--;
                    GUI.changed = true;
                }
                if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texMinus), iconStyle);
            }
            else
            {
                // check for moving the point
                if (SetScale(pos + offset, texMinus, ref iconStyle)) Handles.Label(pos + offset, new GUIContent(texDot), iconStyle);
                Vector3 result = Handles.FreeMoveHandle(
                    pos + offset,
                    Quaternion.identity,
                    HandleScale(pos+offset),
                    Vector3.zero, Handles.CircleCap);

                Vector3 global = (result - offset);
                if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Global) global = SnapVector(global);
                Vector3 local = inv * (global - path.transform.position);
                if (Ferr_Menu.SnapMode == Ferr2DT_SnapMode.Local ) local  = SnapVector(local);
                path.pathVerts[i] = new Vector2(
                    local.x / path.transform.localScale.x,
                    local.y / path.transform.localScale.y);

                // if using terrain, check to see for any edge overrides
#if FERR2D_TERRAIN
                if (terrain && i+1 < path.pathVerts.Count) {
                    float scale = HandleScale(pos+offset) * 0.5f;
                    Vector3 dirOff = Vector3.zero;
                    if (i + 1 < path.pathVerts.Count || path.closed == true) {
                        int index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                        Vector3 delta = path.pathVerts[index] - path.pathVerts[i];
                        delta.Normalize();
                        Vector3 norm = new Vector3(-delta.y, delta.x, 0);
                        dirOff = delta * scale * 3 + new Vector3(norm.x, norm.y, 0) * scale * 2;
                    }

                    if (SetScale(pos + offset + dirOff, texMinus, ref iconStyle, 0.5f)) Handles.Label(pos + offset + dirOff, new GUIContent(GetDirIcon(terrain.directionOverrides[i])), iconStyle);
                    if (Handles.Button( pos + offset + dirOff, Quaternion.identity, scale, scale, Handles.CircleCap)) {
                        terrain.directionOverrides[i] = NextDir(terrain.directionOverrides[i]);
                        GUI.changed = true;
                    }
                }
#endif

                // make sure we can add new point at the midpoints!
                if (i + 1 < path.pathVerts.Count || path.closed == true)
                {
                    int index = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                    Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0), path.transform.localScale);
                    Vector3 mid  = (pos + pos2) / 2;

                    if (Handles.Button(mid + offset, Quaternion.identity, HandleScale(mid+offset), HandleScale(mid+offset), Handles.CircleCap))
                    {
                        path.pathVerts.Insert(index, inv * new Vector2((mid.x - path.transform.position.x) / path.transform.localScale.x, (mid.y - path.transform.position.y) / path.transform.localScale.y));
#if FERR2D_TERRAIN
                        if (terrain)
                            terrain.directionOverrides.Insert(index, Ferr2DT_TerrainDirection.None);
#endif
                    }
                    if (SetScale(mid + offset, texDotPlus, ref iconStyle)) Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle);
                }
            }
        }
    }
Exemple #20
0
    /// <summary>
    /// The Ferr2DT_IPath method, gets called automatically whenever the Ferr2DT path gets updated in the
    /// editor. This will completely recreate the the visual mesh (only) for the terrain. If you want
    /// To recreate the collider as well, that's a separate call to RecreateCollider.
    /// </summary>
    public void RecreatePath()
    {
        //System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
        //sw.Start();

        if (path == null)
        {
            path = GetComponent <Ferr2D_Path> ();
        }
        if (dMesh == null)
        {
            dMesh = new Ferr2DT_DynamicMesh();
        }
        if (terrainMaterial == null)
        {
            Debug.LogWarning("Cannot create terrain without a Terrain Material!");
            return;
        }

        MatchOverrides();

        // double check the materials!
        ForceMaterial(terrainMaterial, true, false);

        dMesh.Clear();
        dMesh.color = vertexColor;

        if (path.Count < 2)
        {
            GetComponent <MeshFilter>().sharedMesh = null;
            return;
        }

        // make sure we can keep a consistent scale for the texture
        if (terrainMaterial.edgeMaterial.mainTexture != null && terrainMaterial.edgeMaterial.mainTexture != null)
        {
            unitsPerUV.x = terrainMaterial.edgeMaterial.mainTexture.width / pixelsPerUnit;
            unitsPerUV.y = terrainMaterial.edgeMaterial.mainTexture.height / pixelsPerUnit;
        }

        if (fill != Ferr2DT_FillMode.FillOnlyClosed && fill != Ferr2DT_FillMode.FillOnlySkirt)
        {
            // split the path into segments based on the split angle
            List <List <Vector2> >          segments = new List <List <Vector2> >           ();
            List <Ferr2DT_TerrainDirection> dirs     = new List <Ferr2DT_TerrainDirection>();

            segments = GetSegments(path.GetVerts(smoothPath, splitDist, splitCorners), out dirs);
            if (dirs.Count < segments.Count)
            {
                dirs.Add(directionOverrides[directionOverrides.Count - 1]);
            }
            List <int> order = new List <int>();
            for (int i = 0; i < segments.Count; i++)
            {
                order.Add(i);
            }

            order.Sort(
                new Ferr2DT_Comparer <int>(
                    (x, y) => GetDescription(segments[y]).zOffset.CompareTo(GetDescription(segments[x]).zOffset)
                    ));

            // process the segments into meshes
            for (int i = 0; i < order.Count; i++)
            {
                AddSegment(segments[order[i]], order.Count <= 1 && path.closed, dirs[order[i]]);
            }
        }
        int[] submesh1 = dMesh.GetCurrentTriangleList();

        // add a fill if the user desires
        if ((fill == Ferr2DT_FillMode.Skirt || fill == Ferr2DT_FillMode.FillOnlySkirt) && terrainMaterial.fillMaterial != null)
        {
            AddFill(true);
        }
        else if ((fill == Ferr2DT_FillMode.Closed || fill == Ferr2DT_FillMode.InvertedClosed || fill == Ferr2DT_FillMode.FillOnlyClosed) && terrainMaterial.fillMaterial != null)
        {
            AddFill(false);
        }
        else if (fill == Ferr2DT_FillMode.None)
        {
        }
        int[] submesh2 = dMesh.GetCurrentTriangleList(submesh1.Length);

        // compile the mesh!
        Mesh   m    = GetComponent <MeshFilter>().sharedMesh;
        string name = "Ferr2DT_PathMesh_" + gameObject.name + gameObject.GetInstanceID();

        if (m == null || m.name != name)
        {
            GetComponent <MeshFilter>().sharedMesh = m = new Mesh();
            m.name = name;
        }
        dMesh.Build(ref m);

        // set up submeshes and submaterials
        m.subMeshCount = 2;
        if (renderer.sharedMaterials.Length < 2)
        {
            Material[] old = renderer.sharedMaterials;
            renderer.sharedMaterials = new Material[2];
            if (old.Length > 0)
            {
                renderer.sharedMaterials[0] = old[0];
            }
        }
        m.SetTriangles(submesh1, 1);
        m.SetTriangles(submesh2, 0);
        //sw.Stop();
        //Debug.Log("Creating mesh took: " + sw.Elapsed.TotalMilliseconds + "ms");
    }
    List <Vector2> OffsetColliderVerts(List <Vector2> aSegment, List <float> aSegmentScales, Ferr2DT_TerrainDirection aDir)
    {
        List <Vector2> result = new List <Vector2>(aSegment);
        int            count  = aSegment.Count;

        for (int v = count - 1; v >= 0; v--)
        {
            Vector2 norm  = smoothPath ? Ferr2D_Path.HermiteGetNormal(aSegment, v, 0, false) : Ferr2D_Path.GetNormal(aSegment, v, false);
            float   scale = v >= aSegmentScales.Count ? 1 : aSegmentScales[v];
            if (fill == Ferr2DT_FillMode.None)
            {
                result.Add(aSegment[v] + new Vector2(norm.x * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top], norm.y * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top]) * scale);
                result[v] += new Vector2(norm.x * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom], norm.y * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom]) * scale;
            }
            else
            {
                float   dist   = surfaceOffset[(int)aDir];
                Vector2 offset = new Vector2(dist, dist);
                result[v] += new Vector2(norm.x * -offset.x, norm.y * -offset.y) * scale;
            }
        }
        return(result);
    }
Exemple #22
0
	private void    DoHandles            (Ferr2D_Path path, GUIStyle iconStyle)
	{
        Vector3             snap         = Event.current.control ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero;
        Transform           transform    = path.transform;
        Matrix4x4           mat          = transform.localToWorldMatrix;
        Matrix4x4           invMat       = transform.worldToLocalMatrix;
        Transform           camTransform = SceneView.lastActiveSceneView.camera.transform;
		Ferr2DT_PathTerrain terrain      = path.GetComponent<Ferr2DT_PathTerrain>();
		if (terrain) terrain.MatchOverrides();
		
		Handles.color = new Color(1, 1, 1, 1);
		for (int i = 0; i < path.pathVerts.Count; i++)
		{
			Vector3 pos        = mat.MultiplyPoint3x4(path.pathVerts[i]);
			Vector3 posStart   = pos;
			bool    isSelected = false;
               if (selectedPoints!= null) isSelected = selectedPoints.Contains(i);
			
            // check if we want to remove points
			if (Event.current.alt)
			{
				float                   handleScale = HandleScale(posStart);
				Handles.DrawCapFunction cap         = (isSelected || selectedPoints.Count <= 0) ? (Handles.DrawCapFunction)CapDotMinusSelected : (Handles.DrawCapFunction)CapDotMinus;
				if (Handles.Button(posStart, camTransform.rotation, handleScale, handleScale, cap))
				{
					if (!isSelected) {
						selectedPoints.Clear();
						selectedPoints.Add(i);
					}
					for (int s = 0; s < selectedPoints.Count; s++) {
						if (terrain) terrain.RemovePoint(selectedPoints[s]);
						else  path.pathVerts.RemoveAt   (selectedPoints[s]);
						if (selectedPoints[s] <= i) i--;
						
						for (int u = 0; u < selectedPoints.Count; u++) {
							if (selectedPoints[u] > selectedPoints[s]) selectedPoints[u] -= 1;
						}
					}
					selectedPoints.Clear();
					GUI.changed = true;
				} else if (Ferr2DT_SceneOverlay.editMode != Ferr2DT_EditMode.None) {
					
					if (terrain && i+1 < path.pathVerts.Count) {
						float   scale     = handleScale * 0.5f;
						Vector3 dirOff    = GetTickerOffset(path, pos, i);
						Vector3 posDirOff = posStart + dirOff;
						
						if (IsVisible(posDirOff)) {
							cap = null;
							if      (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override) cap  = GetDirIcon(terrain.directionOverrides[i]);
							else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale   ) cap  = CapDotScale;
							if      (Event.current.alt)                                          cap  = CapDotReset;
							
							if (Handles.Button(posDirOff, camTransform.rotation, scale, scale, cap)) {
								if (selectedPoints.Count < 2 || isSelected == false) {
									selectedPoints.Clear();
									selectedPoints.Add(i);
									isSelected = true;
								}
								
								for (int s = 0; s < selectedPoints.Count; s++) {
									if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override)
										terrain.directionOverrides[selectedPoints[s]] = Ferr2DT_TerrainDirection.None;
									else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
										terrain.vertScales        [selectedPoints[s]] = 1;
								}
								GUI.changed = true;
							}
						}
					}
				}
			} else {
                // check for moving the point
				Handles.DrawCapFunction cap = CapDot;
				if (Event.current.control) cap = isSelected ? (Handles.DrawCapFunction)CapDotSelectedSnap : (Handles.DrawCapFunction)CapDotSnap;
				else                       cap = isSelected ? (Handles.DrawCapFunction)CapDotSelected     : (Handles.DrawCapFunction)CapDot;
				
				Vector3 result = Handles.FreeMoveHandle(
					posStart,
					camTransform.rotation,
					HandleScale(pos),
					snap, 
					cap);
				
				if (result != posStart) {
					
					if (selectedPoints.Count < 2 || isSelected == false) {
						selectedPoints.Clear();
						selectedPoints.Add(i);
						isSelected = true;
					}
					
					if (!(Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapRelative))
						result = GetRealPoint(result, transform);

					Vector3 global = result;
					if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal) global = SnapVector(global, snap);
					Vector3 local  = invMat.MultiplyPoint3x4(global);
					if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal ) local  = SnapVector(local, snap);
					if (!Event.current.control && Ferr2DT_SceneOverlay.smartSnap) {
						local = SmartSnap(local, path.pathVerts, selectedPoints, Ferr2DT_Menu.SmartSnapDist);
					}
					
					Vector2 relative = new Vector2( local.x, local.y) - path.pathVerts[i];
					
					for (int s = 0; s < selectedPoints.Count; s++) {
						path.pathVerts[selectedPoints[s]] += relative;
					}
				}
				
                // if using terrain, check to see for any edge overrides
				if (Ferr2DT_SceneOverlay.showIndices) {
					Vector3 labelPos = posStart + (Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed);
					Handles.color    = Color.white;
					Handles.Label(labelPos, "" + i);
					Handles.color    = new Color(1, 1, 1, 0);
				}
				
				if (terrain) {
					float   scale     = HandleScale (pos) * 0.5f;
					Vector3 dirOff    = GetTickerOffset (path, pos, i);
					Vector3 posDirOff = posStart + dirOff;
					
					if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override && i+1 < path.pathVerts.Count) {
						if (IsVisible(posDirOff) && terrain.directionOverrides != null) {
							cap = Event.current.alt ? (Handles.DrawCapFunction)CapDotReset : GetDirIcon(terrain.directionOverrides[i]);
							if (Handles.Button(posDirOff, camTransform.rotation, scale, scale, cap)) {
								if (selectedPoints.Count < 2 || isSelected == false) {
									selectedPoints.Clear();
									selectedPoints.Add(i);
									isSelected = true;
								}
								
								Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]);
								for (int s = 0; s < selectedPoints.Count; s++) {
									terrain.directionOverrides[selectedPoints[s]] = dir;
								}
								GUI.changed = true;
							}
						}
						
					} else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) {
						if (IsVisible(posDirOff)) {
                            cap = Event.current.alt ? (Handles.DrawCapFunction)CapDotReset : (Handles.DrawCapFunction)CapDotScale;
							
							Vector3 scaleMove = Handles.FreeMoveHandle(posDirOff, camTransform.rotation, scale, Vector3.zero, cap);
							float   scaleAmt  = scaleMove.y - posDirOff.y;
							if (Mathf.Abs(scaleAmt) > 0.01f ) {
								if (selectedPoints.Count < 2 || isSelected == false) {
									selectedPoints.Clear();
									selectedPoints.Add(i);
									isSelected = true;
								}
								
								float vertScale = terrain.vertScales[i] - Event.current.delta.y / 100f;
								vertScale = Mathf.Clamp(vertScale, 0.2f, 3f);
								for (int s = 0; s < selectedPoints.Count; s++) {
									terrain.vertScales[selectedPoints[s]] = vertScale;
								}
								GUI.changed = true;
							}
						}
					}
				}
				
                // make sure we can add new point at the midpoints!
				if (i + 1 < path.pathVerts.Count || path.closed == true) {
					int     index       = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
					Vector3 pos2        = mat.MultiplyPoint3x4(path.pathVerts[index]);
					Vector3 mid         = (pos + pos2) / 2;
					float   handleScale = HandleScale(mid);
					
					if (Handles.Button(mid, camTransform.rotation, handleScale, handleScale, CapDotPlus)) {
						Vector2 pt = invMat.MultiplyPoint3x4(mid);
						if (terrain)
							terrain.AddPoint(pt, index);
						else
							path.pathVerts.Insert(index, pt);
					}
				}
			}
		}
		
		if (Event.current.type == EventType.keyDown && Event.current.keyCode == KeyCode.Delete && selectedPoints.Count > 0) {
			for (int s = 0; s < selectedPoints.Count; s++) {
				if (terrain) terrain.RemovePoint(selectedPoints[s]);
				else  path.pathVerts.RemoveAt   (selectedPoints[s]);
				
				for (int u = 0; u < selectedPoints.Count; u++) {
					if (selectedPoints[u] > selectedPoints[s]) selectedPoints[u] -= 1;
				}
			}
			selectedPoints.Clear();
			GUI.changed = true;
			Event.current.Use();
		}
	}
    private void SlicedQuad(List <Vector2> aSegment, int aVert, float aStart, float aEnd, int aCuts, bool aSmoothed, bool aClosed, Ferr2DT_SegmentDescription aDesc, float aStartScale, float aEndScale)
    {
        Vector2[] pos    = new Vector2[aCuts];
        Vector2[] norm   = new Vector2[aCuts];
        float  [] scales = new float  [aCuts];
        Vector3   tn1    = Ferr2D_Path.GetNormal(aSegment, aVert, aClosed);
        Vector3   tn2    = Ferr2D_Path.GetNormal(aSegment, aVert + 1, aClosed);

        // get the data needed to make the quad
        for (int i = 0; i < aCuts; i++)
        {
            float percent = aStart + (i / (float)(aCuts - 1)) * (aEnd - aStart);
            if (aSmoothed)
            {
                pos [i] = Ferr2D_Path.HermiteGetPt(aSegment, aVert, percent, aClosed);
                norm[i] = Ferr2D_Path.HermiteGetNormal(aSegment, aVert, percent, aClosed);
            }
            else
            {
                pos [i] = Vector2.Lerp(aSegment[aVert], aSegment[aVert + 1], percent);
                norm[i] = Vector2.Lerp(tn1, tn2, percent);
            }
            scales[i] = Mathf.Lerp(aStartScale, aEndScale, (i / (float)(aCuts - 1)));
        }

        int tSeed = 0;

        if (randomByWorldCoordinates)
        {
            tSeed = UnityEngine.Random.seed;
            UnityEngine.Random.seed = (int)(pos[0].x * 700000 + pos[0].y * 30000);
        }

        Rect  body = terrainMaterial.ToUV(aDesc.body[UnityEngine.Random.Range(0, aDesc.body.Length)]);
        float d    = (body.height / 2) * unitsPerUV.y;
        float yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;

        if (randomByWorldCoordinates)
        {
            UnityEngine.Random.seed = tSeed;
        }

        // put the data together into a mesh
        int p1 = 0, p2 = 0, p3 = 0;

        for (int i = 0; i < aCuts; i++)
        {
            float percent = (i / (float)(aCuts - 1));

            Vector3 pos1 = pos [i];
            Vector3 n1   = norm[i];
            int     v1   = DMesh.AddVertex(pos1.x + n1.x * (d * scales[i] + yOff), pos1.y + n1.y * (d * scales[i] + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y);
            int     v2   = DMesh.AddVertex(pos1.x - n1.x * (d * scales[i] - yOff), pos1.y - n1.y * (d * scales[i] - yOff), slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y    : body.yMax);
            int     v3   = splitMiddle ? DMesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, percent), Mathf.Lerp(body.y, body.yMax, 0.5f)) : -1;

            if (i != 0)
            {
                if (!splitMiddle)
                {
                    DMesh.AddFace(v2, p2, p1, v1);
                }
                else
                {
                    DMesh.AddFace(v2, p2, p3, v3);
                    DMesh.AddFace(v3, p3, p1, v1);
                }
            }

            p1 = v1;
            p2 = v2;
            p3 = v3;
        }
    }
    private void DoHandles(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>();
        if (terrain) terrain.MatchOverrides();
        Quaternion inv = Quaternion.Inverse(path.transform.rotation);

        Handles.color = new Color(1, 1, 1, 0);
        for (int i = 0; i < path.pathVerts.Count; i++)
        {
            Vector3 pos        = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[i].x, path.pathVerts[i].y, 0), path.transform.localScale);
            Vector3 posOff     = pos + offset;
            bool    isSelected = selectedPoints.Contains(i);

            // check if we want to remove points
            if (Event.current.alt)
            {
                float handleScale = HandleScale(posOff);
                if (IsVisible(posOff)) {
                    SetScale(posOff, texMinus, ref iconStyle);
                    Handles.Label(posOff, new GUIContent((isSelected || selectedPoints.Count <= 0) ? texMinusSelected : texMinus), iconStyle);
                }

                if (Handles.Button(posOff, SceneView.lastActiveSceneView.camera.transform.rotation, handleScale, handleScale, Handles.CircleCap))
                {
                    if (!isSelected) {
                        selectedPoints.Clear();
                        selectedPoints.Add(i);
                    }
                    for (int s = 0; s < selectedPoints.Count; s++) {
                        if (terrain) terrain.RemovePoint(selectedPoints[s]);
                        else  path.pathVerts.RemoveAt   (selectedPoints[s]);
                        if (selectedPoints[s] <= i) i--;

                        for (int u = 0; u < selectedPoints.Count; u++) {
                            if (selectedPoints[u] > selectedPoints[s]) selectedPoints[u] -= 1;
                        }
                    }
                    selectedPoints.Clear();
                    GUI.changed = true;
                } else if (Ferr2DT_SceneOverlay.editMode != Ferr2DT_EditMode.None) {

                    if (terrain && i+1 < path.pathVerts.Count) {
                        float   scale     = handleScale * 0.5f;
                        Vector3 dirOff    = GetTickerOffset(path, pos, i);
                        Vector3 posDirOff = posOff + dirOff;

                        if (IsVisible(posDirOff)) {
                            Texture2D icon = null;
                            if      (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override) icon = GetDirIcon(terrain.directionOverrides[i]);
                            else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale   ) icon = texScale;
                            if      (Event.current.alt)                                          icon = texReset;

                            SetScale(posDirOff, icon, ref iconStyle, 0.5f);
                            Handles.Label(posDirOff, new GUIContent(icon), iconStyle);

                            if (Handles.Button(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, scale, Handles.CircleCap)) {
                                if (selectedPoints.Count < 2 || isSelected == false) {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                for (int s = 0; s < selectedPoints.Count; s++) {
                                    if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override)
                                        terrain.directionOverrides[selectedPoints[s]] = Ferr2DT_TerrainDirection.None;
                                    else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale)
                                        terrain.vertScales        [selectedPoints[s]] = 1;
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                }
            } else {
                // check for moving the point
                Texture2D tex = null;
                if (Event.current.control) tex = isSelected ? texDotSelectedSnap : texDotSnap;
                else                       tex = isSelected ? texDotSelected     : texDot;

                if (IsVisible(posOff)) {
                    SetScale(posOff, texMinus, ref iconStyle);
                    Handles.Label(posOff, new GUIContent(tex), iconStyle);
                }
                Vector3 snap   = Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapRelative ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero;
                Vector3 result = Handles.FreeMoveHandle(
                    posOff,
                    SceneView.lastActiveSceneView.camera.transform.rotation,
                    HandleScale(pos+offset),
                    snap,
                    Handles.CircleCap);

                if (result != posOff) {

                    if (selectedPoints.Count < 2 || isSelected == false) {
                        selectedPoints.Clear();
                        selectedPoints.Add(i);
                        isSelected = true;
                    }

                    if (!(Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapRelative))
                        result = GetRealPoint(result, path.transform.position.z);
                    Vector3 global = (result - offset);
                    if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapGlobal) global = SnapVector(global);
                    Vector3 local  = inv * (global - path.transform.position);
                    if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapLocal ) local  = SnapVector(local);
                    if (!Event.current.control && Ferr2DT_SceneOverlay.smartSnap) {
                        local = SmartSnap(local, path.pathVerts, selectedPoints, Ferr_Menu.SmartSnapDist);
                    }

                    Vector2 relative = new Vector2(
                        local.x / path.transform.localScale.x,
                        local.y / path.transform.localScale.y) - path.pathVerts[i];

                    for (int s = 0; s < selectedPoints.Count; s++) {
                        path.pathVerts[selectedPoints[s]] += relative;
                    }
                }

                // if using terrain, check to see for any edge overrides
                if (Ferr2DT_SceneOverlay.showIndices) {
                    Vector3 labelPos = posOff + (Vector3)Ferr2D_Path.GetNormal(path.pathVerts, i, path.closed);
                    Handles.color    = Color.white;
                    Handles.Label(labelPos, "" + i);
                    Handles.color    = new Color(1, 1, 1, 0);
                }

                if (terrain) {// && i+1 < path.pathVerts.Count) {
                    float   scale     = HandleScale    (pos+offset) * 0.5f;
                    Vector3 dirOff    = GetTickerOffset(path, pos, i);
                    Vector3 posDirOff = posOff + dirOff;

                    if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Override && i+1 < path.pathVerts.Count) {
                        if (IsVisible(posDirOff)) {
                            SetScale(posDirOff, texMinus, ref iconStyle, 0.5f);
                            Handles.Label(posDirOff, new GUIContent(Event.current.alt ? texReset : GetDirIcon(terrain.directionOverrides[i])), iconStyle);

                            if (Handles.Button(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, scale, Handles.CircleCap)) {
                                if (selectedPoints.Count < 2 || isSelected == false) {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                Ferr2DT_TerrainDirection dir = NextDir(terrain.directionOverrides[i]);
                                for (int s = 0; s < selectedPoints.Count; s++) {
                                    terrain.directionOverrides[selectedPoints[s]] = dir;
                                }
                                GUI.changed = true;
                            }
                        }

                    } else if (Ferr2DT_SceneOverlay.editMode == Ferr2DT_EditMode.Scale) {
                        if (IsVisible(posDirOff)) {
                            SetScale(posDirOff, texMinus, ref iconStyle, 0.5f);
                            Handles.Label(posDirOff, new GUIContent(Event.current.alt ? texReset : texScale), iconStyle);

                            Vector3 scaleMove = Handles.FreeMoveHandle(posDirOff, SceneView.lastActiveSceneView.camera.transform.rotation, scale, Vector3.zero, Handles.CircleCap);
                            float   scaleAmt  = scaleMove.y - posDirOff.y;
                            if (Mathf.Abs(scaleAmt) > 0.01f ) {
                                if (selectedPoints.Count < 2 || isSelected == false) {
                                    selectedPoints.Clear();
                                    selectedPoints.Add(i);
                                    isSelected = true;
                                }

                                float vertScale = terrain.vertScales[i] - Event.current.delta.y / 100f;
                                vertScale = Mathf.Clamp(vertScale, 0.2f, 3f);
                                for (int s = 0; s < selectedPoints.Count; s++) {
                                    terrain.vertScales[selectedPoints[s]] = vertScale;
                                }
                                GUI.changed = true;
                            }
                        }
                    }
                }

                // make sure we can add new point at the midpoints!
                if (i + 1 < path.pathVerts.Count || path.closed == true) {
                    int     index       = path.closed && i + 1 == path.pathVerts.Count ? 0 : i + 1;
                    Vector3 pos2        = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[index].x, path.pathVerts[index].y, 0), path.transform.localScale);
                    Vector3 mid         = (pos + pos2) / 2;
                    float   handleScale = HandleScale(mid + offset);

                    if (Handles.Button(mid + offset, SceneView.lastActiveSceneView.camera.transform.rotation, handleScale, handleScale, Handles.CircleCap)) {
                        Vector2 pt = inv * new Vector2((mid.x - path.transform.position.x) / path.transform.localScale.x, (mid.y - path.transform.position.y) / path.transform.localScale.y);
                        if (terrain)
                            terrain.AddPoint(pt, index);
                        else
                            path.pathVerts.Insert(index, pt);
                    }
                    if (IsVisible(mid + offset)) {
                        SetScale(mid + offset, texDotPlus, ref iconStyle);
                        Handles.Label(mid + offset, new GUIContent(texDotPlus), iconStyle);
                    }
                }
            }
        }

        if (Event.current.type == EventType.keyDown && Event.current.keyCode == KeyCode.Delete && selectedPoints.Count > 0) {
            for (int s = 0; s < selectedPoints.Count; s++) {
                if (terrain) terrain.RemovePoint(selectedPoints[s]);
                else  path.pathVerts.RemoveAt   (selectedPoints[s]);

                for (int u = 0; u < selectedPoints.Count; u++) {
                    if (selectedPoints[u] > selectedPoints[s]) selectedPoints[u] -= 1;
                }
            }
            selectedPoints.Clear();
            GUI.changed = true;
            Event.current.Use();
        }
    }
    private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle)
    {
#if FERR2D_TERRAIN
        Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent<Ferr2DT_PathTerrain>();
#endif

        Vector2 pos = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y);

        int closestID = path.GetClosestSeg(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
        int secondID  = closestID + 1 >= path.Count ? 0 : closestID + 1;

        float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
        float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);

        Handles.color = Color.white;
        if (!(secondID == 0 && !path.closed && firstDist > secondDist))
        {
            Handles.DrawLine(
                path.transform.position + new Vector3(pos.x, pos.y, 0),
                path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale));
        }
        if (!(secondID == 0 && !path.closed && firstDist < secondDist))
        {
            Handles.DrawLine(
                path.transform.position + new Vector3(pos.x, pos.y, 0),
                path.transform.position + Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale));
        }
        Handles.color = new Color(1, 1, 1, 0);

        Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset;
        if (Handles.Button(handlePos, Quaternion.identity, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap))
        {
            if (secondID == 0)
            {
                if (firstDist < secondDist)
                {
                    path.pathVerts.Add(new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
#if FERR2D_TERRAIN
                    if (terrain)
                        terrain.directionOverrides.Add(Ferr2DT_TerrainDirection.None);
#endif
                }
                else
                {
                    path.pathVerts.Insert(0, new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
#if FERR2D_TERRAIN
                    if (terrain)
                        terrain.directionOverrides.Insert(0, Ferr2DT_TerrainDirection.None);
#endif
                }
            }
            else
            {
                path.pathVerts.Insert(Mathf.Max(closestID, secondID), new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
#if FERR2D_TERRAIN
                if (terrain)
                    terrain.directionOverrides.Insert(Mathf.Max(closestID, secondID), Ferr2DT_TerrainDirection.None);
#endif
            }
            GUI.changed = true;
        }
        if (SetScale(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, texDotPlus, ref iconStyle)) Handles.Label(new Vector3(pos.x, pos.y, 0) + path.transform.position + offset, new GUIContent(texDotPlus), iconStyle);
    }
    private void AddEdge()
    {
        // split the path into segments based on the split angle
        List <List <int>               > segments = new List <List <int>               >();
        List <Ferr2DT_TerrainDirection>  dirs     = new List <Ferr2DT_TerrainDirection>();
        List <int> order = new List <int>();

        segments = GetSegments(Path.GetVertsRaw(), out dirs);
        if (dirs.Count < segments.Count)
        {
            dirs.Add(directionOverrides[directionOverrides.Count - 1]);
        }
        for (int i = 0; i < segments.Count; i++)
        {
            order.Add(i);
        }

        order.Sort(
            new Ferr.LambdaComparer <int>(
                (x, y) => {
            Ferr2DT_TerrainDirection dirx = dirs[x] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[x], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[x];
            Ferr2DT_TerrainDirection diry = dirs[y] == Ferr2DT_TerrainDirection.None ? Ferr2D_Path.GetDirection(Path.pathVerts, segments[y], 0, fill == Ferr2DT_FillMode.InvertedClosed) : dirs[y];
            return(terrainMaterial.GetDescriptor(diry).zOffset.CompareTo(terrainMaterial.GetDescriptor(dirx).zOffset));
        }
                ));

        // process the segments into meshes
        for (int i = 0; i < order.Count; i++)
        {
            List <int> currSeg = segments[order[i]];
            List <int> prevSeg = order[i] - 1 < 0 ?  segments[segments.Count - 1] : segments[order[i] - 1];
            List <int> nextSeg = segments[(order[i] + 1) % segments.Count];

            int curr = currSeg[0];
            int prev = prevSeg[prevSeg.Count - 2];
            int next = currSeg[1];

            Vector2 p1        = Path.pathVerts[prev] - Path.pathVerts[curr];
            Vector2 p2        = Path.pathVerts[next] - Path.pathVerts[curr];
            bool    leftInner = Mathf.Atan2(p1.x * p2.y - p1.y * p2.x, Vector2.Dot(p1, p2)) < 0;

            curr = currSeg[currSeg.Count - 1];
            prev = currSeg[currSeg.Count - 2];
            next = nextSeg[1];

            p1 = Path.pathVerts[prev] - Path.pathVerts[curr];
            p2 = Path.pathVerts[next] - Path.pathVerts[curr];
            bool rightInner = Mathf.Atan2(p1.x * p2.y - p1.y * p2.x, Vector2.Dot(p1, p2)) < 0;

            AddSegment(Ferr2D_Path.IndicesToPath(Path.pathVerts, segments[order[i]]), leftInner, rightInner, GetScalesFromIndices(segments[order[i]]), order.Count <= 1 && Path.closed, smoothPath, dirs[order[i]]);
        }
    }
 private void DoPath(Ferr2D_Path path)
 {
     Handles.color = Color.white;
     List<Vector2> verts = path.GetVertsRaw();
     for (int i = 0; i < verts.Count - 1; i++)
     {
         Vector3 pos  = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i    ].x, verts[i    ].y, 0), path.transform.localScale);
         Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[i + 1].x, verts[i + 1].y, 0), path.transform.localScale);
         Handles.DrawLine(pos + offset, pos2 + offset);
     }
     if (path.closed)
     {
         Vector3 pos  = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[0              ].x, verts[0              ].y, 0), path.transform.localScale);
         Vector3 pos2 = path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(verts[verts.Count - 1].x, verts[verts.Count - 1].y, 0), path.transform.localScale);
         Handles.DrawLine(pos + offset, pos2 + offset);
     }
 }
    private void AddCap(List <Vector2> aSegment, Ferr2DT_SegmentDescription aDesc, bool aInner, float aDir, float aScale, bool aSmooth)
    {
        int     index = 0;
        Vector2 dir   = Vector2.zero;

        if (aDir < 0)
        {
            index = 0;
            dir   = aSegment[0] - aSegment[1];
        }
        else
        {
            index = aSegment.Count - 1;
            dir   = aSegment[aSegment.Count - 1] - aSegment[aSegment.Count - 2];
        }
        dir.Normalize();
        Vector2 norm = aSmooth ? Ferr2D_Path.HermiteGetNormal(aSegment, index, 0, false): Ferr2D_Path.GetNormal(aSegment, index, false);
        Vector2 pos  = aSegment[index];
        float   yOff = fill == Ferr2DT_FillMode.InvertedClosed ? -aDesc.yOffset : aDesc.yOffset;
        Rect    cap;

        if (aDir < 0)
        {
            if (fill == Ferr2DT_FillMode.InvertedClosed)
            {
                cap = (!aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap);
            }
            else
            {
                cap = (aInner && aDesc.innerLeftCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap) : terrainMaterial.ToUV(aDesc.leftCap);
            }
        }
        else
        {
            if (fill == Ferr2DT_FillMode.InvertedClosed)
            {
                cap = (!aInner && aDesc.innerLeftCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerLeftCap) : terrainMaterial.ToUV(aDesc.leftCap);
            }
            else
            {
                cap = (aInner && aDesc.innerRightCap.width > 0) ? terrainMaterial.ToUV(aDesc.innerRightCap) : terrainMaterial.ToUV(aDesc.rightCap);
            }
        }

        float width = cap.width * unitsPerUV.x;
        float scale = (cap.height / 2) * unitsPerUV.y * aScale;

        float minU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.xMax : cap.x;
        float maxU = fill == Ferr2DT_FillMode.InvertedClosed ? cap.x    : cap.xMax;
        float minV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.yMax : cap.y;
        float maxV = fill == Ferr2DT_FillMode.InvertedClosed ? cap.y    : cap.yMax;

        if (aDir >= 0)
        {
            float t = minU;
            minU = maxU;
            maxU = t;
        }

        int v1 = DMesh.AddVertex(pos + dir * width + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(minU, minV));
        int v2 = DMesh.AddVertex(pos + norm * (scale + yOff), -slantAmount + aDesc.zOffset, new Vector2(maxU, minV));

        int v15 = splitMiddle ? DMesh.AddVertex(pos + dir * width + (norm * yOff), aDesc.zOffset, new Vector2(minU, cap.y + (cap.height / 2))) : -1;
        int v25 = splitMiddle ? DMesh.AddVertex(pos + (norm * yOff), aDesc.zOffset, new Vector2(maxU, cap.y + (cap.height / 2))) : -1;

        int v3 = DMesh.AddVertex(pos - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(maxU, maxV));
        int v4 = DMesh.AddVertex(pos + dir * width - norm * (scale - yOff), slantAmount + aDesc.zOffset, new Vector2(minU, maxV));

        if (splitMiddle && aDir < 0)
        {
            DMesh.AddFace(v1, v2, v25, v15);
            DMesh.AddFace(v15, v25, v3, v4);
        }
        else if (splitMiddle && aDir >= 0)
        {
            DMesh.AddFace(v2, v1, v15, v25);
            DMesh.AddFace(v25, v15, v4, v3);
        }
        else if (aDir < 0)
        {
            DMesh.AddFace(v1, v2, v3, v4);
        }
        else
        {
            DMesh.AddFace(v2, v1, v4, v3);
        }
    }
    private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Ferr2DT_PathTerrain terrain  = path.gameObject.GetComponent<Ferr2DT_PathTerrain>();
        Quaternion          inv      = Quaternion.Inverse(path.transform.rotation);
        Vector2             pos      = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y);
        bool                hasDummy = path.pathVerts.Count <= 0;

        if (hasDummy) path.pathVerts.Add(Vector2.zero);

        int   closestID  = path.GetClosestSeg(inv * new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
        int   secondID   = closestID + 1 >= path.Count ? 0 : closestID + 1;

        float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
        float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);

        Vector3 local  = pos;
        if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapLocal ) local  = SnapVector(local );
        Vector3 global = path.transform.position + local;
        if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapGlobal) global = SnapVector(global);

        Handles.color = Color.white;
        if (!(secondID == 0 && !path.closed && firstDist > secondDist))
        {
            Handles.DrawLine(
                global,
                path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale));
        }
        if (!(secondID == 0 && !path.closed && firstDist < secondDist))
        {
            Handles.DrawLine(
                global,
                path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale));
        }
        Handles.color = new Color(1, 1, 1, 0);

        Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset;
        if (IsVisible(handlePos)) {
            if (Handles.Button(handlePos, SceneView.lastActiveSceneView.camera.transform.rotation, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap))
            {
                Vector3    finalPos = inv * (new Vector3(global.x / path.transform.localScale.x, global.y / path.transform.localScale.y, 0) - path.transform.position);
                if (secondID == 0) {
                    if (firstDist < secondDist) {
                        if (terrain)
                            terrain.AddPoint(finalPos);
                        else
                            path.pathVerts.Add(finalPos);
                    } else {
                        if (terrain)
                            terrain.AddPoint(finalPos, 0);
                        else
                            path.pathVerts.Insert(0, finalPos);
                    }
                } else {
                    if (terrain)
                        terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID));
                    else
                        path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos);
                }
                selectedPoints.Clear();
                GUI.changed = true;
            }

            SetScale(handlePos, texDotPlus, ref iconStyle);
            Handles.Label(handlePos, new GUIContent(texDotPlus), iconStyle);
        }

        if (hasDummy) path.pathVerts.RemoveAt(0);
    }
Exemple #30
0
    private void DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Ferr2DT_PathTerrain terrain = path.gameObject.GetComponent <Ferr2DT_PathTerrain>();
        Quaternion          inv     = Quaternion.Inverse(path.transform.rotation);
        Vector2             pos     = GetMousePos(Event.current.mousePosition, path.transform.position.z) - new Vector2(path.transform.position.x, path.transform.position.y);
        bool hasDummy = path.pathVerts.Count <= 0;

        if (hasDummy)
        {
            path.pathVerts.Add(Vector2.zero);
        }

        int closestID = path.GetClosestSeg(inv * new Vector2(pos.x / path.transform.localScale.x, pos.y / path.transform.localScale.y));
        int secondID  = closestID + 1 >= path.Count ? 0 : closestID + 1;

        float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
        float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);

        Vector3 local = pos;

        if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapLocal)
        {
            local = SnapVector(local);
        }
        Vector3 global = path.transform.position + local;

        if (Event.current.control && Ferr_Menu.SnapMode == Ferr2DT_SnapMode.SnapGlobal)
        {
            global = SnapVector(global);
        }

        Handles.color = Color.white;
        if (!(secondID == 0 && !path.closed && firstDist > secondDist))
        {
            Handles.DrawLine(
                global,
                path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[closestID].x, path.pathVerts[closestID].y, 0), path.transform.localScale));
        }
        if (!(secondID == 0 && !path.closed && firstDist < secondDist))
        {
            Handles.DrawLine(
                global,
                path.transform.position + path.transform.rotation * Vector3.Scale(new Vector3(path.pathVerts[secondID].x, path.pathVerts[secondID].y, 0), path.transform.localScale));
        }
        Handles.color = new Color(1, 1, 1, 0);

        Vector3 handlePos = new Vector3(pos.x, pos.y, 0) + path.transform.position + offset;

        if (IsVisible(handlePos))
        {
            if (Handles.Button(handlePos, SceneView.lastActiveSceneView.camera.transform.rotation, HandleScale(handlePos), HandleScale(handlePos), Handles.CircleCap))
            {
                Vector3 finalPos = inv * (new Vector3(global.x / path.transform.localScale.x, global.y / path.transform.localScale.y, 0) - path.transform.position);
                if (secondID == 0)
                {
                    if (firstDist < secondDist)
                    {
                        if (terrain)
                        {
                            terrain.AddPoint(finalPos);
                        }
                        else
                        {
                            path.pathVerts.Add(finalPos);
                        }
                    }
                    else
                    {
                        if (terrain)
                        {
                            terrain.AddPoint(finalPos, 0);
                        }
                        else
                        {
                            path.pathVerts.Insert(0, finalPos);
                        }
                    }
                }
                else
                {
                    if (terrain)
                    {
                        terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID));
                    }
                    else
                    {
                        path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos);
                    }
                }
                if (selectedPoints != null)
                {
                    selectedPoints.Clear();
                }
                GUI.changed = true;
            }

            SetScale(handlePos, texDotPlus, ref iconStyle);
            Handles.Label(handlePos, new GUIContent(texDotPlus), iconStyle);
        }

        if (hasDummy)
        {
            path.pathVerts.RemoveAt(0);
        }
    }
Exemple #31
0
    /// <summary>
    /// This method will close a list of split segments, merging and adding points to the end chunks.
    /// </summary>
    /// <param name="aSegmentList">List of split segments that make up the path.</param>
    /// <param name="aCorners">If there are corners or not.</param>
    /// <returns>A closed loop of segments.</returns>
    public static bool                     CloseEnds(List <Vector2> aPath, ref List <List <int> > aSegmentList, ref List <Ferr2DT_TerrainDirection> aSegmentDirections, bool aCorners, bool aInverted)
    {
        int     startID   = aSegmentList[0][0];
        Vector2 start     = aPath[startID];
        Vector2 startNext = aPath[aSegmentList[0][1]];

        int     endID   = aSegmentList[aSegmentList.Count - 1][aSegmentList[aSegmentList.Count - 1].Count - 1];
        Vector2 end     = aPath[endID];
        Vector2 endPrev = aPath[aSegmentList[aSegmentList.Count - 1][aSegmentList[aSegmentList.Count - 1].Count - 2]];

        if (aCorners == false)
        {
            aSegmentList[0].Add(startID);
            return(true);
        }

        bool endCorner   = Ferr2D_Path.GetDirection(endPrev, end) != Ferr2D_Path.GetDirection(end, start);
        bool startCorner = Ferr2D_Path.GetDirection(end, start) != Ferr2D_Path.GetDirection(start, startNext);

        if (endCorner && startCorner)
        {
            List <int> lastSeg = new List <int>();
            lastSeg.Add(endID);
            lastSeg.Add(startID);

            aSegmentList.Add(lastSeg);

            Ferr2DT_TerrainDirection dir = GetDirection(start, end);
            if (aInverted && dir == Ferr2DT_TerrainDirection.Top)
            {
                dir = Ferr2DT_TerrainDirection.Bottom;
            }
            if (aInverted && dir == Ferr2DT_TerrainDirection.Bottom)
            {
                dir = Ferr2DT_TerrainDirection.Top;
            }
            if (aInverted && dir == Ferr2DT_TerrainDirection.Right)
            {
                dir = Ferr2DT_TerrainDirection.Left;
            }
            if (aInverted && dir == Ferr2DT_TerrainDirection.Left)
            {
                dir = Ferr2DT_TerrainDirection.Right;
            }

            aSegmentDirections.Add(dir);
        }
        else if (endCorner && !startCorner)
        {
            aSegmentList[0].Insert(0, endID);
        }
        else if (!endCorner && startCorner)
        {
            aSegmentList[aSegmentList.Count - 1].Add(startID);
        }
        else
        {
            aSegmentList[0].InsertRange(0, aSegmentList[aSegmentList.Count - 1]);
            aSegmentList.RemoveAt(aSegmentList.Count - 1);
            aSegmentDirections.RemoveAt(aSegmentDirections.Count - 1);
        }
        return(true);
    }
    public override void OnInspectorGUI()
    {
        Ferr2D_Path path       = (Ferr2D_Path)target;
        bool        updateMesh = false;

        // if this was an undo, refresh stuff too
        if (Event.current.type == EventType.ValidateCommand)
        {
            switch (Event.current.commandName)
            {
            case "UndoRedoPerformed":

                path.UpdateDependants(true);
                if (OnChanged != null)
                {
                    OnChanged();
                }
                return;
            }
        }

        EditorGUILayout.PropertyField(closed);
        EditorGUI.BeginChangeCheck();
        EditorGUILayout.PropertyField(pathVerts, true);
        if (EditorGUI.EndChangeCheck() && PrefabUtility.GetCorrespondingObjectFromSource(target) != null)
        {
            NudgeArray(pathVerts);
        }

        // button for updating the origin of the object
        if (GUILayout.Button("Center Position"))
        {
            Undo.RecordObject(target, "Modified Path");
            path.ReCenter();
            updateMesh = true;
        }

        Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>();

        if (!path.closed && (terrain.fill == Ferr2DT_FillMode.Closed || terrain.fill == Ferr2DT_FillMode.InvertedClosed || terrain.fill == Ferr2DT_FillMode.FillOnlyClosed))
        {
            Undo.RecordObject(target, "Modified Path");
            path.closed = true;
            updateMesh  = true;
        }
        if (path.closed && (terrain.fill == Ferr2DT_FillMode.FillOnlySkirt || terrain.fill == Ferr2DT_FillMode.Skirt))
        {
            Undo.RecordObject(target, "Modified Path");
            path.closed = false;
            updateMesh  = true;
        }

        // update dependants when it changes
        if (updateMesh || serializedObject.ApplyModifiedProperties())
        {
            if (OnChanged != null)
            {
                OnChanged();
            }
            path.UpdateDependants(true);
            EditorUtility.SetDirty(target);
        }
    }
    private List <Vector2> LegacyOffsetColliderVerts(List <Vector2> aSegment, List <float> aSegmentScales, Ferr2DT_TerrainDirection aDir)
    {
        List <Vector2> result = new List <Vector2>(aSegment);
        int            count  = aSegment.Count;

        for (int v = count - 1; v >= 0; v--)
        {
            Vector2 norm      = smoothPath ? Ferr2D_Path.HermiteGetNormal(aSegment, v, 0, false) : Ferr2D_Path.GetNormal(aSegment, v, false);
            Vector2 segNormal = Ferr2D_Path.GetSegmentNormal(v, aSegment, false);
            float   scale     = v >= aSegmentScales.Count ? 1 : aSegmentScales[v];
            float   rootScale = smoothPath ? 1 : 1f / Mathf.Abs(Mathf.Cos(Vector2.Angle(-segNormal, norm) * Mathf.Deg2Rad));
            scale = scale * rootScale;

            if (fill == Ferr2DT_FillMode.None)
            {
                result.Add(aSegment[v] + new Vector2(norm.x * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top], norm.y * surfaceOffset[(int)Ferr2DT_TerrainDirection.Top]) * scale);
                result[v] += new Vector2(norm.x * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom], norm.y * -surfaceOffset[(int)Ferr2DT_TerrainDirection.Bottom]) * scale;
            }
            else
            {
                float   dist   = surfaceOffset[(int)aDir];
                Vector2 offset = new Vector2(dist, dist);
                result[v] += new Vector2(norm.x * -offset.x, norm.y * -offset.y) * scale;
            }
        }
        return(result);
    }
    private void DoCutOverrideModeHandles(Ferr2D_Path path, Ferr2DT_PathTerrain terrain, Matrix4x4 mat, Transform camTransform)
    {
        List <List <int>               > segments = new List <List <int>               >();
        List <Ferr2DT_TerrainDirection>  dirs     = new List <Ferr2DT_TerrainDirection>();
        List <Vector2> rawVerts = path.GetVertsRaw();

        // cut the terrain into segments, we need segment info to draw these points
        segments = terrain.GetSegments(rawVerts, out dirs);

        for (int s = 0; s < segments.Count; s++)
        {
            List <int>     currSeg   = segments[s];
            List <Vector2> currVerts = Ferr2D_Path.IndicesToList(rawVerts, currSeg);
            List <Ferr2DT_PathTerrain.CutOverrides> overrides = Ferr2D_Path.IndicesToList(terrain.cutOverrides, currSeg);

            // find information about this segment
            Ferr2DT_TerrainDirection   currDir = dirs[s];
            Ferr2DT_SegmentDescription desc    = default(Ferr2DT_SegmentDescription);

            if (currDir != Ferr2DT_TerrainDirection.None)
            {
                desc = terrain.TerrainMaterial.GetDescriptor(currDir);
            }
            else
            {
                desc = terrain.GetDescription(currSeg);
            }

            // if there's no body segment choices, don't bother with the rest of this
            if (desc.body.Length < 2)
            {
                continue;
            }

            Vector2 capLeftSlideDir  = (currVerts[1] - currVerts[0]);
            Vector2 capRightSlideDir = (currVerts[currVerts.Count - 2] - currVerts[currVerts.Count - 1]);
            capLeftSlideDir.Normalize();
            capRightSlideDir.Normalize();
            currVerts[0] -= capLeftSlideDir * desc.capOffset;
            currVerts[currVerts.Count - 1] -= capRightSlideDir * desc.capOffset;

            float distance = Ferr2D_Path.GetSegmentLength(currVerts);

            // how many texture cuts are there on the segment
            float bodyWidth   = desc.body[0].width * (terrain.TerrainMaterial.edgeMaterial.mainTexture.width / terrain.pixelsPerUnit);
            int   textureCuts = Mathf.Max(1, Mathf.FloorToInt(distance / bodyWidth + 0.5f));

            // data is attached to the points still, check if we've switched to a new point
            int activePt       = -1;
            int activeLocalCut = -1;
            for (int c = 0; c < textureCuts; c++)
            {
                float pctGlobal = c / (float)textureCuts;

                int   ptLocal  = 0;
                float pctLocal = 0;
                Ferr2D_Path.PathGlobalPercentToLocal(currVerts, pctGlobal, out ptLocal, out pctLocal, distance, false);

                if (ptLocal != activePt)
                {
                    // if they size down, we need to shorten the data too
                    if (activePt != -1)
                    {
                        CapListSize <int>(ref overrides[activePt].data, activeLocalCut + 3);
                    }
                    activePt       = ptLocal;
                    activeLocalCut = 0;

                    if (overrides[activePt].data == null)
                    {
                        overrides[activePt].data = new List <int>();
                    }
                }

                while (activeLocalCut >= overrides[activePt].data.Count)
                {
                    overrides[activePt].data.Add(0);
                }

                CapFunction cap            = CapDotAuto;
                int         activeOverride = overrides[activePt].data[activeLocalCut];
                if (activeOverride != 0)
                {
                    if (activeOverride == 1)
                    {
                        cap = CapDot1;
                    }
                    else if (activeOverride == 2)
                    {
                        cap = CapDot2;
                    }
                    else if (activeOverride == 3)
                    {
                        cap = CapDot3;
                    }
                    else if (activeOverride == 4)
                    {
                        cap = CapDot4;
                    }
                    else if (activeOverride == 5)
                    {
                        cap = CapDot5;
                    }
                    else if (activeOverride >= 6)
                    {
                        cap = CapDotN;
                    }
                }
                if (Event.current.alt)
                {
                    cap = CapDotReset;
                }

                int   ptShow  = 0;
                float pctShow = 0;
                Ferr2D_Path.PathGlobalPercentToLocal(currVerts, pctGlobal + (1f / textureCuts) * 0.5f, out ptShow, out pctShow, distance, false);

                Vector2 pt  = Ferr2D_Path.LinearGetPt(currVerts, ptShow, pctShow, false);
                Vector3 pos = mat.MultiplyPoint3x4(pt);
                float   sc  = HandleScale(pos) * Ferr2D_Visual.SmallHandleSize;
                if (Handles.Button(pos, camTransform.rotation, sc, sc, cap))
                {
                    Undo.RecordObject(terrain, "Lock Texture Segment");

                    overrides[activePt].data[activeLocalCut] = Event.current.alt ? 0 : (activeOverride + 1) % (desc.body.Length + 1);
                    EditorUtility.SetDirty(terrain);
                    GUI.changed = true;
                }

                activeLocalCut += 1;
            }
            if (activePt != -1)
            {
                CapListSize <int>(ref overrides[activePt].data, activeLocalCut + 3);
            }
        }
    }
    public Ferr2DT_SegmentDescription  GetDescription(List <int> aSegment)
    {
        Ferr2DT_TerrainDirection dir = Ferr2D_Path.GetDirection(Path.pathVerts, aSegment, 0, fill == Ferr2DT_FillMode.InvertedClosed);

        return(TerrainMaterial.GetDescriptor(dir));
    }
Exemple #36
0
    void OnTriggerExit2D(Collider2D collider)
    {
        if (collider.tag == "terrain")
        {
            if (terrainsTransform.Contains(collider.transform.position))
            {
                return;
            }
            //for (int i = 0; i < terrainsTransform.Count; i++) {
            //
            //	if (collider.transform == terrainsTransform[i]) Debug.Log(123);
            //}
            terrainsTransform.Add(collider.transform.position);
            exitPoint = transform.position;
            Vector2 diff        = exitPoint - enterPoint;
            float   pointBDiffC = Mathf.Sqrt(diff.x * diff.x + diff.y * diff.y);
            float   diffX       = 15 / pointBDiffC * diff.x;
            float   diffY       = 15 / pointBDiffC * diff.y;

            exitPoint = new Vector2(diffX, diffY) + enterPoint;
            //Debug.Log ("exit: " + collider.name + exitPoint);

            Ferr2D_Path    terrain = collider.GetComponent <Ferr2D_Path>();
            List <Vector2> pos = new List <Vector2>();
            List <int>     point = new List <int>();
            Vector2        firstPoint = new Vector2(0, 0);
            Vector2        secondPoint = new Vector2(0, 0);
            int            firstPointA = -1, secondPointA = -1;
            Vector2        posTemp, posA, posB;
            int            terrainCount = terrain.Count;
            for (int i = 0; i < terrainCount; i++)
            {
                if (i == terrainCount - 1)
                {
                    posA    = terrain.pathVerts[0] + new Vector2(collider.transform.position.x, collider.transform.position.y);
                    posB    = terrain.pathVerts[i] + new Vector2(collider.transform.position.x, collider.transform.position.y);
                    posTemp = lineIntersectPos(enterPoint, exitPoint, posA, posB);
                }
                else
                {
                    posA    = terrain.pathVerts[i + 1] + new Vector2(collider.transform.position.x, collider.transform.position.y);
                    posB    = terrain.pathVerts[i] + new Vector2(collider.transform.position.x, collider.transform.position.y);
                    posTemp = lineIntersectPos(enterPoint, exitPoint, posA, posB);
                }
                if (posTemp.x != 10000)
                {
                    if (Mathf.Abs(posTemp.x - posA.x) <= 0.02F && Mathf.Abs(posTemp.y - posA.y) <= 0.02F)
                    {
                        posTemp = posA;
                    }
                    if (Mathf.Abs(posTemp.x - posB.x) <= 0.02F && Mathf.Abs(posTemp.y - posB.y) <= 0.02F)
                    {
                        posTemp = posB;
                    }
                    //Debug.Log("enterPoint: " + enterPoint);
                    //Debug.Log("exitPoint: " + exitPoint);
                    //Debug.Log("posA: " + posA);
                    //Debug.Log("posB: " + posB);
                    //Debug.Log("pos: " + posTemp);

                    pos.Add(posTemp);
                    point.Add(i);
                }

                //Debug.Log("pos.x: " + pos.x);
            }

            //sorting
            float          minLength = 100;
            List <Vector2> posSort   = new List <Vector2>();
            List <int>     pointSort = new List <int>();
            int            j         = -1;
            for (int i = 0; i < pos.Count; i++)
            {
                for (int y = 0; y < pos.Count; y++)
                {
                    if ((pos[y] - enterPoint).magnitude < minLength)
                    {
                        minLength = (pos[y] - enterPoint).magnitude;
                        j         = y;
                    }
                }
                minLength = 100;
                posSort.Add(pos[j]);
                pos[j] = new Vector2(100, 100);
                pointSort.Add(point[j]);
            }

            for (int y = 0; y < posSort.Count - 1; y += 2)
            {
                terrain = collider.GetComponent <Ferr2D_Path>();
                int g = 0;
                if (y > 0)
                {
                    //Debug.Log("terrain.pathVerts[1]: " + terrain.pathVerts[1]);
                    //Debug.Log("posSort[y - 1]: " + posSort[y - 1]);
                    if (terrain.pathVerts[1] == posSort[y - 1] - new Vector2(collider.transform.position.x, collider.transform.position.y))
                    {
                        g = y - 1;
                    }
                    else
                    {
                        g = y - 2;
                    }
                    for (int q = y; q < posSort.Count; q++)
                    {
                        //Debug.Log ("pointSort[q]: " + pointSort[q]);
                        //Debug.Log ("pointSort[g]: " + pointSort[g]);
                        //Debug.Log ("g: " + g);
                        pointSort[q] = pointSort[q] - pointSort[g] + 1;
                        if (pointSort[q] < 0)
                        {
                            pointSort[q] += terrainCount;
                        }
                    }
                }
                firstPointA  = pointSort[y];
                secondPointA = pointSort[y + 1];
                firstPoint   = posSort[y] - new Vector2(collider.transform.position.x, collider.transform.position.y);
                secondPoint  = posSort[y + 1] - new Vector2(collider.transform.position.x, collider.transform.position.y);

                //Debug.Log ("fp: " + firstPoint);
                //Debug.Log ("sp: " + secondPoint);
                bool           flag         = true;
                int            i            = -1;
                List <Vector2> firstFigure  = new List <Vector2>();
                List <Vector2> secondFigure = new List <Vector2>();
                terrainCount = terrain.Count;
                //Debug.Log("pathVerts: ");
                //for (int e = 0; e < terrainCount; e++) Debug.Log(terrain.pathVerts[e]);

                while (flag)
                {
                    if (i == -1)
                    {
                        //i = firstPointA;
                        //Debug.Log (firstPointA);
                        firstFigure.Add(firstPoint);
                        //terrain.pathVerts.Add(firstPoint);
                        //Debug.Log (secondPointA);
                        firstFigure.Add(secondPoint);
                        i = secondPointA + 1;
                    }
                    if (i >= terrainCount)
                    {
                        i = 0;
                    }
                    if (i == firstPointA)
                    {
                        flag = false;
                    }
                    //Debug.Log (i);
                    if (terrain.pathVerts[i] != firstPoint && terrain.pathVerts[i] != secondPoint)
                    {
                        firstFigure.Add(terrain.pathVerts[i]);
                    }
                    i++;
                }
                flag = true;
                i    = -1;
                while (flag)
                {
                    if (i == -1)
                    {
                        secondFigure.Add(secondPoint);
                        secondFigure.Add(firstPoint);
                        i = firstPointA + 1;
                    }
                    if (i >= terrainCount)
                    {
                        i = 0;
                    }
                    if (i == secondPointA)
                    {
                        flag = false;
                    }
                    //Debug.Log(i);
                    if (terrain.pathVerts[i] != firstPoint && terrain.pathVerts[i] != secondPoint)
                    {
                        secondFigure.Add(terrain.pathVerts[i]);
                    }
                    i++;
                }
                terrain.pathVerts.Clear();

                if (getSq(firstFigure) >= getSq(secondFigure))
                {
                    terrain.pathVerts.AddRange(firstFigure);
                }
                else
                {
                    terrain.pathVerts.AddRange(secondFigure);
                }

                //Debug.Log (terrain.pathVerts[0]);
                //terrain.UpdateDependants();
                Ferr2DT_PathTerrain pathTerrain = collider.GetComponent <Ferr2DT_PathTerrain>();
                pathTerrain.RecreatePath();
                pathTerrain.RecreateCollider();
            }
            for (int i = 0; i < gGrootClass.terrainGrootChains.Count; i++)
            {
                gGrootClass.terrainGrootChain terr = gGrootClass.terrainGrootChains[i];
                if (terr.terrain == collider.gameObject)
                {
                    if (!terr.terrain.GetComponent <Collider2D>().OverlapPoint(terr.chain.transform.position))
                    {
                        terr.chain.transform.parent.SendMessage("OnMouseDown");
                        gGrootClass.terrainGrootChains.Remove(terr);
                        i--;
                    }
                }
            }
        }
    }
    public void LegacyUpgrade()
    {
        if (!IsLegacy)
        {
            return;
        }

                #if UNITY_EDITOR
        UnityEditor.Undo.RecordObject(gameObject, "Upgrade Ferr2D Terrain");
                #endif

        Ferr2D_Path oldPath = GetComponent <Ferr2D_Path>();
        MatchOverrides();

        // upgrade the path
        pathData        = new Ferr2DPath();
        pathData.Closed = oldPath.closed;
        for (int i = 0; i < oldPath.pathVerts.Count; i++)
        {
            int            next      = Ferr.PathUtil.WrapIndex(i - 1, Path.Count, Path.closed);
            Ferr.PointType pointType = Ferr.PointType.Sharp;
            if (smoothPath)
            {
                Ferr2DT_TerrainDirection prevSegmentDirection = Ferr2D_Path.GetDirection(Path.pathVerts, next, fill == Ferr2DT_FillMode.InvertedClosed, Path.closed, directionOverrides);
                Ferr2DT_TerrainDirection nextSegmentDirection = Ferr2D_Path.GetDirection(Path.pathVerts, i, fill == Ferr2DT_FillMode.InvertedClosed, Path.closed, directionOverrides);
                if (prevSegmentDirection == nextSegmentDirection)
                {
                    pointType = Ferr.PointType.Auto;
                }
            }

            Ferr2D_PointData data = new Ferr2D_PointData();
            data.scale             = vertScales[next];
            data.directionOverride = (int)directionOverrides[next];
            data.cutOverrides      = cutOverrides[next].data;
            pathData.Add(oldPath.pathVerts[i], data, pointType);
        }
        pathData.ReverseSelf();
        pathData.SetDirty();

        // remove old path values
        directionOverrides = null;
        cutOverrides       = null;
        vertScales         = null;

        // upgrade collider settings
        if (createCollider)
        {
            if (useEdgeCollider)
            {
                colliderMode = Ferr2D_ColliderMode.Edge2D;
            }
            else if (create3DCollider)
            {
                colliderMode = Ferr2D_ColliderMode.Mesh3D;
            }
            else
            {
                colliderMode = Ferr2D_ColliderMode.Polygon2D;
            }
        }
        else
        {
            colliderMode = Ferr2D_ColliderMode.None;
        }

        // upgrade the fill settings
        switch (fill)
        {
        case Ferr2DT_FillMode.None:
            edgeMode = Ferr2D_SectionMode.Normal;
            fillMode = Ferr2D_SectionMode.None; break;

        case Ferr2DT_FillMode.Closed:
            edgeMode = Ferr2D_SectionMode.Normal;
            fillMode = Ferr2D_SectionMode.Normal; break;

        case Ferr2DT_FillMode.InvertedClosed:
            edgeMode = Ferr2D_SectionMode.Invert;
            fillMode = Ferr2D_SectionMode.Invert; break;

        case Ferr2DT_FillMode.FillOnlyClosed:
            edgeMode = Ferr2D_SectionMode.None;
            fillMode = Ferr2D_SectionMode.Normal; break;

        case Ferr2DT_FillMode.Skirt:
            edgeMode = Ferr2D_SectionMode.Normal;
            fillMode = Ferr2D_SectionMode.Normal;
            useSkirt = true; break;

        case Ferr2DT_FillMode.FillOnlySkirt:
            edgeMode = Ferr2D_SectionMode.None;
            fillMode = Ferr2D_SectionMode.Normal;
            useSkirt = true; break;
        }

        isLegacy = false;

                #if UNITY_EDITOR
        UnityEditor.Undo.DestroyObjectImmediate(oldPath);
                #else
        Destroy(oldPath);
                #endif

        Build(true);

                #if UNITY_EDITOR
        UnityEditor.SceneView.RepaintAll();
                #endif
    }
    private void    DragSelect(Ferr2D_Path path)
    {
        if (Event.current.type == EventType.Repaint)
        {
            if (drag)
            {
                Vector3 pt1 = HandleUtility.GUIPointToWorldRay(dragStart).GetPoint(0.2f);
                Vector3 pt2 = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).GetPoint(0.2f);
                Vector3 pt3 = HandleUtility.GUIPointToWorldRay(new Vector2(dragStart.x, Event.current.mousePosition.y)).GetPoint(0.2f);
                Vector3 pt4 = HandleUtility.GUIPointToWorldRay(new Vector2(Event.current.mousePosition.x, dragStart.y)).GetPoint(0.2f);
                Handles.DrawSolidRectangleWithOutline(new Vector3[] { pt1, pt3, pt2, pt4 }, new Color(0, 0.5f, 0.25f, 0.25f), new Color(0, 0.5f, 0.25f, 0.5f));
            }
        }

        if (Event.current.shift && Event.current.control)
        {
            switch (Event.current.type)
            {
            case EventType.MouseDrag:
                SceneView.RepaintAll();
                break;

            case EventType.MouseMove:
                SceneView.RepaintAll();
                break;

            case EventType.MouseDown:
                dragStart = Event.current.mousePosition;
                drag      = true;

                break;

            case EventType.MouseUp:
                Vector2 dragEnd = Event.current.mousePosition;
                selectedPoints.Clear();
                for (int i = 0; i < path.pathVerts.Count; i += 1)
                {
                    float left   = Mathf.Min(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x));
                    float right  = Mathf.Max(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x));
                    float top    = Mathf.Min(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y));
                    float bottom = Mathf.Max(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y));

                    Rect r = new Rect(left, top, right - left, bottom - top);
                    if (r.Contains(HandleUtility.WorldToGUIPoint(path.transform.TransformPoint(path.pathVerts[i]))))
                    {
                        selectedPoints.Add(i);
                    }
                }

                HandleUtility.AddDefaultControl(0);
                drag = false;
                Repaint();
                break;

            case EventType.Layout:
                HandleUtility.AddDefaultControl(GetHashCode());
                break;
            }
        }
        else if (drag == true)
        {
            drag = false;
            Repaint();
        }
    }
    private void LegacyAddVertexColumn(Ferr2DT_SegmentDescription aDesc, List <Vector2> aSegment, List <float> aSegmentScale, bool aClosed, Ferr2D_DynamicMesh mesh, Rect body, float d, float yOff, bool aConnectFace, float slicePercent, int ptLocal, float pctLocal, ref int p1, ref int p2, ref int p3)
    {
        Vector2 pos1 = smoothPath ? Ferr2D_Path.HermiteGetPt(aSegment, ptLocal, pctLocal, aClosed) : Ferr2D_Path.LinearGetPt(aSegment, ptLocal, pctLocal, aClosed);
        Vector2 n1   = smoothPath ? Ferr2D_Path.HermiteGetNormal(aSegment, ptLocal, pctLocal, aClosed) : Ferr2D_Path.LinearGetNormal(aSegment, ptLocal, pctLocal, aClosed);
        float   s    = aClosed    ? Mathf.Lerp(aSegmentScale[ptLocal], aSegmentScale[(ptLocal + 1) % aSegmentScale.Count], pctLocal) : Mathf.Lerp(aSegmentScale[ptLocal], aSegmentScale[Mathf.Min(ptLocal + 1, aSegmentScale.Count - 1)], pctLocal);

        // this compensates for scale distortion when corners are very sharp, but the normals are not long enough to keep the edge the appropriate width
        // not actually a problem for smooth paths
        if (!smoothPath)
        {
            n1.Normalize();
            float rootScale = 1f / Mathf.Abs(Mathf.Cos(Vector2.Angle(Ferr2D_Path.GetSegmentNormal(ptLocal, aSegment, aClosed), n1) * Mathf.Deg2Rad));
            s = s * rootScale;
        }

        int v1 = mesh.AddVertex(pos1.x + n1.x * (d * s + yOff), pos1.y + n1.y * (d * s + yOff), -slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), fill == Ferr2DT_FillMode.InvertedClosed ? body.yMax : body.y);
        int v2 = mesh.AddVertex(pos1.x - n1.x * (d * s - yOff), pos1.y - n1.y * (d * s - yOff), slantAmount + aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), fill == Ferr2DT_FillMode.InvertedClosed ? body.y : body.yMax);
        int v3 = splitMiddle ? mesh.AddVertex(pos1.x + n1.x * yOff, pos1.y + n1.y * yOff, aDesc.zOffset, Mathf.Lerp(body.x, body.xMax, slicePercent), Mathf.Lerp(body.y, body.yMax, 0.5f)) : -1;

        if (aConnectFace)
        {
            if (!splitMiddle)
            {
                mesh.AddFace(v2, p2, p1, v1);
            }
            else
            {
                mesh.AddFace(v2, p2, p3, v3);
                mesh.AddFace(v3, p3, p1, v1);
            }
        }

        p1 = v1;
        p2 = v2;
        p3 = v3;
    }
    private void    DoShiftAdd(Ferr2D_Path path, GUIStyle iconStyle)
    {
        Vector3             snap         = Event.current.control ? new Vector3(EditorPrefs.GetFloat("MoveSnapX"), EditorPrefs.GetFloat("MoveSnapY"), EditorPrefs.GetFloat("MoveSnapZ")) : Vector3.zero;
        Ferr2DT_PathTerrain terrain      = path.gameObject.GetComponent <Ferr2DT_PathTerrain>();
        Transform           transform    = path.transform;
        Transform           camTransform = SceneView.lastActiveSceneView.camera.transform;
        Vector3             pos          = transform.InverseTransformPoint(GetMousePos(Event.current.mousePosition, transform));
        bool hasDummy = path.pathVerts.Count <= 0;

        if (hasDummy)
        {
            path.pathVerts.Add(Vector2.zero);
        }

        int closestID = path.GetClosestSeg(pos);
        int secondID  = closestID + 1 >= path.Count ? 0 : closestID + 1;

        float firstDist  = Vector2.Distance(pos, path.pathVerts[closestID]);
        float secondDist = Vector2.Distance(pos, path.pathVerts[secondID]);

        Vector3 local = pos;

        if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapLocal)
        {
            local = SnapVector(local, snap);
        }
        Vector3 global = transform.TransformPoint(pos);

        if (Event.current.control && Ferr2DT_Menu.SnapMode == Ferr2DT_Menu.SnapType.SnapGlobal)
        {
            global = SnapVector(global, snap);
        }

        Handles.color = Color.white;
        if (!(secondID == 0 && !path.closed && firstDist > secondDist))
        {
            Handles.DrawLine(global, transform.TransformPoint(path.pathVerts[closestID]));
        }
        if (!(secondID == 0 && !path.closed && firstDist < secondDist))
        {
            Handles.DrawLine(global, transform.TransformPoint(path.pathVerts[secondID]));
        }
        Handles.color = new Color(1, 1, 1, 1);

        Vector3 handlePos = transform.TransformPoint(pos);
        float   scale     = HandleScale(handlePos);

        if (Handles.Button(handlePos, camTransform.rotation, scale, scale, CapDotPlus))
        {
            Vector3 finalPos = transform.InverseTransformPoint(global);
            if (secondID == 0)
            {
                if (firstDist < secondDist)
                {
                    if (terrain)
                    {
                        terrain.AddPoint(finalPos);
                    }
                    else
                    {
                        path.pathVerts.Add(finalPos);
                    }
                }
                else
                {
                    if (terrain)
                    {
                        terrain.AddPoint(finalPos, 0);
                    }
                    else
                    {
                        path.pathVerts.Insert(0, finalPos);
                    }
                }
            }
            else
            {
                if (terrain)
                {
                    terrain.AddPoint(finalPos, Mathf.Max(closestID, secondID));
                }
                else
                {
                    path.pathVerts.Insert(Mathf.Max(closestID, secondID), finalPos);
                }
            }
            selectedPoints.Clear();
            GUI.changed = true;
        }

        if (hasDummy)
        {
            path.pathVerts.RemoveAt(0);
        }
    }
    public override void OnInspectorGUI()
    {
        EditorTools.TitleField("地板編輯工具");
        Undo.RecordObject(target, "Modified Path");

        Ferr2D_Path path = (Ferr2D_Path)target;

        // if this was an undo, refresh stuff too
        if (Event.current.type == EventType.ValidateCommand)
        {
            switch (Event.current.commandName)
            {
            case "UndoRedoPerformed":

                path.UpdateDependants(true);
                if (OnChanged != null)
                {
                    OnChanged();
                }
                return;
            }
        }

        path.closed = EditorGUILayout.Toggle("封閉地面", path.closed);
        if (path)
        {
            // display the path verts list info
            showVerts = EditorGUILayout.Foldout(showVerts, "頂點座標");
        }
        EditorGUI.indentLevel = 2;
        if (showVerts)
        {
            int size = EditorGUILayout.IntField("數量: ", path.pathVerts.Count);
            while (path.pathVerts.Count > size)
            {
                path.pathVerts.RemoveAt(path.pathVerts.Count - 1);
            }
            while (path.pathVerts.Count < size)
            {
                path.pathVerts.Add(new Vector2(0, 0));
            }
        }
        // draw all the verts! Long list~
        for (int i = 0; showVerts && i < path.pathVerts.Count; i++)
        {
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.LabelField("#" + i, GUILayout.Width(60));
            path.pathVerts[i] = new Vector2(
                EditorGUILayout.FloatField(path.pathVerts[i].x),
                EditorGUILayout.FloatField(path.pathVerts[i].y));
            EditorGUILayout.EndHorizontal();
        }

        // button for updating the origin of the object

        if (GUILayout.Button("座標重置"))
        {
            path.ReCenter();
        }

        bool updateClosed           = false;
        Ferr2DT_PathTerrain terrain = path.GetComponent <Ferr2DT_PathTerrain>();

        if (!path.closed && terrain != null && (terrain.fill == Ferr2DT_FillMode.Closed || terrain.fill == Ferr2DT_FillMode.InvertedClosed || terrain.fill == Ferr2DT_FillMode.FillOnlyClosed))
        {
            path.closed  = true;
            updateClosed = true;
        }
        if (terrain != null && path.closed && (terrain.fill == Ferr2DT_FillMode.FillOnlySkirt || terrain.fill == Ferr2DT_FillMode.Skirt))
        {
            path.closed  = false;
            updateClosed = true;
        }

        // update dependants when it changes
        if (GUI.changed || updateClosed)
        {
            path.UpdateDependants(false);
            EditorUtility.SetDirty(target);
        }

        sizeX = EditorTools.IntField(sizeX, "寬");
        sizeY = EditorTools.IntField(sizeY, "長");

        if (GUILayout.Button("地板格式化"))
        {
            path.pathVerts = new List <Vector2>();
            path.pathVerts.Add(new Vector2(sizeX, sizeY) * 0.5F);
            path.pathVerts.Add(new Vector2(sizeX, -sizeY) * 0.5F);
            path.pathVerts.Add(new Vector2(-sizeX, -sizeY) * 0.5F);
            path.pathVerts.Add(new Vector2(-sizeX, sizeY) * 0.5F);
            UpdateDependentsSmart(path, false, false);
            EditorUtility.SetDirty(target);
            prevChanged = true;

            BoxCollider2D box2D = path.GetComponent <BoxCollider2D>();
            if (box2D)
            {
                path.GetComponent <BoxCollider2D>().size = new Vector2(sizeX, sizeY);
                EditorUtility.SetDirty(path.GetComponent <BoxCollider2D>());
            }
        }

        if (GUILayout.Button("進階地板設定"))
        {
            GroundBase groundBase = path.GetComponent <GroundBase>();
            if (!groundBase)
            {
                path.gameObject.AddComponent <GroundBase>();
            }
        }

        EditorTools.Mig();
    }
Exemple #42
0
    private Ferr2DT_SegmentDescription  GetDescription(List <Vector2> aSegment)
    {
        Ferr2DT_TerrainDirection dir = Ferr2D_Path.GetDirection(aSegment, 0, fill == Ferr2DT_FillMode.InvertedClosed);

        return(terrainMaterial.GetDescriptor(dir));
    }
    void OnGUI()
    {
        radius      = EditorGUILayout.FloatField("Radius", radius);
        placeAround = (Transform)EditorGUILayout.ObjectField(placeAround, typeof(Transform), true);

        GUILayout.Label("Parent Transform for Points", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();
        doTransform = EditorGUILayout.Toggle(doTransform, GUILayout.Width(14f));
        parentItem  = (Transform)EditorGUILayout.ObjectField(parentItem, typeof(Transform), true);
        EditorGUILayout.EndHorizontal();

        GUILayout.Label("EdgeCollider GameObject", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();
        doEdgeCollider = EditorGUILayout.Toggle(doEdgeCollider, GUILayout.Width(14f));
        edgeCollider   = (EdgeCollider2D)EditorGUILayout.ObjectField(edgeCollider, typeof(EdgeCollider2D), true);
        EditorGUILayout.EndHorizontal();

        GUILayout.Label("Ferr2D terrain points", EditorStyles.boldLabel);
        EditorGUILayout.BeginHorizontal();
        doFerrTerrain = EditorGUILayout.Toggle(doFerrTerrain, GUILayout.Width(14f));
        path          = (Ferr2D_Path)EditorGUILayout.ObjectField(path, typeof(Ferr2D_Path), true);
        EditorGUILayout.EndHorizontal();


        if (GUI.Button(new Rect(3, 170, position.width - 6, 20), "Make a Circle"))
        {
            if (doTransform && parentItem)
            {
                Transform[] transforms = parentItem.GetComponentsInChildren <Transform>();
                Vector2[]   tempPoints = new Vector2[transforms.Length];

                int i = 0;
                foreach (Transform t in transforms)
                {
                    tempPoints[i].x = t.position.x;
                    tempPoints[i].y = t.position.y;

                    i++;
                }

                if (placeAround)
                {
                    PlacePointsInACircle(ref tempPoints, radius, placeAround.position);
                }
                else
                {
                    PlacePointsInACircle(ref tempPoints, radius, Vector2.zero);
                }

                i = 0;
                foreach (Vector2 p in tempPoints)
                {
                    transforms[i].position = new Vector3(p.x, p.y, 0f);
                    i++;
                }
            }
            if (doEdgeCollider && edgeCollider)
            {
                Vector2[] tempPoints = edgeCollider.points;

                if (placeAround)
                {
                    PlacePointsInACircle(ref tempPoints, radius, placeAround.position);
                }
                else
                {
                    PlacePointsInACircle(ref tempPoints, radius, Vector2.zero);
                }

                edgeCollider.points = tempPoints;
            }
            if (doFerrTerrain && path)
            {
                Vector2[] tempPoints = path.GetVertsRaw().ToArray();

                if (placeAround)
                {
                    PlacePointsInACircle(ref tempPoints, radius, placeAround.position, false);
                }
                else
                {
                    PlacePointsInACircle(ref tempPoints, radius, Vector2.zero, false);
                }

                path.pathVerts = new List <Vector2>(tempPoints);

                path.UpdateColliders();
                path.UpdateDependants(true);
            }
        }
    }
Exemple #44
0
	private void    DragSelect           (Ferr2D_Path path) {
		
		if (Event.current.type == EventType.repaint) {
			if (drag) {
				Vector3 pt1 = HandleUtility.GUIPointToWorldRay(dragStart).GetPoint(0.2f);
				Vector3 pt2 = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).GetPoint(0.2f);
				Vector3 pt3 = HandleUtility.GUIPointToWorldRay(new Vector2(dragStart.x, Event.current.mousePosition.y)).GetPoint(0.2f);
				Vector3 pt4 = HandleUtility.GUIPointToWorldRay(new Vector2(Event.current.mousePosition.x, dragStart.y)).GetPoint(0.2f);
				Handles.DrawSolidRectangleWithOutline(new Vector3[] { pt1, pt3, pt2, pt4 }, new Color(0, 0.5f, 0.25f, 0.25f), new Color(0, 0.5f, 0.25f, 0.5f));
			}
		}
		
		if (Event.current.shift && Event.current.control) {
			switch(Event.current.type) {
			case EventType.mouseDrag:
				SceneView.RepaintAll();
				break;
			case EventType.mouseMove:
				SceneView.RepaintAll();
				break;
			case EventType.mouseDown:
				dragStart = Event.current.mousePosition;
				drag = true;
				
				break;
			case EventType.mouseUp:
				Vector2 dragEnd = Event.current.mousePosition;
				selectedPoints.Clear();
				for	(int i=0;i<path.pathVerts.Count;i+=1) {
					float left   = Mathf.Min(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x));
					float right  = Mathf.Max(dragStart.x, dragStart.x + (dragEnd.x - dragStart.x));
					float top    = Mathf.Min(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y));
					float bottom = Mathf.Max(dragStart.y, dragStart.y + (dragEnd.y - dragStart.y));
					
					Rect r = new Rect(left, top, right-left, bottom-top);
					if (r.Contains(HandleUtility.WorldToGUIPoint(path.transform.TransformPoint( path.pathVerts[i]) ) )) {
						selectedPoints.Add(i);
					}
				}
				
				HandleUtility.AddDefaultControl(0);
				drag = false;
				Repaint();
				break;
			case EventType.layout :
				HandleUtility.AddDefaultControl(GetHashCode());
				break;
			}
		} else if (drag == true) {
			drag = false;
			Repaint();
		}
	}
Exemple #45
0
	Mesh GetMesh() {
		MeshFilter filter  = GetComponent<MeshFilter>();
		string     newName = GetMeshName();
		Mesh       result  = filter.sharedMesh;
		
		if (IsPrefab()) {
#if UNITY_EDITOR
			if (filter.sharedMesh == null || filter.sharedMesh.name != newName) {
				string path      = UnityEditor.AssetDatabase.GetAssetPath(this) + "/Meshes/" + newName + ".asset";
				Mesh   assetMesh = UnityEditor.AssetDatabase.LoadAssetAtPath(path, typeof(Mesh)) as Mesh;
				if (assetMesh != null) { 
					result = assetMesh;
				} else {
					path = System.IO.Path.GetDirectoryName(UnityEditor.AssetDatabase.GetAssetPath(this)) + "/Meshes";
					string assetName = "/" + newName + ".asset";
					result = new Mesh();
					result.name = newName;
					
					if (!Directory.Exists(path)) {
						Directory.CreateDirectory(path);
					}
					try {
						UnityEditor.AssetDatabase.CreateAsset(result, path + assetName);
						UnityEditor.AssetDatabase.Refresh();
					} catch {
						Debug.LogError("Unable to save terrain prefab mesh! Likely, you deleted the mesh files, and the prefab is still referencing them. Restarting your Unity editor should solve this minor issue.");
					}
				}
			}
#endif
		} else {
			if (filter.sharedMesh == null || filter.sharedMesh.name != newName) {
				result = new Mesh();
			}
		}
		result.name = newName;
		return result;
	}
Exemple #46
0
	private Vector3 GetTickerOffset      (Ferr2D_Path path, Vector3  aRootPos, int aIndex) {
		float   scale  = HandleScale(aRootPos) * 0.5f;
		Vector3 result = Vector3.zero;
		
		int     index  = (aIndex + 1) % path.pathVerts.Count;
		Vector3 delta  = Vector3.Normalize(path.pathVerts[index] - path.pathVerts[aIndex]);
		Vector3 norm   = new Vector3(-delta.y, delta.x, 0);
		result = delta * scale * 3 + new Vector3(norm.x, norm.y, 0) * scale * 2;

		return result;
	}
    private void                RecreateCollider2D()
    {
        List <Collider2D>      colliders = new List <Collider2D>(1);
        List <List <Vector2> > segs      = GetColliderVerts();
        bool closed = collidersBottom && collidersLeft && collidersRight && collidersTop;

        if (useEdgeCollider)
        {
            EdgeCollider2D[]      edges    = GetComponents <EdgeCollider2D>();
            List <EdgeCollider2D> edgePool = new List <EdgeCollider2D>(edges);
            int extra = edges.Length - segs.Count;

            if (extra > 0)
            {
                // we have too many, remove a few
                for (int i = 0; i < extra; i += 1)
                {
                    Destroy(edgePool[0]);
                    edgePool.RemoveAt(0);
                }
            }
            else
            {
                // we have too few, add in a few
                for (int i = 0; i < Mathf.Abs(extra); i += 1)
                {
                    edgePool.Add(gameObject.AddComponent <EdgeCollider2D>());
                }
            }

            for (int i = 0; i < segs.Count; i++)
            {
                EdgeCollider2D edge = edgePool[i];
                edge.points = segs[i].ToArray();
                colliders.Add(edge);
            }
        }
        else
        {
            // make sure there's a collider component on this object
            PolygonCollider2D poly = GetComponent <PolygonCollider2D>();
            if (poly == null)
            {
                poly = gameObject.AddComponent <PolygonCollider2D>();
            }
            colliders.Add(poly);

            poly.pathCount = segs.Count;
            if (segs.Count > 1 || !closed)
            {
                for (int i = 0; i < segs.Count; i++)
                {
                    poly.SetPath(i, ExpandColliderPath(segs[i], colliderThickness).ToArray());
                }
            }
            else
            {
                if (fill == Ferr2DT_FillMode.InvertedClosed)
                {
                    Rect bounds = Ferr2D_Path.GetBounds(segs[0]);
                    poly.pathCount = 2;
                    poly.SetPath(0, segs[0].ToArray());
                    poly.SetPath(1, new Vector2[] {
                        new Vector2(bounds.xMin - bounds.width, bounds.yMax + bounds.height),
                        new Vector2(bounds.xMax + bounds.width, bounds.yMax + bounds.height),
                        new Vector2(bounds.xMax + bounds.width, bounds.yMin - bounds.height),
                        new Vector2(bounds.xMin - bounds.width, bounds.yMin - bounds.height)
                    });
                }
                else
                {
                    if (segs.Count > 0 && segs[0].Count > 0)
                    {
                        poly.SetPath(0, segs[0].ToArray());
                    }
                }
            }
        }


        for (int i = 0; i < colliders.Count; i += 1)
        {
            colliders[i].isTrigger      = isTrigger;
            colliders[i].sharedMaterial = physicsMaterial2D;
                        #if UNITY_5
            colliders[i].usedByEffector = usedByEffector;
                        #endif
        }
    }
Exemple #48
0
	private void    DoPath               (Ferr2D_Path path)
	{
		Handles.color = Color.white;
		List<Vector2> verts     = path.GetVertsRaw();
        Matrix4x4     mat       = path.transform.localToWorldMatrix;

		for (int i = 0; i < verts.Count - 1; i++)
		{
			Vector3 pos  = mat.MultiplyPoint3x4(verts[i]);
			Vector3 pos2 = mat.MultiplyPoint3x4(verts[i + 1]);
			Handles.DrawLine(pos, pos2);
		}
		if (path.closed)
		{
			Vector3 pos  = mat.MultiplyPoint3x4(verts[0]);
			Vector3 pos2 = mat.MultiplyPoint3x4(verts[verts.Count - 1]);
			Handles.DrawLine(pos, pos2);
		}
	}
    /// <summary>
    /// Retrieves a list of line segments that directly represent the collision volume of the terrain. This includes offsets and removed edges.
    /// </summary>
    /// <returns>A list of line segments.</returns>
    public List <List <Vector2> > GetColliderVerts()
    {
        List <Vector2> tVerts = Path.GetVertsRaw();

        // drop a skirt on skirt-based terrain
        if ((fill == Ferr2DT_FillMode.Skirt || fill == Ferr2DT_FillMode.FillOnlySkirt) && tVerts.Count > 0)
        {
            Vector2 start = tVerts[0];
            Vector2 end   = tVerts[tVerts.Count - 1];
            tVerts.Add(new Vector2(end.x, fillY));
            tVerts.Add(new Vector2(start.x, fillY));
            tVerts.Add(new Vector2(start.x, start.y));
        }

        float fillDist = (terrainMaterial.ToUV(terrainMaterial.GetBody((Ferr2DT_TerrainDirection)0, 0)).width *(terrainMaterial.edgeMaterial.mainTexture.width / pixelsPerUnit)) / (Mathf.Max(1, splitCount)) * splitDist;
        List <Ferr2DT_TerrainDirection> dirs   = new List <Ferr2DT_TerrainDirection>();
        List <List <Vector2> >          result = new List <List <Vector2>           >();
        List <List <int> > list = GetSegments(tVerts, out dirs);
        List <Vector2>     curr = new List <Vector2>();

        // remove segments that aren't on the terrain
        for (int i = 0; i < list.Count; i++)
        {
            if ((dirs[i] == Ferr2DT_TerrainDirection.Bottom && !collidersBottom) ||
                (dirs[i] == Ferr2DT_TerrainDirection.Left && !collidersLeft) ||
                (dirs[i] == Ferr2DT_TerrainDirection.Top && !collidersTop) ||
                (dirs[i] == Ferr2DT_TerrainDirection.Right && !collidersRight))
            {
                if (curr.Count > 0)
                {
                    result.Add(new List <Vector2>(curr));
                    curr.Clear(                       );
                }
            }
            else
            {
                // create a list of verts and scales for this edge
                List <float>   tScales = null;
                List <Vector2> tList   = null;
                Ferr2D_Path.IndicesToPath(tVerts, vertScales, list[i], out tList, out tScales);

                // smooth it!
                if (smoothPath && tList.Count > 2)
                {
                    Ferr2D_Path.SmoothSegment(tList, tScales, fillDist, false, out tList, out tScales);
                }

                // offset the verts based on scale and terrain edge info
                tList = OffsetColliderVerts(tList, tScales, dirs[i]);

                // sharpen corners properly!
                if (curr.Count > 0 && sharpCorners)
                {
                    MergeCorner(ref curr, ref tList);
                }

                curr.AddRange(tList);
            }
        }
        if (sharpCorners)
        {
            MergeCorner(ref curr, ref curr);
        }
        if (curr.Count > 0)
        {
            result.Add(curr);
        }

        return(result);
    }