public void AddNeighbourIfPossible(ObjectPlacementPathTileConnectionGridCell neighbour) { if (neighbour.ZIndex == ZIndex) { if (neighbour.XIndex == XIndex + 1) { _rightNeighbour = neighbour; CalculateNumberOfNeighbours(); } else if (neighbour.XIndex == XIndex - 1) { _leftNeighbour = neighbour; CalculateNumberOfNeighbours(); } } else if (neighbour.XIndex == XIndex) { if (neighbour.ZIndex == ZIndex + 1) { _forwardNeighbour = neighbour; CalculateNumberOfNeighbours(); } else if (neighbour.ZIndex == ZIndex - 1) { _backNeighbour = neighbour; CalculateNumberOfNeighbours(); } } }
public void EstablishCellNeighbours() { foreach (var pair in _occupiedCells) { ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell = pair.Value; var potentialNeighbour = new ObjectPlacementPathTileConnectionGridCellIndices(tileConnectionGridCell.XIndex + 1, tileConnectionGridCell.ZIndex); if (IsCellOccupied(potentialNeighbour)) { tileConnectionGridCell.AddNeighbourIfPossible(GetCellAtIndicesIfOccupied(potentialNeighbour)); } potentialNeighbour = new ObjectPlacementPathTileConnectionGridCellIndices(tileConnectionGridCell.XIndex - 1, tileConnectionGridCell.ZIndex); if (IsCellOccupied(potentialNeighbour)) { tileConnectionGridCell.AddNeighbourIfPossible(GetCellAtIndicesIfOccupied(potentialNeighbour)); } potentialNeighbour = new ObjectPlacementPathTileConnectionGridCellIndices(tileConnectionGridCell.XIndex, tileConnectionGridCell.ZIndex + 1); if (IsCellOccupied(potentialNeighbour)) { tileConnectionGridCell.AddNeighbourIfPossible(GetCellAtIndicesIfOccupied(potentialNeighbour)); } potentialNeighbour = new ObjectPlacementPathTileConnectionGridCellIndices(tileConnectionGridCell.XIndex, tileConnectionGridCell.ZIndex - 1); if (IsCellOccupied(potentialNeighbour)) { tileConnectionGridCell.AddNeighbourIfPossible(GetCellAtIndicesIfOccupied(potentialNeighbour)); } } }
public void DetectTileConnectionTypesForAllOccupiedCells() { ObjectPlacementBoxStack firstStackInFirstPathSegment = _path.GetSegmentByIndex(0).GetStackByIndex(0); foreach (var pair in _occupiedCells) { ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell = pair.Value; int numberOfNeighbours = tileConnectionGridCell.NumberOfNeighbours; if (numberOfNeighbours == 0) { tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Begin; } else if (numberOfNeighbours == 1) { if (tileConnectionGridCell.TileConnectionStack == firstStackInFirstPathSegment) { tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Begin; } else { tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.End; } } else if (numberOfNeighbours == 2) { if (tileConnectionGridCell.HasLeftAndRightNeighbours() || tileConnectionGridCell.HasForwardAndBackNeightbours()) { tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Forward; } else { tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Turn; } } else if (numberOfNeighbours == 3) { tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.TJunction; } else { tileConnectionGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Cross; } } }
public List <ObjectPlacementPathTileConnectionGridCell> Detect(ObjectPlacementPath path, float tileXZSize) { _tileXZSize = tileXZSize; List <ObjectPlacementBoxStackSegment> allPathSegments = path.GetAllSegments(); if (allPathSegments.Count == 0) { return(new List <ObjectPlacementPathTileConnectionGridCell>()); } // Create the grid cell instances which are occupied by tiles Vector3 gridOrigin = path.ExtensionPlane.ProjectPoint(allPathSegments[0].GetStackByIndex(0).BasePosition); var tileConnectionGrid = new ObjectPlacementPathTileConnectionGrid(_tileXZSize, gridOrigin, path); foreach (ObjectPlacementBoxStackSegment segment in allPathSegments) { for (int stackIndex = 0; stackIndex < segment.NumberOfStacks; ++stackIndex) { ObjectPlacementBoxStack stack = segment.GetStackByIndex(stackIndex); if (stack.IsOverlappedByAnotherStack) { continue; } var tileConnectionGridCell = new ObjectPlacementPathTileConnectionGridCell(tileConnectionGrid.CalculateCellIndicesFromPosition(stack.BasePosition), tileConnectionGrid); tileConnectionGridCell.TileConnectionSegment = segment; tileConnectionGridCell.TileConnectionStack = stack; tileConnectionGridCell.TileConnectionPath = path; if (!tileConnectionGrid.IsCellOccupied(tileConnectionGridCell.CellIndices)) { tileConnectionGrid.AddCell(tileConnectionGridCell); } } } tileConnectionGrid.EstablishCellNeighbours(); tileConnectionGrid.DetectTileConnectionTypesForAllOccupiedCells(); return(tileConnectionGrid.OccupiedTileConnectionCells); }
public Quaternion Calculate(ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell) { ObjectPlacementPath path = tileConnectionGridCell.TileConnectionPath; ObjectPlacementPathTileConnectionSettings tileConnectionSettings = path.Settings.TileConnectionSettings; Plane extensionPlane = path.ExtensionPlane; ObjectPlacementBoxStackSegment tileConnectionSegment = tileConnectionGridCell.TileConnectionSegment; ObjectPlacementBoxStack tileConnectionStack = tileConnectionGridCell.TileConnectionStack; bool usingSprites = tileConnectionSettings.UsesSprites(); float yAxisRotationInDegrees = ObjectPlacementPathTileConnectionYAxisRotations.GetAngleInDegrees(tileConnectionSettings.GetSettingsForTileConnectionType(tileConnectionGridCell.TileConnectionType).YAxisRotation); Quaternion yAxisRotation = Quaternion.AngleAxis(yAxisRotationInDegrees, extensionPlane.normal); Quaternion defaultRotation = Quaternion.LookRotation(path.ExtensionPlaneLookAxis, extensionPlane.normal); if (usingSprites) { defaultRotation = Quaternion.LookRotation(extensionPlane.normal, path.ExtensionPlaneLookAxis); } ObjectPlacementPathTileConnectionType tileConnectionType = tileConnectionGridCell.TileConnectionType; if (tileConnectionType == ObjectPlacementPathTileConnectionType.Autofill) { return(yAxisRotation * defaultRotation); } else if (tileConnectionType == ObjectPlacementPathTileConnectionType.Begin) { if (tileConnectionGridCell.NumberOfNeighbours == 0) { return(yAxisRotation * defaultRotation); } else { ObjectPlacementBoxStack neighbour = tileConnectionGridCell.GetFirstNeighbour().TileConnectionStack; Vector3 toNeighbour = tileConnectionStack.GetNormalizedBasePositionConnectionVectorTo(neighbour); if (usingSprites) { return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toNeighbour)); } return(yAxisRotation * Quaternion.LookRotation(toNeighbour, extensionPlane.normal)); } } else if (tileConnectionType == ObjectPlacementPathTileConnectionType.End) { ObjectPlacementBoxStack neighbour = tileConnectionGridCell.GetFirstNeighbour().TileConnectionStack; Vector3 toEndTile = neighbour.GetNormalizedBasePositionConnectionVectorTo(tileConnectionStack); if (usingSprites) { return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toEndTile)); } return(yAxisRotation * Quaternion.LookRotation(toEndTile, extensionPlane.normal)); } else if (tileConnectionType == ObjectPlacementPathTileConnectionType.Cross) { return(yAxisRotation * defaultRotation); } else if (tileConnectionType == ObjectPlacementPathTileConnectionType.TJunction) { ObjectPlacementBoxStack baseOfTJunction = null; if (tileConnectionGridCell.RightNeighbour != null && tileConnectionGridCell.LeftNeighbour != null) { baseOfTJunction = tileConnectionGridCell.ForwardNeighbour != null ? tileConnectionGridCell.ForwardNeighbour.TileConnectionStack : tileConnectionGridCell.BackNeighbour.TileConnectionStack; } else { baseOfTJunction = tileConnectionGridCell.RightNeighbour != null ? tileConnectionGridCell.RightNeighbour.TileConnectionStack : tileConnectionGridCell.LeftNeighbour.TileConnectionStack; } Vector3 toTJunction = baseOfTJunction.GetNormalizedBasePositionConnectionVectorTo(tileConnectionStack); if (usingSprites) { return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toTJunction)); } return(yAxisRotation * Quaternion.LookRotation(toTJunction, extensionPlane.normal)); } else if (tileConnectionType == ObjectPlacementPathTileConnectionType.Forward) { if (tileConnectionSegment.NumberOfStacks == 1) { if (tileConnectionGridCell.HasForwardAndBackNeightbours()) { ObjectPlacementBoxStack forwardNeighbour = tileConnectionGridCell.ForwardNeighbour.TileConnectionStack; ObjectPlacementBoxStack backNeighbour = tileConnectionGridCell.BackNeighbour.TileConnectionStack; Vector3 toForwardNeighbour = backNeighbour.GetNormalizedBasePositionConnectionVectorTo(forwardNeighbour); if (usingSprites) { return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toForwardNeighbour)); } return(yAxisRotation * Quaternion.LookRotation(toForwardNeighbour, extensionPlane.normal)); } else { ObjectPlacementBoxStack leftNeighbour = tileConnectionGridCell.LeftNeighbour.TileConnectionStack; ObjectPlacementBoxStack rightNeighbour = tileConnectionGridCell.RightNeighbour.TileConnectionStack; Vector3 toRightNeighbour = leftNeighbour.GetNormalizedBasePositionConnectionVectorTo(rightNeighbour); if (usingSprites) { return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, toRightNeighbour)); } return(yAxisRotation * Quaternion.LookRotation(toRightNeighbour, extensionPlane.normal)); } } else { if (usingSprites) { return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, tileConnectionSegment.ExtensionDirection)); } return(yAxisRotation * Quaternion.LookRotation(tileConnectionSegment.ExtensionDirection, extensionPlane.normal)); } } else { ObjectPlacementBoxStack firstNeighbour, secondNeighbour; if (tileConnectionGridCell.RightNeighbour != null) { firstNeighbour = tileConnectionGridCell.RightNeighbour.TileConnectionStack; secondNeighbour = tileConnectionGridCell.ForwardNeighbour != null ? tileConnectionGridCell.ForwardNeighbour.TileConnectionStack : tileConnectionGridCell.BackNeighbour.TileConnectionStack; } else if (tileConnectionGridCell.LeftNeighbour != null) { firstNeighbour = tileConnectionGridCell.LeftNeighbour.TileConnectionStack; secondNeighbour = tileConnectionGridCell.ForwardNeighbour != null ? tileConnectionGridCell.ForwardNeighbour.TileConnectionStack : tileConnectionGridCell.BackNeighbour.TileConnectionStack; } else if (tileConnectionGridCell.ForwardNeighbour != null) { firstNeighbour = tileConnectionGridCell.ForwardNeighbour.TileConnectionStack; secondNeighbour = tileConnectionGridCell.RightNeighbour != null ? tileConnectionGridCell.RightNeighbour.TileConnectionStack : tileConnectionGridCell.LeftNeighbour.TileConnectionStack; } else { firstNeighbour = tileConnectionGridCell.BackNeighbour.TileConnectionStack; secondNeighbour = tileConnectionGridCell.RightNeighbour != null ? tileConnectionGridCell.RightNeighbour.TileConnectionStack : tileConnectionGridCell.LeftNeighbour.TileConnectionStack; } Vector3 tileLook, tileRight; tileLook = firstNeighbour.GetNormalizedBasePositionConnectionVectorTo(tileConnectionStack); tileRight = tileConnectionStack.GetNormalizedBasePositionConnectionVectorTo(secondNeighbour); Vector3 tileUp = Vector3.Cross(tileLook, tileRight); if (Vector3.Dot(tileUp, extensionPlane.normal) < 0.0f) { tileLook = -tileRight; } if (usingSprites) { return(yAxisRotation * Quaternion.LookRotation(extensionPlane.normal, tileLook)); } return(yAxisRotation * Quaternion.LookRotation(tileLook, extensionPlane.normal)); } }
public static List <OrientedBox> GetTileConnectionExtrusionOrientedBoxes(ObjectPlacementPathTileConnectionGridCell tileConnectionGridCell) { ObjectPlacementBoxStack tileConnectionStack = tileConnectionGridCell.TileConnectionStack; ObjectPlacementPathTileConnectionTypeSettings tileConnectionTypeSettings = tileConnectionGridCell.TileConnectionPath.Settings.TileConnectionSettings.GetSettingsForTileConnectionType(tileConnectionGridCell.TileConnectionType); if (tileConnectionStack != null) { if (tileConnectionStack.NumberOfBoxes == 0) { return(new List <OrientedBox>()); } if (tileConnectionTypeSettings.IsAnyExtrusionNecessary()) { // Handle upwards extrusion Vector3 nextTilePositionForUpwardsExtrusion; Vector3 extrudeOffset; Vector3 pathExtensionPlaneNormal = tileConnectionGridCell.TileConnectionPath.ExtensionPlane.normal; var tileConnectionYOffsetVectorCalculator = new ObjectPlacementPathTileConnectionYOffsetVectorCalculator(); Vector3 yOffsetVector = tileConnectionYOffsetVectorCalculator.Calculate(tileConnectionTypeSettings, tileConnectionGridCell.TileConnectionPath); extrudeOffset = pathExtensionPlaneNormal * tileConnectionStack.GetBoxSizeAlongNormalizedDirection(pathExtensionPlaneNormal); if (tileConnectionStack.IsGrowingUpwards) { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(tileConnectionStack.NumberOfBoxes - 1).Center + extrudeOffset; } else { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(0).Center + extrudeOffset; } var extrudedBox = new OrientedBox(); extrudedBox.Rotation = tileConnectionStack.Rotation; extrudedBox.ModelSpaceSize = tileConnectionStack.BoxSize; var extrusionOrientedBoxes = new List <OrientedBox>(); for (int extrudeIndex = 0; extrudeIndex < tileConnectionTypeSettings.UpwardsExtrusionAmount; ++extrudeIndex) { extrudedBox.Center = nextTilePositionForUpwardsExtrusion + yOffsetVector; extrusionOrientedBoxes.Add(new OrientedBox(extrudedBox)); nextTilePositionForUpwardsExtrusion += extrudeOffset; } // Handle downwards extrusion extrudeOffset = -pathExtensionPlaneNormal *tileConnectionStack.GetBoxSizeAlongNormalizedDirection(pathExtensionPlaneNormal); if (tileConnectionStack.IsGrowingDownwards) { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(tileConnectionStack.NumberOfBoxes - 1).Center + extrudeOffset; } else { nextTilePositionForUpwardsExtrusion = tileConnectionStack.GetBoxByIndex(0).Center + extrudeOffset; } for (int extrudeIndex = 0; extrudeIndex < tileConnectionTypeSettings.DownwardsExtrusionAmount; ++extrudeIndex) { extrudedBox.Center = nextTilePositionForUpwardsExtrusion + yOffsetVector; extrusionOrientedBoxes.Add(new OrientedBox(extrudedBox)); nextTilePositionForUpwardsExtrusion += extrudeOffset; } return(extrusionOrientedBoxes); } else { return(new List <OrientedBox>()); } } else { return(new List <OrientedBox>()); } }
public List <ObjectPlacementPathTileConnectionGridCell> CreateAndReturnAutofillTileConnectionCells() { ObjectPlacementPathTileConnectionSettings tileConnectionSettings = _path.Settings.TileConnectionSettings; if (!tileConnectionSettings.DoesAutofillTileConnectionHavePrefabAssociated()) { return(new List <ObjectPlacementPathTileConnectionGridCell>()); } Plane pathExtensionPlane = _path.ExtensionPlane; OrientedBox autofillPrefabOrientedBox = tileConnectionSettings.GetSettingsForTileConnectionType(ObjectPlacementPathTileConnectionType.Autofill).Prefab.UnityPrefab.GetHierarchyWorldOrientedBox(); Vector3 autofillStackBoxSize = new Vector3(_cellXZSize, autofillPrefabOrientedBox.ScaledSize.y, _cellXZSize); Quaternion autofillStackRotation = Quaternion.LookRotation(_path.ExtensionPlaneLookAxis, pathExtensionPlane.normal); bool[,] cellAutofillFlags = new bool[NumberOfCellsOnX, NumberOfCellsOnZ]; // We will first set all occupied cells to true foreach (var pair in _occupiedCells) { cellAutofillFlags[pair.Key.XIndex - MinCellIndexX, pair.Key.ZIndex - MinCellIndexZ] = true; } var autofillGridCells = new List <ObjectPlacementPathTileConnectionGridCell>(NumberOfCellsOnX * NumberOfCellsOnZ); for (int z = MinCellIndexZ; z <= MaxCellIndexZ; ++z) { for (int x = MinCellIndexX; x <= MaxCellIndexX; ++x) { if (cellAutofillFlags[x - MinCellIndexX, z - MinCellIndexZ]) { continue; } var traversedIndices = new HashSet <ObjectPlacementPathTileConnectionGridCellIndices>(); if (DetectCellsWhichLeadOutsideOfGridRecurse(cellAutofillFlags, x, z, traversedIndices)) { foreach (ObjectPlacementPathTileConnectionGridCellIndices indices in traversedIndices) { cellAutofillFlags[indices.XIndex - MinCellIndexX, indices.ZIndex - MinCellIndexZ] = true; } } if (!cellAutofillFlags[x - MinCellIndexX, z - MinCellIndexZ]) { var autofillGridCell = new ObjectPlacementPathTileConnectionGridCell(new ObjectPlacementPathTileConnectionGridCellIndices(x, z), this); autofillGridCells.Add(autofillGridCell); AddCell(autofillGridCell); var tileConnectionStack = new ObjectPlacementBoxStack(); tileConnectionStack.SetBoxSize(autofillStackBoxSize); tileConnectionStack.SetRotation(autofillStackRotation); tileConnectionStack.SetBasePosition(CalculateCellPosition(x, z)); tileConnectionStack.PlaceOnPlane(pathExtensionPlane); tileConnectionStack.GrowUpwards(1); autofillGridCell.TileConnectionStack = tileConnectionStack; autofillGridCell.TileConnectionPath = _path; autofillGridCell.TileConnectionType = ObjectPlacementPathTileConnectionType.Autofill; } } } return(autofillGridCells); }
public void AddCell(ObjectPlacementPathTileConnectionGridCell cell) { _occupiedCells.Add(cell.CellIndices, cell); _cellLimitsAreDirty = true; }