// TODO. Display status string? (right now only on/off texture, but True/False, Yes/No, Enabled/Disabled options) public BooleanElement(PropertyFieldWrapper memberInfo, object modConfig, IList <bool> array = null, int index = -1) : base(memberInfo, modConfig, (IList)array) { this._toggleTexture = TextureManager.Load("Images/UI/Settings_Toggle"); if (array != null) { _IsOnFunction = () => array[index]; this.OnClick += (ev, v) => { array[index] = !array[index]; Interface.modConfig.SetPendingChanges(); }; } else { this._IsOnFunction = () => (bool)memberInfo.GetValue(modConfig); if (memberInfo.CanWrite) { this.OnClick += (ev, v) => { memberInfo.SetValue(modConfig, !(bool)memberInfo.GetValue(modConfig)); Interface.modConfig.SetPendingChanges(); } } ; } }
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(ProjectileDefinition)) { e = new ProjectileDefinitionElement(); } else if (type == typeof(NPCDefinition)) { e = new NPCDefinitionElement(); } else if (type == typeof(PrefixDefinition)) { e = new PrefixDefinitionElement(); } 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)) { SliderAttribute sliderAttribute = ConfigManager.GetCustomAttribute <SliderAttribute>(memberInfo, item, list); if (sliderAttribute != 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); } var tuple = new Tuple <UIElement, UIElement>(container, e); if (parent == Interface.modConfig.mainConfigList) { Interface.modConfig.mainConfigItems.Add(tuple); } return(tuple); } return(null); }
public ColorObject(PropertyFieldWrapper memberInfo, object item) { this.item = item; this.memberInfo = memberInfo; current = (Color)memberInfo.GetValue(item); }
bool AllowNull => array == null; // nulls don't make sense for a collection, but a standalone might be useful. NonNull attribute might be nice. // Label: // Members // Members public ObjectElement(PropertyFieldWrapper memberInfo, object item, IList array = null, int index = -1, bool ignoreSeparatePage = false) : base(memberInfo, item, array) { this.index = index; this.ignoreSeparatePage = ignoreSeparatePage; _GetValue = () => memberInfo.GetValue(this.item); _SetValue = (object value) => { if (!memberInfo.CanWrite) { return; } memberInfo.SetValue(this.item, value); }; if (array != null) { _GetValue = () => array[index]; _SetValue = (object value) => { array[index] = value; Interface.modConfig.SetPendingChanges(); }; // TODO: only do this if ToString is overriden. var listType = memberInfo.Type.GetGenericArguments()[0]; bool hasToString = listType.GetMethod("ToString", new Type[0]).DeclaringType != typeof(object); if (hasToString) { _TextDisplayFunction = () => index + 1 + ": " + (array[index]?.ToString() ?? "null"); AbridgedTextDisplayFunction = () => (array[index]?.ToString() ?? "null"); } else { _TextDisplayFunction = () => index + 1 + ": "; } } else { bool hasToString = memberInfo.Type.GetMethod("ToString", new Type[0]).DeclaringType != typeof(object); if (hasToString) { _TextDisplayFunction = () => (labelAttribute == null ? memberInfo.Name : labelAttribute.Label) + (_GetValue() == null ? "" : ": " + _GetValue().ToString()); AbridgedTextDisplayFunction = () => _GetValue()?.ToString() ?? ""; } } if (_GetValue() == null && !AllowNull) { object data = Activator.CreateInstance(memberInfo.Type); JsonConvert.PopulateObject("{}", data, ConfigManager.serializerSettings); //JsonDefaultValueAttribute jsonDefaultValueAttribute = (JsonDefaultValueAttribute)Attribute.GetCustomAttribute(memberInfo.MemberInfo, typeof(JsonDefaultValueAttribute)); //if (jsonDefaultValueAttribute != null) //{ // JsonConvert.PopulateObject(jsonDefaultValueAttribute.json, subitem, ConfigManager.serializerSettings); //} _SetValue(data); } separatePage = ConfigManager.GetCustomAttribute <SeparatePageAttribute>(memberInfo, item, array) != null; //separatePage = separatePage && !ignoreSeparatePage; //separatePage = (SeparatePageAttribute)Attribute.GetCustomAttribute(memberInfo.MemberInfo, typeof(SeparatePageAttribute)) != null; if (separatePage && !ignoreSeparatePage) { // TODO: UITextPanel doesn't update... separatePageButton = new UITextPanel <FuncStringWrapper>(new FuncStringWrapper() { func = _TextDisplayFunction }); separatePageButton.HAlign = 0.5f; //e.Recalculate(); //elementHeight = (int)e.GetOuterDimensions().Height; separatePageButton.OnClick += (a, c) => { UIModConfig.SwitchToSubConfig(this.separatePagePanel); /* Interface.modConfig.uIElement.RemoveChild(Interface.modConfig.configPanelStack.Peek()); * Interface.modConfig.uIElement.Append(separateListPanel); * Interface.modConfig.configPanelStack.Push(separateListPanel);*/ //separateListPanel.SetScrollbar(Interface.modConfig.uIScrollbar); //UIPanel panel = new UIPanel(); //panel.Width.Set(200, 0); //panel.Height.Set(200, 0); //panel.Left.Set(200, 0); //panel.Top.Set(200, 0); //Interface.modConfig.Append(panel); //Interface.modConfig.subMenu.Enqueue(subitem); //Interface.modConfig.DoMenuModeState(); }; //e = new UIText($"{memberInfo.Name} click for more ({type.Name})."); //e.OnClick += (a, b) => { }; } //data = _GetValue();// memberInfo.GetValue(this.item); //drawLabel = false; dataList = new NestedUIList(); dataList.Width.Set(-14, 1f); dataList.Left.Set(14, 0f); dataList.Height.Set(-30, 1f); dataList.Top.Set(30, 0); dataList.ListPadding = 5f; Append(dataList); //string name = memberInfo.Name; //if (labelAttribute != null) //{ // name = labelAttribute.Label; //} if (array == null) { // drawLabel = false; TODO uncomment } initializeButton = new UIModConfigHoverImage(playTexture, "Initialize"); initializeButton.Top.Pixels += 4; initializeButton.Left.Pixels -= 3; initializeButton.HAlign = 1f; initializeButton.OnClick += (a, b) => { Main.PlaySound(21); object data = Activator.CreateInstance(memberInfo.Type); // Crashes JSONItem JsonConvert.PopulateObject("{}", data, ConfigManager.serializerSettings); // Seems to fail on all data structures? //JsonDefaultValueAttribute jsonDefaultValueAttribute = (JsonDefaultValueAttribute)Attribute.GetCustomAttribute(memberInfo.MemberInfo, typeof(JsonDefaultValueAttribute)); //if (jsonDefaultValueAttribute != null) //{ // JsonConvert.PopulateObject(jsonDefaultValueAttribute.json, subitem, ConfigManager.serializerSettings); //} _SetValue(data); //SeparatePageAttribute here? pendingChanges = true; //RemoveChild(initializeButton); //Append(deleteButton); //Append(expandButton); SetupList(); Interface.modConfig.RecalculateChildren(); Interface.modConfig.SetPendingChanges(); }; expandButton = new UIModConfigHoverImage(expandedTexture, "Expand"); expandButton.Top.Set(4, 0f); // 10, -25: 4, -52 expandButton.Left.Set(-52, 1f); expandButton.OnClick += (a, b) => { expanded = !expanded; pendingChanges = true; }; deleteButton = new UIModConfigHoverImage(deleteTexture, "Clear"); deleteButton.Top.Set(4, 0f); deleteButton.Left.Set(-25, 1f); deleteButton.OnClick += (a, b) => { _SetValue(null); pendingChanges = true; SetupList(); //Interface.modConfig.RecalculateChildren(); Interface.modConfig.SetPendingChanges(); }; if (_GetValue() != null) { //Append(expandButton); //Append(deleteButton); SetupList(); } else { Append(initializeButton); //sortedContainer.Append(initializeButton); } pendingChanges = true; Recalculate(); }
public Vector2Object(PropertyFieldWrapper memberInfo, object item) { this.item = item; this.memberInfo = memberInfo; current = (Vector2)memberInfo.GetValue(item); }
public static Tuple <UIElement, UIElement> WrapIt(UIElement parent, ref int top, PropertyFieldWrapper memberInfo, object item, int order, object array = null, Type arrayType = null, int index = -1) { int elementHeight = 0; Type type = memberInfo.Type; if (arrayType != null) { type = arrayType; } UIElement e = null; // TODO: Other common structs? -- Rectangle, Point CustomModConfigItemAttribute customUI = ConfigManager.GetCustomAttribute <CustomModConfigItemAttribute>(memberInfo, null, null); if (customUI != null) { Type customUIType = customUI.t; ConstructorInfo ctor = customUIType.GetConstructor(new[] { typeof(PropertyFieldWrapper), typeof(object), typeof(int), typeof(IList), typeof(int) }); if (ctor != null) { object[] arguments = new object[] { memberInfo, item, 0, array, index }; object instance = ctor.Invoke(arguments); e = instance as UIElement; if (e != null) { //e.Recalculate(); //elementHeight = (int)e.GetOuterDimensions().Height; //elementHeight = 400; //e.GetHeight(); } else { e = new UIText($"CustomUI for {memberInfo.Name} does not inherit from UIElement."); } } else { e = new UIText($"CustomUI for {memberInfo.Name} does not have the correct constructor."); } } else if (item.GetType() == typeof(HeaderAttribute)) { //e = new UIText($"{memberInfo.GetValue(item)}", .4f, true); //e.SetPadding(6); e = new HeaderElement((string)memberInfo.GetValue(item)); } else if (type == typeof(ItemDefinition)) { e = new ItemDefinitionElement(memberInfo, item, (IList <ItemDefinition>)array, index); } else if (type == typeof(Color)) { e = new ColorElement(memberInfo, item, (IList <Color>)array, index); //elementHeight = (int)(e as UIModConfigColorItem).GetHeight(); } else if (type == typeof(Vector2)) { e = new Vector2Element(memberInfo, item, (IList <Vector2>)array, index); } else if (type == typeof(bool)) // isassignedfrom? { e = new BooleanElement(memberInfo, item, (IList <bool>)array, index); } else if (type == typeof(float)) { e = new FloatElement(memberInfo, item, (IList <float>)array, index); } else if (type == typeof(byte)) { e = new ByteElement(memberInfo, item, (IList <byte>)array, index); } else if (type == typeof(uint)) { e = new UIntElement(memberInfo, item, (IList <uint>)array, index); } else if (type == typeof(int)) { RangeAttribute rangeAttribute = ConfigManager.GetCustomAttribute <RangeAttribute>(memberInfo, item, array); if (rangeAttribute != null) { e = new IntRangeElement(memberInfo, item, (IList <int>)array, index); } else { e = new IntInputElement(memberInfo, item, (IList <int>)array, index); } } else if (type == typeof(string)) { OptionStringsAttribute ost = ConfigManager.GetCustomAttribute <OptionStringsAttribute>(memberInfo, item, array); if (ost != null) { e = new StringOptionElement(memberInfo, item, (IList <string>)array, index); } else { e = new StringInputElement(memberInfo, item, (IList <string>)array, index); } } else if (type.IsEnum) { if (array != null) { e = new UIText($"{memberInfo.Name} not handled yet ({type.Name})."); } else { e = new EnumElement(memberInfo, item); } } else if (type.IsArray) { e = new ArrayElement(memberInfo, item); //elementHeight = 225; } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List <>)) { e = new ListElement(memberInfo, item); //elementHeight = 225; } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(HashSet <>)) { e = new SetElement(memberInfo, item); } else if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Dictionary <,>)) { e = new DictionaryElement(memberInfo, item); //elementHeight = 300; } else if (type.IsClass) { e = new ObjectElement(memberInfo, item, (IList)array, index /*, 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) { e.Recalculate(); elementHeight = (int)e.GetOuterDimensions().Height; var container = GetContainer(e, index == -1 ? order : index); container.Height.Pixels = elementHeight; UIList list = parent as UIList; if (list != null) { list.Add(container); float p = list.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 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? }