// ~~ private

// ~ Non-Static

// ~~ public

// ~~ private
    private void Awake()
    {
        if (!InstanceValidation.SingleInstanceExists <EventSystem>())
        {
            RootLog.Log(
                "No event system.",
                Severity.Warning
                );
        }

        gameObject.name = "Root Windows";

        _windowManager = gameObject.AddComponent <WindowManager>();
        Debug.Log("Subscribing WindowManager to RootWindows events.");

        _subjectEvent = new RootEvent <string, ISubject>();

        _registerDataEvent =
            new RootEvent <string, IViewData, string>();
        _registerSelfAbilityEvent =
            new RootEvent <string, Action, Action, string>();
        _registerLocationAbilityEvent =
            new RootEvent <string, Action, Action <Vector3>, string>();
        _registerObjectAbilityEvent =
            new RootEvent <string, Action, Action <GameObject[]>, string>();

        _deregisterDataEvent =
            new RootEvent <string, IViewData, string>();
        _deregisterSelfAbilityEvent =
            new RootEvent <string, Action, Action, string>();
        _deregisterLocationAbilityEvent =
            new RootEvent <string, Action, Action <Vector3>, string>();
        _deregisterObjectAbilityEvent =
            new RootEvent <string, Action, Action <GameObject[]>, string>();

        _setBGColorEvent = new RootEvent <string, Color, string>();

        _subjectEvent.Subscribe(HandleSubject);

        _registerDataEvent.Subscribe(HandleRegisterData);
        _registerSelfAbilityEvent.Subscribe(HandleRegisterSelfAbility);
        _registerLocationAbilityEvent.Subscribe(HandleRegisterLocationAbility);
        _registerObjectAbilityEvent.Subscribe(HandleRegisterObjectAbility);

        _deregisterDataEvent.Subscribe(HandleDeregisterData);
        _deregisterSelfAbilityEvent.Subscribe(HandleDeregisterSelfAbility);
        _deregisterLocationAbilityEvent.Subscribe(HandleDeregisterLocationAbility);
        _deregisterObjectAbilityEvent.Subscribe(HandleDeregisterObjectAbility);

        _setBGColorEvent.Subscribe(HandleSetBGColor);
    }
// ~~ private

// INDEXERS ~~~~~~~~~~

// ~ Static

// ~~ public

// ~~ private

// ~ Non-Static

// ~~ public

// ~~ private

// METHODS ~~~~~~~~~

// ~ Static

// ~~ public

// ~~ private

// ~ Non-Static

// ~~ public

    public static void AttachCamera(HexMap map, float hexSize)
    {
        HexGridCamera resultMono;

        _hexOuterRadius = hexSize;

        if (InstanceValidation.InstanceExists <HexGridCamera>())
        {
            resultMono = InstanceValidation.GetFirstInstance <HexGridCamera>();
            resultMono.transform.SetParent(map.transform, false);
            resultMono.TargetGrid = map;
            resultMono.enabled    = true;
            if (InstanceValidation.SingleInstanceExists <HexGridCamera>())
            {
                RootLog.Log(
                    "Single instance of camera already exists. " +
                    "Attaching instance to grid.",
                    Severity.Information,
                    "HexGridCamera"
                    );
            }
            else
            {
                RootLog.Log(
                    "Multiple instances of camera already exist. " +
                    "Attaching first instance to grid.",
                    Severity.Information,
                    "HexGridCamera"
                    );
            }
        }
        else
        {
            GameObject resultObj = new GameObject("HexGridCamera");
            resultMono = resultObj.AddComponent <HexGridCamera>();
            resultMono.transform.SetParent(map.transform, false);
            resultMono.TargetGrid = map;
            resultMono.enabled    = true;

            GameObject swivelObj = new GameObject("Swivel");
            swivelObj.SetParent(resultObj, false);
            swivelObj.transform.localRotation = Quaternion.Euler(45, 0, 0);

            resultMono.Swivel = swivelObj.transform;

            GameObject stickObj = new GameObject("Stick");
            stickObj.SetParent(swivelObj, false);
            stickObj.transform.localPosition = new Vector3(
                0, 0, -45
                );

            resultMono.Stick = stickObj.transform;

            GameObject cameraObj = new GameObject("Camera");
            cameraObj.SetParent(stickObj, false);
            cameraObj.tag = "MainCamera";
            cameraObj.transform.localRotation = Quaternion.Euler(5, 0, 0);

            Camera cameraMono = cameraObj.AddComponent <Camera>();
            cameraObj.AddComponent <PhysicsRaycaster>();
            cameraMono.nearClipPlane = 0.3f;
            cameraMono.farClipPlane  = 1000f;
            cameraMono.depth         = -1f;

            resultMono.transform.SetParent(map.transform, false);

            if (map.GridCenter)
            {
                resultMono.SetPosition(
                    map,
                    map.GridCenter.transform.position.x,
                    map.GridCenter.transform.position.z,
                    _hexOuterRadius
                    );
            }
        }
    }