/// <summary> /// Adds crime options tab to tabstrip. /// </summary> /// <param name="tabStrip">Tab strip to add to</param> /// <param name="tabIndex">Index number of tab</param> internal CrimePanel(UITabstrip tabStrip, int tabIndex) { // Add tab and helper. UIPanel panel = PanelUtils.AddTextTab(tabStrip, Translations.Translate("RPR_OPT_CRI"), tabIndex, out UIButton _); UIHelper helper = new UIHelper(panel); panel.autoLayout = true; // Add slider component. UISlider newSlider = UIControls.AddSlider(panel, Translations.Translate("RPR_OPT_CML"), 1f, 200f, 1f, ModSettings.crimeMultiplier); newSlider.tooltipBox = TooltipUtils.TooltipBox; newSlider.tooltip = Translations.Translate("RPR_OPT_CML_TIP"); // Value label. UIPanel sliderPanel = (UIPanel)newSlider.parent; UILabel valueLabel = sliderPanel.AddUIComponent <UILabel>(); valueLabel.name = "ValueLabel"; valueLabel.relativePosition = UIControls.PositionRightOf(newSlider, 8f, 1f); // Set initial text. PercentSliderText(newSlider, newSlider.value); // Slider change event. newSlider.eventValueChanged += (control, value) => { // Update value label. PercentSliderText(control, value); // Update setting. ModSettings.crimeMultiplier = value; }; }
/// <summary> /// Adds button to access building details from building info panels. /// </summary> internal static void AddInfoPanelButton() { // Zoned building panel - get parent panel and add button. ZonedBuildingWorldInfoPanel infoPanel = UIView.library.Get <ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); zonedButton = UIControls.AddButton(infoPanel.component, infoPanel.component.width - 133f - 10, 120, Translations.Translate("RPR_REALPOP"), 133f, 19.5f, 0.65f); zonedButton.textPadding = new RectOffset(2, 2, 4, 0); // Just in case other mods are interfering. zonedButton.Enable(); // Event handler. zonedButton.eventClick += (control, clickEvent) => { // Select current building in the building details panel and show. Open(InstanceManager.GetPrefabInfo(WorldInfoPanel.GetCurrentInstanceID()) as BuildingInfo); }; // Service building panel - get parent panel and add button. CityServiceWorldInfoPanel servicePanel = UIView.library.Get <CityServiceWorldInfoPanel>(typeof(CityServiceWorldInfoPanel).Name); serviceButton = UIControls.AddButton(servicePanel.component, servicePanel.component.width - 133f - 10, 120, Translations.Translate("RPR_REALPOP"), 133f, 19.5f, 0.65f); serviceButton.textPadding = new RectOffset(2, 2, 4, 0); // Event handler. serviceButton.eventClick += (control, clickEvent) => { // Select current building in the building details panel and show. Open(InstanceManager.GetPrefabInfo(WorldInfoPanel.GetCurrentInstanceID()) as BuildingInfo); }; }
/// <summary> /// Adds panel footer controls (pack name textfield and buttons). /// </summary> /// <param name="yPos">Reference Y position</param> protected void PanelFooter(float yPos) { // Additional space before name textfield. float currentY = yPos + RowHeight; // Pack name textfield. PackNameField = UIControls.BigTextField(panel, 140f, currentY); PackNameField.isEnabled = false; UILabel packNameLabel = UIControls.AddLabel(PackNameField, -100f, (PackNameField.height - 18f) / 2, Translations.Translate("RPR_OPT_EDT_NAM")); // Space for buttons. currentY += 50f; // 'Add new' button. UIButton addNewButton = UIControls.AddButton(panel, 20f, currentY, Translations.Translate("RPR_OPT_NEW")); addNewButton.eventClicked += AddPack; // Save pack button. saveButton = UIControls.AddButton(panel, 250f, currentY, Translations.Translate("RPR_OPT_SAA")); saveButton.eventClicked += Save; // Delete pack button. deleteButton = UIControls.AddButton(panel, 480f, currentY, Translations.Translate("RPR_OPT_DEL")); deleteButton.eventClicked += DeletePack; }
/// <summary> /// Adds footer buttons to the panel. /// </summary> /// <param name="yPos">Relative Y position for buttons</param> protected override void FooterButtons(float yPos) { base.FooterButtons(yPos); // Save button. UIButton saveButton = UIControls.AddButton(panel, (Margin * 3) + 300f, yPos, Translations.Translate("RPR_OPT_SAA"), 150f); saveButton.eventClicked += Apply; }
/// <summary> /// Harmony Postfix patch to ZonedBuildingWorldInfoPanel.UpdateBindings to display visitor counts for commercial buildings. /// </summary> public static void Postfix() { // Currently selected building. ushort building = WorldInfoPanel.GetCurrentInstanceID().Building; // Create visit label if it isn't already set up. if (visitLabel == null) { // Get info panel. ZonedBuildingWorldInfoPanel infoPanel = UIView.library.Get <ZonedBuildingWorldInfoPanel>(typeof(ZonedBuildingWorldInfoPanel).Name); // Add current visitor count label. visitLabel = UIControls.AddLabel(infoPanel.component, 65f, 280f, Translations.Translate("RPR_INF_VIS"), textScale: 0.75f); visitLabel.textColor = new Color32(185, 221, 254, 255); visitLabel.font = Resources.FindObjectsOfTypeAll <UIFont>().FirstOrDefault((UIFont f) => f.name == "OpenSans-Regular"); // Position under existing Highly Educated workers count row in line with total workplace count label. UIComponent situationLabel = infoPanel.Find("WorkSituation"); UIComponent workerLabel = infoPanel.Find("HighlyEducatedWorkers"); if (situationLabel != null && workerLabel != null) { visitLabel.absolutePosition = new Vector2(situationLabel.absolutePosition.x, workerLabel.absolutePosition.y + 25f); } else { Logging.Error("couldn't find ZonedBuildingWorldInfoPanel components"); } } // Local references. Building[] buildingBuffer = Singleton <BuildingManager> .instance.m_buildings.m_buffer; BuildingInfo buildingInfo = buildingBuffer[building].Info; // Is this a commercial building? CommercialBuildingAI commercialAI = buildingInfo.GetAI() as CommercialBuildingAI; if (commercialAI == null) { // Not a commercial building - hide the label. visitLabel.Hide(); } else { // Commercial building - show the label. visitLabel.Show(); // Get current visitor count. int aliveCount = 0, totalCount = 0; Citizen.BehaviourData behaviour = new Citizen.BehaviourData(); GetVisitBehaviour(commercialAI, building, ref buildingBuffer[building], ref behaviour, ref aliveCount, ref totalCount); // Display visitor count. visitLabel.text = totalCount.ToString() + " / " + commercialAI.CalculateVisitplaceCount((ItemClass.Level)buildingBuffer[building].m_level, new ColossalFramework.Math.Randomizer(building), buildingBuffer[building].Width, buildingBuffer[building].Length).ToString() + " " + Translations.Translate("RPR_INF_VIS"); } }
/// <summary> /// Adds footer buttons to the panel. /// </summary> /// <param name="yPos">Relative Y position for buttons</param> protected virtual void FooterButtons(float yPos) { // Reset button. UIButton resetButton = UIControls.AddButton(panel, Margin, yPos, Translations.Translate("RPR_OPT_RTD"), 150f); resetButton.eventClicked += ResetDefaults; // Revert button. UIButton revertToSaveButton = UIControls.AddButton(panel, (Margin * 2) + 150f, yPos, Translations.Translate("RPR_OPT_RTS"), 150f); revertToSaveButton.eventClicked += ResetSaved; }
/// <summary> /// Adds editing options tab to tabstrip. /// </summary> /// <param name="tabStrip">Tab strip to add to</param> /// <param name="tabIndex">Index number of tab</param> internal FloorPanel(UITabstrip tabStrip, int tabIndex) : base(tabStrip, tabIndex) { // Add title. float currentY = PanelUtils.TitleLabel(panel, TabTooltipKey); // Initialise arrays floorHeightField = new UITextField(); firstMinField = new UITextField(); firstExtraField = new UITextField(); firstEmptyCheck = new UICheckBox(); // Pack selection dropdown. packDropDown = UIControls.AddPlainDropDown(panel, Translations.Translate("RPR_OPT_CPK"), new string[0], -1); packDropDown.parent.relativePosition = new Vector3(20f, currentY); packDropDown.eventSelectedIndexChanged += PackChanged; // Headings. currentY += 140f; PanelUtils.ColumnLabel(panel, FloorHeightX, currentY, ColumnWidth, Translations.Translate("RPR_CAL_VOL_FLH"), Translations.Translate("RPR_CAL_VOL_FLH_TIP"), 1.0f); PanelUtils.ColumnLabel(panel, FirstMinX, currentY, ColumnWidth, Translations.Translate("RPR_CAL_VOL_FMN"), Translations.Translate("RPR_CAL_VOL_FMN_TIP"), 1.0f); PanelUtils.ColumnLabel(panel, FirstMaxX, currentY, ColumnWidth, Translations.Translate("RPR_CAL_VOL_FMX"), Translations.Translate("RPR_CAL_VOL_FMX_TIP"), 1.0f); PanelUtils.ColumnLabel(panel, FirstEmptyX, currentY, ColumnWidth, Translations.Translate("RPR_CAL_VOL_IGF"), Translations.Translate("RPR_CAL_VOL_IGF_TIP"), 1.0f); // Add level textfields. currentY += RowHeight; floorHeightField = UIControls.AddTextField(panel, FloorHeightX + Margin, currentY, width: TextFieldWidth, tooltip: Translations.Translate("RPR_CAL_VOL_FLH_TIP")); floorHeightField.eventTextChanged += (control, value) => PanelUtils.FloatTextFilter((UITextField)control, value); floorHeightField.tooltipBox = TooltipUtils.TooltipBox; firstMinField = UIControls.AddTextField(panel, FirstMinX + Margin, currentY, width: TextFieldWidth, tooltip: Translations.Translate("RPR_CAL_VOL_FMN_TIP")); firstMinField.eventTextChanged += (control, value) => PanelUtils.FloatTextFilter((UITextField)control, value); firstMinField.tooltipBox = TooltipUtils.TooltipBox; firstExtraField = UIControls.AddTextField(panel, FirstMaxX + Margin, currentY, width: TextFieldWidth, tooltip: Translations.Translate("RPR_CAL_VOL_FMX_TIP")); firstExtraField.eventTextChanged += (control, value) => PanelUtils.FloatTextFilter((UITextField)control, value); firstExtraField.tooltipBox = TooltipUtils.TooltipBox; firstEmptyCheck = UIControls.AddCheckBox(panel, FirstEmptyX + (ColumnWidth / 2), currentY, tooltip: Translations.Translate("RPR_CAL_VOL_IGF_TIP")); firstEmptyCheck.tooltipBox = TooltipUtils.TooltipBox; // Move to next row. currentY += RowHeight; // Add footer controls. PanelFooter(currentY); // Populate pack menu and set onitial pack selection. packDropDown.items = PackList(); packDropDown.selectedIndex = 0; }
/// <summary> /// Adds an input text field at the specified coordinates. /// </summary> /// <param name="textField">Textfield object</param> /// <param name="panel">panel to add to</param> /// <param name="posX">Relative X postion</param> /// <param name="posY">Relative Y position</param> /// <param name="tooltip">Tooltip, if any</param> protected UITextField AddTextField(UIPanel panel, float width, float posX, float posY, string tooltip = null) { UITextField textField = UIControls.SmallTextField(panel, posX, posY, width); textField.eventTextChanged += (control, value) => PanelUtils.IntTextFilter((UITextField)control, value); // Add tooltip. if (tooltip != null) { textField.tooltip = tooltip; } return(textField); }
/// <summary> /// Adds header controls to the panel. /// </summary> /// <param name="yPos">Relative Y position for buttons</param> /// <returns>Relative Y coordinate below the finished setup</returns> protected override float PanelHeader(float yPos) { // Y position reference. float currentY = yPos + Margin; // Add 'Use legacy by default' header. // Label. UILabel legacyLabel = UIControls.AddLabel(panel, Margin, currentY, Translations.Translate(LegacyCheckLabel), panel.width - Margin, textScale: 0.9f); currentY += legacyLabel.height + 5f; // Use legacy by default for this save check. UICheckBox legacyThisSaveCheck = UIControls.LabelledCheckBox(panel, Margin * 2, currentY, Translations.Translate("RPR_DEF_LTS")); legacyThisSaveCheck.label.wordWrap = true; legacyThisSaveCheck.label.autoSize = false; legacyThisSaveCheck.label.width = 710f; legacyThisSaveCheck.label.autoHeight = true; legacyThisSaveCheck.isChecked = ThisLegacyCategory; legacyThisSaveCheck.eventCheckChanged += (control, isChecked) => { ThisLegacyCategory = isChecked; UpdateControls(); SettingsUtils.SaveSettings(); }; // Use legacy by default for new saves check. currentY += 20f; UICheckBox legacyNewSaveCheck = UIControls.LabelledCheckBox(panel, Margin * 2, currentY, Translations.Translate("RPR_DEF_LAS")); legacyNewSaveCheck.label.wordWrap = true; legacyNewSaveCheck.label.autoSize = false; legacyNewSaveCheck.label.width = 710f; legacyNewSaveCheck.label.autoHeight = true; legacyNewSaveCheck.isChecked = NewLegacyCategory; legacyNewSaveCheck.eventCheckChanged += (control, isChecked) => { NewLegacyCategory = isChecked; UpdateControls(); SettingsUtils.SaveSettings(); }; // Spacer bar. currentY += 25f; UIControls.OptionsSpacer(panel, Margin, currentY, panel.width - (Margin * 2f)); return(currentY + 10f); }
/// <summary> /// Adds a title label across the top of the specified UIComponent. /// </summary> /// <param name="parent">Parent component</param> /// <param name="titleKey">Title translation key</param> /// <returns>Y position below title</returns> internal static float TitleLabel(UIComponent parent, string titleKey) { // Margin. const float Margin = 5f; // Add title. UILabel titleLabel = UIControls.AddLabel(parent, 0f, Margin, Translations.Translate(titleKey), parent.width, 1.5f); titleLabel.textAlignment = UIHorizontalAlignment.Center; titleLabel.font = Resources.FindObjectsOfTypeAll <UIFont>().FirstOrDefault((UIFont f) => f.name == "OpenSans-Semibold"); UIControls.OptionsSpacer(parent, Margin, titleLabel.height + (Margin * 2f), parent.width - (Margin * 2f)); return(Margin + titleLabel.height + Margin + 5f + Margin); }
/// <summary> /// Adds control buttons to the bottom of the panel. /// </summary> /// <param name="panel">UI panel instance</param> protected void AddButtons(UIPanel panel) { // Add extra space. currentY += Margin; // Reset button. UIButton resetButton = UIControls.AddButton(panel, Margin, currentY, Translations.Translate("RPR_OPT_RTD"), 150f); resetButton.eventClicked += (component, clickEvent) => ResetToDefaults(); UIButton revertToSaveButton = UIControls.AddButton(panel, (Margin * 2) + 150f, currentY, Translations.Translate("RPR_OPT_RTS"), 150f); revertToSaveButton.eventClicked += (component, clickEvent) => { XMLUtilsWG.ReadFromXML(); PopulateFields(); }; UIButton saveButton = UIControls.AddButton(panel, (Margin * 3) + 300f, currentY, Translations.Translate("RPR_OPT_SAA"), 150f); saveButton.eventClicked += (component, clickEvent) => ApplyFields(); }
/// <summary> /// Adds a textfield with a label to the left. /// </summary> /// <param name="yPos">Relative y-position of textfield</param> /// <param name="key">Translation key for label</param> /// <returns></returns> private UILabelledTextfield AddLabelledTextfield(float yPos, string key) { // Create textfield. UILabelledTextfield newField = new UILabelledTextfield { textField = UIControls.AddTextField(this, MarginPadding + LabelWidth + MarginPadding, yPos, width: this.width - (MarginPadding * 3) - LabelWidth) }; newField.textField.clipChildren = false; // Label. newField.label = newField.textField.AddUIComponent <UILabel>(); newField.label.anchor = UIAnchorStyle.Right | UIAnchorStyle.CenterVertical; newField.label.relativePosition = new Vector2(-MarginPadding * 2f, newField.textField.height / 2); newField.label.textAlignment = UIHorizontalAlignment.Right; newField.label.textScale = 0.7f; newField.label.text = Translations.Translate(key); return(newField); }
/// <summary> /// Adds mod options tab to tabstrip. /// </summary> /// <param name="tabStrip">Tab strip to add to</param> /// <param name="tabIndex">Index number of tab</param> internal ModOptionsPanel(UITabstrip tabStrip, int tabIndex) { // Add tab and helper. UIPanel panel = PanelUtils.AddTextTab(tabStrip, Translations.Translate("RPR_OPT_MOD"), tabIndex, out UIButton _); UIHelper helper = new UIHelper(panel); panel.autoLayout = true; // Language dropdown. UIDropDown languageDrop = UIControls.AddPlainDropDown(panel, Translations.Translate("TRN_CHOICE"), Translations.LanguageList, Translations.Index); languageDrop.eventSelectedIndexChanged += (control, index) => { Translations.Index = index; SettingsUtils.SaveSettings(); }; // Hotkey control. panel.gameObject.AddComponent <OptionsKeymapping>(); }
/// <summary> /// Sets up the defaults dropdown menus. /// </summary> /// <param name="yPos">Relative Y position for buttons</param> /// <returns>Relative Y coordinate below the finished setup</returns> private float SetUpMenus(float yPos) { // Layout constants. const float LeftColumn = 200f; const float MenuWidth = 300f; // Starting y position. float currentY = yPos + Margin; for (int i = 0; i < SubServiceNames.Length; ++i) { // Row icon and label. PanelUtils.RowHeaderIcon(panel, ref currentY, SubServiceNames[i], IconNames[i], AtlasNames[i]); // Pop pack dropdown. PopMenus[i] = UIControls.AddLabelledDropDown(panel, LeftColumn, currentY, Translations.Translate("RPR_CAL_DEN"), MenuWidth, height: 20f, itemVertPadding: 6, accomodateLabel: false); // Save current index in object user data. PopMenus[i].objectUserData = i; // Event handler. PopMenus[i].eventSelectedIndexChanged += PopMenuChanged; // Floor pack on next row. currentY += RowHeight; // Floor pack dropdown. FloorMenus[i] = UIControls.AddLabelledDropDown(panel, LeftColumn, currentY, Translations.Translate("RPR_CAL_BFL"), MenuWidth, height: 20f, itemVertPadding: 6, accomodateLabel: false); // Add any additional controls. currentY = RowAdditions(currentY, i); // Next row. currentY += RowHeight + Margin; } // Return finishing Y position. return(currentY); }
/// <summary> /// Adds school options tab to tabstrip. /// </summary> /// <param name="tabStrip">Tab strip to add to</param> /// <param name="tabIndex">Index number of tab</param> internal EducationPanel(UITabstrip tabStrip, int tabIndex) { // Add tab and helper. UIPanel panel = PanelUtils.AddTextTab(tabStrip, Translations.Translate("RPR_OPT_SCH"), tabIndex, out UIButton _); UIHelper helper = new UIHelper(panel); panel.autoLayout = true; // Enable realistic schools checkbox. UICheckBox schoolCapacityCheck = UIControls.AddPlainCheckBox(panel, Translations.Translate("RPR_OPT_SEN")); schoolCapacityCheck.isChecked = ModSettings.enableSchoolPop; schoolCapacityCheck.eventCheckChanged += (control, isChecked) => ModSettings.enableSchoolPop = isChecked; // Enable realistic schools checkbox. UICheckBox schoolPropertyCheck = UIControls.AddPlainCheckBox(panel, Translations.Translate("RPR_OPT_SEJ")); schoolPropertyCheck.isChecked = ModSettings.enableSchoolProperties; schoolPropertyCheck.eventCheckChanged += (control, isChecked) => ModSettings.enableSchoolProperties = isChecked; // School default multiplier. Simple integer. UISlider schoolMult = UIControls.AddSliderWithValue(panel, Translations.Translate("RPR_OPT_SDM"), 1f, 5f, 0.5f, ModSettings.DefaultSchoolMult, (value) => { ModSettings.DefaultSchoolMult = value; }); }
/// <summary> /// Adds a slider with a multiplier label below. /// </summary> /// <param name="parent">Panel to add the control to</param> /// <param name="text">Descriptive label text</param> /// <param name="min">Slider minimum value</param> /// <param name="max">Slider maximum value</param> /// <param name="step">Slider minimum step</param> /// <param name="defaultValue">Slider initial value</param> /// <param name="eventCallback">Slider event handler</param> /// <param name="width">Slider width (excluding value label to right) (default 600)</param> /// <returns>New UI slider with attached labels</returns> private UISlider AddSliderWithMultipler(UIComponent parent, string text, float min, float max, float step, float defaultValue, OnValueChanged eventCallback, float width = 600f) { // Add slider component. UISlider newSlider = UIControls.AddSlider(parent, text, min, max, step, defaultValue, width); UIPanel sliderPanel = (UIPanel)newSlider.parent; // Value label. UILabel valueLabel = sliderPanel.AddUIComponent <UILabel>(); valueLabel.name = "ValueLabel"; valueLabel.relativePosition = UIControls.PositionUnder(newSlider, 2, 0f); valueLabel.text = "x" + newSlider.value.ToString(); // Event handler to update value label. newSlider.eventValueChanged += (component, value) => { valueLabel.text = "x" + value.ToString(); // Execute provided callback. eventCallback(value); }; return(newSlider); }
/// <summary> /// Create the panel; we no longer use Start() as that's not sufficiently reliable (race conditions), and is no longer needed, with the new create/destroy process. /// </summary> public void Setup() { // Generic setup. isVisible = true; canFocus = true; isInteractive = true; backgroundSprite = "UnlockingPanel"; autoLayout = false; autoLayoutDirection = LayoutDirection.Vertical; autoLayoutPadding.top = 5; autoLayoutPadding.right = 5; builtinKeyNavigation = true; clipChildren = true; // Panel title. UILabel title = this.AddUIComponent <UILabel>(); title.relativePosition = new Vector3(0, TitleY); title.textAlignment = UIHorizontalAlignment.Center; title.text = Translations.Translate("RPR_CUS_TITLE"); title.textScale = 1.2f; title.autoSize = false; title.width = this.width; title.height = 30; // Checkboxes. popCheck = UIControls.LabelledCheckBox(this, 20f, PopCheckY, Translations.Translate("RPR_EDT_POP"), textScale: 1.0f); floorCheck = UIControls.LabelledCheckBox(this, 20f, FloorCheckY, Translations.Translate("RPR_EDT_FLR"), textScale: 1.0f); // Text fields. homeJobsCount = AddLabelledTextfield(HomeJobY, "RPR_LBL_HOM"); firstFloorField = AddLabelledTextfield(FirstFloorY, "RPR_LBL_OFF"); floorHeightField = AddLabelledTextfield(FloorHeightY, "RPR_LBL_OFH"); homeJobLabel = homeJobsCount.label; // Save button. saveButton = UIControls.AddButton(this, MarginPadding, SaveY, Translations.Translate("RPR_CUS_ADD")); saveButton.tooltip = Translations.Translate("RPR_CUS_ADD_TIP"); saveButton.Disable(); // Delete button. deleteButton = UIControls.AddButton(this, MarginPadding, DeleteY, Translations.Translate("RPR_CUS_DEL")); deleteButton.tooltip = Translations.Translate("RPR_CUS_DEL_TIP"); deleteButton.Disable(); // Message label (initially hidden). messageLabel = this.AddUIComponent <UILabel>(); messageLabel.relativePosition = new Vector3(MarginPadding, MessageY); messageLabel.textAlignment = UIHorizontalAlignment.Left; messageLabel.autoSize = false; messageLabel.autoHeight = true; messageLabel.wordWrap = true; messageLabel.width = this.width - (MarginPadding * 2); messageLabel.isVisible = false; messageLabel.text = "No message to display"; // Checkbox event handlers. popCheck.eventCheckChanged += (component, isChecked) => { // If this is now selected and floorCheck is also selected, deselect floorCheck. if (isChecked && floorCheck.isChecked) { floorCheck.isChecked = false; } }; floorCheck.eventCheckChanged += (component, isChecked) => { // If this is now selected and popCheck is also selected, deselect popCheck. if (isChecked && popCheck.isChecked) { popCheck.isChecked = false; } }; // Save button event handler. saveButton.eventClick += (component, clickEvent) => SaveAndApply(); // Delete button event handler. deleteButton.eventClick += (component, clickEvent) => DeleteOverride(); }
/// <summary> /// Create the panel; we no longer use Start() as that's not sufficiently reliable (race conditions), and is no longer needed, with the new create/destroy process. /// </summary> internal void Setup() { // Generic setup. isVisible = true; canFocus = true; isInteractive = true; backgroundSprite = "UnlockingPanel"; autoLayout = false; autoSize = false; width = parent.width; height = 395f; builtinKeyNavigation = true; clipChildren = true; // Labels. floorHeightLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_FLH", RightColumn, Row1, "RPR_CAL_VOL_FLH_TIP"); firstMinLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_FMN", RightColumn, Row2, "RPR_CAL_VOL_FMN_TIP"); firstExtraLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_FMX", RightColumn, Row3, "RPR_CAL_VOL_FMX_TIP"); numFloorsLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_FLR", RightColumn, Row5, "RPR_CAL_VOL_FLR_TIP"); floorAreaLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_TFA", RightColumn, Row6, "RPR_CAL_VOL_TFA_TIP"); totalHomesLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_HOU", RightColumn, Row7, "RPR_CAL_VOL_UTS_TIP"); totalJobsLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_WOR", RightColumn, Row7, "RPR_CAL_VOL_UTS_TIP"); totalStudentsLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_STU", RightColumn, Row7, "RPR_CAL_VOL_UTS_TIP"); visitCountLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_VIS", RightColumn, Row8, "RPR_CAL_VOL_VIS_TIP"); productionLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_PRD", RightColumn, Row8, "RPR_CAL_VOL_PRD_TIP"); unitsLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_UNI", LeftColumn, Row2, "RPR_CAL_VOL_UNI_TIP"); emptyPercentLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_EPC", LeftColumn, Row2, "RPR_CAL_VOL_EPC_TIP"); emptyAreaLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_EMP", LeftColumn, Row3, "RPR_CAL_VOL_EMP_TIP"); perLabel = AddVolumetricLabel(this, "RPR_CAL_VOL_APU", LeftColumn, Row4, "RPR_CAL_VOL_APU_TIP"); schoolWorkerLabel = AddVolumetricLabel(this, "RPR_CAL_SCH_WKR", LeftColumn, Row7, "RPR_CAL_SCH_WKR_TIP"); costLabel = AddVolumetricLabel(this, "RPR_CAL_SCH_CST", LeftColumn, Row8, "RPR_CAL_SCH_CST_TIP"); // Intially hidden (just to avoid ugliness if no building is selected). totalHomesLabel.Hide(); totalStudentsLabel.Hide(); // Fixed population checkbox. fixedPopCheckBox = CalcCheckBox(this, "RPR_CAL_VOL_FXP", LeftColumn, Row1, "RPR_CAL_VOL_FXP_TIP"); fixedPopCheckBox.isInteractive = false; fixedPopCheckBox.Disable(); // Multi-floor units checkbox. multiFloorCheckBox = CalcCheckBox(this, "RPR_CAL_VOL_MFU", LeftColumn, Row5, "RPR_CAL_VOL_MFU_TIP"); multiFloorCheckBox.isInteractive = false; multiFloorCheckBox.Disable(); // Ignore first floor checkbox. ignoreFirstCheckBox = CalcCheckBox(this, "RPR_CAL_VOL_IGF", RightColumn, Row4, "RPR_CAL_VOL_IGF_TIP"); ignoreFirstCheckBox.isInteractive = false; ignoreFirstCheckBox.Disable(); // Message label. messageLabel = UIControls.AddLabel(this, Margin, MessageY, string.Empty); // Floor list - attached to root panel as scrolling and interactivity can be unreliable otherwise. floorsList = UIFastList.Create <UIFloorRow>(BuildingDetailsPanel.Panel); // Size, appearance and behaviour. floorsList.backgroundSprite = "UnlockingPanel"; floorsList.width = this.width; floorsList.isInteractive = true; floorsList.canSelect = false; floorsList.rowHeight = 20; floorsList.autoHideScrollbar = true;; ResetFloorListPosition(); // Data. floorsList.rowsData = new FastList <object>(); floorsList.selectedIndex = -1; // Toggle floorsList visibility on this panel's visibility change (because floorsList is attached to root panel). this.eventVisibilityChanged += (control, isVisible) => floorsList.isVisible = isVisible; }
/// <summary> /// Adds editing options tab to tabstrip. /// </summary> /// <param name="tabStrip">Tab strip to add to</param> /// <param name="tabIndex">Index number of tab</param> internal PopulationPanel(UITabstrip tabStrip, int tabIndex) : base(tabStrip, tabIndex) { // Add title. float currentY = PanelUtils.TitleLabel(panel, TabTooltipKey); // Initialise arrays emptyAreaFields = new UITextField[5]; emptyPercentFields = new UITextField[5]; fixedPopChecks = new UICheckBox[5]; fixedPopFields = new UITextField[5]; areaPerFields = new UITextField[5]; multiFloorChecks = new UICheckBox[5]; rowLabels = new UILabel[5]; // Service selection dropdown. serviceDropDown = UIControls.AddPlainDropDown(panel, Translations.Translate("RPR_OPT_SVC"), serviceNames, -1); serviceDropDown.parent.relativePosition = new Vector3(20f, currentY); serviceDropDown.eventSelectedIndexChanged += ServiceChanged; // Pack selection dropdown. packDropDown = UIControls.AddPlainDropDown(panel, Translations.Translate("RPR_OPT_CPK"), new string[0], -1); currentY += 70f; packDropDown.parent.relativePosition = new Vector3(20f, currentY); packDropDown.eventSelectedIndexChanged += PackChanged; // Label strings - cached to avoid calling Translations.Translate each time (for the tooltips, anwyay, including the others makes code more readable). string emptyArea = Translations.Translate("RPR_CAL_VOL_EMP"); string emptyAreaTip = Translations.Translate("RPR_CAL_VOL_EMP_TIP"); string emptyPercent = Translations.Translate("RPR_CAL_VOL_EPC"); string emptyPercentTip = Translations.Translate("RPR_CAL_VOL_EPC_TIP"); string useFixedPop = Translations.Translate("RPR_CAL_VOL_FXP"); string useFixedPopTip = Translations.Translate("RPR_CAL_VOL_FXP_TIP"); string fixedPop = Translations.Translate("RPR_CAL_VOL_UNI"); string fixedPopTip = Translations.Translate("RPR_CAL_VOL_UNI_TIP"); string areaPer = Translations.Translate("RPR_CAL_VOL_APU"); string areaPerTip = Translations.Translate("RPR_CAL_VOL_APU_TIP"); string multiFloor = Translations.Translate("RPR_CAL_VOL_MFU"); string multiFloorTip = Translations.Translate("RPR_CAL_VOL_MFU_TIP"); // Headings. currentY += 140f; PanelUtils.ColumnLabel(panel, EmptyAreaX, currentY, ColumnWidth, emptyArea, emptyAreaTip, 1.0f); PanelUtils.ColumnLabel(panel, EmptyPercentX, currentY, ColumnWidth, emptyPercent, emptyPercentTip, 1.0f); PanelUtils.ColumnLabel(panel, PopCheckX, currentY, ColumnWidth, useFixedPop, useFixedPopTip, 1.0f); PanelUtils.ColumnLabel(panel, FixedPopX, currentY, ColumnWidth, fixedPop, fixedPopTip, 1.0f); PanelUtils.ColumnLabel(panel, AreaPerX, currentY, ColumnWidth, areaPer, areaPerTip, 1.0f); PanelUtils.ColumnLabel(panel, MultiFloorX, currentY, ColumnWidth, multiFloor, multiFloorTip, 1.0f); // Add level textfields. for (int i = 0; i < 5; ++i) { // Row label. rowLabels[i] = RowLabel(panel, currentY, Translations.Translate("RPR_OPT_LVL") + " " + (i + 1).ToString()); emptyPercentFields[i] = UIControls.AddTextField(panel, EmptyPercentX + Margin, currentY, width: TextFieldWidth, tooltip: emptyPercentTip); emptyPercentFields[i].eventTextChanged += (control, value) => PanelUtils.IntTextFilter((UITextField)control, value); emptyPercentFields[i].tooltipBox = TooltipUtils.TooltipBox; emptyAreaFields[i] = UIControls.AddTextField(panel, EmptyAreaX + Margin, currentY, width: TextFieldWidth, tooltip: emptyAreaTip); emptyAreaFields[i].eventTextChanged += (control, value) => PanelUtils.FloatTextFilter((UITextField)control, value); emptyAreaFields[i].tooltipBox = TooltipUtils.TooltipBox; // Fixed pop checkboxes - ensure i is saved as objectUserData for use by event handler. Starts unchecked by default. fixedPopChecks[i] = UIControls.AddCheckBox(panel, PopCheckX + (ColumnWidth / 2), currentY, tooltip: useFixedPopTip); fixedPopChecks[i].objectUserData = i; fixedPopChecks[i].eventCheckChanged += FixedPopCheckChanged; fixedPopChecks[i].tooltipBox = TooltipUtils.TooltipBox; // Fixed population fields start hidden by default. fixedPopFields[i] = UIControls.AddTextField(panel, FixedPopX + Margin, currentY, width: TextFieldWidth, tooltip: fixedPopTip); fixedPopFields[i].eventTextChanged += (control, value) => PanelUtils.IntTextFilter((UITextField)control, value); fixedPopFields[i].tooltipBox = TooltipUtils.TooltipBox; fixedPopFields[i].Hide(); areaPerFields[i] = UIControls.AddTextField(panel, AreaPerX + Margin, currentY, width: TextFieldWidth, tooltip: areaPerTip); areaPerFields[i].eventTextChanged += (control, value) => PanelUtils.FloatTextFilter((UITextField)control, value); areaPerFields[i].tooltipBox = TooltipUtils.TooltipBox; multiFloorChecks[i] = UIControls.AddCheckBox(panel, MultiFloorX + (ColumnWidth / 2), currentY, tooltip: multiFloorTip); multiFloorChecks[i].tooltipBox = TooltipUtils.TooltipBox; // Move to next row. currentY += RowHeight; } // Add footer controls. PanelFooter(currentY); // Set service menu to initial state (residential), which will also update textfield visibility via event handler. serviceDropDown.selectedIndex = 0; }
/// <summary> /// Set up filter bar. /// We don't use Start() here as we need to access the category toggle states to set up the initial filtering list before Start() is called by UnityEngine. /// </summary> public void Setup() { // Catgegory buttons. categoryToggles = new UICheckBox[(int)BuildingCategories.NumCategories]; for (int i = 0; i < (int)BuildingCategories.NumCategories; i++) { // Basic setup. categoryToggles[i] = UIUtils.CreateIconToggle(this, CategoryIcons.atlases[i], CategoryIcons.spriteNames[i], CategoryIcons.spriteNames[i] + "Disabled"); categoryToggles[i].tooltip = Translations.Translate(CategoryIcons.tooltips[i]); categoryToggles[i].relativePosition = new Vector3(40 * i, 0); categoryToggles[i].isChecked = true; categoryToggles[i].readOnly = true; // Single click event handler - toggle state of this button. categoryToggles[i].eventClick += (c, p) => { // If either shift or control is NOT held down, deselect all other toggles. if (!(Input.GetKey(KeyCode.LeftShift) || Input.GetKey(KeyCode.RightShift) || Input.GetKey(KeyCode.LeftControl) || Input.GetKey(KeyCode.RightControl))) { for (int j = 0; j < (int)BuildingCategories.NumCategories; j++) { categoryToggles[j].isChecked = false; } } // Select this toggle. ((UICheckBox)c).isChecked = true; // Trigger an update. EventFilteringChanged(this, 0); }; } // 'All categories' button. allCategories = UIControls.AddButton(this, 445f, 5f, Translations.Translate("RPR_CAT_ALL"), 120f); // All categories event handler. allCategories.eventClick += (c, p) => { // Select all category toggles. for (int i = 0; i < (int)BuildingCategories.NumCategories; i++) { categoryToggles[i].isChecked = true; } // Trigger an update. EventFilteringChanged(this, 0); }; // Name filter. nameFilter = UIControls.BigLabelledTextField(this, width - 200f, 0, Translations.Translate("RPR_FIL_NAME")); // Name filter event handling - update on any change. nameFilter.eventTextChanged += (control, text) => EventFilteringChanged(this, 5); nameFilter.eventTextSubmitted += (control, text) => EventFilteringChanged(this, 5); // Settings filter label. UILabel filterLabel = SettingsFilterLabel(55f, Translations.Translate("RPR_FIL_SET")); // Settings filter checkboxes. settingsFilter = new UICheckBox[(int)FilterCategories.NumCategories]; for (int i = 0; i < (int)FilterCategories.NumCategories; ++i) { settingsFilter[i] = this.AddUIComponent <UICheckBox>(); settingsFilter[i].width = 20f; settingsFilter[i].height = 20f; settingsFilter[i].clipChildren = true; settingsFilter[i].relativePosition = new Vector3(AnyX + (FilterSpacing * i), 45f); // Checkbox sprites. UISprite sprite = settingsFilter[i].AddUIComponent <UISprite>(); sprite.spriteName = "ToggleBase"; sprite.size = new Vector2(20f, 20f); sprite.relativePosition = Vector3.zero; settingsFilter[i].checkedBoxObject = sprite.AddUIComponent <UISprite>(); ((UISprite)settingsFilter[i].checkedBoxObject).spriteName = "ToggleBaseFocused"; settingsFilter[i].checkedBoxObject.size = new Vector2(20f, 20f); settingsFilter[i].checkedBoxObject.relativePosition = Vector3.zero; // Tooltip. settingsFilter[i].tooltip = Translations.Translate(FilterTooltipKeys[i]); // Special event handling for 'any' checkbox. if (i == (int)FilterCategories.Any) { settingsFilter[i].eventCheckChanged += (control, isChecked) => { if (isChecked) { // Unselect all other checkboxes if 'any' is checked. settingsFilter[(int)FilterCategories.HasOverride].isChecked = false; settingsFilter[(int)FilterCategories.HasNonDefault].isChecked = false; } }; } else { // Non-'any' checkboxes. // Unselect 'any' checkbox if any other is checked. settingsFilter[i].eventCheckChanged += (control, isChecked) => { if (isChecked) { settingsFilter[0].isChecked = false; } }; } // Trigger filtering changed event if any checkbox is changed. settingsFilter[i].eventCheckChanged += (control, isChecked) => { EventFilteringChanged(this, 0); }; } }
/// <summary> /// Create the mod calcs panel; we no longer use Start() as that's not sufficiently reliable (race conditions), and is no longer needed, with the new create/destroy process. /// </summary> internal void Setup() { // Basic setup. clipChildren = true; // Title. title = this.AddUIComponent <UILabel>(); title.relativePosition = new Vector3(0, 0); title.textAlignment = UIHorizontalAlignment.Center; title.text = Translations.Translate("RPR_CAL_MOD"); title.textScale = 1.2f; title.autoSize = false; title.width = this.width; // Column titles. UILabel densityTitle = ColumnLabel(this, Translations.Translate("RPR_CAL_DEN"), Margin, ColumnLabelY); UILabel floorTitle = ColumnLabel(this, Translations.Translate("RPR_CAL_BFL"), RightColumnX, ColumnLabelY); // Volumetric calculations panel. volumetricPanel = this.AddUIComponent <UIVolumetricPanel>(); volumetricPanel.relativePosition = new Vector2(0f, BaseCalcY); volumetricPanel.height = this.height - title.height + 80f; volumetricPanel.width = this.width; volumetricPanel.Setup(); // Legacy calculations panel - copy volumetric calculations panel. legacyPanel = this.AddUIComponent <UILegacyCalcs>(); legacyPanel.relativePosition = volumetricPanel.relativePosition; legacyPanel.height = volumetricPanel.height; legacyPanel.width = volumetricPanel.width; legacyPanel.Setup(); legacyPanel.Hide(); // Floor dropdown panel - set size manually to avoid invisible overlap of calculations panel (preventing e.g. tooltips). floorPanel = this.AddUIComponent <UIPanel>(); floorPanel.relativePosition = new Vector2(RightColumnX, MenuY); floorPanel.autoSize = false; floorPanel.width = RightColumnX - this.width; floorPanel.height = BaseCalcY - MenuY; floorPanel.autoLayout = false; floorPanel.clipChildren = false; floorPanel.Show(); // Floor override label (for when floor dropdown menu is hidden). floorOverrideLabel = UIControls.AddLabel(this, RightColumnX, MenuY, Translations.Translate("RPR_CAL_FOV"), this.width - RightColumnX, 0.7f); floorOverrideLabel.Hide(); // Pack dropdowns. popMenu = UIControls.AddDropDown(this, Margin, MenuY, ComponentWidth); floorMenu = UIControls.AddDropDown(floorPanel, 0f, 0f, ComponentWidth); // School dropdown panel. schoolPanel = this.AddUIComponent <UIPanel>(); schoolPanel.relativePosition = new Vector2(Margin, Row2LabelY); schoolPanel.autoSize = false; schoolPanel.autoLayout = false; schoolPanel.clipChildren = false; schoolPanel.height = ApplyX - Row2LabelY; schoolPanel.width = this.width - (Margin * 2); // School panel title and dropdown menu. UILabel schoolTitle = ColumnLabel(schoolPanel, Translations.Translate("RPR_CAL_SCH_PRO"), 0, 0); schoolMenu = UIControls.AddDropDown(schoolPanel, 0f, LabelHeight, ComponentWidth); schoolPanel.Hide(); // Pack descriptions. popDescription = Description(this, Margin, DescriptionY); floorDescription = Description(floorPanel, 0f, DescriptionY - MenuY); schoolDescription = Description(schoolPanel, 0f, LabelHeight + DescriptionY - MenuY); // Apply button. applyButton = UIControls.AddButton(this, ApplyX, BaseSaveY, Translations.Translate("RPR_OPT_SAA"), ButtonWidth); applyButton.eventClicked += (control, clickEvent) => ApplySettings(); // Dropdown event handlers. popMenu.eventSelectedIndexChanged += (component, index) => UpdatePopSelection(index); floorMenu.eventSelectedIndexChanged += (component, index) => UpdateFloorSelection(index); schoolMenu.eventSelectedIndexChanged += (component, index) => UpdateSchoolSelection(index); // Add school multiplier slider (starts hidden). multSlider = AddSliderWithMultipler(schoolPanel, string.Empty, 1f, 5f, 0.5f, ModSettings.DefaultSchoolMult, (value) => UpdateMultiplier(value), ComponentWidth); multSlider.parent.relativePosition = new Vector2(RightColumnX, 10f); multSlider.parent.Hide(); // Muliplier checkbox. multCheck = UIControls.LabelledCheckBox(schoolPanel, RightColumnX, 18f, Translations.Translate("RPR_CAL_CAP_OVR")); // Multiplier default label. multDefaultLabel = UIControls.AddLabel(schoolPanel, RightColumnX + 21f, 40f, Translations.Translate("RPR_CAL_CAP_DEF") + " x" + ModSettings.DefaultSchoolMult, textScale: 0.8f); // Multplier checkbox event handler. multCheck.eventCheckChanged += (control, isChecked) => MultiplierCheckChanged(isChecked); }