/// <summary> /// Creates a dropdown bound to a field or property. You need to supply a collection of dropdown choices. /// </summary> public GameObject Dropdown <T>(Expression <Func <T> > memberAccessExpr, IEnumerable <IEDropdownChoice> choices, int width, int labelWidth, string label = null, string tooltip = null ) { #region Old code /* * //+ FOR REFERENCE: * const int nerfedXPTableWidth = 515; * UIDropdownMenu drop; * nerfedXPTableDropdown.transform.GetChild(1).GetChild(0).localScale = new Vector3(nerfedXPTableWidth, 32, 1); // width of combobox * nerfedXPTableDropdown.transform.GetChild(1).GetChild(3).localPosition = new Vector3(nerfedXPTableWidth - 27, 10, 0); // position of down arrow * nerfedXPTableDropdown.transform.GetChild(1).GetChild(2).GetChild(0).localScale = new Vector3(nerfedXPTableWidth, 37, 0); // width of dropdown * nerfedXPTableDropdown.transform.GetChild(1).Component<UIDropdownMenu>().OptionRootText.lineWidth = nerfedXPTableWidth; * nerfedXPTableDropdown.transform.GetChild(1).Component<UIDropdownMenu>().SelectedText.lineWidth = nerfedXPTableWidth; * nerfedXPTableDropdown.transform.GetChild(1).Component<UIDropdownMenu>().OptionGrid.cellWidth = nerfedXPTableWidth; * nerfedXPTableDropdown.transform.GetChild(1).Component<UIDropdownMenu>().Options = nerfedXPTableChoices; * //nerfedXPTableDropdown.transform.GetChild(1).Component<UIDropdownMenu>().SelectedItem = nerfedXPTableChoices[PlayerPrefs.GetInt("NerfedXPTableSetting")]; * //nerfedXPTableDropdown.transform.GetChild(1).Component<UIDropdownMenu>().OnDropdownOptionChangedEvent += new UIDropdownMenu.DropdownOptionChanged(OnNerfedXPTableSettingChanged); * nerfedXPTableDropdown.transform.GetChild(0).Component<UILabel>().lineWidth = 300; * nerfedXPTableDropdown.transform.GetChild(0).Component<UILabel>().shrinkToFit = false; * nerfedXPTableDropdown.transform.GetChild(0).Component<GUIStringLabel>().DatabaseString = new GUIDatabaseString(++StringId); * nerfedXPTableDropdown.Component<UIOptionsTag>().TooltipString = new GUIDatabaseString(++StringId); * // end of adding dropdown */ #endregion if (ExampleDropdown == null) { throw IEDebug.Exception(null, "You must initialize the ExampleDropdown to create a dropdown.", null); } var pos = new Vector3(0, 0, 0); var getter = ReflectHelper.CreateGetter(memberAccessExpr); var setter = ReflectHelper.CreateSetter(memberAccessExpr); var asMemberExpr = (MemberExpression)memberAccessExpr.Body; var comboBox = (UIOptionsTag)Object.Instantiate(ExampleDropdown); comboBox.transform.parent = CurrentParent; //+ Basic setup comboBox.name = asMemberExpr.Member.Name; //! You have to explicitly set localPosition and localScale to something after Instantiate!!! //! Otherwise, the UI will broken, but no exception will be reported. comboBox.transform.localPosition = pos; comboBox.transform.localScale = new Vector3(1, 1, 1); var dropdown = comboBox.transform.ComponentsInDescendants <UIDropdownMenu>(true).Single(); label = label ?? ReflectHelper.GetLabelInfo(asMemberExpr.Member); tooltip = tooltip ?? ReflectHelper.GetDescriptionInfo(asMemberExpr.Member); //+ Set the labels //There are multiple things called Label in this visual tree, but only one with a GUIStringLabel component. var guiLabel = comboBox.transform.ComponentsInDescendants <GUIStringLabel>(true).Single(); if (labelWidth > 0) { guiLabel.DatabaseString = IEModString.Register(label); var uiLabel = guiLabel.gameObject.Component <UILabel>(); uiLabel.lineWidth = labelWidth; } else { guiLabel.DatabaseString = IEModString.Register(""); var uiLabel = guiLabel.gameObject.Component <UILabel>(); uiLabel.lineWidth = labelWidth; } var uiTag = comboBox.Component <UIOptionsTag>(); uiTag.TooltipString = IEModString.Register(tooltip); //+ set the choices and SelectedItem var choicesArr = choices.ToArray(); dropdown.Options = choicesArr.ToArray(); dropdown.SelectedItem = choicesArr.SingleOrDefault(x => object.Equals(x.Value, getter())) ?? dropdown.Options[0]; //+ Set position and scale //To get the names, I used the GetChild calls as reference, and dumped the comboBox to the log using UnityObjectDumper. var comboBoxBackground = comboBox.Descendant("Background"); comboBoxBackground.transform.localScale = new Vector3(width, 32, 1); //this is the width of the combobox var arrowThing = comboBox.Descendant("ArrowPivot"); arrowThing.transform.localPosition = new Vector3(width - 27, 10, 0); dropdown.OptionRootText.lineWidth = width; dropdown.SelectedText.lineWidth = width; dropdown.OptionGrid.cellWidth = width; var optGrid = dropdown.OptionGrid; //+ Set the default handler that binds the control to the member dropdown.OnDropdownOptionChangedEvent += option => { var asChoice = (IEDropdownChoice)option; setter((T)asChoice.Value); }; return(comboBox.gameObject); }
/// <summary> /// Creates a new dropdown/combo box bound to an enum-valued field or property. The enum part is important, as this is how the dropdown's options are generated. Labels are taken from attributes. /// </summary> /// <typeparam name="T">The type of the field/property. MUST be an enum type.</typeparam> /// <param name="enumMemberAccessExpr">A simple member access expression for accessing the property/field you want to bind this control to. For example, <c>() => IEModOptions.YourProperty</c></param> /// <param name="width">The width of the dropdown. You have to specify it now because setting it is complicated.</param> /// <param name="labelWidth">The width of the GUI label attached to the dropdown. If you set it to 0, there will be no label.</param> /// <param name="localPos">The transform.localPosition of the dropdown. You can set this later.</param> /// <returns></returns> public GameObject EnumBoundDropdown <T>(Expression <Func <T> > enumMemberAccessExpr, int width, int labelWidth) where T : struct, IConvertible, IFormattable, IComparable { /* * * //+ FOR REFERENCE: * const int nerfedXPTableWidth = 515; * UIDropdownMenu drop; * nerfedXPTableDropdown.transform.GetChild(1).GetChild(0).localScale = new Vector3(nerfedXPTableWidth, 32, 1); // width of combobox * nerfedXPTableDropdown.transform.GetChild(1).GetChild(3).localPosition = new Vector3(nerfedXPTableWidth - 27, 10, 0); // position of down arrow * nerfedXPTableDropdown.transform.GetChild(1).GetChild(2).GetChild(0).localScale = new Vector3(nerfedXPTableWidth, 37, 0); // width of dropdown * nerfedXPTableDropdown.transform.GetChild(1).GetComponent<UIDropdownMenu>().OptionRootText.lineWidth = nerfedXPTableWidth; * nerfedXPTableDropdown.transform.GetChild(1).GetComponent<UIDropdownMenu>().SelectedText.lineWidth = nerfedXPTableWidth; * nerfedXPTableDropdown.transform.GetChild(1).GetComponent<UIDropdownMenu>().OptionGrid.cellWidth = nerfedXPTableWidth; * nerfedXPTableDropdown.transform.GetChild(1).GetComponent<UIDropdownMenu>().Options = nerfedXPTableChoices; * //nerfedXPTableDropdown.transform.GetChild(1).GetComponent<UIDropdownMenu>().SelectedItem = nerfedXPTableChoices[PlayerPrefs.GetInt("NerfedXPTableSetting")]; * //nerfedXPTableDropdown.transform.GetChild(1).GetComponent<UIDropdownMenu>().OnDropdownOptionChangedEvent += new UIDropdownMenu.DropdownOptionChanged(OnNerfedXPTableSettingChanged); * nerfedXPTableDropdown.transform.GetChild(0).GetComponent<UILabel>().lineWidth = 300; * nerfedXPTableDropdown.transform.GetChild(0).GetComponent<UILabel>().shrinkToFit = false; * nerfedXPTableDropdown.transform.GetChild(0).GetComponent<GUIStringLabel>().DatabaseString = new GUIDatabaseString(++StringId); * nerfedXPTableDropdown.GetComponent<UIOptionsTag>().TooltipString = new GUIDatabaseString(++StringId); * // end of adding dropdown */ if (!typeof(T).IsEnum) { IEDebug.Exception(null, "Expected an enum type, but got {0}", typeof(T)); } if (ExampleComboBox == null) { IEDebug.Exception(null, "You must initialize the ExampleComboBox to create a combo box.", null); } var pos = new Vector3(0, 0, 0); var getter = ReflectHelper.CreateGetter(enumMemberAccessExpr); var setter = ReflectHelper.CreateSetter(enumMemberAccessExpr); var asMemberExpr = (MemberExpression)enumMemberAccessExpr.Body; var comboBox = (GameObject)GameObject.Instantiate(ExampleComboBox); comboBox.transform.parent = CurrentParent; //+ Basic setup comboBox.name = asMemberExpr.Member.Name; //! You have to explicitly set localPosition and localScale to something after Instantiate!!! //! Otherwise, the UI will broken, but no exception will be reported. comboBox.transform.localPosition = pos; comboBox.transform.localScale = new Vector3(1, 1, 1); var dropdown = comboBox.transform.GetComponentsInChildren <UIDropdownMenu>(true).Single(); var label = GetLabel(asMemberExpr.Member); var desc = GetDesc(asMemberExpr.Member); //+ Set the labels //There are multiple things called Label in this visual tree, but only one with a GUIStringLabel component. var guiLabel = comboBox.transform.GetComponentsInChildren <GUIStringLabel>(true).Single(); if (labelWidth > 0) { guiLabel.DatabaseString = IEModString.Register(label); var uiLabel = guiLabel.gameObject.GetComponent <UILabel>(); uiLabel.lineWidth = labelWidth; } else { guiLabel.DatabaseString = IEModString.Register(""); var uiLabel = guiLabel.gameObject.GetComponent <UILabel>(); uiLabel.lineWidth = labelWidth; } var uiTag = comboBox.GetComponent <UIOptionsTag>(); uiTag.TooltipString = IEModString.Register(desc); //+ set the choices and SelectedItem var choices = EnumToChoices(typeof(T)); dropdown.Options = choices.Cast <object>().ToArray(); dropdown.SelectedItem = choices.SingleOrDefault(x => x.Value.Equals(getter())) ?? dropdown.Options[0]; //+ Set position and scale //To get the names, I used the GetChild calls as reference, and dumped the comboBox to the log using UnityObjectDumper. var comboBoxBackground = comboBox.GetDescendant("Background"); var oldWidth = comboBoxBackground.transform.localScale.x; comboBoxBackground.transform.localScale = new Vector3(width, 32, 1); //this is the width of the combobox var arrowThing = comboBox.GetDescendant("ArrowPivot"); arrowThing.transform.localPosition = new Vector3(width - 27, 10, 0); dropdown.OptionRootText.lineWidth = width; dropdown.SelectedText.lineWidth = width; dropdown.OptionGrid.cellWidth = width; var optGrid = dropdown.OptionGrid; //+ Set the default handler that binds the control to the member dropdown.OnDropdownOptionChangedEvent += option => { var asChoice = (IEComboBoxChoice)option; setter((T)asChoice.Value); }; return(comboBox); }