void DisplayContextMenu()
        {
            _menuStrip = new ContextMenuStrip();
            // Adds a new camera into the scene
            _menuStrip.Items.Add("Add New Camera", null, (p1, p2) =>
            {
                lock (Plugin.Instance.Cameras)
                {
                    string cameraName = CameraUtilities.GetNextCameraName();
                    Plugin.Log($"Adding new config with name {cameraName}.cfg");
                    CameraUtilities.AddNewCamera(cameraName);
                    CameraUtilities.ReloadCameras();
                    CloseContextMenu();
                }
            });

            // Instantiates an exact copy of the currently selected camera
            _menuStrip.Items.Add("Duplicate Selected Camera", null, (p1, p2) =>
            {
                lock (Plugin.Instance.Cameras)
                {
                    string cameraName = CameraUtilities.GetNextCameraName();
                    Plugin.Log($"Adding {cameraName}");
                    CameraUtilities.AddNewCamera(cameraName, Config);
                    CameraUtilities.ReloadCameras();
                    CloseContextMenu();
                }
            });

            // Removes the selected camera from the scene, and deletes the config associated with it
            _menuStrip.Items.Add("Remove Selected Camera", null, (p1, p2) =>
            {
                lock (Plugin.Instance.Cameras)
                {
                    if (CameraUtilities.RemoveCamera(this))
                    {
                        _isCameraDestroyed = true;
                        CreateScreenRenderTexture();
                        CloseContextMenu();
                        Plugin.Log("Camera removed!");
                    }
                    else
                    {
                        MessageBox.Show("Cannot remove main camera!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                }
            });
            _menuStrip.Items.Add(new ToolStripSeparator());

            // Toggles between third/first person
            _menuStrip.Items.Add(Config.thirdPerson ? "First Person" : "Third Person", null, (p1, p2) =>
            {
                Config.thirdPerson = !Config.thirdPerson;
                ThirdPerson        = Config.thirdPerson;
                ThirdPersonPos     = Config.Position;
                ThirdPersonRot     = Config.Rotation;
                FirstPersonOffset  = Config.FirstPersonPositionOffset;
                CreateScreenRenderTexture();
                CloseContextMenu();
                Config.Save();
            });

            if (Config.thirdPerson)
            {
                // Hides/unhides the third person camera that appears when a camera is in third person mode
                _menuStrip.Items.Add(Config.showThirdPersonCamera ? "Hide Third Person Camera" : "Show Third Person Camera", null, (p1, p2) =>
                {
                    Config.showThirdPersonCamera = !Config.showThirdPersonCamera;
                    Config.Save();
                    CreateScreenRenderTexture();
                    CloseContextMenu();
                });

                // Hides/unhides the third person camera that appears when a camera is in third person mode
                _menuStrip.Items.Add("Reset Camera Position/Rotation", null, (p1, p2) =>
                {
                    Config.Position = Config.DefaultPosition;
                    Config.Rotation = Config.DefaultRotation;
                    Config.FirstPersonPositionOffset = Config.DefaultFirstPersonPositionOffset;
                    ThirdPersonPos    = Config.DefaultPosition;
                    ThirdPersonRot    = Config.DefaultRotation;
                    FirstPersonOffset = Config.FirstPersonPositionOffset;
                    Config.Save();
                    CloseContextMenu();
                });

                _menuStrip.Items.Add(Config.droneCam ? "Disable DroneCam" : "Ënable Drone Cam", null, (p1, p2) =>
                {
                    if (Config.droneCam && droneCam != null)
                    {
                        Config.droneCam = false;
                        droneCam.CleanUp();
                        Destroy(droneCam);
                    }
                    else
                    {
                        Config.droneCam = true;
                        droneCam        = gameObject.AddComponent <DroneCam.DroneCam>();
                        droneCam.SetupCam(Path.GetFileName(Config.FilePath));
                    }
                    Config.droneCam = false;
                    Config.Save();
                });
            }
            _menuStrip.Items.Add(new ToolStripSeparator());

            // Toggle transparent walls
            _menuStrip.Items.Add(Config.transparentWalls ? "Solid Walls" : "Transparent Walls", null, (p1, p2) =>
            {
                Config.transparentWalls = !Config.transparentWalls;
                SetCullingMask();
                CloseContextMenu();
                Config.Save();
            });

            _menuStrip.Items.Add(new ToolStripSeparator());

            var _layoutMenu = new ToolStripMenuItem("Layout");

            _controlTracker.Add(_layoutMenu);

            // Sets the layer associated with the current camera
            _layoutMenu.DropDownItems.Add(new ToolStripLabel("Layer"));
            var _layerBox = new ToolStripNumberControl();

            _controlTracker.Add(_layerBox);
            _layerBox.Maximum       = int.MaxValue;
            _layerBox.Minimum       = int.MinValue;
            _layerBox.Value         = Config.layer;
            _layerBox.ValueChanged += (sender, args) =>
            {
                Config.layer = (int)_layerBox.Value;
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_layerBox);

            // FOV
            _layoutMenu.DropDownItems.Add(new ToolStripLabel("FOV"));
            var _fov = new ToolStripNumberControl();

            _controlTracker.Add(_fov);
            _fov.Maximum = 179;
            _fov.Minimum = 0;
            _fov.Value   = (decimal)Config.fov;

            _fov.ValueChanged += (sender, args) =>
            {
                Config.fov = (int)_fov.Value;
                SetFOV();
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_fov);

            // Render Scale
            _layoutMenu.DropDownItems.Add(new ToolStripLabel("Render Scale"));
            var _renderScale = new ToolStripNumberControl();

            _controlTracker.Add(_renderScale);
            _renderScale.Maximum       = 4;
            _renderScale.Minimum       = 0.1M;
            _renderScale.Increment     = 0.1M;
            _renderScale.DecimalPlaces = 1;
            _renderScale.Value         = (decimal)Config.renderScale;

            _renderScale.ValueChanged += (sender, args) =>
            {
                Config.renderScale = (float)_renderScale.Value;
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_renderScale);


            // Sets the size of the current cameras pixelrect
            _layoutMenu.DropDownItems.Add(new ToolStripLabel("Size"));
            var _widthBox = new ToolStripNumberControl();

            _controlTracker.Add(_widthBox);
            _widthBox.Maximum       = Screen.width;
            _widthBox.Minimum       = 0;
            _widthBox.Value         = Config.screenWidth;
            _widthBox.ValueChanged += (sender, args) =>
            {
                Config.screenWidth = (int)_widthBox.Value;
                GL.Clear(false, true, Color.black, 0);
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_widthBox);
            var _heightBox = new ToolStripNumberControl();

            _controlTracker.Add(_heightBox);
            _heightBox.Maximum       = Screen.height;
            _heightBox.Minimum       = 0;
            _heightBox.Value         = Config.screenHeight;
            _heightBox.ValueChanged += (sender, args) =>
            {
                Config.screenHeight = (int)_heightBox.Value;
                GL.Clear(false, true, Color.black, 0);
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_heightBox);

            // Set the location of the current cameras pixelrect
            _layoutMenu.DropDownItems.Add(new ToolStripLabel("Position"));
            var _xBox = new ToolStripNumberControl();

            _controlTracker.Add(_xBox);
            _xBox.Maximum       = Screen.width;
            _xBox.Minimum       = 0;
            _xBox.Value         = Config.screenPosX;
            _xBox.ValueChanged += (sender, args) =>
            {
                Config.screenPosX = (int)_xBox.Value;
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_xBox);
            var _yBox = new ToolStripNumberControl();

            _controlTracker.Add(_yBox);
            _yBox.Maximum       = Screen.height;
            _yBox.Minimum       = 0;
            _yBox.Value         = Config.screenPosY;
            _yBox.ValueChanged += (sender, args) =>
            {
                Config.screenPosY = (int)_yBox.Value;
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_yBox);


            // Fit to canvas checkbox
            var _fitToCanvasBox = new ToolStripCheckBox("Fit to Canvas");

            _controlTracker.Add(_fitToCanvasBox);
            _fitToCanvasBox.Checked         = Config.fitToCanvas;
            _fitToCanvasBox.CheckedChanged += (sender, args) =>
            {
                Config.fitToCanvas = _fitToCanvasBox.Checked;
                _widthBox.Enabled  = !Config.fitToCanvas;
                _heightBox.Enabled = !Config.fitToCanvas;
                _xBox.Enabled      = !Config.fitToCanvas;
                _yBox.Enabled      = !Config.fitToCanvas;
                CreateScreenRenderTexture();
                Config.Save();
            };
            _layoutMenu.DropDownItems.Add(_fitToCanvasBox);

            // Finally, add our layout menu to the main menustrip
            _menuStrip.Items.Add(_layoutMenu);

            // Set the initial state for our width/height boxes depending on whether or not fitToCanvas is enabled
            _widthBox.Enabled  = !Config.fitToCanvas;
            _heightBox.Enabled = !Config.fitToCanvas;
            _xBox.Enabled      = !Config.fitToCanvas;
            _yBox.Enabled      = !Config.fitToCanvas;

            // Scripts submenu
            var _scriptsMenu = new ToolStripMenuItem("Scripts");

            _controlTracker.Add(_scriptsMenu);

            // Add menu
            var _addMenu = new ToolStripMenuItem("Add");

            _controlTracker.Add(_addMenu);

            // Add camera movement script
            ToolStripItem _addCameraMovement = _addMenu.DropDownItems.Add("Camera Movement", null, (p1, p2) =>
            {
                OpenFileDialog ofd = new OpenFileDialog();
                string path        = Path.Combine(Environment.CurrentDirectory, "UserData", "CameraPlus", "Scripts");
                CameraMovement.CreateExampleScript();
                ofd.InitialDirectory = path;
                ofd.Title            = "Select a script";
                ofd.FileOk          += (sender, e) =>
                {
                    string file = ((OpenFileDialog)sender).FileName;
                    if (File.Exists(file))
                    {
                        Config.movementScriptPath = file;
                        Config.Save();
                        AddMovementScript();
                    }
                };
                ofd.ShowDialog();
                CloseContextMenu();
            });

            _addCameraMovement.Enabled = !File.Exists(Config.movementScriptPath) || (Config.movementScriptPath == "SongMovementScript" || Config.movementScriptPath == String.Empty);

            // Add song camera movement script
            ToolStripItem _addSongMovement = _addMenu.DropDownItems.Add("Song Camera Movement", null, (p1, p2) =>
            {
                Config.movementScriptPath = "SongMovementScript";
                Config.Save();
                AddMovementScript();
                CloseContextMenu();
            });

            _addSongMovement.Enabled = Config.movementScriptPath != "SongMovementScript";
            _scriptsMenu.DropDownItems.Add(_addMenu);

            // Remove menu
            var _removeMenu = new ToolStripMenuItem("Remove");

            _controlTracker.Add(_removeMenu);

            // Remove camera movement script
            ToolStripItem _removeCameraMovement = _removeMenu.DropDownItems.Add("Camera Movement", null, (p1, p2) =>
            {
                Config.movementScriptPath = String.Empty;
                if (_cameraMovement)
                {
                    _cameraMovement.Shutdown();
                }
                Config.Save();
                CloseContextMenu();
            });

            _removeCameraMovement.Enabled = !_addCameraMovement.Enabled;

            // Remove song camera movement script
            ToolStripItem _removeSongMovement = _removeMenu.DropDownItems.Add("Song Camera Movement", null, (p1, p2) =>
            {
                Config.movementScriptPath = String.Empty;
                if (_cameraMovement)
                {
                    _cameraMovement.Shutdown();
                }
                Config.Save();
                CloseContextMenu();
            });

            _removeSongMovement.Enabled = !_addSongMovement.Enabled;
            _scriptsMenu.DropDownItems.Add(_removeMenu);
            _menuStrip.Items.Add(_scriptsMenu);

            // Extras submenu
            var _extrasMenu = new ToolStripMenuItem("Extras");

            _controlTracker.Add(_extrasMenu);
            // Just the right number...
            _extrasMenu.DropDownItems.Add("Spawn 38 Cameras", null, (p1, p2) =>
            {
                StartCoroutine(CameraUtilities.Spawn38Cameras());
                CloseContextMenu();
            });
            _menuStrip.Items.Add(_extrasMenu);
        }
        protected IEnumerator DelayedInit()
        {
            yield return(_waitForMainCamera);


            _mainCamera = Camera.main;
            _menuStrip  = null;
            XRSettings.showDeviceView = false;

            Config.ConfigChangedEvent += PluginOnConfigChangedEvent;

            var gameObj = Instantiate(_mainCamera.gameObject);

            gameObj.SetActive(false);
            gameObj.name = "Camera Plus";
            gameObj.tag  = "Untagged";
            while (gameObj.transform.childCount > 0)
            {
                DestroyImmediate(gameObj.transform.GetChild(0).gameObject);
            }
            DestroyImmediate(gameObj.GetComponent("CameraRenderCallbacksManager"));
            DestroyImmediate(gameObj.GetComponent("AudioListener"));
            DestroyImmediate(gameObj.GetComponent("MeshCollider"));

            _cam = gameObj.GetComponent <Camera>();
            _cam.stereoTargetEye = StereoTargetEyeMask.None;
            _cam.enabled         = true;
            _cam.name            = Path.GetFileName(Config.FilePath);

            var _liv = _cam.GetComponent <LIV.SDK.Unity.LIV>();

            if (_liv)
            {
                Destroy(_liv);
            }

            _screenCamera = new GameObject("Screen Camera").AddComponent <ScreenCameraBehaviour>();

            if (_previewMaterial == null)
            {
                _previewMaterial = new Material(Shader.Find("Hidden/BlitCopyWithDepth"));
            }

            gameObj.SetActive(true);

            var camera = _mainCamera.transform;

            transform.position = camera.position;
            transform.rotation = camera.rotation;

            gameObj.transform.parent        = transform;
            gameObj.transform.localPosition = Vector3.zero;
            gameObj.transform.localRotation = Quaternion.identity;
            gameObj.transform.localScale    = Vector3.one;

            _cameraCubeGO = GameObject.CreatePrimitive(PrimitiveType.Cube);
            DontDestroyOnLoad(_cameraCubeGO);
            _cameraCubeGO.SetActive(ThirdPerson);
            _cameraCube            = _cameraCubeGO.transform;
            _cameraCube.localScale = new Vector3(0.15f, 0.15f, 0.22f);
            _cameraCube.name       = "CameraCube";

            _quad = GameObject.CreatePrimitive(PrimitiveType.Quad);
            DontDestroyOnLoad(_quad);
            DestroyImmediate(_quad.GetComponent <Collider>());
            _quad.GetComponent <MeshRenderer>().material = _previewMaterial;
            _quad.transform.parent           = _cameraCube;
            _quad.transform.localPosition    = new Vector3(-1f * ((_cam.aspect - 1) / 2 + 1), 0, 0.22f);
            _quad.transform.localEulerAngles = new Vector3(0, 180, 0);
            _quad.transform.localScale       = new Vector3(_cam.aspect, 1, 1);
            _cameraPreviewQuad = _quad;

            ReadConfig();

            if (ThirdPerson)
            {
                ThirdPersonPos = Config.Position;
                ThirdPersonRot = Config.Rotation;

                transform.position    = ThirdPersonPos;
                transform.eulerAngles = ThirdPersonRot;

                _cameraCube.position    = ThirdPersonPos;
                _cameraCube.eulerAngles = ThirdPersonRot;

                if (Config.droneCam && droneCam == null)
                {
                    try
                    {
                        droneCam = gameObject.AddComponent <DroneCam.DroneCam>();
                        droneCam.SetupCam(Path.GetFileName(Config.FilePath));
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine("CamPlusDroneErr:\n{0} {1} {2}", e.GetType().ToString(), e.Message, e.StackTrace);
                    }
                }
            }

            // Add our camera movement script if the movement script path is set
            if (Config.movementScriptPath != String.Empty)
            {
                AddMovementScript();
            }

            SetCullingMask();

            CameraMovement.CreateExampleScript();

            Plugin.Instance.ActiveSceneChanged += SceneManager_activeSceneChanged;

            FirstPersonOffset = Config.FirstPersonPositionOffset;

            SceneManager_activeSceneChanged(new Scene(), new Scene());
            Plugin.Log($"Camera \"{Path.GetFileName(Config.FilePath)}\" successfully initialized!\"");
        }