示例#1
0
        /// <summary>
        /// This helper function checks to see if there are any object in curIndex cooridnate index. If there are none,
        /// the origIndex must have had a perimeter wall and the wallsToPlace map is acoordingly updated. However, if
        /// there were objects at the curIndex coordinate index, the search continues on and a mutually recursive
        /// call back to GetPerimeterWalls is made.
        /// </summary>
        /// <param name="curIndex">The current coordinate index.</param>
        /// <param name="direction">The direction of the perimeter wall to test for.</param>
        /// <param name="wallsToPlace">The current threaded map of perimeter walls to place.</param>
        /// <param name="visited">The current list of coordinate Indices already visited.</param>
        /// <param name="origIndex"> The coordinate index one step before this, where the perimeter wall will be placed.</param>
        /// <param name="sceneGraphManager"> The active Scene Graph.</param>
        private static void GetPerimeterWallsHelper(IntVector3 curIndex, WWWalls direction,
                                                    Dictionary <IntVector3, WWWalls> wallsToPlace, List <IntVector3> visited, IntVector3 origIndex,
                                                    SceneGraphManager sceneGraphManager)
        {
            // TODO potentially filter out non Floor tiles, and Props.
            List <WWObject> objects = sceneGraphManager.GetObjectsInCoordinateIndex(new Coordinate(curIndex));

            if (objects.Count == 0) // empty coordinate index, must have originated from an coordinate index with a perimeter
            {
                if (wallsToPlace.ContainsKey(origIndex))
                {
                    // append by OR to existing perimeter walls at the coordinate index
                    wallsToPlace[origIndex] = direction | wallsToPlace[origIndex];
                }
                else
                {
                    // add a new entry into wallsToPlace
                    wallsToPlace.Add(origIndex, direction);
                }
            }
            else // search further for a perimeter
            {
                GetPerimeterWalls(wallsToPlace, visited, curIndex, sceneGraphManager);
            }
        }
        /// <summary>
        /// Serializable boolean values are used to make editing metadata in the inspector easier,
        /// but they must be converted to the enum bitflag for use.
        /// </summary>
        /// <returns>WWWalls equivalent to the serializable boolean values set in the inspector.</returns>
        public WWWalls GetWallsEnum()
        {
            WWWalls result = 0;

            if (north)
            {
                result = result | WWWalls.North;
            }
            if (east)
            {
                result = result | WWWalls.East;
            }
            if (south)
            {
                result = result | WWWalls.South;
            }
            if (west)
            {
                result = result | WWWalls.West;
            }
            if (top)
            {
                result = result | WWWalls.Top;
            }
            if (bottom)
            {
                result = result | WWWalls.Bottom;
            }

            return(result);
        }
        /// <see cref="SceneGraphManager.GetWallsAtCoordinate"/>
        public WWWalls GetWallsAtCoordinate(Coordinate coordinate)
        {
            List <WWObject> objects = GetObjectsInCoordinateIndex(coordinate);
            WWWalls         walls   = 0;

            foreach (WWObject obj in objects)
            {
                walls = walls | obj.GetWallsWRotationApplied();
            }
            return(walls);
        }
示例#4
0
        public static WWWalls GetRotatedWWWalls(WWResourceMetadata metadata, int rotation)
        {
            int yRotation = rotation % 360 + (rotation < 0 ? 360 : 0);

            // rotation should only be 1 of 4 discrete values, 0, 90, 180, and 270
            bool isvalidRotation = yRotation == 0 || yRotation == 90 || yRotation == 180 || yRotation == 270 ||
                                   yRotation == 360;

            if (!isvalidRotation)
            {
                Debug.LogError(string.Format("WWWallsHelper : {0} is an invalid rotation.", yRotation));
            }

            bool north;
            bool east;
            bool south;
            bool west;

            if (yRotation == 0 || yRotation == 360)
            {
                north = metadata.wwTileMetadata.wwWallMetadata.north;
                east  = metadata.wwTileMetadata.wwWallMetadata.east;
                south = metadata.wwTileMetadata.wwWallMetadata.south;
                west  = metadata.wwTileMetadata.wwWallMetadata.west;
            }
            else if (yRotation == 90)
            {
                north = metadata.wwTileMetadata.wwWallMetadata.west;
                east  = metadata.wwTileMetadata.wwWallMetadata.north;
                south = metadata.wwTileMetadata.wwWallMetadata.east;
                west  = metadata.wwTileMetadata.wwWallMetadata.south;
            }
            else if (yRotation == 180)
            {
                north = metadata.wwTileMetadata.wwWallMetadata.south;
                east  = metadata.wwTileMetadata.wwWallMetadata.west;
                south = metadata.wwTileMetadata.wwWallMetadata.north;
                west  = metadata.wwTileMetadata.wwWallMetadata.east;
            }
            else // (yRotation == 270)
            {
                north = metadata.wwTileMetadata.wwWallMetadata.east;
                east  = metadata.wwTileMetadata.wwWallMetadata.south;
                south = metadata.wwTileMetadata.wwWallMetadata.west;
                west  = metadata.wwTileMetadata.wwWallMetadata.north;
            }

            bool    top             = metadata.wwTileMetadata.wwWallMetadata.top;
            bool    bottom          = metadata.wwTileMetadata.wwWallMetadata.bottom;
            var     rotatedMetaData = new WWWallMetadata(north, east, south, west, top, bottom);
            WWWalls walls           = rotatedMetaData.GetWallsEnum();

            return(walls);
        }
示例#5
0
        /// <summary>
        /// Loads from the resourceTag a WWObject, then attempts to find a valid rotation for the WWObject,
        /// such that it fits with existing Objects at the specified Coordinate Index, and finally places and
        /// adds the WWObject wall to the active Scene Graph.
        /// </summary>
        /// <param name="coordIndex">The coordinate index for this perimeter wall</param>
        /// <param name="perimeterWallOpening">The direction for the perimeter wall</param>
        /// <param name="resourceTag">The resource tag for of the WWObject to place as the perimeter wall.</param>
        private static void TryToPlaceWall(IntVector3 coordIndex, WWWalls perimeterWallOpening, string resourceTag)
        {
            // the collisions that need to be taken into account to see if the WWObject belonging to resourceTag can fit
            WWWalls wallsToFit = ~perimeterWallOpening |
                                 ManagerRegistry.Instance.GetAnInstance <SceneGraphManager>().
                                 GetWallsAtCoordinate(new Coordinate(coordIndex));
            WWResource         resource         = WWResourceController.GetResource(resourceTag);
            WWResourceMetadata resourceMetadata = resource.GetMetaData();

            // Try possible rotations for the resource, and place the resource at the first rotation that fits.
            for (var r = 0; r < 360; r += 90) // only rotations of 90 degrees are valid
            {
                WWWalls wallToPlace = WWWallsHelper.GetRotatedWWWalls(resourceMetadata, r);
                bool    doesCollide = Convert.ToBoolean(wallToPlace & wallsToFit); // should be 0 or False if no collision
                if (!doesCollide)
                {
                    PlaceWallObject(coordIndex, r, resourceTag); // add the wall to the active Scene Graph
                    return;                                      // a valid rotation was found for the WWObject, no need to try further rotations
                }
            }
        }
示例#6
0
        /// <summary>
        /// Given a resourceTag, loads the WWObject belonging to the resource and returns a list of all possible
        /// valid rotations for the WWObject that do not collide with existing WWObjects at the given position
        /// in the active Scene Graph. Useful for assisting the player with auto rotation of tiles.
        /// </summary>
        /// <param name="position">The Unity Space position to convert to Coordinate Index to determine valid rotations in.</param>
        /// <param name="resourceTag">The resourceTag belonging to the desired WWObject.</param>
        /// <returns></returns>
        public static List <int> GetPossibleRotations(Vector3 position, string resourceTag)
        {
            var        result     = new List <int>(); // the resulting list of possible rotations, currently empty
            Coordinate coordinate = CoordinateHelper.UnityCoordToWWCoord(position);
            WWWalls    wallsToFit = ManagerRegistry.Instance.GetAnInstance <SceneGraphManager>().GetWallsAtCoordinate(coordinate);

            // check to see if any of the 4 possible rotations would fit given resource's walls
            WWResource         resource         = WWResourceController.GetResource(resourceTag);
            WWResourceMetadata resourceMetadata = resource.GetMetaData();

            for (var r = 0; r < 360; r += 90) // only rotations of 90 degrees are valid
            {
                WWWalls newWalls    = WWWallsHelper.GetRotatedWWWalls(resourceMetadata, r);
                bool    doesCollide = Convert.ToBoolean(newWalls & wallsToFit); // should be 0 or False if no collision
                if (!doesCollide)
                {
                    result.Add(r);
                }
            }
            return(result);
        }
 /// <summary>
 /// Consumes a WWObject and determines whether this object can fit at its current coordinate,
 /// taking into consideration rotation, or if it collides with other WWObjects being maintained
 /// by this data structure. This is private method and it safe to assume that the WWObject being tested
 /// for collision has not yet been added to this data structure. Note: it would be easy to do a Guid
 /// comparison before checking collision if the use case ever arises in the future.
 /// </summary>
 /// <param name="wwObject">The object to test for collision.</param>
 /// <returns>True if the WWObject can fit without colliding given its current coordinate.</returns>
 private bool Collides(WWObject wwObject)
 {
     if (coordinates.ContainsKey(wwObject.GetCoordinate().Index)) // any objects at coordinate?
     {
         List <WWObject> objectsAtCoord = GetObjects(wwObject.GetCoordinate());
         WWWalls         totalWalls     = 0;                                     // this is a bit mask which will keep the running total of wall collisions
         foreach (WWObject obj in objectsAtCoord)                                // only need to do collision checking at the coordinate index
         {
             if (obj.ResourceMetadata.wwObjectMetadata.type.Equals(WWType.Tile)) // ignore non Tile types
             {
                 // get the walls of the WWObject after applying its rotation transformation
                 WWWalls walls = WWWallsHelper.GetRotatedWWWalls(obj.ResourceMetadata, obj.GetRotation());
                 totalWalls = totalWalls | walls; // OR the walls with the running sum stored in totalWalls
             }
         }
         // now get the walls for the object that is being collision checked for
         WWWalls newWalls    = WWWallsHelper.GetRotatedWWWalls(wwObject.ResourceMetadata, wwObject.GetRotation());
         bool    doesCollide = Convert.ToBoolean(newWalls & totalWalls); // 0 or False if no collision
         return(doesCollide);
     }
     return(false); // if there are no objects at the index, obviously there are no collisions
 }