581 lines
17 KiB
C#
581 lines
17 KiB
C#
using System.Collections.Generic;
|
|
using Bansonic;
|
|
using DG.Tweening;
|
|
using UnityEngine;
|
|
using UnityEngine.SceneManagement;
|
|
using UnityEngine.UI;
|
|
|
|
public class eula_and_warnings : MonoBehaviour
|
|
{
|
|
private const string MainSceneName = "Main_main";
|
|
private const string RankingConsentPrefKey = "before_everything_agree_ranking";
|
|
private const string FirstLaunchCompletedPrefKey = "before_everything_first_launch_completed";
|
|
private const string LightWarningAcceptedPrefKey = "before_everything_light_warning_accepted";
|
|
private const string UserInfoAcceptedPrefKey = "before_everything_user_info_accepted";
|
|
private const float LightWarningMinimumSeconds = 5f;
|
|
private const float FadeDuration = 0.3f;
|
|
private const float RequiredScrollReadThreshold = 0.1f;
|
|
|
|
[Header("objs")]
|
|
[SerializeField] GameObject lightWarningObj;
|
|
[SerializeField] GameObject uInfoEulaObj;
|
|
|
|
[Header("canvas groups")]
|
|
[SerializeField] CanvasGroup lightWarningCG;
|
|
[SerializeField] CanvasGroup uInfoEulaCG;
|
|
|
|
[Header("intro")]
|
|
[SerializeField] float lightWarningFadeInDelay = 0f;
|
|
|
|
[Header("light warnings")]
|
|
[SerializeField] Toggle lw_uhaveRead;
|
|
[SerializeField] Button lw_next;
|
|
[SerializeField] Button lw_quit;
|
|
|
|
[Header("user infomation eula")]
|
|
[SerializeField] Toggle uie_uhaveRead;
|
|
[SerializeField] Toggle uie_agreeRanking;
|
|
[SerializeField] Button uie_next;
|
|
[SerializeField] Button uie_quit;
|
|
|
|
[SerializeField] ScrollRect uie_scrollRect;
|
|
|
|
private float _lightWarningShownAtRealtime;
|
|
private AsyncOperation _mainScenePreloadOperation;
|
|
private Tween _lightWarningTween;
|
|
private Tween _userInfoTween;
|
|
private bool _isTransitioning;
|
|
private bool _mainScenePreloadRequested;
|
|
private bool _mainScenePreloadReady;
|
|
private bool _hasCompletedFirstLaunch;
|
|
private bool _hasAcceptedLightWarning;
|
|
private bool _hasAcceptedUserInfoEula;
|
|
private readonly List<GameObject> _hiddenMainSceneRoots = new List<GameObject>();
|
|
|
|
private void Awake()
|
|
{
|
|
AutoAssignReferences();
|
|
ForceInitialState();
|
|
BindEvents();
|
|
}
|
|
|
|
private void Start()
|
|
{
|
|
LoadPersistedConsentState();
|
|
|
|
if (ShouldSkipConfirmationFlow())
|
|
{
|
|
ActivateMainScene();
|
|
return;
|
|
}
|
|
|
|
PlayLightWarningIntro();
|
|
}
|
|
|
|
private void OnDestroy()
|
|
{
|
|
if (lw_next != null) lw_next.onClick.RemoveListener(HandleLightWarningNextClicked);
|
|
if (lw_quit != null) lw_quit.onClick.RemoveListener(HandleLightWarningQuitClicked);
|
|
if (uie_next != null) uie_next.onClick.RemoveListener(HandleUserInfoNextClicked);
|
|
if (uie_quit != null) uie_quit.onClick.RemoveListener(HandleUserInfoQuitClicked);
|
|
|
|
_lightWarningTween?.Kill();
|
|
_userInfoTween?.Kill();
|
|
}
|
|
|
|
private void ForceInitialState()
|
|
{
|
|
if (lightWarningObj != null) lightWarningObj.SetActive(true);
|
|
if (uInfoEulaObj != null) uInfoEulaObj.SetActive(false);
|
|
|
|
SetupCanvasGroup(lightWarningCG, false);
|
|
SetupCanvasGroup(uInfoEulaCG, false);
|
|
|
|
if (lw_uhaveRead != null) lw_uhaveRead.SetIsOnWithoutNotify(false);
|
|
if (uie_uhaveRead != null) uie_uhaveRead.SetIsOnWithoutNotify(false);
|
|
|
|
if (uie_agreeRanking != null)
|
|
{
|
|
bool agreeRanking = PlayerPrefs.GetInt(RankingConsentPrefKey, 0) == 1;
|
|
uie_agreeRanking.SetIsOnWithoutNotify(agreeRanking);
|
|
}
|
|
|
|
if (uie_scrollRect != null)
|
|
{
|
|
Canvas.ForceUpdateCanvases();
|
|
uie_scrollRect.verticalNormalizedPosition = 1f;
|
|
}
|
|
|
|
_lightWarningShownAtRealtime = Time.realtimeSinceStartup;
|
|
_isTransitioning = false;
|
|
}
|
|
|
|
private void LoadPersistedConsentState()
|
|
{
|
|
_hasCompletedFirstLaunch = PlayerPrefs.GetInt(FirstLaunchCompletedPrefKey, 0) == 1;
|
|
_hasAcceptedLightWarning = PlayerPrefs.GetInt(LightWarningAcceptedPrefKey, 0) == 1;
|
|
_hasAcceptedUserInfoEula = PlayerPrefs.GetInt(UserInfoAcceptedPrefKey, 0) == 1;
|
|
}
|
|
|
|
private bool ShouldSkipConfirmationFlow()
|
|
{
|
|
return _hasCompletedFirstLaunch && _hasAcceptedLightWarning && _hasAcceptedUserInfoEula;
|
|
}
|
|
|
|
private void PlayLightWarningIntro()
|
|
{
|
|
if (lightWarningObj == null || lightWarningCG == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
lightWarningObj.SetActive(true);
|
|
lightWarningCG.alpha = 0f;
|
|
lightWarningCG.interactable = false;
|
|
lightWarningCG.blocksRaycasts = false;
|
|
|
|
_lightWarningTween?.Kill();
|
|
_lightWarningTween = lightWarningCG
|
|
.DOFade(1f, FadeDuration)
|
|
.SetDelay(Mathf.Max(0f, lightWarningFadeInDelay))
|
|
.SetUpdate(true)
|
|
.OnStart(() => _lightWarningShownAtRealtime = Time.realtimeSinceStartup)
|
|
.OnComplete(() => SetupCanvasGroup(lightWarningCG, true));
|
|
}
|
|
|
|
private void BindEvents()
|
|
{
|
|
if (lw_next != null)
|
|
{
|
|
lw_next.onClick.RemoveListener(HandleLightWarningNextClicked);
|
|
lw_next.onClick.AddListener(HandleLightWarningNextClicked);
|
|
}
|
|
|
|
if (lw_quit != null)
|
|
{
|
|
lw_quit.onClick.RemoveListener(HandleLightWarningQuitClicked);
|
|
lw_quit.onClick.AddListener(HandleLightWarningQuitClicked);
|
|
}
|
|
|
|
if (uie_next != null)
|
|
{
|
|
uie_next.onClick.RemoveListener(HandleUserInfoNextClicked);
|
|
uie_next.onClick.AddListener(HandleUserInfoNextClicked);
|
|
}
|
|
|
|
if (uie_quit != null)
|
|
{
|
|
uie_quit.onClick.RemoveListener(HandleUserInfoQuitClicked);
|
|
uie_quit.onClick.AddListener(HandleUserInfoQuitClicked);
|
|
}
|
|
}
|
|
|
|
private void BeginPreloadMainScene()
|
|
{
|
|
if (!Application.isPlaying || _mainScenePreloadRequested)
|
|
{
|
|
return;
|
|
}
|
|
|
|
_mainScenePreloadRequested = true;
|
|
StartCoroutine(PreloadMainSceneRoutine());
|
|
}
|
|
|
|
private System.Collections.IEnumerator PreloadMainSceneRoutine()
|
|
{
|
|
_mainScenePreloadOperation = SceneManager.LoadSceneAsync(MainSceneName, LoadSceneMode.Additive);
|
|
if (_mainScenePreloadOperation == null)
|
|
{
|
|
yield break;
|
|
}
|
|
|
|
_mainScenePreloadOperation.allowSceneActivation = false;
|
|
|
|
while (_mainScenePreloadOperation.progress < 0.9f)
|
|
{
|
|
yield return null;
|
|
}
|
|
|
|
HidePreloadedMainSceneRoots();
|
|
_mainScenePreloadReady = true;
|
|
}
|
|
|
|
private void HandleLightWarningNextClicked()
|
|
{
|
|
if (_isTransitioning)
|
|
{
|
|
return;
|
|
}
|
|
|
|
float staySeconds = Time.realtimeSinceStartup - _lightWarningShownAtRealtime;
|
|
float remainSeconds = Mathf.Max(0f, LightWarningMinimumSeconds - staySeconds);
|
|
bool hasRead = lw_uhaveRead != null && lw_uhaveRead.isOn;
|
|
|
|
if (!hasRead || remainSeconds > 0f)
|
|
{
|
|
if (!hasRead && remainSeconds > 0f)
|
|
{
|
|
gNotice.error.display($"您必须知悉相关风险,还需停留{Mathf.CeilToInt(remainSeconds)}秒后才可进入");
|
|
}
|
|
else if (!hasRead)
|
|
{
|
|
gNotice.error.display("您必须知悉相关风险");
|
|
}
|
|
else
|
|
{
|
|
gNotice.error.display($"还需停留{Mathf.CeilToInt(remainSeconds)}秒后才可进入");
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
_hasAcceptedLightWarning = true;
|
|
PlayerPrefs.SetInt(LightWarningAcceptedPrefKey, 1);
|
|
PlayerPrefs.Save();
|
|
|
|
TransitionCanvasGroup(lightWarningObj, lightWarningCG, false, () =>
|
|
{
|
|
BeginPreloadMainScene();
|
|
TransitionCanvasGroup(uInfoEulaObj, uInfoEulaCG, true, null);
|
|
});
|
|
}
|
|
|
|
private void HandleLightWarningQuitClicked()
|
|
{
|
|
MarkPolicyRejectedAndQuit();
|
|
}
|
|
|
|
private void HandleUserInfoNextClicked()
|
|
{
|
|
if (_isTransitioning)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (!HasScrolledToBottom())
|
|
{
|
|
gNotice.error.display("必须完整阅读");
|
|
return;
|
|
}
|
|
|
|
if (uie_uhaveRead == null || !uie_uhaveRead.isOn)
|
|
{
|
|
gNotice.error.display("请勾选“我已知晓”");
|
|
return;
|
|
}
|
|
|
|
bool agreeRanking = uie_agreeRanking != null && uie_agreeRanking.isOn;
|
|
_hasAcceptedUserInfoEula = true;
|
|
_hasCompletedFirstLaunch = true;
|
|
PlayerPrefs.SetInt(UserInfoAcceptedPrefKey, 1);
|
|
PlayerPrefs.SetInt(FirstLaunchCompletedPrefKey, 1);
|
|
PlayerPrefs.SetInt(RankingConsentPrefKey, agreeRanking ? 1 : 0);
|
|
PlayerPrefs.Save();
|
|
|
|
TransitionCanvasGroup(uInfoEulaObj, uInfoEulaCG, false, ActivateMainScene);
|
|
}
|
|
|
|
private void HandleUserInfoQuitClicked()
|
|
{
|
|
MarkPolicyRejectedAndQuit();
|
|
}
|
|
|
|
private static void MarkPolicyRejectedAndQuit()
|
|
{
|
|
#if UNITY_EDITOR
|
|
UnityEditor.EditorApplication.isPlaying = false;
|
|
#else
|
|
Application.Quit();
|
|
#endif
|
|
}
|
|
|
|
private void ActivateMainScene()
|
|
{
|
|
if (_mainScenePreloadReady)
|
|
{
|
|
if (!gTransition.Run(ActivatePreloadedMainSceneRoutineWithoutFade()))
|
|
{
|
|
StartCoroutine(ActivatePreloadedMainSceneRoutineWithoutFade());
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (!gTransition.LoadScene(MainSceneName, LoadSceneMode.Single))
|
|
{
|
|
SceneManager.LoadScene(MainSceneName, LoadSceneMode.Single);
|
|
}
|
|
}
|
|
|
|
private System.Collections.IEnumerator ActivatePreloadedMainSceneRoutineWithoutFade()
|
|
{
|
|
Scene sourceScene = gameObject.scene;
|
|
if (_mainScenePreloadOperation == null)
|
|
{
|
|
if (!gTransition.LoadScene(MainSceneName, LoadSceneMode.Single))
|
|
{
|
|
SceneManager.LoadScene(MainSceneName, LoadSceneMode.Single);
|
|
}
|
|
yield break;
|
|
}
|
|
|
|
_mainScenePreloadOperation.allowSceneActivation = true;
|
|
while (!_mainScenePreloadOperation.isDone)
|
|
{
|
|
yield return null;
|
|
}
|
|
|
|
RestorePreloadedMainSceneRoots();
|
|
Scene mainScene = SceneManager.GetSceneByName(MainSceneName);
|
|
if (mainScene.isLoaded)
|
|
{
|
|
SceneManager.SetActiveScene(mainScene);
|
|
}
|
|
|
|
if (sourceScene.IsValid() && sourceScene.isLoaded && sourceScene.name == "beforeEverything")
|
|
{
|
|
yield return SceneManager.UnloadSceneAsync(sourceScene);
|
|
}
|
|
|
|
_mainScenePreloadOperation = null;
|
|
_mainScenePreloadReady = false;
|
|
}
|
|
|
|
private void HidePreloadedMainSceneRoots()
|
|
{
|
|
_hiddenMainSceneRoots.Clear();
|
|
|
|
Scene mainScene = SceneManager.GetSceneByName(MainSceneName);
|
|
if (!mainScene.IsValid() || !mainScene.isLoaded)
|
|
{
|
|
return;
|
|
}
|
|
|
|
List<GameObject> roots = new List<GameObject>();
|
|
mainScene.GetRootGameObjects(roots);
|
|
for (int i = 0; i < roots.Count; i++)
|
|
{
|
|
GameObject root = roots[i];
|
|
if (root == null || !root.activeSelf)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
_hiddenMainSceneRoots.Add(root);
|
|
root.SetActive(false);
|
|
}
|
|
}
|
|
|
|
private void RestorePreloadedMainSceneRoots()
|
|
{
|
|
for (int i = 0; i < _hiddenMainSceneRoots.Count; i++)
|
|
{
|
|
GameObject root = _hiddenMainSceneRoots[i];
|
|
if (root != null)
|
|
{
|
|
root.SetActive(true);
|
|
}
|
|
}
|
|
|
|
_hiddenMainSceneRoots.Clear();
|
|
}
|
|
|
|
private bool HasScrolledToBottom()
|
|
{
|
|
if (uie_scrollRect == null)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
if (!uie_scrollRect.vertical)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
return uie_scrollRect.verticalNormalizedPosition <= RequiredScrollReadThreshold;
|
|
}
|
|
|
|
private void TransitionCanvasGroup(GameObject targetObj, CanvasGroup targetGroup, bool show, TweenCallback onComplete)
|
|
{
|
|
if (targetObj == null || targetGroup == null)
|
|
{
|
|
onComplete?.Invoke();
|
|
return;
|
|
}
|
|
|
|
_isTransitioning = true;
|
|
|
|
if (show)
|
|
{
|
|
targetObj.SetActive(true);
|
|
targetGroup.alpha = 0f;
|
|
targetGroup.interactable = false;
|
|
targetGroup.blocksRaycasts = false;
|
|
}
|
|
|
|
Tween tween = targetGroup
|
|
.DOFade(show ? 1f : 0f, FadeDuration)
|
|
.SetUpdate(true)
|
|
.OnComplete(() =>
|
|
{
|
|
SetupCanvasGroup(targetGroup, show);
|
|
if (!show)
|
|
{
|
|
targetObj.SetActive(false);
|
|
}
|
|
|
|
_isTransitioning = false;
|
|
onComplete?.Invoke();
|
|
});
|
|
|
|
if (ReferenceEquals(targetGroup, lightWarningCG))
|
|
{
|
|
_lightWarningTween?.Kill();
|
|
_lightWarningTween = tween;
|
|
}
|
|
else if (ReferenceEquals(targetGroup, uInfoEulaCG))
|
|
{
|
|
_userInfoTween?.Kill();
|
|
_userInfoTween = tween;
|
|
}
|
|
}
|
|
|
|
private static void SetupCanvasGroup(CanvasGroup group, bool visible)
|
|
{
|
|
if (group == null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
group.alpha = visible ? 1f : 0f;
|
|
group.interactable = visible;
|
|
group.blocksRaycasts = visible;
|
|
}
|
|
|
|
private void AutoAssignReferences()
|
|
{
|
|
if (lightWarningObj == null && lightWarningCG != null)
|
|
{
|
|
lightWarningObj = lightWarningCG.gameObject;
|
|
}
|
|
|
|
if (uInfoEulaObj == null && uInfoEulaCG != null)
|
|
{
|
|
uInfoEulaObj = uInfoEulaCG.gameObject;
|
|
}
|
|
|
|
if (lightWarningObj == null)
|
|
{
|
|
lightWarningObj = FindSceneObject("illnessWarnings");
|
|
}
|
|
|
|
if (uInfoEulaObj == null)
|
|
{
|
|
uInfoEulaObj = FindSceneObject("userDataProcessing");
|
|
}
|
|
|
|
if (lightWarningCG == null && lightWarningObj != null)
|
|
{
|
|
lightWarningCG = lightWarningObj.GetComponent<CanvasGroup>();
|
|
}
|
|
|
|
if (uInfoEulaCG == null && uInfoEulaObj != null)
|
|
{
|
|
uInfoEulaCG = uInfoEulaObj.GetComponent<CanvasGroup>();
|
|
}
|
|
|
|
if (lw_uhaveRead == null && lightWarningObj != null)
|
|
{
|
|
lw_uhaveRead = FindComponentInChildrenByName<Toggle>(lightWarningObj.transform, "uread");
|
|
}
|
|
|
|
if (lw_next == null && lightWarningObj != null)
|
|
{
|
|
lw_next = FindComponentInChildrenByName<Button>(lightWarningObj.transform, "enter");
|
|
}
|
|
|
|
if (lw_quit == null && lightWarningObj != null)
|
|
{
|
|
lw_quit = FindComponentInChildrenByName<Button>(lightWarningObj.transform, "quit");
|
|
}
|
|
|
|
if (uie_uhaveRead == null && uInfoEulaObj != null)
|
|
{
|
|
uie_uhaveRead = FindComponentInChildrenByName<Toggle>(uInfoEulaObj.transform, "uread");
|
|
}
|
|
|
|
if (uie_agreeRanking == null && uInfoEulaObj != null)
|
|
{
|
|
uie_agreeRanking = FindComponentInChildrenByName<Toggle>(uInfoEulaObj.transform, "joinRankingList");
|
|
}
|
|
|
|
if (uie_next == null && uInfoEulaObj != null)
|
|
{
|
|
uie_next = FindComponentInChildrenByName<Button>(uInfoEulaObj.transform, "enter");
|
|
}
|
|
|
|
if (uie_quit == null && uInfoEulaObj != null)
|
|
{
|
|
uie_quit = FindComponentInChildrenByName<Button>(uInfoEulaObj.transform, "quit");
|
|
}
|
|
|
|
if (uie_scrollRect == null && uInfoEulaObj != null)
|
|
{
|
|
uie_scrollRect = FindComponentInChildrenByName<ScrollRect>(uInfoEulaObj.transform, "sv");
|
|
if (uie_scrollRect == null)
|
|
{
|
|
uie_scrollRect = uInfoEulaObj.GetComponentInChildren<ScrollRect>(true);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static GameObject FindSceneObject(string objectName)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(objectName))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
GameObject[] allObjects = Resources.FindObjectsOfTypeAll<GameObject>();
|
|
for (int i = 0; i < allObjects.Length; i++)
|
|
{
|
|
GameObject go = allObjects[i];
|
|
if (go == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (!go.scene.IsValid() || !go.scene.isLoaded)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (go.name == objectName)
|
|
{
|
|
return go;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private static T FindComponentInChildrenByName<T>(Transform root, string objectName) where T : Component
|
|
{
|
|
if (root == null || string.IsNullOrWhiteSpace(objectName))
|
|
{
|
|
return null;
|
|
}
|
|
|
|
T[] components = root.GetComponentsInChildren<T>(true);
|
|
for (int i = 0; i < components.Length; i++)
|
|
{
|
|
T component = components[i];
|
|
if (component != null && component.gameObject.name == objectName)
|
|
{
|
|
return component;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|