/**
     * Sets prop location to just infront of the wall sprite it is attached to.
     */
    Vector3 WallPropLocationFix(Vector2Int spriteSize, Vector2Int spriteLocation, SpritePositionType relativePos)
    {
        Vector3 propPosition = WallSpriteLocationFix(spriteSize, spriteLocation, relativePos);
        float   propXPos     = propPosition.x;
        float   propZPos     = propPosition.z;

        switch (relativePos)
        {
        case SpritePositionType.Left:
            propXPos += 0.01f;
            break;

        case SpritePositionType.Right:
            propXPos -= 0.01f;
            break;

        case SpritePositionType.Top:
            propZPos -= 0.01f;
            break;

        case SpritePositionType.Bottom:
            propZPos += 0.01f;
            break;
        }

        return(new Vector3(propXPos, propPosition.y, propZPos));
    }
    /**
     * Changes a sprite position to be placed as if it's center of transformation
     * is on the bottom left side of the sprite, and not the centre of the sprite.
     */
    Vector3 SpriteLocationFix(Vector2Int spriteSize, Vector2Int spriteLocation, SpritePositionType relativePos)
    {
        float spriteLocationX = spriteLocation.x + (spriteSize.x / 2.0f);
        float spriteLocationZ = spriteLocation.y + (spriteSize.y / 2.0f);
        float spriteLocationY = 0.0f;

        if (relativePos != SpritePositionType.None)
        {
            spriteLocationY = 0.5f;

            if (relativePos == SpritePositionType.Left)
            {
                spriteLocationX = spriteLocation.x;
            }
            else if (relativePos == SpritePositionType.Right)
            {
                spriteLocationX = spriteLocation.x + spriteSize.x;
            }

            if (relativePos == SpritePositionType.Top)
            {
                spriteLocationZ = spriteLocation.y + spriteSize.x;
            }
            else if (relativePos == SpritePositionType.Bottom)
            {
                spriteLocationZ = spriteLocation.y;
            }
        }

        return(new Vector3(spriteLocationX, spriteLocationY, spriteLocationZ));
    }
    void PlaceHallway(Vector2Int location)
    {
        if (!DetectSprite(FloorSpriteLocationFix(new Vector2Int(1, 1), location)))
        {
            /*
             * Before creating hallways, the program must find out what walls to delete, and learn the hallways relative
             * position, based on the deleted walls.
             */
            Vector3 wallDetection = FloorSpriteLocationFix(new Vector2Int(1, 1), location);
            wallDetection = new Vector3(wallDetection.x, wallDetection.y + 0.7f, wallDetection.z);
            int        layer      = 1 << LayerMask.NameToLayer("Environment");
            Collider[] wallsFound = Physics.OverlapSphere(wallDetection, 0.6f, layer);

            SpritePositionType hallwayWalls = (
                SpritePositionType.Top |
                SpritePositionType.Bottom |
                SpritePositionType.Left |
                SpritePositionType.Right);

            foreach (Collider wall in wallsFound)
            {
                if (!wall.tag.Equals("Prop"))
                {
                    float wallXPos = wall.gameObject.transform.position.x;
                    float wallZPos = wall.gameObject.transform.position.z;

                    if (wallXPos > wallDetection.x)
                    {
                        hallwayWalls = hallwayWalls & ~SpritePositionType.Right;
                    }
                    if (wallXPos < wallDetection.x)
                    {
                        hallwayWalls = hallwayWalls & ~SpritePositionType.Left;
                    }
                    if (wallZPos > wallDetection.z)
                    {
                        hallwayWalls = hallwayWalls & ~SpritePositionType.Top;
                    }
                    if (wallZPos < wallDetection.z)
                    {
                        hallwayWalls = hallwayWalls & ~SpritePositionType.Bottom;
                    }
                }

                Destroy(wall.gameObject);
            }

            PlaceFloorSprite(location, new Vector2Int(1, 1), "Hallway");
            PlaceWallSprite(location, new Vector2Int(1, 1), hallwayWalls);
        }
    }
    //Modified to place a sprite on each unit of a room.
    void PlaceRoom(Vector2Int location, Vector2Int size)
    {
        for (int i = 0; i < size.x; i++)
        {
            for (int j = 0; j < size.y; j++)
            {
                SpritePositionType spriteRelativePosition = GetSpriteRelativePosition(i, j, size);

                Vector2Int nextSpriteLocation = new Vector2Int(location.x + i, location.y + j);
                PlaceFloorSprite(nextSpriteLocation, new Vector2Int(1, 1), "Room");
                PlaceWallSprite(nextSpriteLocation, new Vector2Int(1, 1), spriteRelativePosition);
            }
        }
    }
    //Method to calculate a sprites position, to understand where walls should be placed.
    SpritePositionType GetSpriteRelativePosition(int xPos, int yPos, Vector2Int size)
    {
        SpritePositionType position = SpritePositionType.None;

        if (xPos == 0)
        {
            position = position | SpritePositionType.Left;
        }
        if (xPos == (size.x - 1))
        {
            position = position | SpritePositionType.Right;
        }
        if (yPos == 0)
        {
            position = position | SpritePositionType.Bottom;
        }
        if (yPos == (size.y - 1))
        {
            position = position | SpritePositionType.Top;
        }

        return(position);
    }
    //Created to place a wall at given flags, with appropriate positions and rotation.
    void PlaceWallSprite(Vector2Int location, Vector2Int size, SpritePositionType relativePos)
    {
        SpritePositionType[] allWallTypes =
        {
            SpritePositionType.Top,
            SpritePositionType.Right,
            SpritePositionType.Bottom,
            SpritePositionType.Left
        };

        if ((relativePos | SpritePositionType.None) != SpritePositionType.None)
        {
            for (int i = 0; i < allWallTypes.Length; i++)
            {
                GameObject         wall       = null;
                SpritePositionType currentPos = relativePos & allWallTypes[i];
                int placePropChance           = random.Next() % 3;

                if (currentPos == allWallTypes[i])
                {
                    wall = Instantiate(NextSprite(wallPrefabs), WallSpriteLocationFix(size, location, currentPos), Quaternion.identity);
                    wall.GetComponent <Transform>().rotation = Quaternion.Euler(0, 90 * i, 0);
                }
                if (wall != null)
                {
                    wall.GetComponent <Transform>().localScale = new Vector3(size.x, size.y, 1);

                    if (placePropChance == 0)
                    {
                        GameObject prop = Instantiate(NextSprite(wallProps), WallPropLocationFix(size, location, currentPos), Quaternion.identity);
                        prop.GetComponent <Transform>().localScale = new Vector3(size.x, size.y, 1);
                        prop.GetComponent <Transform>().rotation   = Quaternion.Euler(0, 90 * i, 0);
                    }
                }
            }
        }
    }
    int GetCornerRoofTiles(Vector3 originalDetector)
    {
        SpritePositionType wallPositions = SpritePositionType.None;

        Vector3 extendedDetector = new Vector3(
            originalDetector.x,
            originalDetector.y,
            originalDetector.z);

        Collider[] wallsFound = Physics.OverlapSphere(extendedDetector, 1.0f);

        int arrayLocation;

        foreach (Collider wall in wallsFound)
        {
            float wallXPos = wall.gameObject.transform.position.x;
            float wallZPos = wall.gameObject.transform.position.z;

            if (wallXPos > extendedDetector.x)
            {
                wallPositions |= SpritePositionType.Right;
            }
            if (wallXPos < extendedDetector.x)
            {
                wallPositions |= SpritePositionType.Left;
            }
            if (wallZPos > extendedDetector.z)
            {
                wallPositions |= SpritePositionType.Top;
            }
            if (wallZPos < extendedDetector.z)
            {
                wallPositions |= SpritePositionType.Bottom;
            }
        }

        switch (wallPositions)
        {
        case SpritePositionType.Top | SpritePositionType.Left:
            arrayLocation = 16;
            break;

        case SpritePositionType.Top | SpritePositionType.Right:
            arrayLocation = 17;
            break;

        case SpritePositionType.Bottom | SpritePositionType.Left:
            arrayLocation = 18;
            break;

        case SpritePositionType.Bottom | SpritePositionType.Right:
            arrayLocation = 19;
            break;

        default:
            arrayLocation = 0;
            break;
        }

        return(arrayLocation);
    }
    //Used to get the required roof tile, based on the walls closest to the roof tile.
    GameObject GetRoofTile(Vector3 location)
    {
        SpritePositionType wallPositions = SpritePositionType.None;

        Vector3 wallDetector = new Vector3(location.x, location.y + 0.7f, location.z);

        Collider[] wallsFound = Physics.OverlapSphere(wallDetector, 0.6f);

        int arrayLocation;

        foreach (Collider wall in wallsFound)
        {
            float wallXPos = wall.gameObject.transform.position.x;
            float wallZPos = wall.gameObject.transform.position.z;

            if (wallXPos > wallDetector.x)
            {
                wallPositions |= SpritePositionType.Right;
            }
            if (wallXPos < wallDetector.x)
            {
                wallPositions |= SpritePositionType.Left;
            }
            if (wallZPos > wallDetector.z)
            {
                wallPositions |= SpritePositionType.Top;
            }
            if (wallZPos < wallDetector.z)
            {
                wallPositions |= SpritePositionType.Bottom;
            }
        }

        switch (wallPositions)
        {
        case SpritePositionType.Top:
            arrayLocation = 1;
            break;

        case SpritePositionType.Bottom:
            arrayLocation = 2;
            break;

        case SpritePositionType.Left:
            arrayLocation = 3;
            break;

        case SpritePositionType.Right:
            arrayLocation = 4;
            break;

        case SpritePositionType.Top | SpritePositionType.Left:
            arrayLocation = 5;
            break;

        case SpritePositionType.Top | SpritePositionType.Right:
            arrayLocation = 6;
            break;

        case SpritePositionType.Bottom | SpritePositionType.Left:
            arrayLocation = 7;
            break;

        case SpritePositionType.Bottom | SpritePositionType.Right:
            arrayLocation = 8;
            break;

        case SpritePositionType.Top | SpritePositionType.Bottom:
            arrayLocation = 9;
            break;

        case SpritePositionType.Left | SpritePositionType.Right:
            arrayLocation = 10;
            break;

        case SpritePositionType.Top | SpritePositionType.Left | SpritePositionType.Right:
            arrayLocation = 11;
            break;

        case SpritePositionType.Bottom | SpritePositionType.Left | SpritePositionType.Right:
            arrayLocation = 12;
            break;

        case SpritePositionType.Top | SpritePositionType.Bottom | SpritePositionType.Left:
            arrayLocation = 13;
            break;

        case SpritePositionType.Top | SpritePositionType.Bottom | SpritePositionType.Right:
            arrayLocation = 14;
            break;

        case SpritePositionType.Top | SpritePositionType.Bottom | SpritePositionType.Left | SpritePositionType.Right:
            arrayLocation = 15;
            break;

        default:
            arrayLocation = GetCornerRoofTiles(wallDetector);
            break;
        }

        return(roofPrefabs[arrayLocation]);
    }
 Vector3 WallSpriteLocationFix(Vector2Int spriteSize, Vector2Int spriteLocation, SpritePositionType relativePos)
 {
     return(SpriteLocationFix(spriteSize, spriteLocation, relativePos));
 }