V3.4.1 整理script位置
This commit is contained in:
@@ -0,0 +1,163 @@
|
||||
using DG.Tweening;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class ButtonActivateColorChanger : MonoBehaviour
|
||||
{
|
||||
public List<Button> clickableButton = new List<Button>();
|
||||
public List<Button> unclickableButton = new List<Button>();
|
||||
|
||||
public Color32 normalTextColor = new Color32(236, 236, 236, 255);
|
||||
public Color32 normalBGColor = new Color32(255, 255, 255, 0);
|
||||
public Color32 highLightTextColor = new Color32(41, 41, 41, 230);
|
||||
public Color32 highLightBGColor = new Color32(255, 255, 255, 103);
|
||||
public Color32 pressedTextColor = new Color32(0, 0, 0, 240);
|
||||
public Color32 pressedBGColor = new Color32(255, 255, 255, 160);
|
||||
public Color32 disableTextColor = new Color32(180, 180, b: 180, 80);
|
||||
public Color32 disableBGColor = new Color32(255, 255, b: 255, 0);
|
||||
public float colorChangeSpeed = 0.1f;
|
||||
|
||||
public bool clickable = true;
|
||||
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
foreach (Button btn in clickableButton)
|
||||
{
|
||||
InitializeEventTriggers(btn, true);
|
||||
}
|
||||
|
||||
foreach (Button btn in unclickableButton)
|
||||
{
|
||||
InitializeEventTriggers(btn, false);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the event triggers for a button to handle its interactive behavior.
|
||||
/// </summary>
|
||||
/// <param name="btn">The button object to initialize.</param>
|
||||
/// <param name="isClickable">Indicates whether the button is clickable.</param>
|
||||
private void InitializeEventTriggers(Button btn, bool isClickable)
|
||||
{
|
||||
EventTrigger eventTrigger = btn.GetComponent<EventTrigger>();
|
||||
if (eventTrigger == null)
|
||||
{
|
||||
eventTrigger = btn.gameObject.AddComponent<EventTrigger>();
|
||||
}
|
||||
|
||||
AddEventTrigger(eventTrigger, EventTriggerType.PointerEnter, (eventData) => OnPointerEnter(btn));
|
||||
AddEventTrigger(eventTrigger, EventTriggerType.PointerExit, (eventData) => OnPointerExit(btn));
|
||||
if (isClickable)
|
||||
{
|
||||
AddEventTrigger(eventTrigger, EventTriggerType.PointerDown, (eventData) => OnPointerDown(btn));
|
||||
AddEventTrigger(eventTrigger, EventTriggerType.PointerUp, (eventData) => OnPointerUp(btn));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an event trigger entry to an event trigger.
|
||||
/// </summary>
|
||||
/// <param name="trigger">The event trigger object.</param>
|
||||
/// <param name="type">The event trigger type.</param>
|
||||
/// <param name="action">The event handler method to execute.</param>
|
||||
private void AddEventTrigger(EventTrigger trigger, EventTriggerType type, UnityEngine.Events.UnityAction<BaseEventData> action)
|
||||
{
|
||||
EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
entry.eventID = type;
|
||||
entry.callback.AddListener(action);
|
||||
trigger.triggers.Add(entry);
|
||||
}
|
||||
|
||||
private void OnPointerEnter(Button btn)
|
||||
{
|
||||
if (btn.interactable)
|
||||
{
|
||||
btn.image.DOColor(highLightBGColor, colorChangeSpeed);
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().DOColor(highLightTextColor, colorChangeSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerExit(Button btn)
|
||||
{
|
||||
if (btn.interactable)
|
||||
{
|
||||
btn.image.DOColor(normalBGColor, colorChangeSpeed);
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().DOColor(normalTextColor, colorChangeSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerDown(Button btn)
|
||||
{
|
||||
if (btn.interactable)
|
||||
{
|
||||
btn.image.DOColor(pressedBGColor, colorChangeSpeed);
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().DOColor(pressedTextColor, colorChangeSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPointerUp(Button btn)
|
||||
{
|
||||
if (btn.interactable)
|
||||
{
|
||||
btn.image.DOColor(highLightBGColor, colorChangeSpeed);
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().DOColor(normalTextColor, colorChangeSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the interactable state of a button and modifies its color based on the state.
|
||||
/// </summary>
|
||||
/// <param name="btn">The button object to change the state and color of.</param>
|
||||
/// <param name="changeTo">Indicates the interactable state to change to.</param>
|
||||
public void ChangeInteractableColor(Button btn, bool changeTo)
|
||||
{
|
||||
btn.interactable = changeTo;
|
||||
if (changeTo)
|
||||
{
|
||||
btn.image.DOColor(normalBGColor, colorChangeSpeed);
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().DOColor(normalTextColor, colorChangeSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
btn.image.DOColor(disableBGColor, colorChangeSpeed);
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().DOColor(disableTextColor, colorChangeSpeed);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a button to the button list and initializes the button's event triggers based on its clickability.
|
||||
/// </summary>
|
||||
/// <param name="btn">The button object to add to the button list.</param>
|
||||
/// <param name="clickable">Indicates whether the button is clickable.</param>
|
||||
public void AddButtonToColorChangerButtonList(Button btn, bool clickable)
|
||||
{
|
||||
if (clickable)
|
||||
{
|
||||
clickableButton.Add(btn);
|
||||
InitializeEventTriggers(btn, clickable);
|
||||
}
|
||||
else
|
||||
{
|
||||
unclickableButton.Add(btn);
|
||||
InitializeEventTriggers(btn, clickable);
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeAllButtonColor()
|
||||
{
|
||||
foreach (Button btn in clickableButton)
|
||||
{
|
||||
btn.image.color = normalBGColor;
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().color = normalTextColor;
|
||||
}
|
||||
foreach (Button btn in unclickableButton)
|
||||
{
|
||||
btn.image.color = disableBGColor;
|
||||
btn.GetComponentInChildren<TextMeshProUGUI>().color = disableTextColor;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3ca7ca2329898e343bafa8ba9db0cbb0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,208 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using XCharts.Runtime;
|
||||
|
||||
public class EnvironmentUIControl : MonoBehaviour
|
||||
{
|
||||
public GameObject targetControllerObj;
|
||||
public GameObject parameterContainerObj;
|
||||
public GameObject groundCanvasObj;
|
||||
public GameObject chartObj;
|
||||
public GameObject HUDObj;
|
||||
public TextMeshProUGUI remainTimeText;
|
||||
public TextMeshProUGUI targetTypeText;
|
||||
public TextMeshProUGUI winLoseText;
|
||||
public TextMeshProUGUI stateText;
|
||||
public float resultTimeout = 1f;
|
||||
public GameObject gaugeImgObj;
|
||||
|
||||
private StringBuilder stateBuilder = new StringBuilder();
|
||||
private LineChart realTimeRewardChart = null;
|
||||
private TargetController targetController;
|
||||
private ParameterContainer paramContainer;
|
||||
private HUDController hudController;
|
||||
private Image gaugeImg;
|
||||
private float overTime = 0f;
|
||||
private int step = 0;
|
||||
private bool resultActive = false;
|
||||
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
targetController = targetControllerObj.GetComponent<TargetController>();
|
||||
paramContainer = parameterContainerObj.GetComponent<ParameterContainer>();
|
||||
gaugeImg = gaugeImgObj.GetComponent<Image>();
|
||||
hudController = HUDObj.GetComponent<HUDController>();
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
private void Update()
|
||||
{
|
||||
// int remainTime = Convert.ToInt32(targetController.startTime + paramContainer.timeLimit - Time.time);
|
||||
remainTimeText.text = "RemainTime:" + Convert.ToInt32(targetController.leftTime).ToString();
|
||||
if (resultActive && Time.time - overTime >= resultTimeout)
|
||||
{
|
||||
// while result is active and show time over timeOut
|
||||
// clear the result
|
||||
Debug.Log("EnvironmentUIControl: clear result");
|
||||
winLoseText.text = "";
|
||||
winLoseText.color = Color.white;
|
||||
resultActive = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateChart(float reward)
|
||||
{
|
||||
if (hudController.chartOn && realTimeRewardChart == null)
|
||||
{
|
||||
InitChart();
|
||||
}
|
||||
step += 1;
|
||||
realTimeRewardChart.AddXAxisData(Convert.ToString(step));
|
||||
realTimeRewardChart.AddData(0, reward);
|
||||
}
|
||||
|
||||
public void InitChart()
|
||||
{
|
||||
if (hudController.chartOn && realTimeRewardChart == null)
|
||||
{
|
||||
Vector3 chartPos = new Vector3(-210f, 90f, 0f) * groundCanvasObj.transform.localScale.x;
|
||||
realTimeRewardChart = chartObj.AddComponent<LineChart>();
|
||||
realTimeRewardChart.Init();
|
||||
}
|
||||
realTimeRewardChart.RemoveData();
|
||||
realTimeRewardChart.AddSerie<Line>("Rewards");
|
||||
}
|
||||
|
||||
public void RemoveChart()
|
||||
{
|
||||
GameObject.Destroy(realTimeRewardChart);
|
||||
realTimeRewardChart = null;
|
||||
}
|
||||
|
||||
// show result in UI
|
||||
public void ShowResult(int resultState)
|
||||
{
|
||||
switch (resultState)
|
||||
{
|
||||
case (int)TargetController.EndType.Win:
|
||||
//Win
|
||||
Debug.Log("win");
|
||||
winLoseText.text = "Win";
|
||||
winLoseText.color = Color.green;
|
||||
overTime = Time.time;
|
||||
resultActive = true;
|
||||
break;
|
||||
|
||||
case (int)TargetController.EndType.Lose:
|
||||
//lose
|
||||
Debug.Log("lose");
|
||||
winLoseText.text = "Lose";
|
||||
winLoseText.color = Color.red;
|
||||
overTime = Time.time;
|
||||
resultActive = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// update firebases target state gauge
|
||||
public void UpdateTargetGauge(float firebasesBelong, float belongMaxPoint)
|
||||
{
|
||||
if (firebasesBelong >= 0)
|
||||
{
|
||||
gaugeImgObj.transform.localPosition = new Vector3(25f, 0, 0);
|
||||
gaugeImg.color = Color.blue;
|
||||
gaugeImg.fillOrigin = 0;
|
||||
gaugeImg.fillAmount = firebasesBelong / belongMaxPoint;
|
||||
}
|
||||
else
|
||||
{
|
||||
gaugeImgObj.transform.localPosition = new Vector3(-25f, 0, 0);
|
||||
gaugeImg.color = Color.red;
|
||||
gaugeImg.fillOrigin = 1;
|
||||
gaugeImg.fillAmount = -firebasesBelong / belongMaxPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// update targetType text
|
||||
public void UpdateTargetType(int targetInt)
|
||||
{
|
||||
switch (targetInt)
|
||||
{
|
||||
case (int)Targets.Go:
|
||||
targetTypeText.text = "GOTO";
|
||||
targetTypeText.color = Color.blue;
|
||||
break;
|
||||
|
||||
case (int)Targets.Attack:
|
||||
targetTypeText.text = "Attack!";
|
||||
targetTypeText.color = Color.red;
|
||||
break;
|
||||
|
||||
case (int)Targets.Defence:
|
||||
targetTypeText.text = "Defence";
|
||||
targetTypeText.color = Color.green;
|
||||
break;
|
||||
|
||||
case (int)Targets.Free:
|
||||
targetTypeText.text = "Free";
|
||||
targetTypeText.color = Color.yellow;
|
||||
break;
|
||||
|
||||
case (int)Targets.Stay:
|
||||
targetTypeText.text = "Stay";
|
||||
targetTypeText.color = Color.white;
|
||||
break;
|
||||
|
||||
default:
|
||||
targetTypeText.text = "TYPE ERROR";
|
||||
targetTypeText.color = Color.red;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// update state text
|
||||
// public TextMeshProUGUI stateText;
|
||||
// targetState[0] = targetTypeInt;
|
||||
// targetState[1] = targetPosition.x / raySensors.viewDistance; // normalization
|
||||
// targetState[2] = targetPosition.y / raySensors.viewDistance;
|
||||
// targetState[3] = targetPosition.z / raySensors.viewDistance;
|
||||
// targetState[4] = blockCont.thisBlock.firebasesAreaDiameter / raySensors.viewDistance;
|
||||
// targetState[5] = blockCont.thisBlock.belongRatio;
|
||||
// float[] myObserve = { transform.localPosition.x/raySensors.viewDistance, transform.localPosition.y / raySensors.viewDistance, transform.localPosition.z / raySensors.viewDistance, transform.eulerAngles.y/360f }
|
||||
// ??????????string??"targetType: 1.0 \r\n targetX: 2.0 \r\n"
|
||||
public void UpdateStateText(float[] targetStates, float inAreaState, float remainTime, bool gunReadyToggle, float[] myObserve, float[] rayTagResultOnehot, float[] rayDisResult)
|
||||
{
|
||||
stateBuilder.Clear();
|
||||
|
||||
stateBuilder.Append($"States:\r\nTType:{targetStates[0]}");
|
||||
stateBuilder.Append("\r\nTargetPosition:\r\nx:");
|
||||
stateBuilder.Append(targetStates[1]);
|
||||
stateBuilder.Append("\r\ny:");
|
||||
stateBuilder.Append(targetStates[2]);
|
||||
stateBuilder.Append("\r\nz:");
|
||||
stateBuilder.Append(targetStates[3]);
|
||||
stateBuilder.Append("\r\nTargetDiameter:");
|
||||
stateBuilder.Append(targetStates[4]);
|
||||
stateBuilder.Append("\r\nTargetBelongRatio:");
|
||||
stateBuilder.Append(targetStates[5]);
|
||||
stateBuilder.Append("\r\nInArea:");
|
||||
stateBuilder.Append(inAreaState);
|
||||
stateBuilder.Append("\r\nRemainTime:");
|
||||
stateBuilder.Append(remainTime);
|
||||
stateBuilder.Append("\r\nGunReady:");
|
||||
stateBuilder.Append(gunReadyToggle);
|
||||
stateBuilder.Append("\r\nMyPosition:");
|
||||
stateBuilder.Append(myObserve[0]).Append(myObserve[1]).Append(myObserve[2]);
|
||||
stateBuilder.Append("\r\nMyRotation:");
|
||||
stateBuilder.Append(myObserve[3]);
|
||||
|
||||
stateText.text = stateBuilder.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3ddb0247fbea1b4799dd33b60ab4f12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,77 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class HUDController : MonoBehaviour
|
||||
{
|
||||
public bool chartOn = false;
|
||||
public GameObject sideChannelObj;
|
||||
public Toggle chartOnToggleObj;
|
||||
public Button saveModelButton;
|
||||
public TMP_InputField chartOnTimeOutInputObj;
|
||||
public TMP_InputField enemyNumInputObj;
|
||||
public float chartOnTimeOut = 1;
|
||||
public int enemyNum = 3;
|
||||
public float chartOnTimeOutDefault = 120f;
|
||||
|
||||
private float chatOntimeStart = 0;
|
||||
private AimBotSideChannelController sideChannelController;
|
||||
private MessageBoxController messageBox;
|
||||
|
||||
private void Start()
|
||||
{
|
||||
sideChannelController = sideChannelObj.GetComponent<AimBotSideChannelController>();
|
||||
messageBox = gameObject.GetComponent<MessageBoxController>();
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (chartOn)
|
||||
{
|
||||
if (Time.time - chatOntimeStart >= chartOnTimeOut)
|
||||
{
|
||||
chartOn = false;
|
||||
chartOnToggleObj.isOn = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void OnChartOnToggleChange()
|
||||
{
|
||||
chatOntimeStart = Time.time;
|
||||
chartOn = chartOnToggleObj.isOn;
|
||||
}
|
||||
|
||||
public void OnEnemyNumTextChange()
|
||||
{
|
||||
try
|
||||
{
|
||||
enemyNum = Math.Abs(int.Parse(enemyNumInputObj.GetComponent<TMP_InputField>().text));
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
enemyNum = 3;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnChartTimeOutTextChange()
|
||||
{
|
||||
try
|
||||
{
|
||||
chartOnTimeOut = Math.Abs(int.Parse(chartOnTimeOutInputObj.GetComponent<TMP_InputField>().text));
|
||||
}
|
||||
catch (NullReferenceException)
|
||||
{
|
||||
chartOnTimeOut = chartOnTimeOutDefault;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnSaveModelButtonPressed()
|
||||
{
|
||||
// Send message to python to save model
|
||||
sideChannelController.SendSideChannelMessage("Command", "SaveModel");
|
||||
messageBox.PushMessage(new List<string> { "☑Model Will be Saved In Next Train Episode:)" }, new List<string> { messageBox.goodColor });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 10f34b6fb217eff4e9be2bfe7044f132
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,15 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class LevelButton : MonoBehaviour
|
||||
{
|
||||
public int level;
|
||||
public TextMeshProUGUI levelText;
|
||||
public void Initialization(int level)
|
||||
{
|
||||
this.level = level;
|
||||
levelText.text = "Level " + level.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6cbfa6f85d7bca847a18555e6afeba0d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,96 @@
|
||||
using DG.Tweening;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class LevelPanel : MonoBehaviour
|
||||
{
|
||||
private int levelNum = 0;
|
||||
private float buttonHeight = 30;
|
||||
public TargetUIController.PrimaryButtonType primaryButtonType;
|
||||
public GameObject levelButtonPrefab;
|
||||
public GameObject hudObj;
|
||||
private TargetUIController targetUIController;
|
||||
public Vector2 defaultPosition = Vector2.zero;
|
||||
public Vector2 targetPosition = Vector2.zero;
|
||||
public Vector2 defaultSize = Vector2.zero;
|
||||
public Vector2 targetSize = Vector2.zero;
|
||||
public bool isFolding = false;
|
||||
public bool isExpanding = false;
|
||||
|
||||
private List<Button> levelButtonList = new List<Button>();
|
||||
|
||||
public ReadOnlyCollection<Button> LevelButtonList
|
||||
{
|
||||
get { return levelButtonList.AsReadOnly(); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the level panel.
|
||||
/// Set the level number, button height, default position and target position.
|
||||
/// Create leve buttonInitialize the level buttons.
|
||||
/// </summary>
|
||||
public void InitLevelPanel(int levelNum, Button parentButton, float buttonHeight = 30)
|
||||
{
|
||||
targetUIController = hudObj.GetComponent<TargetUIController>();
|
||||
// set level panel parameters
|
||||
this.levelNum = levelNum;
|
||||
this.buttonHeight = buttonHeight;
|
||||
defaultSize = new Vector2(parentButton.GetComponent<RectTransform>().sizeDelta.x, 0); ;
|
||||
defaultPosition = parentButton.GetComponent<RectTransform>().anchoredPosition;
|
||||
targetSize = new Vector2(defaultSize.x, buttonHeight * levelNum);
|
||||
targetPosition = new Vector2(-parentButton.GetComponent<RectTransform>().sizeDelta.x,
|
||||
parentButton.GetComponent<RectTransform>().anchoredPosition.y + (levelNum - 1) * buttonHeight / 2);
|
||||
// limit the target position is screen range
|
||||
if (targetPosition.y > 0)
|
||||
{
|
||||
targetPosition.y = 0;
|
||||
}
|
||||
|
||||
// create level buttons
|
||||
for (int i = 0; i < levelNum; i++)
|
||||
{
|
||||
GameObject newButton = Instantiate(levelButtonPrefab, transform);
|
||||
levelButtonList.Add(newButton.GetComponent<Button>());
|
||||
newButton.GetComponent<LevelButton>().Initialization(i);
|
||||
newButton.GetComponent<Button>().onClick.AddListener(delegate { targetUIController.LevelButtonPressed(primaryButtonType, newButton.GetComponent<LevelButton>().level); });
|
||||
}
|
||||
// fold panel to default position immediately
|
||||
FoldLevelPanel();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// fold the level panel.
|
||||
/// </summary>
|
||||
/// <param name="animeTime">fold animation time,0 without animation</param>
|
||||
public void FoldLevelPanel(float animeTime = 0)
|
||||
{
|
||||
isFolding = true;
|
||||
DOTween.To(() => gameObject.GetComponent<RectTransform>().anchoredPosition,
|
||||
x => gameObject.GetComponent<RectTransform>().anchoredPosition = x,
|
||||
defaultPosition,
|
||||
animeTime).SetEase(Ease.OutCirc).Play().OnComplete(() => isFolding = false);
|
||||
DOTween.To(() => gameObject.GetComponent<RectTransform>().sizeDelta,
|
||||
x => gameObject.GetComponent<RectTransform>().sizeDelta = x,
|
||||
defaultSize,
|
||||
animeTime).SetEase(Ease.OutCirc).Play();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// expand the level panel.
|
||||
/// </summary>
|
||||
/// <param name="animeTime">expand animation time,0 without animation</param>
|
||||
public void ExpandLevelPanel(float animeTime = 0)
|
||||
{
|
||||
isExpanding = true;
|
||||
DOTween.To(() => gameObject.GetComponent<RectTransform>().anchoredPosition,
|
||||
x => gameObject.GetComponent<RectTransform>().anchoredPosition = x,
|
||||
targetPosition,
|
||||
animeTime).SetEase(Ease.OutCirc).Play().OnComplete(() => isExpanding = false);
|
||||
DOTween.To(() => gameObject.GetComponent<RectTransform>().sizeDelta,
|
||||
x => gameObject.GetComponent<RectTransform>().sizeDelta = x,
|
||||
targetSize,
|
||||
animeTime).SetEase(Ease.OutCirc).Play();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02d6bdfbf02e0894e80967002bc8c730
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,98 @@
|
||||
using System.Collections.Generic;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class MessageBoxController : MonoBehaviour
|
||||
{
|
||||
public int maxMessageNum = 50;
|
||||
public string defaultColor = "white";
|
||||
public string warningColor = "#ffa500ff";
|
||||
public string errorColor = "#800000ff";
|
||||
public string goodColor = "#00ff00ff";
|
||||
public GameObject messagePanelObj;
|
||||
public GameObject messageTextPrefab;
|
||||
|
||||
[SerializeField]
|
||||
private List<Message> messages = new List<Message>();
|
||||
|
||||
/// <summary>
|
||||
/// Pushes a simple message to the message list.
|
||||
/// </summary>
|
||||
/// <param name="text">The message text.</param>
|
||||
/// <remarks>
|
||||
/// This method pushes a simple text message to the message list and handles message overflow to ensure that the message list does not grow indefinitely.
|
||||
/// </remarks>
|
||||
public void PushMessage(string text)
|
||||
{
|
||||
// push simple message to message list
|
||||
MessageOverflowHandler();
|
||||
Message newMessage = new Message();
|
||||
newMessage.text = text;
|
||||
|
||||
GameObject newText = Instantiate(messageTextPrefab, messagePanelObj.transform);
|
||||
newMessage.textObject = newText.GetComponent<TextMeshProUGUI>();
|
||||
newMessage.textObject.text = newMessage.text;
|
||||
|
||||
messages.Add(newMessage);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Pushes multi-color messages to the message list.
|
||||
/// </summary>
|
||||
/// <param name="messageList">The list of message texts.</param>
|
||||
/// <param name="colorList">The list of colors.</param>
|
||||
/// <remarks>
|
||||
/// This method pushes multi-color text messages to the message list and handles message overflow to ensure that the message list does not grow indefinitely.
|
||||
/// If the lengths of the message text list and the color list do not match, it either removes excess colors or adds white color to the extra messages.
|
||||
/// </remarks>
|
||||
public void PushMessage(List<string> messageList,List<string> colorList)
|
||||
{
|
||||
// check messages and colors list length match
|
||||
if (messageList.Count != colorList.Count)
|
||||
{
|
||||
// delete extra colors or add white color to extra messages
|
||||
if (messageList.Count > colorList.Count)
|
||||
{
|
||||
while(messageList.Count > colorList.Count)
|
||||
{
|
||||
colorList.Add(defaultColor);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
colorList.RemoveRange(messageList.Count, colorList.Count - messageList.Count);
|
||||
}
|
||||
|
||||
}
|
||||
MessageOverflowHandler();
|
||||
Message newMessage = new Message();
|
||||
newMessage.text = "";
|
||||
// assemble message text with color
|
||||
for (int i = 0; i < messageList.Count; i++)
|
||||
{
|
||||
newMessage.text += "<color=" + colorList[i] + ">" + messageList[i] + "</color>";
|
||||
}
|
||||
GameObject newText = Instantiate(messageTextPrefab, messagePanelObj.transform);
|
||||
newMessage.textObject = newText.GetComponent<TextMeshProUGUI>();
|
||||
newMessage.textObject.text = newMessage.text;
|
||||
|
||||
messages.Add(newMessage);
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class Message
|
||||
{
|
||||
public string text;
|
||||
public TMPro.TextMeshProUGUI textObject;
|
||||
}
|
||||
|
||||
private void MessageOverflowHandler()
|
||||
{
|
||||
// destroy the oldest message if message list is full
|
||||
if (messages.Count >= maxMessageNum)
|
||||
{
|
||||
Destroy(messages[0].textObject.gameObject);
|
||||
messages.RemoveAt(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0d0b754dfadef484bbd36745abf1d796
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,37 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
public class RayInfoUI : MonoBehaviour
|
||||
{
|
||||
private TextMeshProUGUI infoText;
|
||||
private bool infoTextReady = false;
|
||||
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
try
|
||||
{
|
||||
infoText = transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>();
|
||||
infoTextReady = true;
|
||||
}
|
||||
catch (UnityException)
|
||||
{
|
||||
infoTextReady = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateInfo(string info, Vector3 infoPosition, Color infoColor, Camera facetoCamera)
|
||||
{
|
||||
if (!infoTextReady)
|
||||
{
|
||||
infoText = transform.GetChild(0).gameObject.GetComponent<TextMeshProUGUI>();
|
||||
}
|
||||
infoText.text = info;
|
||||
infoText.color = infoColor;
|
||||
transform.position = infoPosition;
|
||||
Vector3 v = facetoCamera.transform.position - infoPosition;
|
||||
v.x = v.z = 0.0f;
|
||||
transform.LookAt(facetoCamera.transform.position - v);
|
||||
transform.Rotate(0, 180, 0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 812dfed7ee1d09c4fa7c3ed8372f54ae
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,172 @@
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class SingleLevelProbabilityPanel : MonoBehaviour
|
||||
{
|
||||
public TextMeshProUGUI levelNameText;
|
||||
public TMP_InputField inputField;
|
||||
public Button lockButton;
|
||||
public Image lockImg;
|
||||
public Image unlockImg;
|
||||
|
||||
public Slider probabilitySlider;
|
||||
|
||||
[SerializeField]
|
||||
private float probabilityValue = 0f;
|
||||
|
||||
private bool isLocked = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the level probability panel, setting the level name and probability value.
|
||||
/// </summary>
|
||||
/// <param name="levelName">The level name.</param>
|
||||
/// <param name="probability">The probability value.</param>
|
||||
public void InitializeLevelProbabilityPanel(string levelName, float probability)
|
||||
{
|
||||
SetLevelName(levelName);
|
||||
SetProbability(probability);
|
||||
InitializeButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize the level probability panel, setting the level number and probability value.
|
||||
/// </summary>
|
||||
/// <param name="levelName">The level number.</param>
|
||||
/// <param name="probability">The probability value.</param>
|
||||
public void InitializeLevelProbabilityPanel(int levelName, float probability)
|
||||
{
|
||||
SetLevelName(levelName);
|
||||
SetProbability(probability);
|
||||
InitializeButton();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the level name.
|
||||
/// </summary>
|
||||
/// <param name="levelName">The level name.</param>
|
||||
public void SetLevelName(string levelName)
|
||||
{
|
||||
levelNameText.text = levelName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the level name.
|
||||
/// </summary>
|
||||
/// <param name="levelName">The level number.</param>
|
||||
public void SetLevelName(int levelName)
|
||||
{
|
||||
levelNameText.text = "Level" + levelName.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the probability value.
|
||||
/// </summary>
|
||||
/// <param name="prob">The probability value.</param>
|
||||
public void SetProbability(float prob)
|
||||
{
|
||||
probabilityValue = prob;
|
||||
UpdateProbabilityText();
|
||||
UpdateProbabilitySlider();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the probability text display and can optionally synchronize the probability slider update.
|
||||
/// </summary>
|
||||
/// <param name="value">The probability value (optional).</param>
|
||||
/// <param name="syncToSlider">Whether to synchronize the probability slider update (default is false).</param>
|
||||
/// <remarks>
|
||||
/// If a probability value (value) is provided, it updates the probability text using that value. Otherwise, it parses the percentage value from the input field and updates the text.
|
||||
/// If syncToSlider is true, it also synchronizes the probability slider update.
|
||||
/// </remarks>
|
||||
public void UpdateProbabilityText(float? value = null)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
probabilityValue = (float)value;
|
||||
}
|
||||
inputField.text = (probabilityValue * 100f).ToString("F1") + "%";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the value of the probability slider and can optionally synchronize the probability text update.
|
||||
/// </summary>
|
||||
/// <param name="value">The probability value (optional).</param>
|
||||
/// <param name="syncToText">Whether to synchronize the probability text update (default is false).</param>
|
||||
/// <remarks>
|
||||
/// If a probability value (value) is provided, it updates the probability slider using that value. Otherwise, it parses the percentage value from the input field and updates the slider.
|
||||
/// If syncToText is true, it also synchronizes the probability text update.
|
||||
/// </remarks>
|
||||
public void UpdateProbabilitySlider(float? value = null)
|
||||
{
|
||||
if (value != null)
|
||||
{
|
||||
probabilityValue = (float)value;
|
||||
}
|
||||
probabilitySlider.value = probabilityValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current probability value.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This property allows external code to read the current probability value.
|
||||
/// </remarks>
|
||||
public float ProbabilityValue
|
||||
{
|
||||
get { return probabilityValue; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the object is locked.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns true if the object is locked; otherwise, returns false.
|
||||
/// </remarks>
|
||||
public bool IsLocked
|
||||
{
|
||||
get { return isLocked; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the object is unlocked.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Returns true if the object is unlocked; otherwise, returns false.
|
||||
/// </remarks>
|
||||
public bool UnLocked
|
||||
{
|
||||
get { return !isLocked; }
|
||||
}
|
||||
|
||||
private void InitializeButton()
|
||||
{
|
||||
EventTrigger eventTrigger = lockButton.GetComponent<EventTrigger>();
|
||||
if (eventTrigger == null)
|
||||
{
|
||||
eventTrigger = lockButton.gameObject.AddComponent<EventTrigger>();
|
||||
}
|
||||
EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
entry.eventID = EventTriggerType.PointerClick;
|
||||
entry.callback.AddListener((data) => { OnLockButtonClicked(); });
|
||||
eventTrigger.triggers.Add(entry);
|
||||
// set lockImg as Unlock
|
||||
isLocked = false;
|
||||
UpdateLockImg();
|
||||
}
|
||||
|
||||
private void OnLockButtonClicked()
|
||||
{
|
||||
isLocked = !isLocked;
|
||||
UpdateLockImg();
|
||||
probabilitySlider.interactable = !isLocked;
|
||||
inputField.interactable = !isLocked;
|
||||
}
|
||||
|
||||
private void UpdateLockImg()
|
||||
{
|
||||
lockImg.gameObject.SetActive(isLocked);
|
||||
unlockImg.gameObject.SetActive(!isLocked);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a8780a678491d04d9395d0243a3dab0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class StartMenuProbabilityPanel : MonoBehaviour
|
||||
{
|
||||
public GameObject singleTargetLevelProbabilityPanel;
|
||||
public GameObject startSceneData;
|
||||
private SceneBlocksSet scenePrefabSet;
|
||||
|
||||
public List<TargetLevelProbabilityPanel> targetLevelProbabilityPanel = new List<TargetLevelProbabilityPanel>();
|
||||
|
||||
private void Start()
|
||||
{
|
||||
scenePrefabSet = startSceneData.GetComponent<StartSeneData>().scenePrefabSet;
|
||||
for (int i = 0; i < scenePrefabSet.targetLevels.Length; i++)
|
||||
{
|
||||
Targets nowTarget = scenePrefabSet.targets[i];
|
||||
targetLevelProbabilityPanel.Add(Instantiate(singleTargetLevelProbabilityPanel, transform).GetComponent<TargetLevelProbabilityPanel>());
|
||||
targetLevelProbabilityPanel[i].IntializePanels(scenePrefabSet.GetLevelNumber(nowTarget), nowTarget.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0195eb0e734c7e747bb7f8b669c80fe5
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,268 @@
|
||||
using System;
|
||||
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;
|
||||
public List<GameObject> singleLevelPanelsObjs = new List<GameObject>();
|
||||
public List<SingleLevelProbabilityPanel> singleLevelPanels = new List<SingleLevelProbabilityPanel>();
|
||||
|
||||
private int panelNum = 0;
|
||||
|
||||
public void IntializePanels(int levelNum, string titleName)
|
||||
{
|
||||
// initialize target level probability panel size
|
||||
float defaultWidth = singleLevelProbabilityPanel.GetComponent<RectTransform>().sizeDelta.x;
|
||||
float defaultLevelHeight = singleLevelProbabilityPanel.GetComponent<RectTransform>().sizeDelta.y;
|
||||
float titleHeight = targetTitleText.GetComponent<RectTransform>().sizeDelta.y;
|
||||
float averageProbability = 1f / levelNum;
|
||||
float lastLevelProbability = 1f - averageProbability * (levelNum - 1);
|
||||
// Debug.Log("averageProbability: " + averageProbability);
|
||||
transform.GetComponent<RectTransform>().sizeDelta = new Vector2(defaultWidth, (defaultLevelHeight * levelNum) + titleHeight);
|
||||
// create title text
|
||||
titleText = Instantiate(targetTitleText, transform);
|
||||
titleText.GetComponent<TextMeshProUGUI>().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<SingleLevelProbabilityPanel>());
|
||||
singleLevelPanels[i].InitializeLevelProbabilityPanel(i, i == levelNum - 1 ? lastLevelProbability : averageProbability);
|
||||
//add onValueChanged event to slider and input field
|
||||
singleLevelPanels[i].probabilitySlider.onValueChanged.AddListener((value) => OnProbabilityValueChange(value, tempIndex));
|
||||
singleLevelPanels[i].inputField.onEndEdit.AddListener((value) => OnProbabilityValueChange(value, tempIndex));
|
||||
}
|
||||
panelNum = levelNum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an event trigger entry to an event trigger.
|
||||
/// </summary>
|
||||
/// <param name="trigger">The event trigger object.</param>
|
||||
/// <param name="type">The event trigger type.</param>
|
||||
/// <param name="action">The event handler method to execute.</param>
|
||||
private void AddEventTrigger(GameObject gameObject, EventTriggerType triggerType, System.Action<BaseEventData> action)
|
||||
{
|
||||
EventTrigger eventTrigger = gameObject.GetComponent<EventTrigger>();
|
||||
if (eventTrigger == null)
|
||||
{
|
||||
eventTrigger = gameObject.AddComponent<EventTrigger>();
|
||||
}
|
||||
EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
entry.eventID = triggerType;
|
||||
entry.callback.AddListener(new UnityEngine.Events.UnityAction<BaseEventData>(action));
|
||||
eventTrigger.triggers.Add(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// On Probability Slider Value Change.Adjust other sliders' value to make sure the total value is 1.
|
||||
/// </summary>
|
||||
/// <param name="value">change to this value</param>
|
||||
/// <param name="exceptedIndex">changed panel index</param>
|
||||
private void OnProbabilityValueChange<T>(T value, int exceptedIndex)
|
||||
{
|
||||
float changedValue = 0f;
|
||||
switch (value)
|
||||
{
|
||||
case float floatValue:
|
||||
changedValue = floatValue;
|
||||
break;
|
||||
case string stringValue:
|
||||
changedValue = float.Parse(stringValue);
|
||||
// limit the value between 0 and 1
|
||||
if(changedValue>1 && changedValue <=100)
|
||||
{
|
||||
changedValue /= 100;
|
||||
}else if(changedValue>100)
|
||||
{
|
||||
changedValue = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Debug.LogError("Invalid value type!");
|
||||
throw new ArgumentException("Unsupported value type");
|
||||
}
|
||||
float newTotalValue = 0; // new total probability value without locked panel
|
||||
int unlockedPanelNum = 0;
|
||||
int remainCorrectionNum = panelNum;
|
||||
float extraValue = 0; // the extra value after probability value changed
|
||||
float maxLimitValue = 1; // the max value of unlocked panel permitted
|
||||
float[] correctionValues = new float[panelNum];
|
||||
|
||||
// calculate total probability value
|
||||
for (int i = 0; i < panelNum; i++)
|
||||
{
|
||||
// disable slider listener
|
||||
singleLevelPanels[i].probabilitySlider.onValueChanged.RemoveAllListeners();
|
||||
if (singleLevelPanels[i].UnLocked)
|
||||
{
|
||||
unlockedPanelNum++;
|
||||
newTotalValue += (i == exceptedIndex ? changedValue : singleLevelPanels[i].ProbabilityValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
// delete locked probability value from maxLimitValue
|
||||
maxLimitValue -= singleLevelPanels[i].ProbabilityValue;
|
||||
}
|
||||
}
|
||||
// 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 at maxLimitValue
|
||||
singleLevelPanels[exceptedIndex].SetProbability(maxLimitValue);
|
||||
enableSliderListener();
|
||||
return;
|
||||
}
|
||||
// Calculate the average correction value
|
||||
extraValue = newTotalValue - maxLimitValue;
|
||||
// initialize correction value to each panel
|
||||
correctionValues = Enumerable.Repeat(extraValue / (unlockedPanelNum - 1), panelNum).ToArray();
|
||||
// make sure all probability value is not less than 0 and equal to 1
|
||||
int iterationCount = 0;
|
||||
while (remainCorrectionNum > 0)
|
||||
{
|
||||
iterationCount++;
|
||||
(correctionValues, remainCorrectionNum) = reCalculateCorrectionValues(correctionValues, exceptedIndex, changedValue, extraValue, maxLimitValue);
|
||||
// protect the infinite loop
|
||||
if (iterationCount >= 100)
|
||||
{
|
||||
Debug.LogError("Infinite loop detected!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// applicate the value to all unlocked panels excepted the changed one
|
||||
applyCorrectionValue(correctionValues);
|
||||
enableSliderListener();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// enable all sliders' onValueChanged action listener
|
||||
/// </summary>
|
||||
private void enableSliderListener()
|
||||
{
|
||||
for (int i = 0; i < panelNum; i++)
|
||||
{
|
||||
int tempIndex = i;
|
||||
singleLevelPanels[i].probabilitySlider.onValueChanged.AddListener((value) => OnProbabilityValueChange(value, tempIndex));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// calculate the correction value to each panel,while the total value is not equal to 1
|
||||
/// </summary>
|
||||
private (float[], int) reCalculateCorrectionValues(float[] correctionValues, int exceptedIndex, float value, float extraValue, float maxLimitValue)
|
||||
{
|
||||
// the number of panels which need to be corrected in next iteration
|
||||
int remainCorrectionNum = 0;
|
||||
List<int> reCorrectionIndex = new List<int>();
|
||||
// the index of the last panel which need to be corrected in this iteration
|
||||
int lastReCorrectionIndex = 0;
|
||||
// another extra value after correctionValue applicate to probability value which value also less than 0
|
||||
// this value will be added to the panel which value is bigger.
|
||||
float underZeroExtraValueAfterCorrected = 0;
|
||||
for (int i = 0; i < panelNum; ++i)
|
||||
{
|
||||
// if the panel is the changed one
|
||||
if (i == exceptedIndex)
|
||||
{
|
||||
// limit the value under maxLimitValue
|
||||
correctionValues[i] = value > maxLimitValue ? (singleLevelPanels[i].ProbabilityValue - maxLimitValue) : (singleLevelPanels[i].ProbabilityValue - value);
|
||||
continue;
|
||||
}
|
||||
// if the panel is locked
|
||||
if (singleLevelPanels[i].IsLocked)
|
||||
{
|
||||
correctionValues[i] = 0;
|
||||
continue;
|
||||
}
|
||||
// if the panel is unlocked
|
||||
// and the probability value is less than 0 or bigger than maxLimitValue
|
||||
if (singleLevelPanels[i].ProbabilityValue < 0 || singleLevelPanels[i].ProbabilityValue > maxLimitValue)
|
||||
{
|
||||
// correct this panel value to 0 or maxLimitValue
|
||||
correctionValues[i] = singleLevelPanels[i].ProbabilityValue;
|
||||
}
|
||||
// probability value will be correct to 0
|
||||
else if (singleLevelPanels[i].ProbabilityValue == correctionValues[i])
|
||||
{
|
||||
// that's good keep this correction value, and add it to the extraValue
|
||||
underZeroExtraValueAfterCorrected += correctionValues[i];
|
||||
}
|
||||
// probability value will be correct over the limit (bigger than maxLimitValue or less than 0)
|
||||
else if (singleLevelPanels[i].ProbabilityValue - correctionValues[i] < 0 || singleLevelPanels[i].ProbabilityValue - correctionValues[i] > maxLimitValue)
|
||||
{
|
||||
// should be corrected to 0 or maxLimitValue,and add it to the extraValue
|
||||
underZeroExtraValueAfterCorrected += singleLevelPanels[i].ProbabilityValue;
|
||||
correctionValues[i] = singleLevelPanels[i].ProbabilityValue;
|
||||
}
|
||||
// left panels correction value which need to be re-corrected
|
||||
else
|
||||
{
|
||||
lastReCorrectionIndex = i;
|
||||
reCorrectionIndex.Add(i);
|
||||
}
|
||||
}
|
||||
foreach (int index in reCorrectionIndex)
|
||||
{
|
||||
// calculate the average correction value
|
||||
float newAverageCorrectionValue = (extraValue - underZeroExtraValueAfterCorrected) / reCorrectionIndex.Count;
|
||||
// if the panel is the last one which need to be corrected.
|
||||
// Avoidance of floating-point rounding error, the last panel correction value will be the extraValue minus the sum of the other panels correction value
|
||||
if (index == lastReCorrectionIndex)
|
||||
{
|
||||
correctionValues[index] = extraValue - (newAverageCorrectionValue * (reCorrectionIndex.Count - 1));
|
||||
// still out of limit after correction, correct it to 0 and activate next iteration
|
||||
if (singleLevelPanels[index].ProbabilityValue - correctionValues[index] < 0 || singleLevelPanels[index].ProbabilityValue - correctionValues[index] > maxLimitValue)
|
||||
{
|
||||
correctionValues[index] = singleLevelPanels[index].ProbabilityValue;
|
||||
remainCorrectionNum++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
correctionValues[index] = newAverageCorrectionValue;
|
||||
// still out of limit after correction, correct it to 0 and activate next iteration
|
||||
if (singleLevelPanels[index].ProbabilityValue - correctionValues[index] < 0 || singleLevelPanels[index].ProbabilityValue - correctionValues[index] > maxLimitValue)
|
||||
{
|
||||
correctionValues[index] = singleLevelPanels[index].ProbabilityValue;
|
||||
remainCorrectionNum++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return (correctionValues, remainCorrectionNum);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// applicate correction value to each panel
|
||||
/// </summary>
|
||||
private void applyCorrectionValue(float[] correctionValues)
|
||||
{
|
||||
for (int i = 0; i < panelNum; i++)
|
||||
{
|
||||
/* if (singleLevelPanels[i].ProbabilityValue - correctionValues[i] < 0)
|
||||
{
|
||||
Debug.LogWarning("Probability value is less than 0");
|
||||
Debug.Log(i);
|
||||
Debug.Log(singleLevelPanels[i].ProbabilityValue);
|
||||
Debug.Log(correctionValues[i]);
|
||||
}*/
|
||||
singleLevelPanels[i].SetProbability(singleLevelPanels[i].ProbabilityValue - correctionValues[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44de9c40b3fc56046a490c8c47631d4d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,253 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
using UnityEngine.UI;
|
||||
|
||||
public class TargetUIController : MonoBehaviour
|
||||
{
|
||||
// Controller to control the UI of the target,
|
||||
// select target type, select prefeb to set or sth.
|
||||
public GameObject targetControllerObj;
|
||||
|
||||
public GameObject mouseSelectorObj;
|
||||
public GameObject environmentUIObj;
|
||||
|
||||
public float levelButtonHeight = 30;
|
||||
|
||||
[Header("PrimaryButton")]
|
||||
public Button clearGameButton;
|
||||
public Button setEnemyButton;
|
||||
public Button setAttackButton;
|
||||
public Button setGotoButton;
|
||||
public Button setFreeButton;
|
||||
public Button setStayButton;
|
||||
public int primaryButtonNumber = 6;
|
||||
|
||||
[Header("LevelPanel")]
|
||||
public GameObject gotoLevelPanel;
|
||||
|
||||
public GameObject attackLevelPanel;
|
||||
public float levelPanelAnimeTime = 0.2f;
|
||||
|
||||
private MouseInMap mouseInMapCon;
|
||||
private EnvironmentUIControl envUICon;
|
||||
private TargetController targetCon;
|
||||
private MessageBoxController messageBoxController;
|
||||
private ButtonActivateColorChanger buttonColorChanger;
|
||||
|
||||
public enum PrimaryButtonType
|
||||
{ Goto, Attack, Free }
|
||||
|
||||
public delegate void PointerInOutUIEventDelegate(Button button, GameObject panel, BaseEventData eventData);
|
||||
|
||||
private void Start()
|
||||
{
|
||||
targetCon = targetControllerObj.GetComponent<TargetController>();
|
||||
mouseInMapCon = mouseSelectorObj.GetComponent<MouseInMap>();
|
||||
envUICon = environmentUIObj.GetComponent<EnvironmentUIControl>();
|
||||
messageBoxController = GetComponent<MessageBoxController>();
|
||||
buttonColorChanger = GetComponent<ButtonActivateColorChanger>();
|
||||
|
||||
gotoLevelPanel.GetComponent<LevelPanel>().InitLevelPanel(
|
||||
targetCon.gotoLevelNum,
|
||||
setGotoButton,
|
||||
levelButtonHeight);
|
||||
attackLevelPanel.GetComponent<LevelPanel>().InitLevelPanel(
|
||||
targetCon.attackLevelNum,
|
||||
setAttackButton,
|
||||
levelButtonHeight);
|
||||
AddLevelButtonToColorChanger(gotoLevelPanel);
|
||||
AddLevelButtonToColorChanger(attackLevelPanel);
|
||||
AddPointerEnterButtonTrigger(setGotoButton, gotoLevelPanel, PointerEnterButtonAction);
|
||||
AddPointerEnterButtonTrigger(setAttackButton, attackLevelPanel, PointerEnterButtonAction);
|
||||
AddPointerExitButtonTrigger(setGotoButton, gotoLevelPanel, PointerExitButtonAction);
|
||||
AddPointerExitButtonTrigger(setAttackButton, attackLevelPanel, PointerExitButtonAction);
|
||||
AddPointerExitLevelPanelTrigger(setGotoButton, gotoLevelPanel, PointerExitLevelPanelAction);
|
||||
AddPointerExitLevelPanelTrigger(setAttackButton, attackLevelPanel, PointerExitLevelPanelAction);
|
||||
buttonColorChanger.InitializeAllButtonColor();
|
||||
ClearGamePressed();
|
||||
}
|
||||
|
||||
public void LevelButtonPressed(PrimaryButtonType primaryButtonType, int level = 0)
|
||||
{
|
||||
switch (primaryButtonType)
|
||||
{
|
||||
case PrimaryButtonType.Goto:
|
||||
SetGotoPressed(level);
|
||||
break;
|
||||
|
||||
case PrimaryButtonType.Attack:
|
||||
SetAttackPressed(level);
|
||||
break;
|
||||
|
||||
default:
|
||||
messageBoxController.PushMessage(new List<string> { "TargetUIController.LevelButtonPressed:", "Button Type Wrong, not level included button" },
|
||||
new List<string> { messageBoxController.errorColor });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Clear Game Button Pressed, delete all enemies and targets
|
||||
public void ClearGamePressed()
|
||||
{
|
||||
// Clear all enemies and targets. set gamemode to Stay mode
|
||||
targetCon.StayModeChange();
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
|
||||
// disable setStayButton and enable other buttons
|
||||
buttonColorChanger.ChangeInteractableColor(clearGameButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setEnemyButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, false);
|
||||
targetCon.PlayInitialize();
|
||||
}
|
||||
|
||||
// Set Free Button Pressed, change Target mode to free mode
|
||||
public void SetFreePressed()
|
||||
{
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
|
||||
targetCon.FreeModeChange();
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setFreeButton, false);
|
||||
}
|
||||
|
||||
// Set Stay Button Pressed, change Target mode to stay mode
|
||||
public void SetStayPressed()
|
||||
{
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.Default);
|
||||
targetCon.StayModeChange();
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, false);
|
||||
buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
|
||||
}
|
||||
|
||||
// Set Enemy Button Pressed, change mouse mode to EnemySetMode
|
||||
public void SetEnemyPressed()
|
||||
{
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.EnemySet);
|
||||
}
|
||||
|
||||
// Set Goto Button Pressed, change mouse mode to GotoSetMode
|
||||
private void SetGotoPressed(int level)
|
||||
{
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.GotoSet, level);
|
||||
buttonColorChanger.ChangeInteractableColor(clearGameButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setEnemyButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
|
||||
}
|
||||
|
||||
// Set Attack Button Pressed, change mouse mode to AttackSetMode
|
||||
private void SetAttackPressed(int level)
|
||||
{
|
||||
mouseInMapCon.ChangeMouseMode(MouseInMap.MouseMode.AttackSet, level);
|
||||
buttonColorChanger.ChangeInteractableColor(clearGameButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setEnemyButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setStayButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setAttackButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setGotoButton, true);
|
||||
buttonColorChanger.ChangeInteractableColor(setFreeButton, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds level buttons from a level panel to the color changer, making them got interactable color.
|
||||
/// </summary>
|
||||
/// <param name="levelPanel">The level panel object containing the level buttons.</param>
|
||||
private void AddLevelButtonToColorChanger(GameObject levelPanel)
|
||||
{
|
||||
foreach(Button btn in levelPanel.GetComponent<LevelPanel>().LevelButtonList)
|
||||
{
|
||||
buttonColorChanger.AddButtonToColorChangerButtonList(btn,true);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sign up pointer enter event for button
|
||||
/// </summary>
|
||||
/// <param name="triggerButton">target button</param>
|
||||
/// <param name="panel">target panel</param>
|
||||
/// <param name="inAction">enter event trigered action</param>
|
||||
private void AddPointerEnterButtonTrigger(Button triggerButton, GameObject panel, PointerInOutUIEventDelegate inAction)
|
||||
{
|
||||
EventTrigger.Entry inEntry = new EventTrigger.Entry();
|
||||
inEntry.eventID = EventTriggerType.PointerEnter;
|
||||
inEntry.callback.AddListener((eventData) => inAction(triggerButton, panel, eventData));
|
||||
triggerButton.GetComponent<EventTrigger>().triggers.Add(inEntry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sign up pointer exit event for button
|
||||
/// </summary>
|
||||
/// <param name="triggerButton">target button</param>
|
||||
/// <param name="panel">target panel</param>
|
||||
/// <param name="inAction">exit event trigered action</param>
|
||||
private void AddPointerExitButtonTrigger(Button triggerButton, GameObject panel, PointerInOutUIEventDelegate outAction)
|
||||
{
|
||||
EventTrigger.Entry outEntry = new EventTrigger.Entry();
|
||||
outEntry.eventID = EventTriggerType.PointerExit;
|
||||
outEntry.callback.AddListener((eventData) => outAction(triggerButton, panel, eventData));
|
||||
triggerButton.GetComponent<EventTrigger>().triggers.Add(outEntry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// sign up pointer exit event for panel
|
||||
/// </summary>
|
||||
/// <param name="triggerButton">target button</param>
|
||||
/// <param name="panel">target panel</param>
|
||||
/// <param name="inAction">exit event trigered action</param>
|
||||
private void AddPointerExitLevelPanelTrigger(Button triggerButton, GameObject panel, PointerInOutUIEventDelegate outAction)
|
||||
{
|
||||
EventTrigger.Entry entry = new EventTrigger.Entry();
|
||||
entry.eventID = EventTriggerType.PointerExit;
|
||||
entry.callback.AddListener((eventData) => outAction(triggerButton, panel, eventData));
|
||||
panel.GetComponent<EventTrigger>().triggers.Add(entry);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pointer enter event action for button
|
||||
/// </summary>
|
||||
/// <param name="button">target button</param>
|
||||
/// <param name="panel">target panel</param>
|
||||
/// <param name="baseEventData">EventTrigger Parameter</param>
|
||||
private void PointerEnterButtonAction(Button button, GameObject panel, BaseEventData baseEventData)
|
||||
{
|
||||
panel.GetComponent<LevelPanel>().ExpandLevelPanel(levelPanelAnimeTime);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pointer exit event action for button
|
||||
/// </summary>
|
||||
/// <param name="button">target button</param>
|
||||
/// <param name="panel">target panel</param>
|
||||
/// <param name="baseEventData">EventTrigger Parameter</param>
|
||||
private void PointerExitButtonAction(Button button, GameObject panel, BaseEventData baseEventData)
|
||||
{
|
||||
bool pointerInPanel = RectTransformUtility.RectangleContainsScreenPoint(panel.GetComponent<RectTransform>(), Input.mousePosition);
|
||||
if (!pointerInPanel)
|
||||
{
|
||||
panel.GetComponent<LevelPanel>().FoldLevelPanel(levelPanelAnimeTime);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// pointer enter event action for level panel
|
||||
/// </summary>
|
||||
/// <param name="button">target button</param>
|
||||
/// <param name="panel">target panel</param>
|
||||
/// <param name="baseEventData">EventTrigger Parameter</param>
|
||||
private void PointerExitLevelPanelAction(Button button, GameObject panel, BaseEventData baseEventData)
|
||||
{
|
||||
bool pointerInButton = RectTransformUtility.RectangleContainsScreenPoint(button.GetComponent<RectTransform>(), Input.mousePosition);
|
||||
if (!pointerInButton)
|
||||
{
|
||||
panel.GetComponent<LevelPanel>().FoldLevelPanel(levelPanelAnimeTime);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3e5f471594a32c24194088f10d716a89
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,18 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class UIColorContainer : MonoBehaviour
|
||||
{
|
||||
// Start is called before the first frame update
|
||||
void Start()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
// Update is called once per frame
|
||||
void Update()
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3fef23608d0a5d242a781d8ca28ed23b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using XCharts.Runtime;
|
||||
|
||||
public class WorldUIController : MonoBehaviour
|
||||
{
|
||||
public LineChart winChart;
|
||||
public int[] totalGames;
|
||||
public int[] winGames;
|
||||
|
||||
private int maxXAxis = 0;
|
||||
|
||||
// Start is called before the first frame update
|
||||
private void Start()
|
||||
{
|
||||
totalGames = new int[(int)Targets.Num];
|
||||
winGames = new int[(int)Targets.Num];
|
||||
Array.Clear(totalGames, 0, (int)Targets.Num);
|
||||
Array.Clear(winGames, 0, (int)Targets.Num);
|
||||
//WinChart.Init();
|
||||
winChart.RemoveData();
|
||||
for (int i = 0; i < (int)Targets.Num; i++)
|
||||
{
|
||||
string lineName = Enum.GetName(typeof(Targets), i);
|
||||
winChart.AddSerie<Line>(lineName);
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateChart(int targetType, int endType)
|
||||
{
|
||||
float winRatio = 0f;
|
||||
switch (endType)
|
||||
{
|
||||
case (int)TargetController.EndType.Win:
|
||||
//Win
|
||||
totalGames[targetType] += 1;
|
||||
winGames[targetType] += 1;
|
||||
winRatio = (float)winGames[targetType] / totalGames[targetType];
|
||||
winChart.AddData(targetType, winRatio);
|
||||
if (totalGames[targetType] > maxXAxis)
|
||||
{
|
||||
maxXAxis = totalGames[targetType];
|
||||
winChart.AddXAxisData(Convert.ToString(maxXAxis));
|
||||
}
|
||||
break;
|
||||
|
||||
case (int)TargetController.EndType.Lose:
|
||||
//lose
|
||||
totalGames[targetType] += 1;
|
||||
winRatio = (float)winGames[targetType] / totalGames[targetType];
|
||||
winChart.AddData(targetType, winRatio);
|
||||
if (totalGames[targetType] > maxXAxis)
|
||||
{
|
||||
maxXAxis = totalGames[targetType];
|
||||
winChart.AddXAxisData(Convert.ToString(maxXAxis));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fe230edb81d2a59409af4d033c8d2e7a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user