private static bool NeedsAll(BeyondComponent bc, BeyondGroup bg, List <string> templatesList, List <Vector3Int> offsetsList, List <cellSide> cellSides, Vector3Int?optionalGroupPos = null) { if (bg == null) { return(false); } Vector3Int groupPos = (optionalGroupPos != null) ? (Vector3Int)optionalGroupPos : bc.groupPosition; foreach (string templateName in templatesList) { foreach (Vector3Int offset in offsetsList) { bool foundOne = false; foreach (cellSide side in cellSides) { if (IsTemplatePresentHere(bg, groupPos + offset, templateName, side)) { foundOne = true; } } if (!foundOne) { return(false); } } } return(true); }
void StartDrag() { ForwardOffsetBeforeDragging = UIController.Instance.forwardOffset; if (ConstraintController.CanPlace(currentBC)) { string templateName = currentBC.template.name; string name = templateName + "_" + (nbObjectsPlaced++); // Place the first Ghost = still green, still not collidin' TemplateController.PlaceObject(currentBC, name, BC_State.Ghost); draggedBC.Add(currentBC); draggingGroup = currentBC.beyondGroup; lastGroupPosition = currentBC.groupPosition; currentBC = null; CreateNewPlaceableObject(templateName); // TODO : another hardcoded position. Not good. Yet, I must move the currentBC to where I started dragging or else I'm going to drag to some unknown place. currentBC.transform.position = draggedBC[0].transform.position; currentBC.transform.rotation = draggedBC[0].transform.rotation; // Instantiate a big bunch of placeable object based on what we are currently dragging for (int i = 0; i < MaxDraggedObjectCount; i++) { BeyondComponent bc = TemplateController.CreateObject(templateName); //TODO Better names, please name = templateName + "_Ghost" + i; bc.SetBCinGroup(draggingGroup, lastGroupPosition); TemplateController.PlaceObject(bc, name, BC_State.Ghost); bc.gameObject.SetActive(false); draggedBC.Add(bc); } } }
/* * Sets the group of this BC, its position in the gorup, and places the object where it must be */ /* * public void setObjectGroup (BeyondGroup g , Vector3Int p , cellSide cs , bool firstObject=false) * { // TODO should make that more robust : what if g is null ? * unsetObjectGroup(); * if (g!=null) * { * beyondGroup = g ; * groupPosition = p ; * side = cs ; * // The first object should not be offset or rotated by the group, since it sets the group position and rotation * if (!firstObject) * { * // Rotate the pivot offset by the group's rotation * Vector3 rotatedPivotOffset = template.pivotOffset ; * rotatedPivotOffset = g.rotation * rotatedPivotOffset ; * // Then by the sideRotation * rotatedPivotOffset = sideRotation(cs) * rotatedPivotOffset ; * * // Move the object to its template offset position * transform.position += rotatedPivotOffset; * * // Rotate the object by the group's rotation + its cellSide rotation * transform.rotation = g.rotation * sideRotation(cs) ; * } * g.addBeyondComponent(this); * } * } */ public void SetBCinGroup(BeyondGroup g, Vector3Int p, bool firstObject = false) { // TODO should make that more robust : what if g is null ? unsetObjectGroup(); if (g != null) { beyondGroup = g; groupPosition = p; // If this template can only be on a specific side, use it, otherwise determine the side based on the rotation of the BC side = (template.fixedSide == null) ? getSideByRotation(this, g, p) : (cellSide)template.fixedSide; //TODO : Maybe I need one last check based on side : is there really no object here on the same postion and rotation // The first object should not be offset or rotated by the group, since it sets the group position and rotation if (!firstObject) { // Rotate the cell's position to apply the group's rotation Vector3 rotatedCellPosition = Utility.RotateAroundPoint(p, Vector3.zero, g.rotation); // Rotate the pivot's position to apply the group's rotation and the side's rotation Vector3 rotatedPivotOffset = Utility.RotateAroundPoint(template.pivotOffset, Vector3.zero, sideRotation(side) * g.rotation); Vector3 ObjectPosition = g.position + rotatedCellPosition + rotatedPivotOffset; transform.position = ObjectPosition; // Rotate the object by the group's rotation + its cellSide rotation transform.rotation = g.rotation * sideRotation(side); } g.addBeyondComponent(this); } }
private List <BeyondGroup> findCloseGroups(BeyondComponent bc, out BeyondGroup closestGroup) { List <BeyondGroup> result = new List <BeyondGroup>(); // Find the groups that are close to this BeyondComponent Collider[] collidersInGroup = Physics.OverlapBox(bc.transform.position, bc.template.castBox + new Vector3(1f, 1f, 1f) * groupSnapTolerance, bc.transform.rotation, ConstraintController.getBuildingsMask()); closestGroup = null; float minDistance = 0; foreach (Collider c in collidersInGroup) { BeyondComponent collided_bc = c.transform.GetComponent <BeyondComponent>(); if (collided_bc != null && collided_bc.beyondGroup != null) { result.Add(collided_bc.beyondGroup); float distance = Vector3.Distance(bc.transform.position, collided_bc.transform.position); if (closestGroup == null || distance < minDistance) { minDistance = distance; closestGroup = collided_bc.beyondGroup; } } } UIController.Instance.SetClosestGroup(closestGroup); return(result); }
public static bool IsTemplatePresentHere(BeyondGroup group, Vector3Int here, string t_name) { if (group == null) { return(false); } // TODO : With the restriction on Ghosts, I can't snap dragged objects. Is there a way around this ? return(group.BeyondComponentsAt(here).Exists(bc => bc.template.name == t_name && bc.state != BC_State.Ghost)); }
private static bool AndConstraints(BeyondComponent bc, BeyondGroup bg, List <Constraints> lc, Vector3Int?optionalGroupPos = null) { foreach (Constraints c in lc) { if (!CheckConstraints(bc, c, bg, optionalGroupPos)) { return(false); } } return(true); }
private static bool FirstInGroup(BeyondComponent bc, BeyondGroup bg) { if (bg == null) { return(true); // By definition, if there's no group, the bc fulfills this constraint } if (bg.componentList.Count == 1) { return(true); } return(false); }
public void StopDragging() { List <GameObject> objectsPlaced = new List <GameObject>(); GameObject FirstObject = Instantiate(GameObject_DragFrom); BeyondComponent BC_DragFrom = GameObject_DragFrom.GetComponent <BeyondComponent>(); FirstObject.GetComponent <BeyondComponent>().CopyValues(BC_DragFrom); SetBlueprintFromGhost(FirstObject); objectsPlaced.Add(FirstObject); Destroy(GameObject_DragFrom); for (int i = 0; i < draggedObjects.Count; i++) // Note: a for loop is better than a foreach that can miss some objects { // TO DO : We need to check a bit more than that: can't have a bunch of objects split in several groups because they failed constraint. All draggedObject should form 1 block // And, as stated in the AvoidCollision Constraint, if adding to an existing group we should check the object is in a valid group position: // As above: no isolated objects, but also no 2 same objects in the same cell, all objects have at least one Snaptarget, etc if (draggedObjects[i].activeSelf && Constraint.CheckRootConstraint(draggedObjects[i])) { GameObject ThisObject = Instantiate(draggedObjects[i]); BeyondComponent BC_ThisObject = draggedObjects[i].GetComponent <BeyondComponent>(); ThisObject.GetComponent <BeyondComponent>().CopyValues(BC_ThisObject); SetBlueprintFromGhost(ThisObject); objectsPlaced.Add(ThisObject); } Destroy(draggedObjects[i]); } draggedObjects.Clear(); DestroyActiveBlueprint(); // When snapping, the Active blueprint is already in a group, which we should use, otherwise create a new one BeyondGroup bg = null; if (SnappedToObject != null) { bg = SnappedToObject.GetComponent <BeyondComponent>().Group; //Debug.Log("I should add all these to the group of the object I was snapped to: "+bg.Name); SnappedToObject = null; } // Create BeyondGroup, add all objects to it foreach (GameObject go in objectsPlaced) { if (bg == null) { bg = CreateNewBeyondGroup(go); } bg.AddObject(go); // Only set the layer at the end, so objects don't collide into each other and fail the constraint check go.layer = LayerMask.NameToLayer("Buildings"); } }
public SavedComponent(BeyondComponent bc) { template = bc.template.name; state = bc.state; group = bc.beyondGroup; side = bc.side; groupPosition = bc.groupPosition; cells = bc.cells; position = bc.transform.position; rotation = bc.transform.rotation; name = bc.transform.gameObject.name; layer = bc.transform.gameObject.layer; isTrigger = bc.transform.gameObject.GetComponent <BoxCollider>().isTrigger; enabled = bc.transform.gameObject.GetComponent <BoxCollider>().enabled; }
public void CreateNewBeyondGroup(BeyondComponent bc, string name = null) { if (name == null) { // Auto give name name = String.Format("Group {0:0000}", place.beyondGroups.Count); } // bc.transform.position - bc.template.pivotOffset : THIS IS ESSENTIAL - This allows us to properly set the pivot of the group BeyondGroup group = new BeyondGroup(name, bc.transform.position - bc.template.pivotOffset, bc.transform.rotation); if (bc != null) { group.addBeyondComponent(bc); // Vector3Int.zero because the first object in a group is at position [0,0,0] bc.SetBCinGroup(group, Vector3Int.zero, true); } place.beyondGroups.Add(group); }
private void PlaceOnClic() { if (Input.GetMouseButtonUp(0)) { //TODO : dragging stuff - make it better for (int i = 0; i < draggedBC.Count; i++) { if (draggedBC[i].gameObject.activeSelf && ConstraintController.CanPlace(draggedBC[i])) { string name = currentBC.template.name + "_" + (nbObjectsPlaced++); TemplateController.PlaceObject(draggedBC[i], name, BC_State.Blueprint); } else { Destroy(draggedBC[i].gameObject); } } Destroy(currentBC.gameObject); draggingGroup = null; draggedBC.Clear(); UIController.Instance.SetForwardOffset(ForwardOffsetBeforeDragging); // reset ForwardOffset to what it was before dragging - less annoying /* * This works for 1 clic : * * if (ConstraintController.CanPlace(currentPlaceableObject)) * { * string name = currentBC.template.name + "_" + (nbObjectsPlaced++) ; * TemplateController.PlaceObject(ref currentPlaceableObject , name , BC_State.Blueprint) ; * } * else * { * //Debug.Log("Destroyed currentPlaceableObject "+ currentPlaceableObject .GetInstanceID()+ " as I couldn't place it"); * Destroy(currentPlaceableObject); * } */ } }
private static bool NeedsOne(BeyondComponent bc, BeyondGroup bg, List <string> templatesList, List <Vector3Int> offsetsList, List <cellSide> cellSides, Vector3Int?optionalGroupPos = null) { if (bg == null) { return(false); } Vector3Int groupPos = (optionalGroupPos != null) ? (Vector3Int)optionalGroupPos : bc.groupPosition; foreach (string templateName in templatesList) { foreach (Vector3Int offset in offsetsList) { foreach (cellSide side in cellSides) { if (IsTemplatePresentHere(bg, groupPos + offset, templateName, side)) { return(true); } } } } Debug.Log("Check constraints NEEDSONE returned FALSE"); return(false); }
public static cellSide getSideByRotation(BeyondComponent bc, BeyondGroup group, Vector3Int pos) { float d = Vector3.Distance(bc.transform.position - bc.template.pivotOffset, group.position + (Vector3)pos); Debug.Log("getSideByRotation. Distance from pivot=" + d); Quaternion r = bc.transform.rotation; //TODO : Back & Front / Left & Right can both be returned based on how close we are from one edge or the other. // So this function must do better than this and work on a transform, not just a Quaternion float angle = Quaternion.Angle(Quaternion.identity, r); if (angle > 45f && angle <= 135f) { return(cellSide.Right); } if (angle > 135f && angle <= 225f) { return(cellSide.Front); } if (angle > 225f && angle <= 315f) { return(cellSide.Left); } return(cellSide.Back); }
//TO DO : refactor that with love & care public BeyondGroup CreateNewBeyondGroup(GameObject go, string name = null) { // Auto give name if (name == null) { name = String.Format("Group {0:0000}", GameManager.instance.Place.BeyondGroups.Count); } BeyondComponent bc = go.GetComponent <BeyondComponent>(); if (bc != null) { // bc.transform.position - bc.template.pivotOffset : THIS IS ESSENTIAL - This allows us to properly set the pivot of the group BeyondGroup group = new BeyondGroup(name, bc.transform.position - bc.Template.CellCentre, bc.transform.rotation); group.AddObject(go); GameManager.instance.Place.BeyondGroups.Add(group); return(group); } else { Debug.LogError("CreateNewBeyondGroup attempted to create an emtpy group"); } return(null); }
public void SetGroupPosition(BeyondGroup bg, Vector3Int pos) { Group = bg; GroupPosition = pos; }
/* * ============================================================ * CONSTRAINTS CHECKING * ============================================================ */ // Check this BC's constraints (optionally in a group) public static bool CheckConstraints(BeyondComponent bc, Constraints c = null, BeyondGroup bg = null, Vector3Int?optionalGroupPos = null) { Constraints constraints = (c == null ? bc.template.constraints : c); //Debug.Log(String.Format("Checking constraint on {0} of group {1}: {2}" , bc.name , (bg==null ? "null" : bg.name) , Constraints.ShowConstraints(constraints))); //int i=0; switch (constraints.operation) { case "OR": //if (i++>1000) {Debug.Log("OR just exploded"); return false;} return(OrConstraints(bc, bg, constraints.constraintsList, optionalGroupPos)); case "AND": //if (i++>1000) {Debug.Log("AND just exploded"); return false;} return(AndConstraints(bc, bg, constraints.constraintsList, optionalGroupPos)); case "TOPCLEAR": //if (i++>1000) {Debug.Log("TOPCLEAR just exploded"); return false;} return(TopClear(bc, constraints.mask)); case "ALLCLEAR": //if (i++>1000) {Debug.Log("ALLCLEAR just exploded"); return false;} return(AllClear(bc, constraints.mask)); case "BASEIN": //if (i++>1000) {Debug.Log("BASEIN just exploded"); return false;} return(BaseInTerrain(bc)); case "NEEDSONE": //if (i++>1000) {Debug.Log("NEEDSONE just exploded"); return false;} return(NeedsOne(bc, bg, constraints.templateNamesList, constraints.offsetsList, constraints.cellSides, optionalGroupPos)); case "NEEDSALL": //if (i++>1000) {Debug.Log("BEEDSALL just exploded"); return false;} return(NeedsAll(bc, bg, constraints.templateNamesList, constraints.offsetsList, constraints.cellSides, optionalGroupPos)); case "FIRSTINGROUP": //if (i++>1000) {Debug.Log("FIRSTINGROUP just exploded"); return false;} return(FirstInGroup(bc, bg)); default: //if (i++>1000) {Debug.Log("CHeckConstraints just exploded"); return false;} return(false); } }
public static bool CanSnapTo(BeyondComponent bc, BeyondGroup group, Vector3Int here) { Debug.Log("CanSnapTo called on " + bc.name + " for group " + (group == null ? "null" : group.name) + " at " + here); if (group == null) { return(false); } if (bc.template.name == "Foundation") { // must not have the same object (Foundation) here if (IsTemplatePresentHere(group, here, "Foundation")) { return(false); } // Must have a neighbouring Foundation in X or Z, same Y if (IsTemplatePresentHere(group, new Vector3Int(here.x - 1, here.y, here.z), "Foundation")) { return(true); } if (IsTemplatePresentHere(group, new Vector3Int(here.x + 1, here.y, here.z), "Foundation")) { return(true); } if (IsTemplatePresentHere(group, new Vector3Int(here.x, here.y, here.z - 1), "Foundation")) { return(true); } if (IsTemplatePresentHere(group, new Vector3Int(here.x, here.y, here.z + 1), "Foundation")) { return(true); } Debug.Log("No neighbouring foundation in group " + group.name); return(false); } if (bc.template.name == "Wall") { if (IsTemplatePresentHere(group, here, bc.template.name, BeyondComponent.getSideByRotation(bc, group, here))) { Debug.Log("CanSnapTo FALSE = Can't have wall in the same position and side"); return(false); // Can't have wall in the same position and side } // There must be a foundation to place a Wall if (IsTemplatePresentHere(group, here, "Foundation")) { Debug.Log("CanSnapTo TRUE = Found foundation"); return(true); } Debug.Log("CanSnapTo FALSE = No foundation"); return(false); } if (bc.template.name == "Wallhole") { if (IsTemplatePresentHere(group, here, bc.template.name, BeyondComponent.getSideByRotation(bc, group, here))) { return(false); // Can't have wallhole in the same position and side } // There must be a foundation to place a Wall if (IsTemplatePresentHere(group, here, "Foundation")) { return(true); } return(false); } if (bc.template.name == "Floor") { // must not have the same object (Floor) here if (IsTemplatePresentHere(group, here, "Floor")) { return(false); } // There must be a Wall 3 cells below if (IsTemplatePresentHere(group, new Vector3Int(here.x, here.y - 3, here.z), "Wall")) { return(true); } // Or a floor next to here if (IsTemplatePresentHere(group, new Vector3Int(here.x - 1, here.y, here.z), "Floor")) { return(true); } if (IsTemplatePresentHere(group, new Vector3Int(here.x + 1, here.y, here.z), "Floor")) { return(true); } if (IsTemplatePresentHere(group, new Vector3Int(here.x, here.y, here.z - 1), "Floor")) { return(true); } if (IsTemplatePresentHere(group, new Vector3Int(here.x, here.y, here.z + 1), "Floor")) { return(true); } return(false); } return(false); }
public void SetClosestGroup(BeyondGroup g) { closestGroup = g; }
public void Awake() { draggedBC = new List <BeyondComponent>(); draggingGroup = null; }