Commit 7e083792 authored by saad's avatar saad

add basemanager class

parent 0a10504d
fileFormatVersion: 2
guid: 745e9c17df962b24a80a69d5da8e5d38
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: d308d9efe86ef6242a75802e1f37de49
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: e5036f96e3c15ea49b96f7ee989dd3c1
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 9e9f7f46a1ba34c338eb95b193ae1327
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: b18b93d4b5d00384ba417df18aeac5a3
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
fileFormatVersion: 2
guid: 92a80e6f6cd90464b8f87b98fc72999a
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
......@@ -211,8 +211,7 @@ Transform:
m_LocalPosition: {x: 0, y: 1, z: -10}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 1399870137}
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!114 &603037699
......@@ -517,76 +516,6 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1001 &1399870136
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 603037698}
m_Modifications:
- target: {fileID: 5575199186091687107, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: ShapeModule.radius.value
value: 40
objectReference: {fileID: 0}
- target: {fileID: 5575199186091687107, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: InitialModule.startSize.scalar
value: 1
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalPosition.x
value: -0.08737
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalPosition.y
value: 10.40678
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalPosition.z
value: 108
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalRotation.w
value: 0.7071068
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalRotation.x
value: -0.7071068
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: -90
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8015466945648444578, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
propertyPath: m_Name
value: DotFloating
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
--- !u!4 &1399870137 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 6955428004947038011, guid: 81b128416c1c2356c8d645340d865e65, type: 3}
m_PrefabInstance: {fileID: 1399870136}
m_PrefabAsset: {fileID: 0}
--- !u!1 &1878716305
GameObject:
m_ObjectHideFlags: 0
......
......@@ -23,29 +23,19 @@ namespace com.al_arcade.cs
Complete,
}
public class CsGameManager : MonoBehaviour, IChallengeGame
public class CsGameManager : BaseGameManager, IChallengeGame
{
public static CsGameManager Instance { get; private set; }
[Header("Settings")]
[SerializeField]
private float sentenceShowDelay = 0.5f;
[SerializeField]
private float feedbackDuration = 1.5f;
[SerializeField]
private float wordClickCooldown = 0.3f;
[SerializeField] private float sentenceShowDelay = 0.5f;
[SerializeField] private float feedbackDuration = 1.5f;
[SerializeField] private float wordClickCooldown = 0.3f;
[Header("Arc Settings")]
[SerializeField]
private float arcRadius = 15f;
[SerializeField]
private float arcSpanDegrees = 120f;
[SerializeField]
private float wordGap = 0.2f;
[SerializeField] private float arcRadius = 15f;
[SerializeField] private float arcSpanDegrees = 120f;
[SerializeField] private float wordGap = 0.2f;
[Header("References")]
public CsBotController bot;
......@@ -54,105 +44,126 @@ namespace com.al_arcade.cs
private CsGameState _state = CsGameState.Idle;
private CsQuestion[] _questions;
private int _currentIndex;
private int _score,
_streak,
_correctCount,
_wrongCount,
_wrongClicks;
private int _wrongClicks;
private List<CsWordButton> _wordButtons = new();
private CsWordButton _wrongWordButton;
private bool _wordClickLocked;
[Header("Events")]
public UnityEvent onGameStart;
public UnityEvent<bool> onAnswerGiven;
[Header("CS Events")]
public UnityEvent<int> onGameComplete;
private Action<bool> _onOptionDropped;
private float _timeLeft;
private bool isTicking;
private DateTime gameStartTime;
// if it reaches 5, you win the game;
int _deltaChangeInSize;
bool showHint = true;
private bool _isTicking;
private int _deltaChangeInSize;
private bool _showHint = true;
CinemachineTargetGroup _targetGroup;
CinemachineGroupFraming _groupFraming;
public event Action<bool, float> OnGameCompleted;
private void Awake()
// ─── Singleton ────────────────────────────────────────────────────────
protected override void Awake()
{
if (Instance != null && Instance != this)
{
Destroy(gameObject);
return;
}
if (Instance != null && Instance != this) { Destroy(gameObject); return; }
Instance = this;
base.Awake();
_targetGroup = FindFirstObjectByType<CinemachineTargetGroup>();
_groupFraming = FindFirstObjectByType<CinemachineGroupFraming>();
}
private void Update()
// ─── BaseGameManager implementation ──────────────────────────────────
protected override string GameTypeKey => "cs";
protected override IEnumerator FetchQuestions(Action<string> onError)
{
if (_state == CsGameState.WaitingForWordClick || _state == CsGameState.WaitingForDrop)
{
_timeLeft -= Time.deltaTime;
if (_timeLeft <= 0)
{
_timeLeft = 0;
_state = CsGameState.Complete;
StartCoroutine(LoseSequence());
}
var session = SSGameSession.EnsureInstance();
var api = SSApiManager.EnsureInstance();
if (_timeLeft < 4f && !isTicking)
{
isTicking = true;
var audio = SSAudioManager.Instance;
audio.Tick(true);
}
else if (_timeLeft >= 4f && isTicking)
{
isTicking = false;
var audio = SSAudioManager.Instance;
audio.Tick(false);
}
if (uiManager != null && uiManager.isMusicOn)
SSAudioManager.EnsureInstance().PlayMusic();
uiManager.SetTimer(_timeLeft);
}
yield return api.FetchCs(
session.buildType, session.classCode,
session.questionCount, session.gradeId,
qs => _questions = qs,
err => onError(err)
);
}
protected override bool HasValidQuestions() =>
_questions != null && _questions.Length > 0;
void UpdateTimer(int delta)
protected override void OnShowLoading() =>
uiManager?.ShowLoading("جاري تحميل الأسئلة...");
protected override void OnHideLoading() =>
uiManager?.HideLoading();
protected override void OnShowError(string message)
{
_timeLeft += delta;
_timeLeft = Mathf.Clamp(_timeLeft, 0, CsPrefabBuilder.Instance.startTime);
uiManager?.ShowError(message);
_state = CsGameState.Idle;
}
protected override IEnumerator OnBeforeBeginGameplay()
{
if (uiManager != null)
yield return uiManager.ShowCountDown();
}
if (_timeLeft < 4f && !isTicking)
protected override void OnTimerTick(float timeLeft)
{
// Ticking sound when under 4 seconds
if (timeLeft < 4f && !_isTicking)
{
isTicking = true;
var audio = SSAudioManager.Instance;
audio.Tick(true);
_isTicking = true;
SSAudioManager.Instance?.Tick(true);
}
else if (_timeLeft >= 4f && isTicking)
else if (timeLeft >= 4f && _isTicking)
{
isTicking = false;
var audio = SSAudioManager.Instance;
audio.Tick(false);
_isTicking = false;
SSAudioManager.Instance?.Tick(false);
}
uiManager.UpdateTimer(_timeLeft, delta > 0);
uiManager?.SetTimer(timeLeft);
}
protected override IEnumerator OnTimeUp()
{
_state = CsGameState.Complete;
yield return LoseSequence();
}
protected override void BeginGameplay()
{
_currentIndex = _score = _streak = _correctCount = _wrongCount = 0;
_deltaChangeInSize = 0;
_timeLeft = CsPrefabBuilder.Instance.startTime; // CS uses its own start time
_timerRunning = true;
if (uiManager != null)
{
uiManager.ShowGameUI();
uiManager.SetScore(0);
uiManager.SetProgress(0, _questions.Length);
}
public void StartGame() => StartCoroutine(StartGameRoutine());
onGameStart?.Invoke();
StartCoroutine(QuestionLoop());
}
// ─── Update: CS also needs the state guard from original ─────────────
protected override void Update()
{
// Only tick timer when waiting for player input
if (_state == CsGameState.WaitingForWordClick || _state == CsGameState.WaitingForDrop)
base.Update();
}
// ─── Public API ───────────────────────────────────────────────────────
public void StartWithQuestions(CsQuestion[] questions)
{
_questions = questions;
......@@ -161,51 +172,38 @@ namespace com.al_arcade.cs
public void ResetGame()
{
StopAllCoroutines();
ResetBaseState();
_deltaChangeInSize = 0;
_state = CsGameState.Idle;
_currentIndex = _score = _streak = _correctCount = _wrongCount = 0;
_isTicking = false;
ClearWordButtons();
if (uiManager != null)
uiManager.ResetUI();
if (bot != null)
bot.ResetBot();
uiManager?.ResetUI();
bot?.ResetBot();
}
public void OnWordClicked(CsWordButton wordButton)
{
if (_state != CsGameState.WaitingForWordClick)
return;
if (_wordClickLocked)
return;
if (_state != CsGameState.WaitingForWordClick) return;
if (_wordClickLocked) return;
if (wordButton.IsWrong)
{
_wrongWordButton = wordButton;
wordButton.Highlight(true);
var audio = SSAudioManager.Instance;
if (audio != null)
audio.PlayCorrectChoice();
var particles = SSParticleManager.Instance;
if (particles != null)
particles.PlaySparks(wordButton.transform.position, SSColorPalette.Accent);
SSAudioManager.Instance?.PlayCorrectChoice();
SSParticleManager.Instance?.PlaySparks(wordButton.transform.position, SSColorPalette.Accent);
_state = CsGameState.WaitingForDrop;
ShowOptions();
}
else
{
UpdateTimer(-CsPrefabBuilder.Instance.wrongAnswerPenaltyTime);
AdjustTimer(-CsPrefabBuilder.Instance.wrongAnswerPenaltyTime);
_wrongClicks++;
_wordClickLocked = true;
wordButton.ShakeWrong();
var audio = SSAudioManager.Instance;
if (audio != null)
audio.PlayWrongBeep();
SSAudioManager.Instance?.PlayWrongBeep();
StartCoroutine(UnlockAfterCooldown());
}
}
......@@ -215,78 +213,34 @@ namespace com.al_arcade.cs
_onOptionDropped?.Invoke(isCorrectOption);
}
private IEnumerator StartGameRoutine()
{
_state = CsGameState.Loading;
if (uiManager != null)
uiManager.ShowLoading("جاري تحميل الأسئلة...");
var session = SSGameSession.EnsureInstance();
var api = SSApiManager.EnsureInstance();
if (uiManager.isMusicOn)
SSAudioManager.EnsureInstance().PlayMusic();
string error = null;
yield return api.FetchCs(
session.buildType,
session.classCode,
session.questionCount,
session.gradeId,
qs => _questions = qs,
err => error = err
);
if (error != null || _questions == null || _questions.Length == 0)
{
if (uiManager != null)
uiManager.ShowError(error ?? "لا توجد أسئلة");
_state = CsGameState.Idle;
yield break;
}
if (uiManager != null)
uiManager.HideLoading();
yield return uiManager.ShowCountDown();
gameStartTime = DateTime.Now;
BeginGameplay();
}
private void BeginGameplay()
// ─── Timer helpers ────────────────────────────────────────────────────
private void AdjustTimer(float delta)
{
_currentIndex = _score = _streak = _correctCount = _wrongCount = 0;
_timeLeft = CsPrefabBuilder.Instance.startTime;
UpdateTimerBy(delta);
_timeLeft = Mathf.Clamp(_timeLeft, 0, CsPrefabBuilder.Instance.startTime);
if (uiManager != null)
{
uiManager.ShowGameUI();
uiManager.SetScore(0);
uiManager.SetProgress(0, _questions.Length);
}
// Re-check tick state after adjustment
if (_timeLeft < 4f && !_isTicking)
{ _isTicking = true; SSAudioManager.Instance?.Tick(true); }
else if (_timeLeft >= 4f && _isTicking)
{ _isTicking = false; SSAudioManager.Instance?.Tick(false); }
onGameStart?.Invoke();
StartCoroutine(QuestionLoop());
uiManager?.UpdateTimer(_timeLeft, delta > 0);
}
// ─── Game loop ────────────────────────────────────────────────────────
private IEnumerator QuestionLoop()
{
while (_currentIndex < _questions.Length)
{
if (_state == CsGameState.Complete)
yield break;
if (_state == CsGameState.Complete) yield break;
yield return PresentQuestion(_questions[_currentIndex]);
_currentIndex++;
if (uiManager != null)
uiManager.SetProgress(_currentIndex, _questions.Length);
uiManager?.SetProgress(_currentIndex, _questions.Length);
}
if (_state == CsGameState.Complete)
yield break;
if (_state == CsGameState.Complete) yield break;
_state = CsGameState.Complete;
yield return LoseSequence();
......@@ -298,9 +252,7 @@ namespace com.al_arcade.cs
_wrongClicks = 0;
_wrongWordButton = null;
if (bot != null)
bot.ShowSpeechBubble();
bot?.ShowSpeechBubble();
ClearWordButtons();
yield return new WaitForSeconds(sentenceShowDelay);
......@@ -308,8 +260,7 @@ namespace com.al_arcade.cs
yield return new WaitForSeconds(1.3f);
_state = CsGameState.WaitingForWordClick;
if (showHint)
uiManager.ShowHint("انقر على الكلمة الخاطئة في الجملة");
if (_showHint) uiManager?.ShowHint("انقر على الكلمة الخاطئة في الجملة");
bool questionComplete = false;
_onOptionDropped = null;
......@@ -321,8 +272,7 @@ namespace com.al_arcade.cs
bool? result = null;
_onOptionDropped = correct => result = correct;
while (result == null)
yield return null;
while (result == null) yield return null;
if (result == true)
{
......@@ -340,8 +290,7 @@ namespace com.al_arcade.cs
}
}
if (uiManager != null)
uiManager.HideOptions();
uiManager?.HideOptions();
yield return new WaitForSeconds(0.5f);
}
......@@ -351,12 +300,10 @@ namespace com.al_arcade.cs
_correctCount++;
_streak++;
_deltaChangeInSize++;
UpdateTimer(CsPrefabBuilder.Instance.correctAnswerBonusTime);
AdjustTimer(CsPrefabBuilder.Instance.correctAnswerBonusTime);
int points = Mathf.Max(100 - _wrongClicks * 15, 25);
if (_streak >= 3)
points += (_streak - 2) * 25;
if (_streak >= 3) points += (_streak - 2) * 25;
_score += points;
if (_wrongWordButton != null)
......@@ -372,26 +319,20 @@ namespace com.al_arcade.cs
SSAudioManager.Instance.PlayCorrectDrag();
yield return new WaitForSeconds(0.4f);
if (bot != null)
bot.PlayHappy();
uiManager.HideHint();
bot?.PlayHappy();
uiManager?.HideHint();
var particles = SSParticleManager.Instance;
if (particles != null && _wrongWordButton != null)
particles.PlayCorrectBurst(_wrongWordButton.transform.position);
uiManager.TickPoints(_deltaChangeInSize);
if (SSParticleManager.Instance != null && _wrongWordButton != null)
SSParticleManager.Instance.PlayCorrectBurst(_wrongWordButton.transform.position);
uiManager?.TickPoints(_deltaChangeInSize);
onAnswerGiven?.Invoke(true);
yield return new WaitForSeconds(0.8f);
if (_deltaChangeInSize == 5)
{
// Win
_state = CsGameState.Complete;
yield return VictorySequence();
yield break;
}
}
......@@ -399,12 +340,9 @@ namespace com.al_arcade.cs
{
_wrongClicks++;
_streak = 0;
_deltaChangeInSize = Mathf.Max(0, _deltaChangeInSize - 1);
_deltaChangeInSize--;
if (_deltaChangeInSize < 0)
_deltaChangeInSize = 0;
UpdateTimer(-CsPrefabBuilder.Instance.wrongAnswerPenaltyTime);
AdjustTimer(-CsPrefabBuilder.Instance.wrongAnswerPenaltyTime);
if (uiManager != null)
{
......@@ -415,8 +353,7 @@ namespace com.al_arcade.cs
SSAudioManager.Instance.PlayWrong();
yield return new WaitForSeconds(0.4f);
if (bot != null)
bot.PlaySad();
bot?.PlaySad();
if (Camera.main != null)
{
......@@ -424,30 +361,60 @@ namespace com.al_arcade.cs
Camera.main.transform.DOShakePosition(0.3f, 0.15f, 10).SetId("csShake");
}
uiManager.TickPoints(_deltaChangeInSize);
uiManager?.TickPoints(_deltaChangeInSize);
yield return new WaitForSeconds(0.8f);
}
private void SpawnWords(CsQuestion question)
// ─── End sequences ────────────────────────────────────────────────────
private IEnumerator VictorySequence()
{
var audio = SSAudioManager.Instance;
audio.PlayVictory();
StartCoroutine(DelayedAction(0.7f, () => audio.PlayCheer())); // shared helper
SSParticleManager.Instance?.PlayScreenConfetti();
bot?.PlayVictoryDance();
yield return new WaitForSeconds(1f);
uiManager?.ShowResults(_score, _correctCount, _wrongClicks, _questions.Length, _streak);
onGameComplete?.Invoke(_score);
SSAudioManager.Instance.StopMusic();
ClearWordButtons();
RecordGameHistory(); // shared helper
OnGameCompleted?.Invoke(true, _timeLeft);
yield return new WaitForSeconds(5f);
SceneManager.LoadScene("App");
}
private IEnumerator LoseSequence()
{
var fullQuestion = question.words != null
? string.Join(" ", Array.ConvertAll(question.words, w => w.word_text))
: "";
SSAudioManager.Instance.PlayDefeat();
uiManager?.ShowResults(_score, _correctCount, _wrongClicks, _questions.Length, _streak, false);
if (question.words == null || question.words.Length == 0)
return;
onGameComplete?.Invoke(_score);
SSAudioManager.Instance.StopMusic();
ClearWordButtons();
OnGameCompleted?.Invoke(false, _timeLeft);
yield return null;
}
// ─── Word / UI helpers ────────────────────────────────────────────────
private void SpawnWords(CsQuestion question)
{
if (question.words == null || question.words.Length == 0) return;
ClearWordButtons();
_groupFraming.CenterOffset = new Vector2(0f, -0.1f);
// Spawn Full Sentence
var sentenceObj = new GameObject("FullQuestion");
sentenceObj.transform.SetParent(wordContainer);
var sentenceWb = sentenceObj.AddComponent<CsSentence>();
sentenceWb.Initialize(question);
return;
}
private void ShowOptions()
......@@ -456,10 +423,10 @@ namespace com.al_arcade.cs
if (uiManager != null)
{
uiManager.ShowOptions(question.options, _wrongWordButton);
if (showHint)
if (_showHint)
{
uiManager.ShowHint("اسحب الإجابة الصحيحة إلى الكلمة الخاطئة");
showHint = false;
_showHint = false;
}
}
}
......@@ -468,10 +435,8 @@ namespace com.al_arcade.cs
{
foreach (Transform child in wordContainer)
{
child.transform.DOScale(Vector3.zero, 0.3f).SetEase(Ease.InBack).OnComplete(() =>
{
Destroy(child.gameObject);
});
child.transform.DOScale(Vector3.zero, 0.3f).SetEase(Ease.InBack)
.OnComplete(() => Destroy(child.gameObject));
}
if (_targetGroup.Targets.Count > 2)
......@@ -490,75 +455,7 @@ namespace com.al_arcade.cs
_wordClickLocked = false;
}
private IEnumerator VictorySequence()
{
var audio = SSAudioManager.Instance;
audio.PlayVictory();
StartCoroutine(DelayedAction(0.7f, () =>
{
audio.PlayCheer();
}));
var particles = SSParticleManager.Instance;
if (particles != null)
particles.PlayScreenConfetti();
if (bot != null)
bot.PlayVictoryDance();
yield return new WaitForSeconds(1f);
if (uiManager != null)
uiManager.ShowResults(
_score,
_correctCount,
_wrongClicks,
_questions.Length,
_streak
);
onGameComplete?.Invoke(_score);
SSAudioManager.Instance.StopMusic();
ClearWordButtons();
GameHistoryService.Instance.AddGame("cs", _score, gameStartTime, DateTime.Now);
OnGameCompleted?.Invoke(true, _timeLeft);
yield return new WaitForSeconds(5f);
SceneManager.LoadScene("App");
}
private IEnumerator DelayedAction(float delay, Action action)
{
yield return new WaitForSeconds(delay);
action?.Invoke();
}
private IEnumerator LoseSequence()
{
var audio = SSAudioManager.Instance;
audio.PlayDefeat();
if (uiManager != null)
uiManager.ShowResults(
_score,
_correctCount,
_wrongClicks,
_questions.Length,
_streak,
false
);
onGameComplete?.Invoke(_score);
SSAudioManager.Instance.StopMusic();
ClearWordButtons();
OnGameCompleted?.Invoke(false, _timeLeft);
yield return null;
}
public int Score => _score;
// ─── Challenge mode ───────────────────────────────────────────────────
private ChallengeManager _challengeManager;
private bool _challengeChecked;
......@@ -575,5 +472,4 @@ namespace com.al_arcade.cs
}
}
}
}
}
\ No newline at end of file
using DG.Tweening;
using UnityEngine;
public class FutureCar : MonoBehaviour
{
[Header("Main Settings")]
[Tooltip("Check to float in place, uncheck to move back and forth.")]
public bool isFloatingInPlace = true;
[Header("Floating Options (Only used if checked above)")]
public float floatSpeed = 1f;
public float floatAmplitude = 0.5f;
[Header("Moving Options (Only used if unchecked above)")]
public float moveSpeed = 5f;
public float travelDistance = 20f;
public float rotationSpeed = 3f;
private Vector3 startPosition;
private Vector3 targetPosition;
private bool movingToTarget = true;
private float initialY;
void Start()
{
// Store the starting spot
startPosition = transform.position;
initialY = transform.position.y;
// Calculate the end of the patrol path based on the car's initial forward direction
targetPosition = startPosition + (transform.forward * travelDistance);
ApplyFloatingMotion();
}
// void Update()
// {
// if (isFloatingInPlace)
// {
// ApplyFloatingMotion();
// }
// else
// {
// ApplyPatrolMotion();
// }
// }
private void ApplyFloatingMotion()
{
var randomDelay = Random.Range(0f, 1f);
transform.DOMoveY(initialY + floatAmplitude, floatSpeed)
.SetEase(Ease.InOutSine)
.SetDelay(randomDelay)
.SetLoops(-1, LoopType.Yoyo);
}
private void ApplyPatrolMotion()
{
// Determine which end of the line we are headed to
Vector3 destination = movingToTarget ? targetPosition : startPosition;
// 1. Move the car
transform.position = Vector3.MoveTowards(transform.position, destination, moveSpeed * Time.deltaTime);
// 2. Rotate the car to face the current destination
Vector3 direction = (destination - transform.position).normalized;
if (direction != Vector3.zero)
{
Quaternion lookRotation = Quaternion.LookRotation(direction);
transform.rotation = Quaternion.Slerp(transform.rotation, lookRotation, Time.deltaTime * rotationSpeed);
}
// 3. If we are very close to the destination, flip the boolean to go the other way
if (Vector3.Distance(transform.position, destination) < 0.1f)
{
movingToTarget = !movingToTarget;
}
}
// This helps you see the path in the Scene View without pressing play
private void OnDrawGizmosSelected()
{
if (!isFloatingInPlace)
{
Gizmos.color = Color.cyan;
Vector3 endPoint = Application.isPlaying ? targetPosition : transform.position + (transform.forward * travelDistance);
Vector3 startPoint = Application.isPlaying ? startPosition : transform.position;
Gizmos.DrawLine(startPoint, endPoint);
Gizmos.DrawWireSphere(endPoint, 0.5f);
}
}
}
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Events;
namespace com.al_arcade.shared
{
/// <summary>
/// Abstract base class for all game managers (TF, MCQ, CS, ...).
/// Handles: singleton wiring, score/streak/counts, timer, API loading
/// skeleton, game history recording, and shared UnityEvents.
///
/// Subclasses MUST:
/// - Declare their own static Instance property
/// - Call base.Awake() (or replicate the guard) in their own Awake()
/// - Implement all abstract members
/// </summary>
public abstract class BaseGameManager : MonoBehaviour
{
// ─── Timer ───────────────────────────────────────────────────────────
[Header("Timer Settings")]
[SerializeField] protected float maxTimePerQuestion = 30f;
protected float _timeLeft;
protected bool _timerRunning;
// ─── Shared runtime state ────────────────────────────────────────────
protected int _score;
protected int _streak;
protected int _correctCount;
protected int _wrongCount;
protected int _currentIndex;
protected int _totalAsked;
protected DateTime gameStartTime;
// ─── Shared UnityEvents ──────────────────────────────────────────────
[Header("Base Events")]
public UnityEvent onGameStart;
public UnityEvent<bool> onAnswerGiven;
// ─────────────────────────────────────────────────────────────────────
// Abstract API – every subclass must implement these
// ─────────────────────────────────────────────────────────────────────
/// <summary>
/// Fetch questions from the API and store them internally.
/// Yield inside to wait for the network call.
/// Set 'error' to a non-null string if something goes wrong.
/// </summary>
protected abstract IEnumerator FetchQuestions(Action<string> onError);
/// <summary>
/// Returns true if the fetch result is considered valid
/// (e.g. questions array is non-null and non-empty).
/// </summary>
protected abstract bool HasValidQuestions();
/// <summary>Called after questions load successfully — start your game loop here.</summary>
protected abstract void BeginGameplay();
/// <summary>Called when the countdown timer hits zero.</summary>
protected abstract IEnumerator OnTimeUp();
/// <summary>
/// The game-type key passed to GameHistoryService (e.g. "tf", "mcq", "cs").
/// </summary>
protected abstract string GameTypeKey { get; }
// ─────────────────────────────────────────────────────────────────────
// Singleton wiring (subclass keeps its own typed static Instance)
// ─────────────────────────────────────────────────────────────────────
protected virtual void Awake()
{
// Subclasses that need extra Awake logic should call base.Awake()
// THEN do their own work.
}
// ─────────────────────────────────────────────────────────────────────
// Timer
// ─────────────────────────────────────────────────────────────────────
protected virtual void Update()
{
if (!_timerRunning) return;
_timeLeft -= Time.deltaTime;
OnTimerTick(_timeLeft);
if (_timeLeft <= 0f)
{
_timeLeft = 0f;
_timerRunning = false;
StartCoroutine(OnTimeUp());
}
}
/// <summary>
/// Called every frame while the timer is running.
/// Override to push the value to your UI manager.
/// </summary>
protected virtual void OnTimerTick(float timeLeft) { }
/// <summary>Add or subtract time and clamp to [0, maxTimePerQuestion].</summary>
protected void UpdateTimerBy(float delta)
{
_timeLeft = Mathf.Clamp(_timeLeft + delta, 0f, maxTimePerQuestion);
}
/// <summary>Ratio 0–1 of time remaining (useful for timer bars).</summary>
public float GetCurrentTimeRatio()
{
if (maxTimePerQuestion <= 0f) return 0f;
return _timeLeft / maxTimePerQuestion;
}
// ─────────────────────────────────────────────────────────────────────
// Shared StartGame / loading skeleton
// ─────────────────────────────────────────────────────────────────────
/// <summary>
/// Starts the full loading + gameplay flow.
/// Call this from your UI "Start" button.
/// </summary>
public virtual void StartGame()
{
StartCoroutine(StartGameRoutine());
}
/// <summary>
/// Shared loading routine: show loader → fetch → handle error → begin.
/// Override OnBeforeBeginGameplay() to insert game-specific steps
/// (e.g. countdown animation) between loading and BeginGameplay().
/// </summary>
protected virtual IEnumerator StartGameRoutine()
{
OnShowLoading();
string error = null;
yield return FetchQuestions(err => error = err);
if (!HasValidQuestions() || error != null)
{
OnShowError(error ?? "لا توجد أسئلة");
yield break;
}
OnHideLoading();
yield return OnBeforeBeginGameplay();
gameStartTime = DateTime.Now;
_timeLeft = maxTimePerQuestion;
_timerRunning = true;
BeginGameplay();
}
/// <summary>Override to call uiManager.ShowLoading(...).</summary>
protected virtual void OnShowLoading() { }
/// <summary>Override to call uiManager.HideLoading().</summary>
protected virtual void OnHideLoading() { }
/// <summary>Override to call uiManager.ShowError(...).</summary>
protected virtual void OnShowError(string message) { }
/// <summary>
/// Hook between loading and BeginGameplay.
/// Use it for countdowns, intro animations, etc.
/// Base implementation does nothing.
/// </summary>
protected virtual IEnumerator OnBeforeBeginGameplay() { yield break; }
// ─────────────────────────────────────────────────────────────────────
// Shared score helpers
// ─────────────────────────────────────────────────────────────────────
/// <summary>
/// Standard streak-based score calculation used by TF and MCQ:
/// base 100 pts + 25 per streak step above the threshold.
/// </summary>
protected int CalculateStreakScore(int streakThreshold = 2)
{
return 100 + (_streak > streakThreshold ? (_streak - streakThreshold) * 25 : 0);
}
// ─────────────────────────────────────────────────────────────────────
// Game history
// ─────────────────────────────────────────────────────────────────────
/// <summary>
/// Records the completed session to GameHistoryService.
/// Call at the end of VictorySequence / GameOverSequence.
/// </summary>
protected void RecordGameHistory()
{
GameHistoryService.Instance.AddGame(GameTypeKey, _score, gameStartTime, DateTime.Now);
}
// ─────────────────────────────────────────────────────────────────────
// Shared reset helpers
// ─────────────────────────────────────────────────────────────────────
/// <summary>
/// Resets all shared counters and timer state.
/// Call at the start of ResetGame() in your subclass.
/// </summary>
protected void ResetBaseState()
{
StopAllCoroutines();
_score = _streak = _correctCount = _wrongCount = _currentIndex = _totalAsked = 0;
_timeLeft = 0f;
_timerRunning = false;
}
// ─────────────────────────────────────────────────────────────────────
// Utility
// ─────────────────────────────────────────────────────────────────────
/// <summary>Runs an action after a delay without blocking a coroutine.</summary>
protected IEnumerator DelayedAction(float delay, Action action)
{
yield return new WaitForSeconds(delay);
action?.Invoke();
}
// ─────────────────────────────────────────────────────────────────────
// Public read-only accessors (common across all games)
// ─────────────────────────────────────────────────────────────────────
public int Score => _score;
public int Streak => _streak;
public int CorrectCount => _correctCount;
public int WrongCount => _wrongCount;
public int CurrentQuestionIndex => _currentIndex;
}
}
fileFormatVersion: 2
guid: c7f3fdf6e62442c5485a9ff394896b54
\ No newline at end of file
guid: 42fbf78681728ed4d92e5b86342792b3
\ No newline at end of file
......@@ -6,13 +6,12 @@ using DG.Tweening;
namespace com.al_arcade.tf
{
using Microsoft.IdentityModel.Tokens;
using shared;
public enum TfGameState
{ Idle, Loading, Playing, Feedback, Complete, GameOver }
public class TfGameManager : MonoBehaviour
public class TfGameManager : BaseGameManager
{
public static TfGameManager Instance { get; private set; }
......@@ -20,6 +19,7 @@ namespace com.al_arcade.tf
[SerializeField] private int stepsToWin = 5;
[SerializeField] private float feedbackDuration = 1.2f;
[SerializeField] private float stepDistance = 3f;
[SerializeField] private float feedbackTime = 5f;
[Header("References")]
public TfHandController handController;
......@@ -29,108 +29,67 @@ namespace com.al_arcade.tf
private TfGameState _state = TfGameState.Idle;
private TfQuestion[] _questions;
private int _currentIndex, _progress, _score, _streak;
private int _correctCount, _wrongCount, _totalAsked;
private int _progress;
private bool _waitingForAnswer;
private int _pendingAnswer = -1;
private DateTime gameStartTime;
[Header("Events")]
public UnityEvent onGameStart;
public UnityEvent<bool> onAnswerGiven;
[Header("TF Events")]
public UnityEvent<int> onProgressChanged;
public UnityEvent onGameComplete;
public UnityEvent onGameOver;
// --- ADDED: Timer Settings ---
[SerializeField] private float maxTimePerQuestion = 30f;
[SerializeField] private float feedbackTime = 5;
private float _currentTime;
private bool _timerRunning;
public float GetCurrentTimeRatio()
{
if (maxTimePerQuestion <= 0f)
return 0f;
return _currentTime / maxTimePerQuestion;
}
private void Awake()
// ─── Singleton ────────────────────────────────────────────────────────
protected override void Awake()
{
if (Instance != null && Instance != this) { Destroy(gameObject); return; }
Instance = this;
base.Awake();
}
public void StartGame()
{
StartCoroutine(StartGameRoutine());
_currentTime = maxTimePerQuestion;
_timerRunning = true;
}
public void StartWithQuestions(TfQuestion[] questions)
{ _questions = questions; BeginGameplay(); }
public void SubmitAnswer(bool answer)
{
if (!_waitingForAnswer) return;
_waitingForAnswer = false;
_pendingAnswer = answer ? 1 : 0;
}
public void ResetGame()
{
StopAllCoroutines();
_state = TfGameState.Idle;
_currentIndex = _progress = _score = _streak = 0;
_correctCount = _wrongCount = _totalAsked = 0;
_questions = null;
_waitingForAnswer = false;
_pendingAnswer = -1;
_timerRunning = false;
_currentTime = 0f;
if (productionLine != null) productionLine.ResetLine();
if (questionScreen != null) questionScreen.Clear();
if (handController != null) handController.Reset();
if (uiManager != null) uiManager.ResetUI();
}
// ─── BaseGameManager implementation ──────────────────────────────────
protected override string GameTypeKey => "tf";
private IEnumerator StartGameRoutine()
protected override IEnumerator FetchQuestions(Action<string> onError)
{
_state = TfGameState.Loading;
if (uiManager != null) uiManager.ShowLoading("جاري تحميل الأسئلة...");
var session = SSGameSession.EnsureInstance();
var api = SSApiManager.EnsureInstance();
string error = null;
yield return api.FetchTf(
session.buildType, session.classCode,
session.questionCount, session.gradeId,
qs => _questions = qs,
err => error = err
err => onError(err)
);
}
if (error != null || _questions == null || _questions.Length == 0)
{
if (uiManager != null) uiManager.ShowError(error ?? "لا توجد أسئلة");
_state = TfGameState.Idle;
yield break;
}
protected override bool HasValidQuestions() =>
_questions != null && _questions.Length > 0;
if (uiManager != null) uiManager.HideLoading();
protected override void OnShowLoading() =>
uiManager?.ShowLoading("جاري تحميل الأسئلة...");
gameStartTime = DateTime.Now;
BeginGameplay();
protected override void OnHideLoading() =>
uiManager?.HideLoading();
protected override void OnShowError(string message)
{
uiManager?.ShowError(message);
_state = TfGameState.Idle;
}
protected override void OnTimerTick(float timeLeft) =>
uiManager?.SetTimer(timeLeft);
protected override IEnumerator OnTimeUp()
{
yield return HandleTimeUp();
}
private void BeginGameplay()
protected override void BeginGameplay()
{
_currentIndex = _progress = _score = _streak = 0;
_correctCount = _wrongCount = _totalAsked = 0;
_progress = 0;
// Reset base counters
_currentIndex = _score = _streak = _correctCount = _wrongCount = _totalAsked = 0;
_state = TfGameState.Playing;
if (uiManager != null)
......@@ -144,40 +103,40 @@ namespace com.al_arcade.tf
StartCoroutine(GameLoop());
}
private void Update()
// ─── Public API ───────────────────────────────────────────────────────
public void StartWithQuestions(TfQuestion[] questions)
{
if (!_timerRunning) return;
_currentTime -= Time.deltaTime;
if (uiManager != null)
uiManager.SetTimer(_currentTime);
if (_currentTime <= 0f)
{
_currentTime = 0f;
_timerRunning = false;
StartCoroutine(HandleTimeUp());
}
_questions = questions;
BeginGameplay();
}
private IEnumerator HandleTimeUp()
{
Debug.Log("Handle Time UP");
_state = TfGameState.GameOver;
_timerRunning = false;
public void SubmitAnswer(bool answer)
{
if (!_waitingForAnswer) return;
_waitingForAnswer = false;
_pendingAnswer = answer ? 1 : 0;
}
if (productionLine != null && productionLine.machineVFXController != null)
productionLine.machineVFXController.PlayExplosion();
public void ResetGame()
{
ResetBaseState(); // clears shared counters + stops coroutines
_state = TfGameState.Idle;
_progress = 0;
_questions = null;
_waitingForAnswer = false;
_pendingAnswer = -1;
yield return new WaitForSeconds(1f);
if (productionLine != null) productionLine.ResetLine();
if (questionScreen != null) questionScreen.Clear();
if (handController != null) handController.Reset();
if (uiManager != null) uiManager.ResetUI();
}
if (uiManager != null)
uiManager.ShowResults(_score, _correctCount, _wrongCount, false);
// ─── Timer feedback override ──────────────────────────────────────────
// TF adjusts time on correct/wrong, so it needs direct access
public float GetTimeLeft() => _timeLeft;
onGameOver?.Invoke();
}
// ─── Game loop ────────────────────────────────────────────────────────
private IEnumerator GameLoop()
{
while (_progress < stepsToWin && _currentIndex < _questions.Length)
......@@ -189,13 +148,11 @@ namespace com.al_arcade.tf
_waitingForAnswer = true;
_pendingAnswer = -1;
_state = TfGameState.Playing;
// --- ADDED: Start timer for this question ---
if (handController != null) handController.SetReady(true);
while (_pendingAnswer < 0)
{
if (Input.GetKeyDown(KeyCode.LeftArrow) || Input.GetKeyDown(KeyCode.A))
SubmitAnswer(true);
if (Input.GetKeyDown(KeyCode.RightArrow) || Input.GetKeyDown(KeyCode.D))
......@@ -215,7 +172,7 @@ namespace com.al_arcade.tf
_correctCount++;
_streak++;
_progress++;
_score += 100 + (_streak > 2 ? (_streak - 2) * 25 : 0);
_score += CalculateStreakScore(); // shared helper
if (handController != null) handController.PlayCorrectFeedback(playerSaidTrue);
if (productionLine != null) yield return productionLine.MoveForward(stepDistance);
......@@ -226,10 +183,11 @@ namespace com.al_arcade.tf
{ if (audio.sfxCorrect != null) audio.PlayCorrect(); else audio.PlayCorrectBeep(); }
var particles = SSParticleManager.Instance;
if (particles != null && Camera.main != null)
if (particles != null)
particles.PlayCorrectBurst(new Vector3(-2, 6f, 13));
_currentTime += 4;
uiManager?.UpdateTimer(_currentTime, true);
UpdateTimerBy(4f); // shared helper
uiManager?.UpdateTimer(_timeLeft, true);
}
else
{
......@@ -251,12 +209,14 @@ namespace com.al_arcade.tf
Camera.main.transform.DOShakePosition(0.4f, 0.3f, 15)
.SetEase(Ease.OutQuad).SetId("camShake");
}
_currentTime -= 2;
uiManager?.UpdateTimer(_currentTime, false);
UpdateTimerBy(-2f); // shared helper
uiManager?.UpdateTimer(_timeLeft, false);
}
onAnswerGiven?.Invoke(isCorrect);
onProgressChanged?.Invoke(_progress);
if (uiManager != null)
{
uiManager.SetProgress(_progress, stepsToWin);
......@@ -276,11 +236,23 @@ namespace com.al_arcade.tf
}
}
private IEnumerator VictorySequence()
// ─── End sequences ────────────────────────────────────────────────────
private IEnumerator HandleTimeUp()
{
Debug.Log("victorySequance");
_state = TfGameState.GameOver;
if (productionLine?.machineVFXController != null)
productionLine.machineVFXController.PlayExplosion();
yield return new WaitForSeconds(1f);
uiManager?.ShowResults(_score, _correctCount, _wrongCount, false);
onGameOver?.Invoke();
}
private IEnumerator VictorySequence()
{
_timerRunning = false;
var audio = SSAudioManager.Instance;
if (audio != null)
{ if (audio.sfxVictory != null) audio.PlayVictory(); else audio.PlaySuccessJingle(); }
......@@ -292,15 +264,14 @@ namespace com.al_arcade.tf
productionLine.machineVFXController.StopAllVFX();
yield return new WaitForSeconds(1.5f);
if (uiManager != null)
uiManager.ShowResults(_score, _correctCount, _wrongCount, true);
GameHistoryService.Instance.AddGame("tf", _score, gameStartTime, DateTime.Now);
uiManager?.ShowResults(_score, _correctCount, _wrongCount, true);
onGameComplete?.Invoke();
RecordGameHistory(); // shared helper
}
// ─── Extra public accessors ───────────────────────────────────────────
public int Progress => _progress;
public int StepsToWin => stepsToWin;
public int Score => _score;
}
}
}
\ No newline at end of file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Correct The Sentence</title>
<!-- ═══ ANTI-CACHE ═══ -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<!-- ═══ PRECONNECT TO CDN — speeds up HLS chunk fetching ═══ -->
<!-- Replace with your actual PeerTube domain -->
<link rel="preconnect" href="https://your-peertube-instance.com" crossorigin>
<link rel="dns-prefetch" href="https://your-peertube-instance.com">
<!-- ═══ PRELOAD HLS.js — starts downloading before Unity even loads ═══ -->
<link rel="preload" href="https://cdn.jsdelivr.net/npm/hls.js@1.5.17/dist/hls.min.js" as="script" crossorigin>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
background: #000;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
/* Prevent pull-to-refresh on mobile */
overscroll-behavior: none;
touch-action: none;
}
#unity-container {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #000;
}
#unity-canvas {
background: #000;
/* Prevent blurry scaling */
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
}
/* ═══ LOADING SCREEN ═══ */
#loading-screen {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: #000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 1000;
transition: opacity 0.5s ease;
}
#loading-screen.fade-out {
opacity: 0;
pointer-events: none;
}
#loading-logo {
max-width: 200px;
max-height: 200px;
margin-bottom: 40px;
animation: logoPulse 2s ease-in-out infinite;
}
@keyframes logoPulse {
0%, 100% { transform: scale(1); opacity: 0.9; }
50% { transform: scale(1.05); opacity: 1; }
}
#loading-bar-container {
width: 280px;
height: 6px;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
overflow: hidden;
margin-bottom: 16px;
}
#loading-bar {
width: 0%;
height: 100%;
background: #FED700;
border-radius: 3px;
transition: width 0.3s ease;
box-shadow: 0 0 10px rgba(254, 215, 0, 0.4);
}
#loading-text {
color: rgba(255, 255, 255, 0.5);
font-size: 13px;
letter-spacing: 0.5px;
}
</style>
</head>
<body>
<div id="unity-container">
<canvas id="unity-canvas" tabindex="-1"></canvas>
</div>
<div id="loading-screen">
<img id="loading-logo" src="logo.png" alt="Loading">
<div id="loading-bar-container">
<div id="loading-bar"></div>
</div>
<div id="loading-text">Loading...</div>
</div>
<script>
// ═══ 16:9 ASPECT RATIO LOCK ═══
function resizeCanvas() {
var container = document.getElementById('unity-container');
var canvas = document.getElementById('unity-canvas');
var windowW = window.innerWidth;
var windowH = window.innerHeight;
var targetAspect = 16 / 9;
var windowAspect = windowW / windowH;
var canvasW, canvasH;
if (windowAspect > targetAspect) {
canvasH = windowH;
canvasW = Math.floor(windowH * targetAspect);
} else {
canvasW = windowW;
canvasH = Math.floor(windowW / targetAspect);
}
canvas.style.width = canvasW + 'px';
canvas.style.height = canvasH + 'px';
canvas.width = canvasW;
canvas.height = canvasH;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// ═══ PRELOAD HLS.js INTO CACHE BEFORE UNITY BOOTS ═══
// This way when the jslib calls ensureHls(), it's already loaded
(function() {
var hlsScript = document.createElement('script');
hlsScript.src = 'https://cdn.jsdelivr.net/npm/hls.js@1.5.17/dist/hls.min.js';
hlsScript.async = true;
document.head.appendChild(hlsScript);
})();
// ═══ UNITY LOADER ═══
var loadingBar = document.getElementById('loading-bar');
var loadingText = document.getElementById('loading-text');
var loadingScreen = document.getElementById('loading-screen');
// Cache-bust the loader URL in development
// Remove the timestamp parameter for production
var buildUrl = "Build";
var cacheBust = ""; // Set to "?t=" + Date.now() during development
var loaderUrl = buildUrl + "/CS Build.loader.js" + cacheBust;
var config = {
dataUrl: buildUrl + "/CS Build.data",
frameworkUrl: buildUrl + "/CS Build.framework.js",
codeUrl: buildUrl + "/CS Build.wasm",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Correct The Sentence",
productVersion: "0.1.0",
// ═══ MEMORY SETTINGS ═══
// Match what you set in Player Settings
// These override if present
};
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = function () {
createUnityInstance(
document.getElementById("unity-canvas"),
config,
function (progress) {
var pct = Math.round(progress * 100);
loadingBar.style.width = pct + '%';
loadingText.textContent = pct < 100 ? 'Loading... ' + pct + '%' : 'Starting...';
}
).then(function (instance) {
loadingScreen.classList.add('fade-out');
setTimeout(function () {
loadingScreen.style.display = 'none';
}, 600);
resizeCanvas();
// ═══ PREVENT ACCIDENTAL NAVIGATION ═══
window.addEventListener('beforeunload', function(e) {
e.preventDefault();
e.returnValue = '';
});
}).catch(function (message) {
loadingText.textContent = 'Error: ' + message;
loadingBar.style.background = '#ff3333';
console.error(message);
});
};
document.body.appendChild(script);
// ═══ PREVENT CONTEXT MENU ON CANVAS ═══
document.getElementById('unity-canvas').addEventListener('contextmenu', function(e) {
e.preventDefault();
});
// ═══ FOCUS CANVAS ON CLICK (fixes keyboard input) ═══
document.addEventListener('click', function() {
document.getElementById('unity-canvas').focus();
});
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
<title>Correct The Sentence</title>
<!-- ═══ ANTI-CACHE ═══ -->
<meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="0">
<!-- ═══ PRECONNECT TO CDN — speeds up HLS chunk fetching ═══ -->
<!-- Replace with your actual PeerTube domain -->
<link rel="preconnect" href="https://your-peertube-instance.com" crossorigin>
<link rel="dns-prefetch" href="https://your-peertube-instance.com">
<!-- ═══ PRELOAD HLS.js — starts downloading before Unity even loads ═══ -->
<link rel="preload" href="https://cdn.jsdelivr.net/npm/hls.js@1.5.17/dist/hls.min.js" as="script" crossorigin>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html, body {
width: 100%;
height: 100%;
overflow: hidden;
background: #000;
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
/* Prevent pull-to-refresh on mobile */
overscroll-behavior: none;
touch-action: none;
}
#unity-container {
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: #000;
}
#unity-canvas {
background: #000;
/* Prevent blurry scaling */
image-rendering: -webkit-optimize-contrast;
image-rendering: crisp-edges;
}
/* ═══ LOADING SCREEN ═══ */
#loading-screen {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
background: #000;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
z-index: 1000;
transition: opacity 0.5s ease;
}
#loading-screen.fade-out {
opacity: 0;
pointer-events: none;
}
#loading-logo {
max-width: 200px;
max-height: 200px;
margin-bottom: 40px;
animation: logoPulse 2s ease-in-out infinite;
}
@keyframes logoPulse {
0%, 100% { transform: scale(1); opacity: 0.9; }
50% { transform: scale(1.05); opacity: 1; }
}
#loading-bar-container {
width: 280px;
height: 6px;
background: rgba(255, 255, 255, 0.1);
border-radius: 3px;
overflow: hidden;
margin-bottom: 16px;
}
#loading-bar {
width: 0%;
height: 100%;
background: #FED700;
border-radius: 3px;
transition: width 0.3s ease;
box-shadow: 0 0 10px rgba(254, 215, 0, 0.4);
}
#loading-text {
color: rgba(255, 255, 255, 0.5);
font-size: 13px;
letter-spacing: 0.5px;
}
</style>
</head>
<body>
<div id="unity-container">
<canvas id="unity-canvas" tabindex="-1"></canvas>
</div>
<div id="loading-screen">
<img id="loading-logo" src="logo.png" alt="Loading">
<div id="loading-bar-container">
<div id="loading-bar"></div>
</div>
<div id="loading-text">Loading...</div>
</div>
<script>
// ═══ 16:9 ASPECT RATIO LOCK ═══
function resizeCanvas() {
var container = document.getElementById('unity-container');
var canvas = document.getElementById('unity-canvas');
var windowW = window.innerWidth;
var windowH = window.innerHeight;
var targetAspect = 16 / 9;
var windowAspect = windowW / windowH;
var canvasW, canvasH;
if (windowAspect > targetAspect) {
canvasH = windowH;
canvasW = Math.floor(windowH * targetAspect);
} else {
canvasW = windowW;
canvasH = Math.floor(windowW / targetAspect);
}
canvas.style.width = canvasW + 'px';
canvas.style.height = canvasH + 'px';
canvas.width = canvasW;
canvas.height = canvasH;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// ═══ PRELOAD HLS.js INTO CACHE BEFORE UNITY BOOTS ═══
// This way when the jslib calls ensureHls(), it's already loaded
(function() {
var hlsScript = document.createElement('script');
hlsScript.src = 'https://cdn.jsdelivr.net/npm/hls.js@1.5.17/dist/hls.min.js';
hlsScript.async = true;
document.head.appendChild(hlsScript);
})();
// ═══ UNITY LOADER ═══
var loadingBar = document.getElementById('loading-bar');
var loadingText = document.getElementById('loading-text');
var loadingScreen = document.getElementById('loading-screen');
// Cache-bust the loader URL in development
// Remove the timestamp parameter for production
var buildUrl = "Build";
var cacheBust = ""; // Set to "?t=" + Date.now() during development
var loaderUrl = buildUrl + "/CS Build.loader.js" + cacheBust;
var config = {
dataUrl: buildUrl + "/CS Build.data",
frameworkUrl: buildUrl + "/CS Build.framework.js",
codeUrl: buildUrl + "/CS Build.wasm",
streamingAssetsUrl: "StreamingAssets",
companyName: "DefaultCompany",
productName: "Correct The Sentence",
productVersion: "0.1.0",
// ═══ MEMORY SETTINGS ═══
// Match what you set in Player Settings
// These override if present
};
var script = document.createElement("script");
script.src = loaderUrl;
script.onload = function () {
createUnityInstance(
document.getElementById("unity-canvas"),
config,
function (progress) {
var pct = Math.round(progress * 100);
loadingBar.style.width = pct + '%';
loadingText.textContent = pct < 100 ? 'Loading... ' + pct + '%' : 'Starting...';
}
).then(function (instance) {
loadingScreen.classList.add('fade-out');
setTimeout(function () {
loadingScreen.style.display = 'none';
}, 600);
resizeCanvas();
// ═══ PREVENT ACCIDENTAL NAVIGATION ═══
window.addEventListener('beforeunload', function(e) {
e.preventDefault();
e.returnValue = '';
});
}).catch(function (message) {
loadingText.textContent = 'Error: ' + message;
loadingBar.style.background = '#ff3333';
console.error(message);
});
};
document.body.appendChild(script);
// ═══ PREVENT CONTEXT MENU ON CANVAS ═══
document.getElementById('unity-canvas').addEventListener('contextmenu', function(e) {
e.preventDefault();
});
// ═══ FOCUS CANVAS ON CLICK (fixes keyboard input) ═══
document.addEventListener('click', function() {
document.getElementById('unity-canvas').focus();
});
</script>
</body>
</html>
......@@ -66,14 +66,14 @@
"url": "https://packages.unity.com"
},
"com.unity.collections": {
"version": "2.6.5",
"version": "2.6.2",
"depth": 1,
"source": "registry",
"dependencies": {
"com.unity.burst": "1.8.27",
"com.unity.burst": "1.8.23",
"com.unity.mathematics": "1.3.2",
"com.unity.test-framework": "1.4.6",
"com.unity.nuget.mono-cecil": "1.11.6",
"com.unity.nuget.mono-cecil": "1.11.5",
"com.unity.test-framework.performance": "3.0.3"
},
"url": "https://packages.unity.com"
......@@ -217,7 +217,7 @@
}
},
"com.unity.splines": {
"version": "2.8.4",
"version": "2.8.2",
"depth": 1,
"source": "registry",
"dependencies": {
......
......@@ -8,41 +8,35 @@ EditorUserSettings:
GraphicsSettingsInspector_UserSettings:
value: 18134705175a055722080a3115371d4a0d55006876786860616b0471b8b2656eacb72ba5a52a362c3c0ee63201181433fe3e101bf3250b06144ca74c24f1190708e016c213c61a52f91c12cac80fd8edd298e1e4d1fde2cacddeacbcc1fee7eef0e3b6faa69af9ceaeaaec81a6d2c2c8c8c4b2e5dfd5ccd3f8cf
flags: 0
QuickInstaller_com.unity.purchasing_installRecorded:
value: 2550581500
flags: 0
QuickInstaller_com.unity.services.levelplay_installRecorded:
value: 2550581500
flags: 0
RecentlyUsedSceneGuid-0:
value: 545005025c000d0b0f5c087516715944424e4d7b747e2568287e4c64b6e1316e
value: 5208560200560f090f5d5e2743730e444516192b757e23667b7e4863b4e36c39
flags: 0
RecentlyUsedSceneGuid-1:
value: 0003525055055d020e0b0a7216755d444215417e787d27362e2f4866b2e1323e
value: 5200570406560d58095e5c75432609124f154e737a2d2432787e4b62b4e1366a
flags: 0
RecentlyUsedSceneGuid-2:
value: 5305515503010a0e0f580977147208444e151a78787b726775711931bbe1613e
value: 545005025c000d0b0f5c087516715944424e4d7b747e2568287e4c64b6e1316e
flags: 0
RecentlyUsedSceneGuid-3:
value: 5304575f5c0c51035d5a5e771271594417154e7c2d7b70647b7b4c35bbe1646d
value: 5305515503010a0e0f580977147208444e151a78787b726775711931bbe1613e
flags: 0
RecentlyUsedSceneGuid-4:
value: 0752035101010f0c54595b2046760e44134e4e7a7f7d71677c2c4836b7b4633e
value: 52080c51560d5f03580b5e7242700c4446164f7d2e7f77612c281f32e0b8603d
flags: 0
RecentlyUsedSceneGuid-5:
value: 5701055506000a030f5c542744260844404f4d73797975367c2c1e6ab7e2653d
value: 060203560401505a595d0a7345200d44404e1b7e2d707e617b7f4d63e7b6606b
flags: 0
RecentlyUsedSceneGuid-6:
value: 060203560401505a595d0a7345200d44404e1b7e2d707e617b7f4d63e7b6606b
value: 0003525055055d020e0b0a7216755d444215417e787d27362e2f4866b2e1323e
flags: 0
RecentlyUsedSceneGuid-7:
value: 550051035503595d5d0a5975167a0e44144e40797a7924632b7c456bb7b23260
value: 5701055506000a030f5c542744260844404f4d73797975367c2c1e6ab7e2653d
flags: 0
RecentlyUsedSceneGuid-8:
value: 52080c51560d5f03580b5e7242700c4446164f7d2e7f77612c281f32e0b8603d
value: 0752035101010f0c54595b2046760e44134e4e7a7f7d71677c2c4836b7b4633e
flags: 0
RecentlyUsedSceneGuid-9:
value: 51070402040250035b0d097b42250e44434e19737d7b7f617c7b4c63e3b33068
value: 5304575f5c0c51035d5a5e771271594417154e7c2d7b70647b7b4c35bbe1646d
flags: 0
UnityEditor.ShaderGraph.Blackboard:
value: 18135939215a0a5004000b0e15254b524c030a3f2964643d120d1230e9e93a3fd6e826abbd2e2d293c4ead313b08042de6030a0afa240c0d020be94c4ba75e435d8715fa32c70d15d11612dacc11fee5d3c5d1fe9ab1bf968e93e2ffcbc3e7e2f0b3ffe0e8b0be9af8ffaeffff8e85dd8390e3949c8899daa7
......
......@@ -19,12 +19,12 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 36
width: 1918
height: 932
width: 1536
height: 716.8
m_MinSize: {x: 300, y: 112}
m_MaxSize: {x: 24288, y: 16192}
vertical: 0
controlID: 37
controlID: 3930
draggingID: 0
--- !u!114 &2
MonoBehaviour:
......@@ -42,15 +42,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Game
m_Image: {fileID: -6423792434712278376, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: 4621777727084837110, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Game\u200B"
m_Pos:
serializedVersion: 2
x: 358
y: 87
width: 1105
height: 573
x: 286.4
y: 79.200005
width: 884.4
height: 355.6
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -70,7 +70,7 @@ MonoBehaviour:
m_ShowGizmos: 0
m_TargetDisplay: 0
m_ClearColor: {r: 0, g: 0, b: 0, a: 0}
m_TargetSize: {x: 1080, y: 2400}
m_TargetSize: {x: 1080, y: 1920}
m_TextureFilterMode: 0
m_TextureHideFlags: 61
m_RenderIMGUI: 1
......@@ -79,16 +79,16 @@ MonoBehaviour:
m_VSyncEnabled: 0
m_Gizmos: 0
m_Stats: 0
m_SelectedSizes: 07000000000000000000000000000000000000000000000000000000000000000000000000000000
m_SelectedSizes: 08000000000000000000000000000000000000000000000000000000000000000000000000000000
m_ZoomArea:
m_HRangeLocked: 0
m_VRangeLocked: 0
hZoomLockedByDefault: 0
vZoomLockedByDefault: 0
m_HBaseRangeMin: -540
m_HBaseRangeMax: 540
m_VBaseRangeMin: -1200
m_VBaseRangeMax: 1200
m_HBaseRangeMin: -432
m_HBaseRangeMax: 432
m_VBaseRangeMin: -768
m_VBaseRangeMax: 768
m_HAllowExceedBaseRangeMin: 1
m_HAllowExceedBaseRangeMax: 1
m_VAllowExceedBaseRangeMin: 1
......@@ -97,7 +97,7 @@ MonoBehaviour:
m_HSlider: 0
m_VSlider: 0
m_IgnoreScrollWheelUntilClicked: 0
m_EnableMouseInput: 1
m_EnableMouseInput: 0
m_EnableSliderZoomHorizontal: 0
m_EnableSliderZoomVertical: 0
m_UniformScale: 1
......@@ -106,23 +106,23 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 21
width: 1105
height: 552
m_Scale: {x: 0.23, y: 0.23}
m_Translation: {x: 552.5, y: 276}
width: 884.4
height: 334.6
m_Scale: {x: 0.21783854, y: 0.21783854}
m_Translation: {x: 442.2, y: 167.3}
m_MarginLeft: 0
m_MarginRight: 0
m_MarginTop: 0
m_MarginBottom: 0
m_LastShownAreaInsideMargins:
serializedVersion: 2
x: -2402.1738
y: -1200
width: 4804.3477
height: 2400
x: -2029.9438
y: -768
width: 4059.8877
height: 1536
m_MinimalGUI: 1
m_defaultScale: 0.23
m_LastWindowPixelSize: {x: 1105, y: 573}
m_defaultScale: 0.21783854
m_LastWindowPixelSize: {x: 1105.5, y: 444.5}
m_ClearInEditMode: 1
m_NoCameraWarning: 1
m_LowResolutionForAspectRatios: 01000000000000000000
......@@ -148,12 +148,12 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 1464
height: 932
width: 1172.8
height: 716.8
m_MinSize: {x: 200, y: 112}
m_MaxSize: {x: 16192, y: 16192}
vertical: 1
controlID: 38
controlID: 3931
draggingID: 0
--- !u!114 &4
MonoBehaviour:
......@@ -174,12 +174,12 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 1464
height: 599
width: 1172.8
height: 381.6
m_MinSize: {x: 200, y: 56}
m_MaxSize: {x: 16192, y: 8096}
vertical: 0
controlID: 39
controlID: 3932
draggingID: 0
--- !u!114 &5
MonoBehaviour:
......@@ -198,8 +198,8 @@ MonoBehaviour:
serializedVersion: 2
x: 0
y: 0
width: 357
height: 599
width: 286.4
height: 381.6
m_MinSize: {x: 201, y: 226}
m_MaxSize: {x: 4001, y: 4026}
m_ActualView: {fileID: 6}
......@@ -223,15 +223,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Hierarchy
m_Image: {fileID: 7966133145522015247, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -3734745235275155857, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Hierarchy\u200B"
m_Pos:
serializedVersion: 2
x: 1
y: 87
width: 356
height: 573
x: 0
y: 79.200005
width: 285.4
height: 355.6
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -249,12 +249,19 @@ MonoBehaviour:
m_TreeViewState:
scrollPos: {x: 0, y: 0}
m_SelectedIDs:
- m_Data: 59072
- m_Data: 64640
m_LastClickedID:
m_Data: 0
m_ExpandedIDs:
- m_Data: -2498
- m_Data: -1512
- m_Data: -54772
- m_Data: -53964
- m_Data: -21446
- m_Data: -19514
- m_Data: -16700
- m_Data: -15986
- m_Data: -3176
- m_Data: -3004
- m_Data: -1588
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -295,10 +302,10 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 357
x: 286.4
y: 0
width: 1107
height: 599
width: 886.4
height: 381.6
m_MinSize: {x: 202, y: 226}
m_MaxSize: {x: 4002, y: 4026}
m_ActualView: {fileID: 2}
......@@ -323,15 +330,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Scene
m_Image: {fileID: 2593428753322112591, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: 8634526014445323508, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Scene\u200B"
m_Pos:
serializedVersion: 2
x: 355
y: 61
width: 1097
height: 606
x: 286.4
y: 79.200005
width: 884.4
height: 355.6
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -388,12 +395,12 @@ MonoBehaviour:
displayed: 1
id: unity-scene-view-toolbar
index: 0
contents: '{"m_Layout":4,"m_Collapsed":false,"m_Folded":false,"m_Floating":false,"m_FloatingSnapOffset":{"x":-322.0,"y":25.0},"m_SnapOffsetDelta":{"x":0.0,"y":0.0},"m_FloatingSnapCorner":1,"m_Size":{"x":0.0,"y":0.0},"m_SizeOverridden":false}'
contents: '{"m_Layout":4,"m_Collapsed":false,"m_Folded":false,"m_Floating":false,"m_FloatingSnapOffset":{"x":-322.0,"y":-331.0},"m_SnapOffsetDelta":{"x":0.0,"y":0.0},"m_FloatingSnapCorner":3,"m_Size":{"x":0.0,"y":0.0},"m_SizeOverridden":false}'
floating: 0
collapsed: 0
snapOffset: {x: -322, y: 25}
snapOffset: {x: -322, y: -331}
snapOffsetDelta: {x: 0, y: 0}
snapCorner: 1
snapCorner: 3
layout: 4
size: {x: 0, y: 0}
sizeOverridden: 0
......@@ -916,9 +923,9 @@ MonoBehaviour:
m_AudioPlay: 0
m_DebugDrawModesUseInteractiveLightBakingData: 0
m_Position:
m_Target: {x: 254.03662, y: 356.294, z: 0}
m_Target: {x: 540, y: 960, z: 0}
speed: 2
m_Value: {x: 632.0484, y: 1166.8389, z: -2.3196595}
m_Value: {x: 540, y: 960, z: 0}
m_RenderMode: 0
m_CameraMode:
drawMode: 0
......@@ -931,10 +938,10 @@ MonoBehaviour:
showFog: 1
showSkybox: 1
showFlares: 1
showImageEffects: 0
showImageEffects: 1
showParticleSystems: 1
showVisualEffectGraphs: 1
m_FxEnabled: 1
m_FxEnabled: 0
m_Grid:
xGrid:
m_Fade:
......@@ -968,9 +975,9 @@ MonoBehaviour:
speed: 2
m_Value: {x: 0, y: 0, z: 0, w: 1}
m_Size:
m_Target: 76.6172
m_Target: 1142.1276
speed: 2
m_Value: 311.54352
m_Value: 1142.1276
m_Ortho:
m_Target: 1
speed: 2
......@@ -1020,9 +1027,9 @@ MonoBehaviour:
m_Position:
serializedVersion: 2
x: 0
y: 599
width: 1464
height: 333
y: 381.6
width: 1172.8
height: 335.19998
m_MinSize: {x: 231, y: 276}
m_MaxSize: {x: 10001, y: 10026}
m_ActualView: {fileID: 10}
......@@ -1049,15 +1056,15 @@ MonoBehaviour:
m_MaxSize: {x: 10000, y: 10000}
m_TitleContent:
m_Text: Project
m_Image: {fileID: -5467254957812901981, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -5179483145760003458, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Project\u200B"
m_Pos:
serializedVersion: 2
x: 1
y: 686
width: 1463
height: 307
x: 0
y: 460.80002
width: 1171.8
height: 309.19998
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1082,7 +1089,7 @@ MonoBehaviour:
m_SkipHidden: 0
m_SearchArea: 1
m_Folders:
- Assets/AppUI/Scenes
- Assets/Scenes/MCQ
m_Globs: []
m_ProductIds:
m_AnyWithAssetOrigin: 0
......@@ -1092,24 +1099,22 @@ MonoBehaviour:
m_ViewMode: 1
m_StartGridSize: 96
m_LastFolders:
- Assets/AppUI/Scenes
- Assets/Scenes/MCQ
m_LastFoldersGridSize: 96
m_LastProjectPath: D:\Dev\Projects\SSBookMinigames\My project
m_LastProjectPath: D:\saad work\Unity project\SSbookminigames\My project
m_LockTracker:
m_IsLocked: 0
m_LastLocalAssetsSearchArea: 1
m_FolderTreeState:
scrollPos: {x: 0, y: 79}
scrollPos: {x: 0, y: 298.71942}
m_SelectedIDs:
- m_Data: 59058
- m_Data: 57302
m_LastClickedID:
m_Data: 59058
m_Data: 57302
m_ExpandedIDs:
- m_Data: 0
- m_Data: 58550
- m_Data: 58882
- m_Data: 1000000000
- m_Data: 2147483647
- m_Data: 56834
- m_Data: 57232
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -1142,7 +1147,7 @@ MonoBehaviour:
m_Data: 0
m_ExpandedIDs:
- m_Data: 0
- m_Data: 58550
- m_Data: 56834
m_RenameOverlay:
m_UserAcceptedRename: 0
m_Name:
......@@ -1170,9 +1175,9 @@ MonoBehaviour:
m_ResourceFile:
m_ListAreaState:
m_SelectedInstanceIDs:
- m_Data: 59072
m_LastClickedInstanceID: 59072
m_HadKeyboardFocusLastEvent: 1
- m_Data: 64640
m_LastClickedInstanceID: 64640
m_HadKeyboardFocusLastEvent: 0
m_ExpandedInstanceIDs:
- m_Data: 46526
- m_Data: 61214
......@@ -1222,15 +1227,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Console
m_Image: {fileID: -4327648978806127646, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -4950941429401207979, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Console\u200B"
m_Pos:
serializedVersion: 2
x: 1
y: 686
width: 1463
height: 307
x: 0
y: 460.80002
width: 1171.8
height: 309.19998
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1260,15 +1265,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Animation
m_Image: {fileID: -8166618308981325432, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -3237396543322336831, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Animation\u200B"
m_Pos:
serializedVersion: 2
x: 1
y: 678
width: 1464
height: 349
x: 0
y: 460.80002
width: 1171.8
height: 309.19998
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1284,7 +1289,7 @@ MonoBehaviour:
m_DynamicPanelBehavior: 0
m_LockTracker:
m_IsLocked: 0
m_LastSelectedObjectID: 0
m_LastSelectedObjectID: 64640
--- !u!114 &13
MonoBehaviour:
m_ObjectHideFlags: 52
......@@ -1301,15 +1306,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Animator
m_Image: {fileID: -1673928668082335149, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: 1711060831702674872, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Animator\u200B"
m_Pos:
serializedVersion: 2
x: 0
y: 680
width: 1466
height: 359
y: 460.80002
width: 1171.8
height: 309.19998
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......@@ -1355,10 +1360,10 @@ MonoBehaviour:
m_Children: []
m_Position:
serializedVersion: 2
x: 1464
x: 1172.8
y: 0
width: 454
height: 932
width: 363.19995
height: 716.8
m_MinSize: {x: 276, y: 76}
m_MaxSize: {x: 4001, y: 4026}
m_ActualView: {fileID: 15}
......@@ -1382,15 +1387,15 @@ MonoBehaviour:
m_MaxSize: {x: 4000, y: 4000}
m_TitleContent:
m_Text: Inspector
m_Image: {fileID: -2667387946076563598, guid: 0000000000000000d000000000000000, type: 0}
m_Image: {fileID: -440750813802333266, guid: 0000000000000000d000000000000000, type: 0}
m_Tooltip:
m_TextWithWhitespace: "Inspector\u200B"
m_Pos:
serializedVersion: 2
x: 1465
y: 87
width: 453
height: 906
x: 1172.8
y: 79.200005
width: 362.19995
height: 690.8
m_SerializedDataModeController:
m_DataMode: 0
m_PreferredDataMode: 0
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment