/// <summary> /// Places a worldobject at a position with a direction /// </summary> /// <param name="worldObject">worldobject</param> /// <param name="position">position</param> /// <param name="wallNormal">direction</param> public void Place(WorldObject worldObject, Vector3 position, Vector3 wallNormal) { BootStrapper.EnvironmentManager.CurrentEnvironment.Place(worldObject, position); worldObject.InitialWallNormal = wallNormal; worldObject.LookTowardsNormal(wallNormal); BarPlacement.RecalcBars(); StagePlacement.RecalcStages(); }
/// <summary> /// <para>Returns an int[4] representing the four sides of <paramref name="obj"/></para> /// <para>Each number represents if that side is blocked by another WorldObject</para> /// <para>[0]: if 1, then left of <paramref name="obj"/> is blocked</para> /// <para>[1]: if 1, then right of <paramref name="obj"/> is blocked</para> /// <para>[2]: if 1, then up of <paramref name="obj"/> is blocked</para> /// <para>[3]: if 1, then down of <paramref name="obj"/> is blocked</para> /// </summary> /// <param name="obj">The WorldObject you wish to see has blocked sides</param> /// <returns>int[4] representing which directions are blocked by other WorldObjects</returns> private static int[] directionsBlocked(WorldObject obj) { Vector3 position = obj.GameObject.transform.position; Vector3 offsetX = new Vector3(obj.Size.x/2 + WhiskerDepth, 0, 0); Vector3 offsetZ = new Vector3(0, 0, obj.Size.z/2 + WhiskerDepth); int[] directionsBlocked = new int[4]; directionsBlocked[0] = IsSpaceAlreadyOccupied(position - offsetX); directionsBlocked[1] = IsSpaceAlreadyOccupied(position + offsetX); directionsBlocked[2] = IsSpaceAlreadyOccupied(position - offsetZ); directionsBlocked[3] = IsSpaceAlreadyOccupied(position + offsetZ); return directionsBlocked; }
/// <summary> /// Places a few worldobjects in a line /// </summary> /// <param name="start">The placement start point</param> /// <param name="end">The placement end point</param> /// <param name="wallNormal">the direction</param> /// <param name="objectName">the object to place</param> /// <returns>list of placed worldobjects</returns> public WorldObject[] PlaceLine(Vector3 start, Vector3 end, Vector3 wallNormal, String objectName) { Vector3 step; var xDiff = start.x - end.x; var zDiff = start.z - end.z; int largerDiff; if (Mathf.Abs(xDiff) > Mathf.Abs(zDiff)) { step = new Vector3(-Mathf.Sign(xDiff), 0, 0); largerDiff = (int)Mathf.Abs(xDiff); } else { step = new Vector3(0, 0, -Mathf.Sign(zDiff)); largerDiff = (int)Mathf.Abs(zDiff); } Vector3 position = start; WorldObject[] createdWorldObjects = new WorldObject[largerDiff + 1]; for (int i = 0; i <= largerDiff; i++) { var currentWorldObject = WorldObject.DetermineObject(objectName); createdWorldObjects[i] = currentWorldObject; currentWorldObject.AdjustSizing(wallNormal); Place(currentWorldObject, position, wallNormal); position += step; } return createdWorldObjects; }
/// <summary> /// Stores relevant information about a particular worldObject to save it to a file /// </summary> /// <param name="worldObject">the object to save</param> public void SaveWorldObject(WorldObject worldObject) { saveableItems.Add(new WorldObjectBuildInfo(worldObject)); }
/// <summary> /// Places a worldobject at a position with a direction /// </summary> /// <param name="worldObject">worldobject</param> /// <param name="position">position</param> public void Place(WorldObject worldObject, Vector3 position) { BootStrapper.EnvironmentManager.CurrentEnvironment.Place(worldObject, position); BarPlacement.RecalcBars(); StagePlacement.RecalcStages(); }
/// <summary> /// Sees if the cursor is over a wall and if a worldobject is placeable on it /// </summary> /// <param name="normal">normal</param> /// <param name="position">position</param> /// <param name="cursor">object to place</param> /// <returns>true if placement possible</returns> public bool WallPlacement(out Vector3 normal, out Vector3 position, WorldObject cursor) { //is the cursor over a wall RaycastHit hit; GameObject gameObject; if (UserWorldBuilder.Raycast(out hit, out gameObject)) { if (gameObject.name.Contains(Wall.IdentifierStatic)) { Vector3 firstWallPosition = hit.transform.position; normal = hit.normal; if (normal.y == 0) { //only wall sides, not the tops //perpendicular vector to normal (right vector from point of view of normal) Vector3 crossRight = Vector3.Cross(Vector3.up, normal).normalized; cursor.LookTowardsNormal(normal); float requiredWidth = cursor.Size.x; Vector3 leftMostWall = firstWallPosition; Vector3 rightMostWall = firstWallPosition; //Scans and checks existance of walls left and right of the selected wall int count = 1; Vector3 scanPosition = firstWallPosition; for (int i = 0; i < requiredWidth - 1; i++) { if (count >= requiredWidth) break; scanPosition += crossRight; if ( BootStrapper.EnvironmentManager.CurrentEnvironment.World.PointAlreadyOccupied( scanPosition)) { count++; rightMostWall = scanPosition; } else { scanPosition = firstWallPosition; for (int j = 0; j < requiredWidth - 1; j++) { if (count >= requiredWidth) break; scanPosition -= crossRight; if ( BootStrapper.EnvironmentManager.CurrentEnvironment.World .PointAlreadyOccupied(scanPosition)) { count++; leftMostWall = scanPosition; } else { break; } } break; } } //if walls are sufficiently wide, then calculate position of wall placed world object if (count >= requiredWidth) { Vector3 centerWall = (leftMostWall + rightMostWall) / 2; Vector3 requiredDepth = normal * (cursor.Size.z / 2); Vector3 wallOffset = normal * (Wall.SizeStatic.z / 2); position = centerWall + requiredDepth + wallOffset; return true; } } } } position = Vector3.zero; normal = Vector3.zero; return false; }
/// <summary> /// Places the <paramref name="worldObject"/> at <paramref name="position"/> /// </summary> /// <param name="worldObject">the object to place</param> /// <param name="position">the position to place it</param> public void Place(WorldObject worldObject, Vector3 position) { Vector3 location; if (worldObject.GridPlaceable) { location = PositionToGridLocation(position, worldObject.Size); } else { location = PositionToLocation(position, worldObject.Size); } World.AddObject(WorldObject.Initialise(worldObject, location, Vector3.zero)); }
/// <summary> /// Gets the Quaternion result of rotating from <paramref name="obj"/>'s current rotation to the angle of <paramref name="yVal"/> /// </summary> /// <param name="obj">The Object to rotate</param> /// <param name="yVal">The angle to rotate to</param> /// <returns>The angle to rotate by</returns> private static Quaternion rotateToY(WorldObject obj, int yVal) { return Quaternion.Euler(obj.GameObject.transform.rotation.eulerAngles.x, yVal, obj.GameObject.transform.rotation.eulerAngles.z); }
/// <summary> /// Initialise the game object into the environment /// </summary> /// <param name="worldObject">The world object to initialise</param> /// <param name="position">Position within the environment</param> /// <param name="wallNormal">The facing direction</param> /// <returns>Initialised WorldObject</returns> public static WorldObject Initialise(WorldObject worldObject, Vector3 position, Vector3 wallNormal) { worldObject.InitialWallNormal = Vector3.zero; worldObject.GameObject = (GameObject)BootStrapper.Initialise( worldObject.Identifier, position + worldObject.InitialPositionOffSet, worldObject.InitialRotationOffSet ); return worldObject; }
/// <summary> /// Basic withinbounds checker, simple AABB collision detection /// </summary> /// <param name="worldObject">Another world object</param> /// <returns>If <paramref name="worldObject"/> is overlapping</returns> public bool WithinBounds(WorldObject worldObject) { Vector3 position = GameObject.transform.position; Vector3 halfSize = this.Size / 2; Vector3 otherPosition = worldObject.GameObject.transform.position; Vector3 otherHalfSize = worldObject.Size / 2; var xDifference = Mathf.Abs(position.x - otherPosition.x); var zDifference = Mathf.Abs(position.z - otherPosition.z); var halfWidthSum = halfSize.x + otherHalfSize.x; var halfLengthSum = halfSize.z + otherHalfSize.z; return (xDifference < halfWidthSum) && (zDifference < halfLengthSum); //AABB }
/// <summary> /// Sets the current placement object /// </summary> /// <param name="objectName">new placement object</param> /// <param name="groundPosition">current ground position</param> public void SetPlacementObject(string objectName, Vector3 groundPosition) { currentItem = objectName; DestroyCursors(); primaryCursor = NewCursor(WorldObject.DetermineObject(objectName), groundPosition); }
/// <summary> /// Sets a cursor material to green /// </summary> /// <param name="cursor">cursor</param> private void SetCursorValid(WorldObject cursor) { cursor.GameObject.GetComponent<Renderer>().material = cursorMaterial; }
/// <summary> /// Sets height of cursor /// </summary> /// <param name="cursor">cursor</param> private void SetCursorHeight(WorldObject cursor) { var position = cursor.GameObject.transform.position; cursor.GameObject.transform.position = new Vector3(position.x, cursor.CursorHeight.y, position.z); }
/// <summary> /// Creates a new cursor with the given worldobject /// </summary> /// <param name="worldObject">the world object the cursor should look like</param> /// <param name="groundPosition">the position of the cursor</param> /// <returns>the new cursor object</returns> private WorldObject NewCursor(WorldObject worldObject, Vector3 groundPosition) { var cursor = WorldObject.Initialise(worldObject, groundPosition, Vector3.zero); SetCursorValid(cursor); Collider collider = cursor.GameObject.GetComponent<Collider>(); if (collider != null) collider.enabled = false; return cursor; }
/// <summary> /// updates ghost cursor /// </summary> /// <param name="groundPosition">current ground position</param> public void UpdateSecondaryCursor(Vector3 groundPosition) { //secondary cursor for drag to place secondCursor = NewCursor(WorldObject.DetermineObject(currentItem), groundPosition); Vector3 mousePosition = groundPosition; Vector3 secondCursorPosition; var xDiff = startPlacement.x - mousePosition.x; var zDiff = startPlacement.z - mousePosition.z; if (Mathf.Abs(xDiff) > Mathf.Abs(zDiff)) { secondCursorPosition = startPlacement + new Vector3(-xDiff, 0, 0); } else { secondCursorPosition = startPlacement + new Vector3(0, 0, -zDiff); } secondCursor.GameObject.transform.position = Environment.Environment.PositionToLocation(secondCursorPosition, primaryCursor.Size); SetCursorHeight(secondCursor); secondCursor.GameObject.transform.rotation = primaryCursor.GameObject.transform.rotation; if (!primaryCursor.GridPlaceable) { // wall placement Vector3 position; Vector3 normal; if (worldBuilderPlacement.WallPlacement(out normal, out position, primaryCursor)) { secondCursor.LookTowardsNormal(normal); SetCursorValid(secondCursor); } else { SetCursorInvalid(secondCursor); } } }