public void RemoveNeighborRoom(Room room)
    {
        bool       removal = false;
        DoorAnchor anchor  = info.doorAnchors[0];

        foreach (KeyValuePair <DoorAnchor, Room> pair in neighborRooms)
        {
            if (pair.Value == room)
            {
                removal = true;
                anchor  = pair.Key;
                break;
            }
        }

        if (removal)
        {
            neighborRooms.Remove(anchor);
        }
    }
    public void AddDoor(DoorAnchor anchor, Door door)
    {
        GameObject doorObject = door.gameObject;
        Vector3    pos;
        Quaternion rot;

        pos = transform.position + anchor.position + anchor.direction * roomOffset / 2;
        rot = Quaternion.LookRotation(anchor.direction);
        doorObject.transform.position = pos;
        doorObject.transform.rotation = rot;
        doorObject.transform.RotateAround(transform.position, transform.up, transform.rotation.eulerAngles.y);

        if (doors.ContainsKey(anchor))
        {
            Debug.LogWarning("Adding door but door already exists at that anchor.");
        }
        else
        {
            doors.Add(anchor, door);
            door.rooms.Add(this);
        }
    }
 public void AddDoor(DoorAnchor anchor, GameObject doorObject)
 {
     AddDoor(anchor, doorObject.GetComponent <Door>());
 }
    /// <summary>
    /// Generate neighbor rooms based on door anchors of the current active room.
    /// </summary>
    ///
    bool GenerateConnectedRooms(Room room)
    {
        System.Random rnd = new System.Random();


        for (int i = 0; i < room.info.doorAnchors.Length; i++)
        {
            //For each door anchor of the active room
            //generate a room
            DoorAnchor currentAnchor = room.info.doorAnchors[i];

            if (room.neighborRooms.ContainsKey(currentAnchor))
            {
                continue;
            }



            //Logical Neighbors with retained Rotation
            RoomDoorAnchor targetRoomDoorAnchor = room.info.logicalNeighbors[i];

            //Random all
            if (random)
            {
                targetRoomDoorAnchor = roomInfoManager.GetRandomRoomDoor();
            }

            newRoomInfo = targetRoomDoorAnchor.room;
            DoorAnchor targetAnchor = targetRoomDoorAnchor.doorAnchor;


            if (returnMode && returnProgress > 5)
            {
                newRoomInfo = baseRoomInfo;
            }


            //DoorAnchor targetAnchor = newRoomInfo.doorAnchors[doorIndex];

            //Assume X = Z
            // Vector3 roomPosition = activeRoom.transform.position + currentAnchor.position + currentAnchor.direction * (newRoomInfo.dimension.x / 2 + roomOffset);

            //Need fix to support Y direction
            //Vector3 roomPosition = room.transform.position + currentAnchor.direction * (currentAnchor.position.magnitude + targetAnchor.position.magnitude + roomOffset);


            //Vector3 roomPosition = room.transform.position + (currentAnchor.position - rotation * targetAnchor.position);

            ////first rotate target anchor to FOWARD
            //Quaternion localRotation = Quaternion.Euler(0, Vector3.SignedAngle(targetAnchor.direction, Vector3.forward, Vector3.up), 0);
            ////then rotate FOWARD(now our new door anchor) to look at the currentAnchor
            //Quaternion roomRotation = Quaternion.LookRotation(-currentAnchor.direction);

            ////rotate around activeroom with activeroom rotation
            //newRoomRotation = localRotation * roomRotation * room.transform.rotation;
            //newRoomPosition = room.transform.position + room.transform.rotation * (roomPosition - room.transform.position);


            Quaternion newRoomRotation = Quaternion.Euler(0, Vector3.SignedAngle(targetAnchor.direction, -(room.transform.rotation * currentAnchor.direction), Vector3.up), 0);
            Vector3    newRoomPosition = room.transform.position + (room.transform.rotation * currentAnchor.position - newRoomRotation * targetAnchor.position);

            //Debug.Log(newRoomRotation.eulerAngles + " " + newRoomPosition);

            //Debug.Log(targetAnchor.direction + " " + (-currentAnchor.direction));

            Vector3 collisionTestPosition = newRoomPosition;
            collisionTestPosition.y += newRoomInfo.dimension.y / 2;
            //check bound collision here!
            if (Physics.CheckBox(collisionTestPosition, newRoomInfo.dimension / 2 - Vector3.one / 2, newRoomRotation))
            {
                i--; //retry!
                regenCounter++;
                if (regenCounter > 100)
                {
                    regenCounter = 0;
                    Debug.Log("Collision Test: Failed to generate neighbor room after multiple tries!" + room.info.roomName + " " + newRoomInfo.roomName);
                    break;
                }
                if (!random)
                {
                    //Reset logical neighbor if in logical mode
                    room.info.logicalNeighbors[i + 1] = roomInfoManager.GetRandomRoomDoor(-currentAnchor.direction, room.info);
                }

                continue;
            }


            Room newRoom = new Room(Instantiate(newRoomInfo.prefab, newRoomPosition, newRoomRotation, transform), newRoomInfo);

            //Register Passage
            roomPassages.Add(new RoomPassage {
                src = new RoomDoorAnchor {
                    room       = room.info,
                    doorAnchor = currentAnchor
                },
                dst = new RoomDoorAnchor {
                    room       = newRoomInfo,
                    doorAnchor = targetAnchor
                }
            });
            //Debug.Log(roomPassages.Count);

            //Link Rooms
            room.neighborRooms[currentAnchor]   = newRoom;
            newRoom.neighborRooms[targetAnchor] = room;
            newRoom.doors[targetAnchor]         = room.doors[currentAnchor];
            room.doors[currentAnchor].rooms.Add(newRoom);
            newRoom.FillDoors(doorPool);

            rooms.Add(newRoom);

            if (returnMode && !returnGenerated)
            {
                if (rnd.Next(2) > 0)
                {
                    returnDoorIndex = i;
                    returnRoom      = newRoom;
                    returnGenerated = true;
                }
            }
        }
        return(true);
    }