/// <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;
        }
Пример #4
0
        /// <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;
        }
Пример #5
0
        /// <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");
            }
        }
Пример #6
0
        /// <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);
        }
Пример #11
0
        /// <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();
        }
Пример #12
0
        /// <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>();
        }
Пример #14
0
        /// <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);
        }
Пример #15
0
        /// <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);
        }
Пример #17
0
        /// <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;
        }
Пример #20
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);
        }