void HighlightHoveringLine() { if (lastHoverLine != null && lastHoverLine != selectedLine) { lastHoverLine.SetSelectState(InteractiveLine.SelectState.NONE); } Ray ray = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition); Vector3 worldMousePos = ray.origin; InteractiveLine closestLine = ApproximateBinarySearch(horizontalLinesByY, worldMousePos.y); if (closestLine == null) { closestLine = ApproximateBinarySearch(verticalLinesByX, worldMousePos.x); } if (closestLine != null && closestLine.selectState == InteractiveLine.SelectState.IMMOBILE) { closestLine = null; } if (closestLine != null && closestLine != selectedLine) { closestLine.SetSelectState(InteractiveLine.SelectState.HOVER); } lastHoverLine = closestLine; }
public void NotifyLineDeleting(InteractiveLine line) { if (line.orientation == InteractiveLine.Orientation.HORIZONTAL) { horizontalLinesByY.Remove(line.point1.y); } else { verticalLinesByX.Remove(line.point1.x); } }
public void OnSceneGUI() { if (drawGrid) { int controlID = EditorGUIUtility.GetControlID(FocusType.Passive); switch (Event.current.GetTypeForControl(controlID)) { // On Layout event (the first event for initialization) record grid as being 0 units away if mouse within grid bounds // else declare infinity away to steal clicks and avoid deselection case EventType.Layout: if (selectedLine == null) { Vector3 worldMousePos = HandleUtility.GUIPointToWorldRay(Event.current.mousePosition).origin; if (worldMousePos.x >= minX && worldMousePos.x <= maxX && worldMousePos.y >= minY && worldMousePos.y <= maxY) { HandleUtility.AddControl(controlID, 0f); } else { HandleUtility.AddControl(controlID, Mathf.Infinity); } } else { HandleUtility.AddDefaultControl(controlID); } break; // All other events perform logic and draw like normal default: HighlightHoveringLine(); if (Event.current.type == EventType.MouseUp) { if (selectedLine != null) { selectedLine.SetSelectState(InteractiveLine.SelectState.NONE); } selectedLine = lastHoverLine; if (selectedLine != null) { selectedLine.SetSelectState(InteractiveLine.SelectState.SELECTED); Event.current.Use(); } } if (selectedLine == null) { ShowAddLineButtons(); } break; } } }
// Intended for loading grid from text file, doesn't normalize lines or check if dictionary already contains public void AddExistingLine(InteractiveLine line) { line.SetContainingGrid(this); if (line.orientation == InteractiveLine.Orientation.HORIZONTAL) { horizontalLinesByY.Add(line.point1.y, line); ++numRowsOfCells; } else { verticalLinesByX.Add(line.point1.x, line); ++numColsOfCells; } UpdateMinMaxs(line); }
// Adds a line to the grid, computing if it's horizontal or vertical, and scales all lines to the same length InteractiveLine AddLine(Vector3 point1, Vector3 point2) { InteractiveLine line = ScriptableObject.CreateInstance <InteractiveLine>(); InteractiveLine.Orientation orientation; if (point1.x == point2.x) { orientation = InteractiveLine.Orientation.VERTICAL; ++numColsOfCells; } else if (point1.y == point2.y) { orientation = InteractiveLine.Orientation.HORIZONTAL; ++numRowsOfCells; } else { Debug.LogError("XYGrid AddLine: Line isn't horizontal or vertical"); DestroyImmediate(line); return(null); } line.Init(point1, point2, this, orientation); if (orientation == InteractiveLine.Orientation.HORIZONTAL) { if (horizontalLinesByY.ContainsKey(point1.y)) { DestroyImmediate(horizontalLinesByY[point1.y]); horizontalLinesByY.Remove(point1.y); } horizontalLinesByY.Add(point1.y, line); } else { if (verticalLinesByX.ContainsKey(point1.x)) { DestroyImmediate(verticalLinesByX[point1.x]); verticalLinesByX.Remove(point1.x); } verticalLinesByX.Add(point1.x, line); } UpdateMinMaxs(line); RescaleLines(); return(line); }
public bool LoadGrid(string fireManagerID) { TextAsset gridText = AssetDatabase.LoadAssetAtPath("Assets/Editor/FireGrids/" + fireManagerID + ".txt", typeof(TextAsset)) as TextAsset; if (gridText) { string allLines = gridText.text; string[] eachLine = allLines.Split('|'); foreach (string line in eachLine) { InteractiveLine interactiveLine = CreateInstance <InteractiveLine>(); JsonUtility.FromJsonOverwrite(line, interactiveLine); AddExistingLine(interactiveLine); } return(true); } else { return(false); } }
// Adds a cell to the grid where other lines cannot pass inside of // Paramter cellCorners is array of 4 Vector3 representing corners of cell in order bottom left, top left, top right, bottom right public void AddIsolatedCell(Vector3[] cellCorners) { isolatedCellMinMaxs.Add(new Vector4(cellCorners[0].x, cellCorners[2].x, cellCorners[0].y, cellCorners[2].y)); // Remove any non-immobile lines inside the new isolated cell area float[] xCoordinates = verticalLinesByX.Keys.ToArray(); float[] yCoordinates = horizontalLinesByY.Keys.ToArray(); bool exactMatchFound; int lowerXBoundIndex = InterpretArrayBinarySearchIndex(Array.BinarySearch(xCoordinates, cellCorners[0].x), out exactMatchFound); int upperXBoundIndex = InterpretArrayBinarySearchIndex(Array.BinarySearch(xCoordinates, cellCorners[2].x), out exactMatchFound); int lowerYBoundIndex = InterpretArrayBinarySearchIndex(Array.BinarySearch(yCoordinates, cellCorners[0].y), out exactMatchFound); int upperYBoundIndex = InterpretArrayBinarySearchIndex(Array.BinarySearch(yCoordinates, cellCorners[2].y), out exactMatchFound); for (; lowerXBoundIndex < upperXBoundIndex; ++lowerXBoundIndex) { if (lowerXBoundIndex < xCoordinates.Length && verticalLinesByX[xCoordinates[lowerXBoundIndex]].selectState != InteractiveLine.SelectState.IMMOBILE) { DestroyImmediate(verticalLinesByX[xCoordinates[lowerXBoundIndex]]); verticalLinesByX.Remove(xCoordinates[lowerXBoundIndex]); } } for (; lowerYBoundIndex < upperYBoundIndex; ++lowerYBoundIndex) { if (lowerYBoundIndex < yCoordinates.Length && horizontalLinesByY[yCoordinates[lowerYBoundIndex]].selectState != InteractiveLine.SelectState.IMMOBILE) { DestroyImmediate(horizontalLinesByY[yCoordinates[lowerYBoundIndex]]); horizontalLinesByY.Remove(yCoordinates[lowerYBoundIndex]); } } InteractiveLine line = AddLine(cellCorners[0], cellCorners[1]); line.SetSelectState(InteractiveLine.SelectState.IMMOBILE); line = AddLine(cellCorners[1], cellCorners[2]); line.SetSelectState(InteractiveLine.SelectState.IMMOBILE); line = AddLine(cellCorners[3], cellCorners[2]); line.SetSelectState(InteractiveLine.SelectState.IMMOBILE); line = AddLine(cellCorners[0], cellCorners[3]); line.SetSelectState(InteractiveLine.SelectState.IMMOBILE); }
public void NotifyLineMoved(InteractiveLine line, float oldCoordinate) { if (line.orientation == InteractiveLine.Orientation.HORIZONTAL) { horizontalLinesByY.Remove(oldCoordinate); --numRowsOfCells; } else { verticalLinesByX.Remove(oldCoordinate); --numColsOfCells; } // Destroy lines that move into isolated cells foreach (Vector4 minMaxs in isolatedCellMinMaxs) { if (line.orientation == InteractiveLine.Orientation.HORIZONTAL) { if (line.point1.y >= minMaxs.z && line.point1.y <= minMaxs.w) { DestroyImmediate(line); return; } } else { if (line.point1.x >= minMaxs.x && line.point1.x <= minMaxs.y) { DestroyImmediate(line); return; } } } AddExistingLine(line); RescaleLines(); }
// Updates variables tracking min and max in X and Y and rescales lines to be same length void UpdateMinMaxs(InteractiveLine line) { float minLineX = Mathf.Min(line.point1.x, line.point2.x); float minLineY = Mathf.Min(line.point1.y, line.point2.y); float maxLineX = Mathf.Max(line.point1.x, line.point2.x); float maxLineY = Mathf.Max(line.point1.y, line.point2.y); if (minLineX < minX) { minX = minLineX; } if (maxLineX > maxX) { maxX = maxLineX; } if (minLineY < minY) { minY = minLineY; } if (maxLineY > maxY) { maxY = maxLineY; } }