private void InitializeContextMenu(GameObject ctxObjectGO, MenuPositionMode menuPosition) { // IMPROVE use of strings Profiler.BeginSample("Proper AddComponent allocation", _ctxObject); _ctxObject = ctxObjectGO.AddMissingComponent<CtxObject>(); Profiler.EndSample(); switch (menuPosition) { case MenuPositionMode.Over: _ctxObject.toOffsetMenu = false; _ctxObject.toPositionMenuAtCursor = false; break; case MenuPositionMode.Offset: _ctxObject.toOffsetMenu = true; _ctxObject.toPositionMenuAtCursor = false; break; case MenuPositionMode.AtCursor: _ctxObject.toOffsetMenu = false; _ctxObject.toPositionMenuAtCursor = true; break; case MenuPositionMode.None: default: throw new NotImplementedException(ErrorMessages.UnanticipatedSwitchValue.Inject(menuPosition)); } // NOTE: Cannot set CtxMenu.items from here as CtxMenu.Awake sets defaultItems = items (null) before I can set items programmatically. // Accordingly, the work around is 1) to either use the editor to set the items using a CtxMenu dedicated to ships, or 2) have this already dedicated // CtxObject hold the .menuItems that are set programmatically when Show is called. if (_availableSubMenus.Count == Constants.Zero) { _availableSubMenus.AddRange(GuiManager.Instance.gameObject.GetSafeComponentsInChildren<CtxMenu>() .Where(menu => menu.gameObject.name.Equals("SubMenu"))); D.Assert(_uniqueSubmenusReqd <= _availableSubMenus.Count); } if (_generalCtxMenu == null) { _generalCtxMenu = GuiManager.Instance.gameObject.GetSafeComponentsInChildren<CtxMenu>() .Single(menu => menu.gameObject.name.Equals("GeneralMenu")); } if (!_generalCtxMenu.items.IsNullOrEmpty()) { // There are already populated items in this CtxMenu. In certain corner cases, this can occur when this object initializes itself while // another object is still showing the menu. One example: Use a context menu to scuttle a Settlement. The destruction of the settlement // immediately changes the system's owner which causes the system's context menu to reinitialize while the Settlement's context menu // has yet to finish hiding. This reinitialization encounters the Settlement's items as they haven't been cleared yet which occurs // when finished hiding. Accordingly, we test for this condition by seeing if the menu is still visible. if (!_generalCtxMenu.IsVisible) { // A hidden CtxMenu should not have any items in its list D.Warn("{0}.{1}.CtxMenu.items = {2}.", ctxObjectGO.name, GetType().Name, _generalCtxMenu.items.Select<CtxMenu.Item, string>(i => i.text).Concatenate()); } } _ctxObject.contextMenu = _generalCtxMenu; // this empty, general purpose CtxMenu will be populated with all menu items held by CtxObject when Show is called if (!_ctxObject.menuItems.IsNullOrEmpty()) { D.Warn("{0}.{1}.CtxObject.menuItems = {2}.", ctxObjectGO.name, GetType().Name, _ctxObject.menuItems.Select<CtxMenu.Item, string>(i => i.text).Concatenate()); } }
/// <summary> /// Initializes a new instance of the <see cref="ACtxControl" /> class. /// </summary> /// <param name="ctxObjectGO">The gameObject where the desired CtxObject is located.</param> /// <param name="uniqueSubmenusReqd">The number of unique sub-menus reqd by this CtxControl.</param> /// <param name="menuPosition">The position to place the menu.</param> public ACtxControl(GameObject ctxObjectGO, int uniqueSubmenusReqd, MenuPositionMode menuPosition) { //D.Log("Creating {0} for {1}.", GetType().Name, ctxObjectGO.name); _gameMgr = GameManager.Instance; _user = _gameMgr.UserPlayer; _uniqueSubmenusReqd = uniqueSubmenusReqd; // done this way to avoid CA2214 - accessing a virtual property from constructor InitializeContextMenu(ctxObjectGO, menuPosition); Subscribe(); }