Advertisement
Guest User

Level Editor

a guest
Apr 25th, 2019
132
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.44 KB | None | 0 0
  1. using System;
  2. using System.Linq;
  3. using System.Collections;
  4. using System.Collections.Generic;
  5.  
  6. using UnityEngine;
  7. using UnityEngineInternal;
  8. using UnityEditor;
  9. using UnityEditorInternal;
  10.  
  11. using Sirenix.OdinInspector;
  12. using Sirenix.OdinInspector.Editor;
  13. using Sirenix.OdinInspector.Internal;
  14. using Sirenix.Utilities.Editor;
  15.  
  16. public class LevelEditor : OdinEditorWindow
  17. {
  18.     #region Nested
  19.  
  20.     public enum Mode { Creation, Edition, Entities, Puzzles, Decor, None }
  21.     public enum Tool { None, Move, PlaceOrRemove, Select }
  22.     #endregion
  23.  
  24.     #region Interface
  25.  
  26.     [SerializeField, OnValueChanged("ModeResolver")]
  27.     private Mode currentMode;
  28.     private void ModeResolver()
  29.     {
  30.         if (currentMode == Mode.Creation) currentRoom = null;
  31.         else if (currentMode != Mode.Creation && currentRoom == null) currentMode = Mode.None;
  32.     }
  33.  
  34.     [SerializeField, OnValueChanged("SwitchToEdit")]
  35.     private Room currentRoom;
  36.     private void SwitchToEdit()
  37.     {
  38.         if (currentRoom != null) currentMode = Mode.Edition;
  39.     }
  40.  
  41.     [SerializeField, ValidateInput("RoomSizeIsValid"), EnableIf("InCreationMod")]
  42.     private Vector2Int roomSize = new Vector2Int(1, 1);
  43.     private bool RoomSizeIsValid(Vector2Int vector2Int)
  44.     {
  45.         return vector2Int != Vector2Int.zero;
  46.     }
  47.     private bool InCreationMod { get { return currentMode == Mode.Creation; } }
  48.  
  49.     [SerializeField]
  50.     private GameObject objToPlace;
  51.     #endregion
  52.  
  53.     #region Fields
  54.  
  55.     private Tool currentTool;
  56.     private bool[] toolStates;
  57.  
  58.     private Grid grid;
  59.  
  60.     private bool isFilling;
  61.     private bool additiveSelection;
  62.     private bool supressiveSelection;
  63.     private List<Bounds> allCellsSelected = new List<Bounds>();
  64.     private List<Bounds> currentCellsSelected = new List<Bounds>();
  65.     private (Bounds start, Bounds end) fillLimits;
  66.     #endregion
  67.  
  68.     #region Window Methods
  69.  
  70.     [MenuItem("Tools/Level Editor")]
  71.     public static void ShowWindow()
  72.     {
  73.         GetWindow<LevelEditor>("Level Editor");
  74.     }
  75.  
  76.     protected new void OnEnable()
  77.     {
  78.         base.OnEnable();      
  79.         toolStates = new bool[Enum.GetNames(typeof(Tool)).Length - 1];
  80.  
  81.         var gridObj = new GameObject("Grid");
  82.  
  83.         grid = gridObj.AddComponent<Grid>();
  84.         grid.cellSwizzle = GridLayout.CellSwizzle.XZY;
  85.         grid.cellSize = new Vector3(1, 1.414214f, 1);
  86.  
  87.         gridObj.hideFlags = HideFlags.HideAndDontSave;
  88.     }
  89.     private void OnFocus()
  90.     {
  91.         SceneView.duringSceneGui -= this.OnSceneGUI;
  92.         SceneView.duringSceneGui += this.OnSceneGUI;
  93.     }
  94.     protected new void OnDestroy()
  95.     {
  96.         base.OnDestroy();
  97.         DestroyImmediate(grid.gameObject);
  98.  
  99.         SceneView.duringSceneGui -= this.OnSceneGUI;
  100.     }
  101.     #endregion
  102.  
  103.     private void OnSceneGUI(SceneView sceneView)
  104.     {
  105.         HandleUtility.AddDefaultControl(GUIUtility.GetControlID(FocusType.Passive));
  106.         if (currentRoom == null && currentMode != Mode.Creation)
  107.         {
  108.             currentMode = Mode.None;
  109.         }
  110.  
  111.         Selection.activeObject = grid;
  112.         var currentEvt = Event.current;
  113.  
  114.         switch (currentMode)
  115.         {
  116.             case Mode.Creation:
  117.                 CreateRoom(currentEvt);
  118.                 break;
  119.             case Mode.Edition:
  120.                 EditRoom(currentEvt);
  121.                 break;
  122.             case Mode.Entities:
  123.                 break;
  124.             case Mode.Puzzles:
  125.                 break;
  126.             case Mode.Decor:
  127.                 break;
  128.         }
  129.         sceneView.Repaint();
  130.  
  131.         /*Handles.BeginGUI();
  132.  
  133.         var toolIcons = new Dictionary<Tool, EditorIcon>()
  134.         {
  135.             {Tool.Move, EditorIcons.Move },
  136.             {Tool.Place, EditorIcons.Pen },
  137.             {Tool.Select, EditorIcons.Ruler }
  138.         };
  139.  
  140.         var toolNames = Enum.GetNames(typeof(Tool));
  141.         for (int i = 0; i < toolNames.Length; i++)
  142.         {
  143.             var value = (Tool)Enum.Parse(typeof(Tool), toolNames[i]);
  144.             var toolRect = new Rect(10 + (30 * i), 10, 30, 30);
  145.  
  146.             var buttonStyle = default(GUIStyle);
  147.             if (i == 0) buttonStyle = EditorStyles.miniButtonLeft;
  148.             else if (i == toolNames.Length - 1) buttonStyle = EditorStyles.miniButtonRight;
  149.             else buttonStyle = EditorStyles.miniButtonMid;
  150.  
  151.             var toolTexture = toolStates[i] ? toolIcons[value].Highlighted : toolIcons[value].Active;
  152.  
  153.             toolStates[i] = GUI.Toggle(toolRect, toolStates[i], toolTexture, buttonStyle);
  154.             if (toolStates[i])
  155.             {
  156.                 currentTool = value;
  157.                 for (int ii = 0; ii < toolStates.Length; ii++)
  158.                 {
  159.                     if (ii != i) toolStates[ii] = false;
  160.                 }
  161.             }
  162.         }
  163.  
  164.         Handles.EndGUI();
  165.  
  166.         Selection.activeObject = grid;
  167.  
  168.         var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
  169.         var plane = new Plane(Vector3.up, Vector3.zero);
  170.        
  171.         if(plane.Raycast(ray, out float rayDistance))
  172.         {
  173.             var point = ray.GetPoint(rayDistance);
  174.             var bounds = grid.GetBoundsLocal(grid.WorldToCell(point));
  175.             bounds = new Bounds(bounds.max, bounds.size);
  176.  
  177.             Handles.DrawSolidRectangleWithOutline(GetVerts(bounds), new Color(1, 1, 1, 0.1f), Color.black);
  178.  
  179.             if (Event.current.OnMouseDown(0) && !cells.Contains(bounds))
  180.             {
  181.                 cells.Add(bounds);
  182.             }
  183.  
  184.             foreach (var cell in cells)
  185.             {
  186.                 Handles.DrawSolidRectangleWithOutline(GetVerts(cell), new Color(1, 0, 0, 0.1f), Color.yellow);
  187.             }
  188.      
  189.             if (cells.Count >= 2)
  190.             {
  191.                 var max = new Vector3(cells.Min(c => c.min.x), 0, cells.Min(c => c.min.z));
  192.                 var min = new Vector3(cells.Max(c => c.max.x), 0, cells.Max(c => c.max.z));
  193.  
  194.                 var roomBounds = new Bounds();
  195.                 roomBounds.SetMinMax(min, max);
  196.  
  197.                 Handles.DrawSolidRectangleWithOutline(GetVerts(roomBounds), new Color(0, 0, 1, 0.1f), Color.red);
  198.             }
  199.             if (Event.current.OnMouseDown(1) && cells.Contains(bounds))
  200.             {
  201.                 Debug.Log("Removing");
  202.                 cells.Remove(bounds);
  203.             }
  204.  
  205.             if (Event.current.OnKeyDown(KeyCode.F) && !isFilling)
  206.             {
  207.                 isFilling = true;
  208.                 fillLimits = (bounds, bounds);
  209.             }
  210.  
  211.             if (isFilling)
  212.             {
  213.                 cellsForFill.Clear();
  214.                 fillLimits.end = bounds;
  215.  
  216.                 int spacingX = Mathf.RoundToInt(Mathf.Abs(fillLimits.end.center.x - fillLimits.start.center.x));
  217.                 int spacingZ = Mathf.RoundToInt(Mathf.Abs(fillLimits.end.center.z - fillLimits.start.center.z) / 1.414214f);
  218.  
  219.                 Vector3 startPoint = fillLimits.start.center;
  220.                 int signX = (fillLimits.start.center.x < fillLimits.end.center.x) ? 1 : -1;
  221.                 int signZ = (fillLimits.start.center.z < fillLimits.end.center.z) ? 1 : -1;
  222.  
  223.                 for (int x = 0; x <= spacingX; x++)
  224.                 {
  225.                     for (int z = 0; z < spacingZ + 1; z++)
  226.                     {
  227.                         Vector3 cellPos = startPoint + (Vector3.right * x * signX) + (Vector3.forward * 1.414214f * z * signZ);
  228.                         Bounds cell = new Bounds(cellPos, new Vector3(1, 0, 1.414214f));
  229.  
  230.                         cellsForFill.Add(cell);
  231.                     }
  232.                 }
  233.  
  234.                 foreach (Bounds cells in cellsForFill)
  235.                 {
  236.                     Handles.DrawSolidRectangleWithOutline(GetVerts(cells), new Color(0, 1, 0, 0.25f), Color.clear);
  237.                 }
  238.             }
  239.  
  240.             if (Event.current.OnKeyUp(KeyCode.F))
  241.             {
  242.                 Debug.Log("acess");
  243.  
  244.                 var cellsForFillCorrected = cellsForFill.Where(c => !cells.Contains(c));
  245.                 cells.AddRange(cellsForFillCorrected);
  246.  
  247.                 isFilling = false;
  248.             }
  249.         }
  250.         sceneView.Repaint();*/
  251.     }
  252.  
  253.     #region Main Methods
  254.  
  255.     private void CreateRoom(Event currentEvt)
  256.     {
  257.         if(GetPointedBounds(out Bounds bounds))
  258.         {
  259.             if (currentEvt.OnMouseDown(0) && RoomSizeIsValid(roomSize))
  260.             {
  261.                 var roomObj = new GameObject("Room");
  262.                 currentRoom = roomObj.AddComponent<Room>();
  263.                 currentRoom.Intialize(bounds, roomSize);
  264.  
  265.                 currentMode = Mode.Edition;
  266.             }
  267.         }
  268.     }
  269.  
  270.     private void EditRoom(Event currentEvt)
  271.     {
  272.         Handles.BeginGUI();
  273.  
  274.         var toolIcons = new Dictionary<Tool, EditorIcon>()
  275.         {
  276.             {Tool.Move, EditorIcons.Move },
  277.             {Tool.PlaceOrRemove, EditorIcons.Pen },
  278.             {Tool.Select, EditorIcons.Ruler }
  279.         };
  280.  
  281.         var toolNames = Enum.GetNames(typeof(Tool)).ToList();
  282.         toolNames.Remove("None");
  283.         for (int i = 0; i < toolNames.Count; i++)
  284.         {
  285.             var value = (Tool)Enum.Parse(typeof(Tool), toolNames[i]);
  286.             var toolRect = new Rect(10 + (30 * i), 10, 30, 30);
  287.  
  288.             var buttonStyle = default(GUIStyle);
  289.             if (i == 0) buttonStyle = EditorStyles.miniButtonLeft;
  290.             else if (i == toolNames.Count - 1) buttonStyle = EditorStyles.miniButtonRight;
  291.             else buttonStyle = EditorStyles.miniButtonMid;
  292.  
  293.             var toolTexture = toolStates[i] ? toolIcons[value].Highlighted : toolIcons[value].Active;
  294.  
  295.             toolStates[i] = GUI.Toggle(toolRect, toolStates[i], toolTexture, buttonStyle);
  296.             if (toolStates[i])
  297.             {
  298.                 currentTool = value;
  299.                 for (int ii = 0; ii < toolStates.Length; ii++)
  300.                 {
  301.                     if (ii != i) toolStates[ii] = false;
  302.                 }
  303.             }
  304.         }
  305.         if (toolStates.All(b => !b)) currentTool = Tool.None;
  306.  
  307.         Handles.EndGUI();
  308.  
  309.         var cells = currentRoom.cellInfos.ConvertAll(cf => cf.bounds);
  310.         if (cells.Count >= 2)
  311.         {
  312.             var max = new Vector3(cells.Min(c => c.min.x), 0, cells.Min(c => c.min.z));
  313.             var min = new Vector3(cells.Max(c => c.max.x), 0, cells.Max(c => c.max.z));
  314.  
  315.             var roomBounds = new Bounds();
  316.             roomBounds.SetMinMax(min, max);
  317.  
  318.             Handles.DrawSolidRectangleWithOutline(GetVerts(roomBounds), new Color(0, 0, 1, 0.1f), Color.red);
  319.         }
  320.         else Handles.DrawSolidRectangleWithOutline(GetVerts(cells[0]), new Color(0, 0, 1, 0.1f), Color.red);
  321.  
  322.         switch (currentTool)
  323.         {
  324.             case Tool.PlaceOrRemove:
  325.                 PlaceOrRemove(currentEvt);
  326.                 break;
  327.             case Tool.Select:
  328.                 SelectZone(currentEvt);
  329.                 break;
  330.         }
  331.  
  332.         if(allCellsSelected.Count != 0)
  333.         {
  334.             foreach (var cell in allCellsSelected)
  335.             {
  336.                 Handles.DrawSolidRectangleWithOutline(GetVerts(cell), new Color(0, 1, 0, 0.25f), Color.clear);
  337.             }
  338.         }
  339.     }
  340.     private void PlaceOrRemove(Event currentEvt)
  341.     {
  342.         if (GetPointedBounds(out Bounds boundsForPlacement) && currentEvt.OnMouseDown(0))
  343.         {
  344.             if (currentRoom.ContainsCell(boundsForPlacement))
  345.             {
  346.                 Remove(boundsForPlacement);
  347.             }
  348.             currentRoom.AddCell(boundsForPlacement, objToPlace);
  349.         }
  350.  
  351.         if (GetPointedBounds(out Bounds boundsForRemoval) && currentEvt.OnMouseDown(1) && currentRoom.ContainsCell(boundsForRemoval))
  352.         {
  353.             Remove(boundsForRemoval);
  354.         }
  355.  
  356.         void Remove(Bounds boundsToRemove)
  357.         {
  358.             var cellToRemove = currentRoom.cellInfos.Find(cf => cf.bounds == boundsToRemove);
  359.             var remove = cellToRemove.RemoveObj(LayerMask.NameToLayer("Default"));
  360.             if (remove) currentRoom.cellInfos.Remove(cellToRemove);
  361.         }
  362.     }
  363.     private void SelectZone(Event currentEvt)
  364.     {
  365.         if (GetPointedBounds(out Bounds bounds))
  366.         {          
  367.             if (currentEvt.OnMouseDown(0) && !isFilling)
  368.             {
  369.                 isFilling = true;
  370.                 fillLimits = (bounds, bounds);
  371.             }
  372.  
  373.             if (isFilling)
  374.             {
  375.                 currentCellsSelected.Clear();
  376.                 fillLimits.end = bounds;
  377.  
  378.                 int spacingX = Mathf.RoundToInt(Mathf.Abs(fillLimits.end.center.x - fillLimits.start.center.x));
  379.                 int spacingZ = Mathf.RoundToInt(Mathf.Abs(fillLimits.end.center.z - fillLimits.start.center.z) / 1.414214f);
  380.  
  381.                 Vector3 startPoint = fillLimits.start.center;
  382.                 int signX = (fillLimits.start.center.x < fillLimits.end.center.x) ? 1 : -1;
  383.                 int signZ = (fillLimits.start.center.z < fillLimits.end.center.z) ? 1 : -1;
  384.  
  385.                 for (int x = 0; x <= spacingX; x++)
  386.                 {
  387.                     for (int z = 0; z < spacingZ + 1; z++)
  388.                     {
  389.                         Vector3 cellPos = startPoint + (Vector3.right * x * signX) + (Vector3.forward * 1.414214f * z * signZ);
  390.                         Bounds cell = new Bounds(cellPos, new Vector3(1, 0, 1.414214f));
  391.  
  392.                         currentCellsSelected.Add(cell);
  393.                     }
  394.                 }
  395.  
  396.                 foreach (Bounds cells in currentCellsSelected)
  397.                 {
  398.                     Handles.DrawSolidRectangleWithOutline(GetVerts(cells), new Color(1, 1, 0, 0.25f), Color.clear);
  399.                 }
  400.             }
  401.  
  402.             if (currentEvt.shift) additiveSelection = true;
  403.             else additiveSelection = false;
  404.  
  405.             if (currentEvt.control) supressiveSelection = true;
  406.             else supressiveSelection = false;
  407.  
  408.             Debug.Log(allCellsSelected.Count);
  409.  
  410.             if (currentEvt.OnMouseUp(0) && isFilling == true)
  411.             {
  412.                 isFilling = false;
  413.                 var correctSelection = new List<Bounds>();
  414.                 if (supressiveSelection)
  415.                 {
  416.                     var test = new Bounds[allCellsSelected.Count];
  417.                     allCellsSelected.CopyTo(test, 0);
  418.                     allCellsSelected.Clear();
  419.                     foreach (var cell in test)
  420.                     {
  421.                         if (!currentCellsSelected.Contains(cell)) allCellsSelected.Add(cell);
  422.                     }
  423.                     //allCellsSelected.RemoveAll(c => currentCellsSelected.Contains(c));
  424.                 }
  425.                 else
  426.                 {
  427.                     if (!additiveSelection)
  428.                     {
  429.                         allCellsSelected.Clear();
  430.                         correctSelection = currentCellsSelected;
  431.                     }
  432.                     else
  433.                     {
  434.                         foreach (var cell in currentCellsSelected)
  435.                         {
  436.                             if (!allCellsSelected.Exists(c => c.center == cell.center)) correctSelection.Add(cell);
  437.                         }
  438.                     }
  439.  
  440.                     allCellsSelected.AddRange(correctSelection);
  441.                 }
  442.                 currentCellsSelected.Clear();
  443.             }
  444.         }
  445.     }
  446.     #endregion
  447.  
  448.     #region General Methods
  449.  
  450.     public bool GetPointedBounds(out Bounds bounds)
  451.     {
  452.         var ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition);
  453.         var plane = new Plane(Vector3.up, Vector3.zero);
  454.  
  455.         if (plane.Raycast(ray, out float rayDistance))
  456.         {
  457.             var point = ray.GetPoint(rayDistance);
  458.             bounds = grid.GetBoundsLocal(grid.WorldToCell(point));
  459.             bounds = new Bounds(new Vector3(bounds.max.x, 0, bounds.max.z), new Vector3(bounds.size.x, 0, bounds.size.z));
  460.  
  461.             Handles.DrawSolidRectangleWithOutline(GetVerts(bounds), new Color(1, 1, 1, 0.1f), Color.black);
  462.  
  463.             return true;
  464.         }
  465.         else
  466.         {
  467.             bounds = new Bounds();
  468.             return false;
  469.         }
  470.     }
  471.     private Vector3[] GetVerts(Bounds bounds)
  472.     {
  473.         Vector3[] verts = new Vector3[]
  474.         {
  475.             new Vector3(bounds.min.x, 0, bounds.min.z),
  476.             new Vector3(bounds.min.x, 0, bounds.max.z),
  477.             new Vector3(bounds.max.x, 0, bounds.max.z),
  478.             new Vector3(bounds.max.x, 0, bounds.min.z),
  479.         };
  480.  
  481.         return verts;
  482.     }
  483.     #endregion
  484. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement