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();
         }
     }
 }
예제 #2
0
        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));
                }
            }
        }
예제 #3
0
        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;
                }
            }
        }
예제 #4
0
        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));
            }
        }
예제 #6
0
        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>());
            }
        }
예제 #7
0
        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);
        }
예제 #8
0
 public void AddCell(ObjectPlacementPathTileConnectionGridCell cell)
 {
     _occupiedCells.Add(cell.CellIndices, cell);
     _cellLimitsAreDirty = true;
 }