/// <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> /// 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 } } }
/// <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 }
/// <summary> /// Returns the Wall collisions for this WWObject, taking into consideration the object's current rotation. /// </summary> /// <returns>The Wall collisions after applying rotation</returns> public WWWalls GetWallsWRotationApplied() { return(WWWallsHelper.GetRotatedWWWalls(ResourceMetadata, GetRotation())); }