aubergine18 said:



Hopefully he won't mind this screenie from upcoming release being posted to clarify what I mean by tabs (I wasn't sure if this is what is meant by "Groups" in the API...)



View attachment 131175



cc: Thanks for the infos - one quick question, is it possible to have a mod options panel with multiple tabs? Joao (T++ dev) is away this week so just asking in his absence.Hopefully he won't mind this screenie from upcoming release being posted to clarify what I mean by tabs (I wasn't sure if this is what is meant by "Groups" in the API...)cc: @sairaf Click to expand...

Code: using System; using ICities; using UnityEngine; using ColossalFramework.UI; namespace DTestMod { public class DTestClass : IUserMod { ........ private void EventCheck(bool c) { Debug.Log(c); } public void OnSettingsUI(UIHelperBase helper) { UIScrollablePanel rootPanel = ((UIHelper)helper).self as UIScrollablePanel; rootPanel.autoLayout = false; UITabstrip strip = rootPanel.AddUIComponent<UITabstrip>(); // Matching the size of the root panel so no scrolling happens accidentally strip.relativePosition = new Vector3(0, 0); strip.size = new Vector2(744, 40); UITabContainer container = rootPanel.AddUIComponent<UITabContainer>(); // Matching the size of the root panel so no scrolling happens accidentally container.relativePosition = new Vector3(0, 40); container.size = new Vector3(744, 713); // Associated the strips to the tabs container strip.tabPages = container; // E.g get some button from the templates and copy the properties in the strip button UIButton template = (UIButton)UITemplateManager.Peek("OptionsButtonTemplate"); UIButton newButton = strip.AddTab("test", template, true); newButton.textColor = template.textColor; newButton.pressedTextColor = template.pressedTextColor; newButton.hoveredTextColor = template.hoveredTextColor; newButton.focusedTextColor = template.hoveredTextColor; newButton.disabledTextColor = template.hoveredTextColor; // Get the current container and use the UIHelper to have something in there UIPanel stripRoot = strip.tabContainer.components[0] as UIPanel; stripRoot.autoLayout = true; UIHelper stripHelper = new UIHelper(stripRoot); UIComponent box = stripHelper.AddCheckbox("New check", true, EventCheck) as UIComponent; box.FitTo(stripRoot, LayoutDirection.Horizontal); newButton = strip.AddTab("test2"); newButton.textColor = template.textColor; newButton.pressedTextColor = template.pressedTextColor; newButton.hoveredTextColor = template.hoveredTextColor; newButton.focusedTextColor = template.hoveredTextColor; newButton.disabledTextColor = template.hoveredTextColor; // And so forth... // Force the strip states to reset strip.selectedIndex = -1; // Set the first tab to active strip.selectedIndex = 0; } } }

Hi,We do not support tabs through the API at the moment but we will likely make it happen in the future.However what you can do now is group features in the same page as sub-section using the AddGroup() method. If you have a tons of settings though, it will cause a rather long scrolling panel.Eventually, if you are feeling adventurous (as we do not officially support direct access to the underlying code) and reaalllyy can't wait, since mods overriding the UI are already referencing the game assembly and the ColossalFramework assembly, make sure to include the relevant namespaces in your using clause and cast the UIHelperBase parameter to UIHelper.Once casted, the getter helper.self will return an object directly referencing the root UIComponent of the panel (in the case of the upper most root, it will be an UIScrollablePanel so cast is needed again) and you can mess around with the content of the panel without API restrictions.Of course, it is quite a lot of work to create all of these manually but in many cases you have already been doing that kind of work around to expose your properties before the patchExample below (you can then set padding, spacing and use the sprites available to your UI to make it pretty but I think you get the idea from this snippet):Note: If you duplicate an object which already exists in the scene (as I think T++ did with the OptionsPanel by duplicating it, cleaning all children and spawning its own UI, make very very sure to also clean up our potential scripts attached to that same object as it results in this example to multiple OptionsPanel instance waiting for events at the same time and when an event triggers, the duplicated-cleaned up version will fire null reference exceptions).Hope that helps a bit,Cheers