internal static UIPanel MakeSeparateListPanel(object item, object subitem, PropertyFieldWrapper memberInfo, IList array, int index, Func <string> AbridgedTextDisplayFunction) { UIPanel uIPanel = new UIPanel(); uIPanel.CopyStyle(Interface.modConfig.uIPanel); uIPanel.BackgroundColor = UICommon.mainPanelBackground; BackgroundColorAttribute bca = ConfigManager.GetCustomAttribute <BackgroundColorAttribute>(memberInfo, subitem, null); if (bca != null) { uIPanel.BackgroundColor = bca.color; } //uIElement.Append(uIPanel); UIList separateList = new UIList(); separateList.CopyStyle(Interface.modConfig.mainConfigList); separateList.Height.Set(-40f, 1f); separateList.Top.Set(40f, 0f); uIPanel.Append(separateList); int i = 0; int top = 0; UIScrollbar uIScrollbar = new UIScrollbar(); uIScrollbar.SetView(100f, 1000f); uIScrollbar.Height.Set(-40f, 1f); uIScrollbar.Top.Set(40f, 0f); uIScrollbar.HAlign = 1f; uIPanel.Append(uIScrollbar); separateList.SetScrollbar(uIScrollbar); string name = ConfigManager.GetCustomAttribute <LabelAttribute>(memberInfo, subitem, null)?.Label ?? memberInfo.Name; if (index != -1) { name = name + " #" + (index + 1); } Interface.modConfig.subPageStack.Push(name); //UIPanel heading = new UIPanel(); //UIText headingText = new UIText(name); name = string.Join(" > ", Interface.modConfig.subPageStack.Reverse()); //.Aggregate((current, next) => current + "/" + next); UITextPanel <string> heading = new UITextPanel <string>(name); // TODO: ToString as well. Separate label? heading.HAlign = 0f; //heading.Width.Set(-10, 0.5f); //heading.Left.Set(60, 0f); heading.Top.Set(-6, 0); heading.Height.Set(40, 0); //var headingContainer = GetContainer(heading, i++); //headingContainer.Height.Pixels = 40; uIPanel.Append(heading); //headingText.Top.Set(6, 0); //headingText.Left.Set(0, .5f); //headingText.HAlign = .5f; //uIPanel.Append(headingText); //top += 40; UITextPanel <string> back = new UITextPanel <string>("Back"); back.HAlign = 1f; back.Width.Set(50, 0f); back.Top.Set(-6, 0); //top += 40; //var capturedCurrent = Interface.modConfig.currentConfigList; back.OnClick += (a, c) => { Interface.modConfig.uIElement.RemoveChild(uIPanel); Interface.modConfig.configPanelStack.Pop(); Interface.modConfig.uIElement.Append(Interface.modConfig.configPanelStack.Peek()); //Interface.modConfig.configPanelStack.Peek().SetScrollbar(Interface.modConfig.uIScrollbar); //Interface.modConfig.currentConfigList = capturedCurrent; }; back.WithFadedMouseOver(); //var backContainer = GetContainer(back, i++); //backContainer.Height.Pixels = 40; uIPanel.Append(back); //var b = new UIText("Test"); //separateList.Add(b); // Make rest of list // load all mod config options into UIList // TODO: Inheritance with ModConfig? DeclaredOnly? if (true) { int order = 0; bool hasToString = false; if (array != null) { var listType = memberInfo.Type.GetGenericArguments()[0]; hasToString = listType.GetMethod("ToString", new Type[0]).DeclaringType != typeof(object); } else { hasToString = memberInfo.Type.GetMethod("ToString", new Type[0]).DeclaringType != typeof(object); } if (AbridgedTextDisplayFunction != null) { var display = new UITextPanel <FuncStringWrapper>(new FuncStringWrapper() { func = AbridgedTextDisplayFunction, }) { DrawPanel = true }; display.Recalculate(); var container = GetContainer(display, order++); container.Height.Pixels = (int)display.GetOuterDimensions().Height; separateList.Add(container); } //if (hasToString) // _TextDisplayFunction = () => index + 1 + ": " + (array[index]?.ToString() ?? "null"); foreach (PropertyFieldWrapper variable in ConfigManager.GetFieldsAndProperties(subitem)) { if (Attribute.IsDefined(variable.MemberInfo, typeof(JsonIgnoreAttribute)) && !Attribute.IsDefined(variable.MemberInfo, typeof(LabelAttribute))) // TODO, appropriately named attribute { continue; } HeaderAttribute header = ConfigManager.GetCustomAttribute <HeaderAttribute>(variable, null, null); if (header != null) { var wrapper = new PropertyFieldWrapper(typeof(HeaderAttribute).GetProperty(nameof(HeaderAttribute.Header))); WrapIt(separateList, ref top, wrapper, header, order++); } WrapIt(separateList, ref top, variable, subitem, order++); } } else { //ignoreSeparatePage just to simplify ToString label--> had some issues. //WrapIt(separateList, ref top, memberInfo, item, 1, ignoreSeparatePage: true); } Interface.modConfig.subPageStack.Pop(); return(uIPanel); }
public DictionaryElement(PropertyFieldWrapper memberInfo, object item) : base(memberInfo, item) { }
public override void OnActivate() { SetMessage("", Color.White); string configDisplayName = ((LabelAttribute)Attribute.GetCustomAttribute(modConfig.GetType(), typeof(LabelAttribute)))?.Label ?? modConfig.Name; headerTextPanel.SetText(modConfig.mod.DisplayName + ": " + configDisplayName); pendingConfig = modConfig.Clone(); pendingChanges = pendingRevertDefaults; if (pendingRevertDefaults) { pendingRevertDefaults = false; ConfigManager.Reset(pendingConfig); pendingChangesUIUpdate = true; } int index = modConfigs.IndexOf(modConfig); int count = modConfigs.Count; //pendingChanges = false; backButton.BackgroundColor = UICommon.defaultUIBlueMouseOver; uIElement.RemoveChild(saveConfigButton); uIElement.RemoveChild(revertConfigButton); uIElement.RemoveChild(previousConfigButton); uIElement.RemoveChild(nextConfigButton); if (index + 1 < count) { uIElement.Append(nextConfigButton); } if (index - 1 >= 0) { uIElement.Append(previousConfigButton); } uIElement.RemoveChild(configPanelStack.Peek()); uIElement.Append(uIPanel); mainConfigList.Clear(); configPanelStack.Clear(); configPanelStack.Push(uIPanel); subPageStack.Clear(); //currentConfigList = mainConfigList; int i = 0; int top = 0; // load all mod config options into UIList // TODO: Inheritance with ModConfig? DeclaredOnly? uIPanel.BackgroundColor = UICommon.mainPanelBackground; var backgroundColorAttribute = (BackgroundColorAttribute)Attribute.GetCustomAttribute(pendingConfig.GetType(), typeof(BackgroundColorAttribute)); if (backgroundColorAttribute != null) { uIPanel.BackgroundColor = backgroundColorAttribute.color; } int order = 0; foreach (PropertyFieldWrapper variable in ConfigManager.GetFieldsAndProperties(pendingConfig)) { if (variable.isProperty && variable.Name == "Mode") { continue; } if (Attribute.IsDefined(variable.MemberInfo, typeof(JsonIgnoreAttribute)) && !Attribute.IsDefined(variable.MemberInfo, typeof(LabelAttribute))) // TODO, appropriately named attribute { continue; } HeaderAttribute header = ConfigManager.GetCustomAttribute <HeaderAttribute>(variable, null, null); if (header != null) { var wrapper = new PropertyFieldWrapper(typeof(HeaderAttribute).GetProperty(nameof(HeaderAttribute.Header))); WrapIt(mainConfigList, ref top, wrapper, header, order++); } WrapIt(mainConfigList, ref top, variable, pendingConfig, order++); } }
public static Tuple <UIElement, UIElement> WrapIt(UIElement parent, ref int top, PropertyFieldWrapper memberInfo, object item, int order, object list = null, Type arrayType = null, int index = -1) { int elementHeight = 0; Type type = memberInfo.Type; if (arrayType != null) { type = arrayType; } UIElement e; // TODO: Other common structs? -- Rectangle, Point CustomModConfigItemAttribute customUI = ConfigManager.GetCustomAttribute <CustomModConfigItemAttribute>(memberInfo, null, null); if (customUI != null) { Type customUIType = customUI.t; if (typeof(ConfigElement).IsAssignableFrom(customUIType)) { ConstructorInfo ctor = customUIType.GetConstructor(new Type[0]); if (ctor != null) { object instance = ctor.Invoke(new object[0]); e = instance as UIElement; } else { e = new UIText($"{customUIType.Name} specified via CustomModConfigItem for {memberInfo.Name} does not have an empty constructor."); } } else { e = new UIText($"{customUIType.Name} specified via CustomModConfigItem for {memberInfo.Name} does not inherit from ConfigElement."); } } else if (item.GetType() == typeof(HeaderAttribute)) { e = new HeaderElement((string)memberInfo.GetValue(item)); } else if (type == typeof(ItemDefinition)) { e = new ItemDefinitionElement(); } else if (type == typeof(Color)) { e = new ColorElement(); } else if (type == typeof(Vector2)) { e = new Vector2Element(); } else if (type == typeof(bool)) // isassignedfrom? { e = new BooleanElement(); } else if (type == typeof(float)) { e = new FloatElement(); } else if (type == typeof(byte)) { e = new ByteElement(); } else if (type == typeof(uint)) { e = new UIntElement(); } else if (type == typeof(int)) { RangeAttribute rangeAttribute = ConfigManager.GetCustomAttribute <RangeAttribute>(memberInfo, item, list); if (rangeAttribute != null) { e = new IntRangeElement(); } else { e = new IntInputElement(); } } else if (type == typeof(string)) { OptionStringsAttribute ost = ConfigManager.GetCustomAttribute <OptionStringsAttribute>(memberInfo, item, list); if (ost != null) { e = new StringOptionElement(); } else { e = new StringInputElement(); } } else if (type.IsEnum) { if (list != null) { e = new UIText($"{memberInfo.Name} not handled yet ({type.Name})."); } else { e = new EnumElement(); } } else if (type.IsArray) { e = new ArrayElement(); } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>)) { e = new ListElement(); } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(HashSet <>)) { e = new SetElement(); } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary <,>)) { e = new DictionaryElement(); } else if (type.IsClass) { e = new ObjectElement(/*, ignoreSeparatePage: ignoreSeparatePage*/); } else if (type.IsValueType && !type.IsPrimitive) { e = new UIText($"{memberInfo.Name} not handled yet ({type.Name}) Structs need special UI."); //e.Top.Pixels += 6; e.Height.Pixels += 6; e.Left.Pixels += 4; object subitem = memberInfo.GetValue(item); } else { e = new UIText($"{memberInfo.Name} not handled yet ({type.Name})"); e.Top.Pixels += 6; e.Left.Pixels += 4; } if (e != null) { if (e is ConfigElement configElement) { configElement.Bind(memberInfo, item, (IList)list, index); configElement.OnBind(); } e.Recalculate(); elementHeight = (int)e.GetOuterDimensions().Height; var container = GetContainer(e, index == -1 ? order : index); container.Height.Pixels = elementHeight; UIList uiList = parent as UIList; if (uiList != null) { uiList.Add(container); float p = uiList.GetTotalHeight(); } else { // Only Vector2 and Color use this I think, but modders can use the non-UIList approach for custom UI and layout. container.Top.Pixels = top; container.Width.Pixels = -20; container.Left.Pixels = 20; top += elementHeight + 4; parent.Append(container); parent.Height.Set(top, 0); } return(new Tuple <UIElement, UIElement>(container, e)); } return(null); }
public ColorObject(PropertyFieldWrapper memberInfo, object item) { this.item = item; this.memberInfo = memberInfo; current = (Color)memberInfo.GetValue(item); }
public ItemDefinitionElement(PropertyFieldWrapper memberInfo, object item, IList <ItemDefinition> array = null, int index = -1) : base(memberInfo, item, (IList)array) { Height.Set(30f, 0f); _GetValue = () => DefaultGetValue(); _SetValue = (ItemDefinition value) => DefaultSetValue(value); if (array != null) { _GetValue = () => array[index]; _SetValue = (ItemDefinition value) => { array[index] = value; Interface.modConfig.SetPendingChanges(); }; _TextDisplayFunction = () => index + 1 + ": "; } //itemChoice = new UIModConfigItemDefinitionChoice(_GetValue()?.GetID() ?? 0, 0.5f); itemChoice = new ItemDefinitionOptionElement(_GetValue(), 0.5f); itemChoice.Top.Set(2f, 0f); itemChoice.Left.Set(-30, 1f); itemChoice.OnClick += (a, b) => { itemSelectionExpanded = !itemSelectionExpanded; updateNeeded = true; }; Append(itemChoice); chooserPanel = new UIPanel(); chooserPanel.Top.Set(30, 0); chooserPanel.Height.Set(200, 0); chooserPanel.Width.Set(0, 1); chooserPanel.BackgroundColor = Color.CornflowerBlue; UIPanel textBoxBackgroundA = new UIPanel(); textBoxBackgroundA.Width.Set(160, 0f); textBoxBackgroundA.Height.Set(30, 0f); textBoxBackgroundA.Top.Set(-6, 0); textBoxBackgroundA.PaddingTop = 0; textBoxBackgroundA.PaddingBottom = 0; chooserFilter = new UIFocusInputTextField("Filter by Name"); chooserFilter.OnTextChange += (a, b) => { updateNeeded = true; }; chooserFilter.OnRightClick += (a, b) => chooserFilter.SetText(""); chooserFilter.Width = StyleDimension.Fill; chooserFilter.Height.Set(-6, 1f); chooserFilter.Top.Set(6, 0f); textBoxBackgroundA.Append(chooserFilter); chooserPanel.Append(textBoxBackgroundA); UIPanel textBoxBackgroundB = new UIPanel(); textBoxBackgroundB.CopyStyle(textBoxBackgroundA); textBoxBackgroundB.Left.Set(180, 0); chooserFilterMod = new UIFocusInputTextField("Filter by Mod"); chooserFilterMod.OnTextChange += (a, b) => { updateNeeded = true; }; chooserFilterMod.OnRightClick += (a, b) => chooserFilterMod.SetText(""); chooserFilterMod.Width = StyleDimension.Fill; chooserFilterMod.Height.Set(-6, 1f); chooserFilterMod.Top.Set(6, 0f); textBoxBackgroundB.Append(chooserFilterMod); chooserPanel.Append(textBoxBackgroundB); chooserGrid = new NestedUIGrid(); chooserGrid.Top.Set(30, 0); chooserGrid.Height.Set(-30, 1); chooserGrid.Width.Set(-12, 1); chooserPanel.Append(chooserGrid); UIScrollbar scrollbar = new UIScrollbar(); scrollbar.SetView(100f, 1000f); scrollbar.Height.Set(-30f, 1f); scrollbar.Top.Set(30f, 0f); scrollbar.Left.Pixels += 8; scrollbar.HAlign = 1f; chooserGrid.SetScrollbar(scrollbar); chooserPanel.Append(scrollbar); //Append(chooserPanel); UIModConfigHoverImageSplit upDownButton = new UIModConfigHoverImageSplit(upDownTexture, "Zoom in", "Zoom out"); upDownButton.Recalculate(); upDownButton.Top.Set(-4f, 0f); upDownButton.Left.Set(-18, 1f); upDownButton.OnClick += (a, b) => { Rectangle r = b.GetDimensions().ToRectangle(); if (a.MousePosition.Y < r.Y + r.Height / 2) { itemScale = Math.Min(1f, itemScale + 0.1f); } else { itemScale = Math.Max(0.5f, itemScale - 0.1f); } foreach (var itemchoice in items) { itemchoice.SetScale(itemScale); } }; chooserPanel.Append(upDownButton); }
public CollectionElement(PropertyFieldWrapper memberInfo, object item) : base(memberInfo, item, null) { data = memberInfo.GetValue(item); defaultListValueAttribute = ConfigManager.GetCustomAttribute <DefaultListValueAttribute>(memberInfo, null, null); MaxHeight.Set(300, 0f); dataListElement = new UIElement(); dataListElement.Width.Set(-10f, 1f); dataListElement.Left.Set(10f, 0f); dataListElement.Height.Set(-30, 1f); dataListElement.Top.Set(30f, 0f); //panel.SetPadding(0); //panel.BackgroundColor = Microsoft.Xna.Framework.Color.Transparent; //panel.BorderColor = Microsoft.Xna.Framework.Color.Transparent; if (data != null) { Append(dataListElement); } dataListElement.OverflowHidden = true; dataList = new NestedUIList(); dataList.Width.Set(-20, 1f); dataList.Left.Set(0, 0f); dataList.Height.Set(0, 1f); dataList.ListPadding = 5f; dataListElement.Append(dataList); UIScrollbar scrollbar = new UIScrollbar(); scrollbar.SetView(100f, 1000f); scrollbar.Height.Set(-16f, 1f); scrollbar.Top.Set(6f, 0f); scrollbar.Left.Pixels -= 3; scrollbar.HAlign = 1f; dataList.SetScrollbar(scrollbar); dataListElement.Append(scrollbar); PrepareTypes(); // allow null collections to simplify modder code for OnDeserialize and allow null and empty lists to have different meanings, etc. SetupList(); if (CanAdd) { initializeButton = new UIModConfigHoverImage(playTexture, "Initialize"); initializeButton.Top.Pixels += 4; initializeButton.Left.Pixels -= 3; initializeButton.HAlign = 1f; initializeButton.OnClick += (a, b) => { Main.PlaySound(SoundID.Tink); InitializeCollection(); SetupList(); Interface.modConfig.RecalculateChildren(); // not needed? Interface.modConfig.SetPendingChanges(); expanded = true; pendingChanges = true; }; addButton = new UIModConfigHoverImage(plusTexture, "Add"); addButton.Top.Set(4, 0f); addButton.Left.Set(-52, 1f); addButton.OnClick += (a, b) => { Main.PlaySound(SoundID.Tink); AddItem(); SetupList(); Interface.modConfig.RecalculateChildren(); Interface.modConfig.SetPendingChanges(); expanded = true; pendingChanges = true; }; deleteButton = new UIModConfigHoverImage(deleteTexture, "Clear"); deleteButton.Top.Set(4, 0f); deleteButton.Left.Set(-25, 1f); deleteButton.OnClick += (a, b) => { Main.PlaySound(SoundID.Tink); NullCollection(); SetupList(); Interface.modConfig.RecalculateChildren(); Interface.modConfig.SetPendingChanges(); pendingChanges = true; }; } expandButton = new UIModConfigHoverImage(collapsedTexture, "Expand"); expandButton.Top.Set(4, 0f); // 10, -25: 4, -52 expandButton.Left.Set(-79, 1f); expandButton.OnClick += (a, b) => { expanded = !expanded; pendingChanges = true; }; upDownButton = new UIModConfigHoverImageSplit(upDownTexture, "Scale Up", "Scale Down"); upDownButton.Top.Set(4, 0f); upDownButton.Left.Set(-106, 1f); upDownButton.OnClick += (a, b) => { Rectangle r = b.GetDimensions().ToRectangle(); if (a.MousePosition.Y < r.Y + r.Height / 2) { scale = Math.Min(2f, scale + 0.5f); } else { scale = Math.Max(1f, scale - 0.5f); } //dataListPanel.RecalculateChildren(); ////dataList.RecalculateChildren(); //float h = dataList.GetTotalHeight(); //MinHeight.Set(Math.Min(Math.Max(h + 84, 100), 300) * scale, 0f); //Recalculate(); //if (Parent != null && Parent is UISortableElement) { // Parent.Height.Pixels = GetOuterDimensions().Height; //} }; //Append(upButton); //var aasdf = Texture2D.FromStream(Main.instance.GraphicsDevice, Assembly.GetExecutingAssembly().GetManifestResourceStream("Terraria.ModLoader.Config.UI.ButtonDecrement.png")); //for (int i = 0; i < 100; i++) { // var vb = Texture2D.FromStream(Main.instance.GraphicsDevice, Assembly.GetExecutingAssembly().GetManifestResourceStream("Terraria.ModLoader.Config.UI.ButtonDecrement.png")); //} pendingChanges = true; Recalculate(); // Needed? }
public Vector2Object(PropertyFieldWrapper memberInfo, object item) { this.item = item; this.memberInfo = memberInfo; current = (Vector2)memberInfo.GetValue(item); }
public ArrayElement(PropertyFieldWrapper memberInfo, object item) : base(memberInfo, item) { // TODO: Allow null maybe? }