using System.Collections.Generic; using System.Linq; using TMPro; using UnityEngine; using UnityEngine.EventSystems; public class TargetLevelProbabilityPanel : MonoBehaviour { public GameObject singleLevelProbabilityPanel; public GameObject targetTitleText; private GameObject titleText; private List singleLevelPanelsObjs = new List(); private List singleLevelPanels = new List(); private int panelNum = 0; public void IntializePanels(int levelNum, string titleName) { // initialize target level probability panel size float defaultWidth = singleLevelProbabilityPanel.GetComponent().sizeDelta.x; float defaultLevelHeight = singleLevelProbabilityPanel.GetComponent().sizeDelta.y; float titleHeight = targetTitleText.GetComponent().sizeDelta.y; float averageProbability = 1f / levelNum; float lastLevelProbability = 1f - averageProbability * (levelNum - 1); Debug.Log("averageProbability: " + averageProbability); transform.GetComponent().sizeDelta = new Vector2(defaultWidth, (defaultLevelHeight * levelNum) + titleHeight); // create title text titleText = Instantiate(targetTitleText, transform); titleText.GetComponent().text = titleName; // create and initialize single level probability panels for (int i = 0; i < levelNum; i++) { int tempIndex = i; singleLevelPanelsObjs.Add(Instantiate(singleLevelProbabilityPanel, transform)); singleLevelPanels.Add(singleLevelPanelsObjs[i].GetComponent()); singleLevelPanels[i].InitializeLevelProbabilityPanel(i, i == levelNum - 1 ? lastLevelProbability : averageProbability); //add onValueChanged event to slider and input field singleLevelPanels[i].probabilitySlider.onValueChanged.AddListener((value) => OnSliderValueChange(value, tempIndex)); } panelNum = levelNum; } /// /// Adds an event trigger entry to an event trigger. /// /// The event trigger object. /// The event trigger type. /// The event handler method to execute. private void AddEventTrigger(GameObject gameObject, EventTriggerType triggerType, System.Action action) { EventTrigger eventTrigger = gameObject.GetComponent(); if (eventTrigger == null) { eventTrigger = gameObject.AddComponent(); } EventTrigger.Entry entry = new EventTrigger.Entry(); entry.eventID = triggerType; entry.callback.AddListener(new UnityEngine.Events.UnityAction(action)); eventTrigger.triggers.Add(entry); } private void OnSliderValueChange(float value, int exceptedIndex) { float newTotalValue = 0; float averageCorrectionValue = 0; int unlockedPanelNum = 0; int remainCorrectionNum = panelNum; float extraValue = 0; float[] correctionValues = new float[panelNum]; // calculate total probability value for (int i = 0; i < panelNum; i++) { // disable slider listener singleLevelPanels[i].probabilitySlider.onValueChanged.RemoveAllListeners(); newTotalValue += (i == exceptedIndex ? value : singleLevelPanels[i].ProbabilityValue); if (singleLevelPanels[i].UnLocked) { unlockedPanelNum++; } } // only have one panel if (panelNum == 1) { singleLevelPanels[exceptedIndex].SetProbability(1); enableSliderListener(); return; } //only one panel is unlocked if (unlockedPanelNum == 1) { // limit this panel value under 1 - (newTotalValue - value) singleLevelPanels[exceptedIndex].SetProbability(newTotalValue - 1 > 0 ? 1 - newTotalValue + value : value); enableSliderListener(); return; } // Calculate the average correction value extraValue = newTotalValue - 1; averageCorrectionValue = extraValue / (unlockedPanelNum - 1); // initialize correction value to each panel correctionValues = Enumerable.Repeat(averageCorrectionValue, panelNum).ToArray(); // make sure all probability value is not less than 0 and equal to 1 int iterationCount = 0; while (remainCorrectionNum > 0) { iterationCount++; Debug.Log(remainCorrectionNum); remainCorrectionNum = 0; List reCorrectionIndex = new List(); int lastReCorrectionIndex = 0; float underZeroExtraValueAfterCorrected = 0; for (int i = 0; i < panelNum; ++i) { // if the panel is the changed one if (i == exceptedIndex) { correctionValues[i] = 0; continue; } // if the panel is locked or the probability value is 0 or the probability value is equal to the correction value if (singleLevelPanels[i].IsLocked || singleLevelPanels[i].ProbabilityValue <= 0) { correctionValues[i] = 0; } else if (singleLevelPanels[i].ProbabilityValue == correctionValues[i]) { underZeroExtraValueAfterCorrected += correctionValues[i]; } else if (singleLevelPanels[i].ProbabilityValue - correctionValues[i] < 0) { underZeroExtraValueAfterCorrected += correctionValues[i]; correctionValues[i] = singleLevelPanels[i].ProbabilityValue; remainCorrectionNum++; } else { lastReCorrectionIndex = i; reCorrectionIndex.Add(i); } } foreach (int index in reCorrectionIndex) { float newAverageCorrectionValue = (extraValue - underZeroExtraValueAfterCorrected) / reCorrectionIndex.Count; // if (index == lastReCorrectionIndex) { correctionValues[index] = extraValue - (newAverageCorrectionValue * (reCorrectionIndex.Count - 1)); } else { correctionValues[index] = newAverageCorrectionValue; } } if (iterationCount >= 100) { break; } } // applicate the value to all unlocked panels excepted the changed one for (int i = 0; i < panelNum; i++) { singleLevelPanels[i].SetProbability(i == exceptedIndex ? value : singleLevelPanels[i].ProbabilityValue - correctionValues[i]); } enableSliderListener(); } private void enableSliderListener() { for (int i = 0; i < panelNum; i++) { int tempIndex = i; singleLevelPanels[i].probabilitySlider.onValueChanged.AddListener((value) => OnSliderValueChange(value, tempIndex)); } } }