private void SealExitWithADoor(ModuleConnector baseExit)
    {
        //Debug.Log("Couldn't find any possible combination. Sealing off the exit with a door");
        var newModule = ProBuilder.Instantiate(DoorPrefab.gameObject, Vector3.zero, Quaternion.identity).GetComponent <Module>();

        newModule.transform.parent = DungeonGameObject.transform;
        var doorExit = newModule.GetExits()[0];

        MatchExits(baseExit, doorExit);

        baseExit.ConnectWith(doorExit);
        doorExit.ConnectWith(baseExit);
    }
    private IEnumerator GenerateNewDungeonCo()
    {
        WaitForSeconds delay = null;

        if (UseDelay)
        {
            delay = new WaitForSeconds(GenerationDelay);
        }

        DungeonGameObject = new GameObject("Dungeon");
        //Get the starting module and orient it
        var startModule = ProBuilder.Instantiate(RootModule, transform.position, transform.rotation).GetComponent <Module>();

        startModule.transform.parent = DungeonGameObject.transform;
        //Get all the exits of the starting module
        var baseModuleExits = new List <ModuleConnector>(startModule.GetExits());

        //Iterate through the number of iterations
        //Only allow "Open" modules for the initial iterations
        for (int iteration = 0; iteration < Iterations; iteration++)
        {
            var newExits          = new List <ModuleConnector>();
            var randomizedModules = new List <GameObject>();
            //Loop through all the basemodule exits
            foreach (var baseModuleExit in baseModuleExits)
            {
                yield return(delay);

                //loop through the random list of available modules, until there is a valid candidate
                randomizedModules.Clear();
                GetRandomizedModuleList(randomizedModules, ModulePrefabs, "Open");

                GameObject newModuleGameObject = null;
                if (!CreateNewModule(baseModuleExit, randomizedModules, newExits, out newModuleGameObject))
                {
                    SealExitWithADoor(baseModuleExit);
                }
            }

            baseModuleExits = newExits;
        }

        StartCoroutine(ApplyFinalIterationCo(baseModuleExits));
    }
    /**
     * The only scenario where CreateNewModule would return false, is if there was no way to generate a module, so we have to seal it off with a door
     */
    private bool CreateNewModule(ModuleConnector baseExit, List <GameObject> availableModulePrefabs, List <ModuleConnector> newExits, out GameObject moduleGameObject)
    {
        bool            foundExit     = false;
        bool            foundModule   = false;
        ModuleConnector newModuleExit = null;

        ModuleConnector[] newModuleExits = null;
        moduleGameObject = null;
        Module newModule = null;

        foreach (var newModulePrefab in availableModulePrefabs)
        {
            //Create the new module prefab
            newModule = ProBuilder.Instantiate(newModulePrefab, Vector3.zero, Quaternion.identity).GetComponent <Module>();
            newModule.transform.parent = DungeonGameObject.transform;
            newModuleExits             = newModule.GetExits();
            Util.ShuffleArray(newModuleExits);

            for (var i = 0; i < newModuleExits.Count(); i++)
            {
                newModuleExit = newModuleExits[i];

                //Match the exits
                MatchExits(baseExit, newModuleExit);

                //Letting a full frame go by so we can do a collision check
                if (CollisionCheck(newModule, baseExit))
                {
                    foundModule = true;
                    foundExit   = true;
                    break;
                }
            }

            //We've tried every exit combination with this module, get a new module
            if (!foundExit)
            {
                Destroy(newModule.gameObject);
                continue;
            }

            //if we've reached here, we have found a suitable exit with a suitable module, or we have not found anything suitable.
            break;
        }

        //We haven't found anything useful. Just make a door, and find another baseModuleExit
        if (!foundModule)
        {
            return(false);
        }

        //the new module was received. All is good. Connect with the base module exit. Find another baseModuleExit to connect with
        baseExit.ConnectWith(newModuleExit);
        newModuleExit.ConnectWith(baseExit);

        if (newExits != null)
        {
            newExits.AddRange(newModuleExits.Where(e => e != newModuleExit));
        }

        CameraPortal cameraPortal = (CameraPortal)newModule.gameObject.GetComponentInChildren(typeof(CameraPortal));

        if (cameraPortal != null)
        {
            Portals.Add(cameraPortal);
        }

        moduleGameObject = newModule.gameObject;
        return(true);
    }
    void Update()
    {
        mPos_screen = Input.mousePosition;

        // If mouse is in the menu, ignore any clicks
        Vector2 mPos_gui = new Vector2(mPos_screen.x, Screen.height - mPos_screen.y);

        if (prefWindow.Contains(mPos_gui))
        {
            return;
        }

        // If left click detected, instantiate the selected prefab where the mouse clicked (lock Z to 0)
        if (Input.GetMouseButtonUp(0))
        {
            // grab mouse position in world space
            Vector3 mPos_world = Camera.main.ScreenToWorldPoint(new Vector3(
                                                                    mPos_screen.x,
                                                                    mPos_screen.y,
                                                                    Camera.main.transform.position.x)); // for some reason I decided to set the cube up on the x axis?

            GameObject myInstantiatedObject;

            switch (objectToInstantiate)
            {
            case ObjectSelectionOptions.Prefab:

                // Use ProBuilder.Instantiate(GameObject) to build cube.  This force rebuilds the mesh
                // immediately.  It is also safe to use with non-ProBuilder objects, and will behave
                // exactly like GameObject.Instantiate() if no pb_Object type is found.
                myInstantiatedObject = ProBuilder.Instantiate(probuilderPrefab, Vector3.zero, Quaternion.identity);

                break;

            ///* These demonstrate how to instantiate ProBuilder Primitive Types
            ///* (called 'Shapes' to differentiate from UnityEngine.PrimitiveType).

            case ObjectSelectionOptions.Cube:

                // Using the basic Shape instantiation, build a cube.  CreatePrimitive() returns a
                // pb_Object, so get the GameObject after instantiation.
                pb_Object pb = ProBuilder.CreatePrimitive(ProBuilder.Shape.Cube);

                // Cubes alone are a little boring, so let's add some color to it
                Color[] cubeColors = new Color[6]
                {
                    Color.green,
                    Color.red,
                    Color.cyan,
                    Color.blue,
                    Color.yellow,
                    Color.magenta
                };

                int i = 0;
                foreach (pb_Face face in pb.faces)
                {
                    pb.SetFaceColor(face, cubeColors[i++]);
                }

                myInstantiatedObject = pb.gameObject;

                // Cube gets a BoxCollider
                myInstantiatedObject.gameObject.AddComponent <BoxCollider>();

                break;

            case ObjectSelectionOptions.Cylinder:

                // ProBuilder also offers an extended interface for creating objects with
                // parameters. "ProBuilder.CreatePrimitive(ProBuilder.Shape.Cylinder);"
                // would also work here.  See the pb_Shape docs for full lists with params.

                // axisDivisions, radius, height, heightCuts
                myInstantiatedObject = pb_Shape.CylinderGenerator(12, .7f, .5f, 0).gameObject;

                // A convex MeshCollider suits a Cylinder nicely
                myInstantiatedObject.gameObject.AddComponent <MeshCollider>().convex = true;

                break;

            case ObjectSelectionOptions.Pipe:

                // ProBuilder also offers an extended interface for creating objects with
                // parameters. "ProBuilder.CreatePrimitive(ProBuilder.Shape.Cylinder);"
                // would also work here.  See the pb_Shape docs for full lists with params.

                // axisDivisions, radius, height, heightCuts
                // float radius, float height, float thickness, int subdivAxis, int subdivHeight)
                myInstantiatedObject = pb_Shape.PipeGenerator(1f, 1f, .3f, 8, 0).gameObject;

                // A convex MeshCollider suits a Pipe nicely
                myInstantiatedObject.gameObject.AddComponent <MeshCollider>().convex = true;

                break;

            default:
                return;
            }

            // Move instantiated object to mouse position
            myInstantiatedObject.transform.position = mPos_world;

            // Add some rotation, cause that's fun
            myInstantiatedObject.transform.localRotation = Quaternion.Euler(
                Random.Range(0f, 360f),
                Random.Range(0f, 360f),
                Random.Range(0f, 360f));

            // Get some physics up in here
            myInstantiatedObject.AddComponent <Rigidbody>();

            // Add this to the list of instantiated gameObjects so we can remove it later
            generatedObjects.Add(myInstantiatedObject);
        }
    }