MiniQuiz and Projector flow Added
This commit is contained in:
parent
26b02343e4
commit
5a17d38946
45
Assets/MiniQuizManager.cs
Normal file
45
Assets/MiniQuizManager.cs
Normal file
@ -0,0 +1,45 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
using TMPro;
|
||||
|
||||
public class MiniQuizManager : MonoBehaviour
|
||||
{
|
||||
public Button[] answerButtons; // Assign in order: A, B, C, D
|
||||
public TextMeshProUGUI[] answerLabels; // Same order as buttons
|
||||
public TextMeshProUGUI feedbackText;
|
||||
|
||||
private string[] answerTexts = new string[]
|
||||
{
|
||||
"Typos in the subject",
|
||||
"Urgent language",
|
||||
"Mismatched sender email",
|
||||
"All of the above"
|
||||
};
|
||||
|
||||
private int correctIndex = 3;
|
||||
|
||||
public void SubmitAnswer(int selectedIndex)
|
||||
{
|
||||
string selectedAnswer = answerTexts[selectedIndex];
|
||||
UserActionLogger.Instance?.LogQuizAnswer(selectedAnswer);
|
||||
|
||||
// Feedback
|
||||
if (selectedIndex == correctIndex)
|
||||
{
|
||||
feedbackText.text = "✅ Correct! All of those were red flags.";
|
||||
}
|
||||
else
|
||||
{
|
||||
feedbackText.text = $"❌ Not quite. The correct answer was: {answerTexts[correctIndex]}";
|
||||
}
|
||||
|
||||
// Lock all buttons
|
||||
foreach (var btn in answerButtons)
|
||||
{
|
||||
btn.interactable = false;
|
||||
}
|
||||
|
||||
// Mark selected
|
||||
answerLabels[selectedIndex].text = "✅ " + answerLabels[selectedIndex].text;
|
||||
}
|
||||
}
|
11
Assets/MiniQuizManager.cs.meta
Normal file
11
Assets/MiniQuizManager.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e91fa26b90b93441b32c069c085f507
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -617,7 +617,7 @@ MonoBehaviour:
|
||||
m_GameObject: {fileID: 5379223866780212926}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b4c7f4a40cc765b4c871298980d3045d, type: 3}
|
||||
m_Script: {fileID: 11500000, guid: 5e486cfb8f5242f4bb3541192679bd01, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier:
|
||||
--- !u!1 &5764583576712336997
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -32,7 +32,6 @@ public class BodyLinkHandler : MonoBehaviour, IPointerClickHandler, IPointerExit
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnPointerClick(PointerEventData eventData)
|
||||
{
|
||||
int linkIndex = TMP_TextUtilities.FindIntersectingLink(tmp, Input.mousePosition, eventData.pressEventCamera);
|
||||
@ -41,9 +40,29 @@ public class BodyLinkHandler : MonoBehaviour, IPointerClickHandler, IPointerExit
|
||||
string linkID = tmp.textInfo.linkInfo[linkIndex].GetLinkID();
|
||||
Debug.Log("🔗 Clicked link: " + linkID);
|
||||
EmailPopupManager.Instance?.ShowPopup(linkID);
|
||||
|
||||
var emailPanelGO = WorldTimelineManager.Instance?.OpenedEmailPanel;
|
||||
if (emailPanelGO != null && emailPanelGO.TryGetComponent<EmailOpenPanel>(out var emailPanel))
|
||||
{
|
||||
EmailData email = emailPanel.Email;
|
||||
if (email != null)
|
||||
{
|
||||
SceneOutcomeManager.Instance?.Clicked(email);
|
||||
UserActionLogger.Instance?.Log($"Clicked link '{linkID}' in email from '{email.senderName}'");
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("📭 EmailData is null in EmailOpenPanel.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("📭 OpenedEmailPanel or EmailOpenPanel script not found.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void OnPointerExit(PointerEventData eventData)
|
||||
{
|
||||
CursorManager.Instance?.SetDefaultCursor();
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b4c7f4a40cc765b4c871298980d3045d
|
||||
guid: 5e486cfb8f5242f4bb3541192679bd01
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2166b6693dad68f408dc926e8b965506
|
||||
guid: a2ef96e578f9abe49abb006299b30dd1
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdfc1490af05318459a63557af7e3ffc
|
||||
guid: 5f6cd8f9035e17c4a8b194a57bc220ea
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@ -19,6 +19,7 @@ public class EmailOpenPanel : MonoBehaviour
|
||||
public Button ignoreBtn;
|
||||
|
||||
private EmailData emailData;
|
||||
public EmailData Email => emailData;
|
||||
|
||||
public void Setup(EmailData data, string initial, Sprite iconSprite)
|
||||
{
|
||||
@ -45,7 +46,11 @@ public class EmailOpenPanel : MonoBehaviour
|
||||
|
||||
void OnAction(string action)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
gameObject.SetActive(false);
|
||||
|
||||
string summary = $"{action.ToUpper()} clicked on email from '{emailData.senderName}' with subject '{emailData.subject}'";
|
||||
|
||||
UserActionLogger.Instance?.Log(summary);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
@ -57,4 +62,5 @@ public class EmailOpenPanel : MonoBehaviour
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0cc1fd5d5866e1d4dad7ab40904b0fe9
|
||||
guid: 8d44862abbde4da439e2a61442be398a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@ -50,5 +50,8 @@ public class EmailUIController : MonoBehaviour
|
||||
WorldTimelineManager.Instance.OpenedEmailPanel = panel;
|
||||
EmailOpenPanel controller = panel.GetComponent<EmailOpenPanel>();
|
||||
controller.Setup(data, cachedInitial, cachedSprite);
|
||||
|
||||
UserActionLogger.Instance?.Log($"Opened email from '{data.senderName}' with subject '{data.subject}'");
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,9 @@ public class SceneOutcomeManager : MonoBehaviour
|
||||
public Transform cameraTarget;
|
||||
public float cameraMoveSpeed = 1.5f;
|
||||
public Camera mainCamera;
|
||||
|
||||
public Transform teacherTarget;
|
||||
public GameObject DebriefObj;
|
||||
public GameObject LaptopCanvas;
|
||||
private void Awake()
|
||||
{
|
||||
Instance = this;
|
||||
@ -68,19 +70,46 @@ public class SceneOutcomeManager : MonoBehaviour
|
||||
|
||||
private IEnumerator MoveCameraToDebrief()
|
||||
{
|
||||
if (mainCamera == null || cameraTarget == null)
|
||||
DebriefObj.SetActive(true);
|
||||
yield return new WaitForSeconds(2);
|
||||
|
||||
if (mainCamera == null || cameraTarget == null || teacherTarget == null)
|
||||
yield break;
|
||||
|
||||
Vector3 startPos = mainCamera.transform.position;
|
||||
Quaternion startRot = mainCamera.transform.rotation;
|
||||
Quaternion finalRot = cameraTarget.rotation;
|
||||
|
||||
float duration = 2f;
|
||||
float t = 0;
|
||||
|
||||
while (t < 1)
|
||||
{
|
||||
t += Time.deltaTime * cameraMoveSpeed;
|
||||
t += Time.deltaTime / duration;
|
||||
|
||||
// Smooth position interpolation
|
||||
mainCamera.transform.position = Vector3.Lerp(startPos, cameraTarget.position, t);
|
||||
mainCamera.transform.rotation = Quaternion.Slerp(startRot, cameraTarget.rotation, t);
|
||||
|
||||
if (t < 0.4f)
|
||||
{
|
||||
LaptopCanvas.SetActive(false);
|
||||
// First half: look at teacher
|
||||
Quaternion lookAtTeacher = Quaternion.LookRotation(teacherTarget.position - mainCamera.transform.position);
|
||||
mainCamera.transform.rotation = Quaternion.Slerp(mainCamera.transform.rotation, lookAtTeacher, Time.deltaTime * 5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Second half: rotate towards final camera rotation
|
||||
float rotT = (t - 0.4f) * 2f; // Normalize from 0–1 for second half
|
||||
mainCamera.transform.rotation = Quaternion.Slerp(mainCamera.transform.rotation, finalRot, rotT);
|
||||
}
|
||||
|
||||
yield return null;
|
||||
}
|
||||
|
||||
// Snap to ensure exact final values
|
||||
mainCamera.transform.position = cameraTarget.position;
|
||||
mainCamera.transform.rotation = finalRot;
|
||||
}
|
||||
|
||||
}
|
||||
|
53
Assets/Scripts/UserActionLogger.cs
Normal file
53
Assets/Scripts/UserActionLogger.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using System.Text;
|
||||
using TMPro;
|
||||
|
||||
public class UserActionLogger : MonoBehaviour
|
||||
{
|
||||
public static UserActionLogger Instance;
|
||||
|
||||
private List<string> logs = new List<string>();
|
||||
public TextMeshProUGUI summaryText;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance == null)
|
||||
Instance = this;
|
||||
else
|
||||
Destroy(gameObject);
|
||||
}
|
||||
|
||||
public void Log(string action)
|
||||
{
|
||||
logs.Add(action);
|
||||
Debug.Log($"📜 Action Logged: {logs.Count}. {action}");
|
||||
}
|
||||
|
||||
public void LogQuizAnswer(string answerText)
|
||||
{
|
||||
Log($"Answered quiz: {answerText}");
|
||||
}
|
||||
|
||||
public string GetFullLog()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < logs.Count; i++)
|
||||
{
|
||||
sb.AppendLine($"{i + 1}. {logs[i]}");
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
[ContextMenu("ShowSummary")]
|
||||
public void ShowSummary()
|
||||
{
|
||||
if (summaryText != null)
|
||||
summaryText.text = GetFullLog();
|
||||
}
|
||||
|
||||
public void ClearLog()
|
||||
{
|
||||
logs.Clear();
|
||||
}
|
||||
}
|
11
Assets/Scripts/UserActionLogger.cs.meta
Normal file
11
Assets/Scripts/UserActionLogger.cs.meta
Normal file
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 20d8955ce25121f43b41083e81df52dd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@ -11,7 +11,7 @@ public class WorldTimelineManager : MonoBehaviour
|
||||
public GameObject newEmailReceived;
|
||||
public GameObject EmailListPanel;
|
||||
public GameObject OpenedEmailPanel;
|
||||
|
||||
public GameObject DataStolen;
|
||||
[Header("Timeline Canvas (World Space)")]
|
||||
public Transform timelineParent;
|
||||
public float panelSpacing = 2f;
|
||||
@ -30,16 +30,17 @@ public class WorldTimelineManager : MonoBehaviour
|
||||
|
||||
public void SnapshotCurrentSequence()
|
||||
{
|
||||
UserActionLogger.Instance.ShowSummary();
|
||||
ClearPlaybackFrames();
|
||||
|
||||
CloneAndAddToTimeline(newEmailReceived);
|
||||
CloneAndAddToTimeline(EmailListPanel);
|
||||
|
||||
if (OpenedEmailPanel != null)
|
||||
{
|
||||
CloneAndAddToTimeline(OpenedEmailPanel);
|
||||
}
|
||||
|
||||
CloneAndAddToTimeline(DataStolen);
|
||||
PlayTimelineLoop();
|
||||
}
|
||||
|
||||
@ -50,7 +51,8 @@ public class WorldTimelineManager : MonoBehaviour
|
||||
GameObject clone = Instantiate(original, timelineParent);
|
||||
clone.transform.localScale = original.transform.localScale;
|
||||
clone.transform.localRotation = Quaternion.identity;
|
||||
clone.transform.localPosition = Vector3.right * panelSpacing * playbackFrames.Count;
|
||||
clone.transform.localPosition = Vector3.zero;
|
||||
//clone.transform.localPosition = Vector3.right * panelSpacing * playbackFrames.Count;
|
||||
|
||||
clone.SetActive(false);
|
||||
DisableButtons(clone);
|
||||
@ -62,7 +64,7 @@ public class WorldTimelineManager : MonoBehaviour
|
||||
{
|
||||
foreach (Button btn in root.GetComponentsInChildren<Button>(true))
|
||||
{
|
||||
btn.interactable = false;
|
||||
btn.enabled = false;
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 91243539438e2954caec899557cb4054
|
||||
guid: 93396d2ba10e0644cb39e79325195d12
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
@ -2,20 +2,24 @@
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!21 &2180264
|
||||
Material:
|
||||
serializedVersion: 6
|
||||
serializedVersion: 8
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: LiberationSans SDF Material
|
||||
m_Shader: {fileID: 4800000, guid: fe393ace9b354375a9cb14cdbbc28be4, type: 3}
|
||||
m_ShaderKeywords:
|
||||
m_Parent: {fileID: 0}
|
||||
m_ModifiedSerializedProperties: 0
|
||||
m_ValidKeywords: []
|
||||
m_InvalidKeywords: []
|
||||
m_LightmapFlags: 1
|
||||
m_EnableInstancingVariants: 0
|
||||
m_DoubleSidedGI: 0
|
||||
m_CustomRenderQueue: -1
|
||||
stringTagMap: {}
|
||||
disabledShaderPasses: []
|
||||
m_LockedProperties:
|
||||
m_SavedProperties:
|
||||
serializedVersion: 3
|
||||
m_TexEnvs:
|
||||
@ -67,6 +71,7 @@ Material:
|
||||
m_Texture: {fileID: 0}
|
||||
m_Scale: {x: 1, y: 1}
|
||||
m_Offset: {x: 0, y: 0}
|
||||
m_Ints: []
|
||||
m_Floats:
|
||||
- _Ambient: 0.5
|
||||
- _Bevel: 0.5
|
||||
@ -107,9 +112,9 @@ Material:
|
||||
- _Parallax: 0.02
|
||||
- _PerspectiveFilter: 0.875
|
||||
- _Reflectivity: 10
|
||||
- _ScaleRatioA: 0.90909094
|
||||
- _ScaleRatioA: 0.9
|
||||
- _ScaleRatioB: 0.73125
|
||||
- _ScaleRatioC: 0.7386364
|
||||
- _ScaleRatioC: 0.73125
|
||||
- _ScaleX: 1
|
||||
- _ScaleY: 1
|
||||
- _ShaderFlags: 0
|
||||
@ -148,6 +153,7 @@ Material:
|
||||
- _ReflectOutlineColor: {r: 0, g: 0, b: 0, a: 1}
|
||||
- _SpecularColor: {r: 1, g: 1, b: 1, a: 1}
|
||||
- _UnderlayColor: {r: 0, g: 0, b: 0, a: 0.5}
|
||||
m_BuildTextureStacks: []
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
@ -165,15 +171,16 @@ MonoBehaviour:
|
||||
materialHashCode: 462855346
|
||||
m_Version: 1.1.0
|
||||
m_SourceFontFileGUID: e3265ab4bf004d28a9537516768c1c75
|
||||
m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75,
|
||||
type: 3}
|
||||
m_SourceFontFile_EditorRef: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3}
|
||||
m_SourceFontFile: {fileID: 12800000, guid: e3265ab4bf004d28a9537516768c1c75, type: 3}
|
||||
m_AtlasPopulationMode: 1
|
||||
m_FaceInfo:
|
||||
m_FaceIndex: 0
|
||||
m_FamilyName: Liberation Sans
|
||||
m_StyleName: Regular
|
||||
m_PointSize: 86
|
||||
m_Scale: 1
|
||||
m_UnitsPerEM: 0
|
||||
m_LineHeight: 98.8916
|
||||
m_AscentLine: 77.853516
|
||||
m_CapLine: 59
|
||||
@ -313,15 +320,21 @@ Texture2D:
|
||||
Hash: 00000000000000000000000000000000
|
||||
m_ForcedFallbackFormat: 4
|
||||
m_DownscaleFallback: 0
|
||||
m_IsAlphaChannelOptional: 0
|
||||
serializedVersion: 2
|
||||
m_Width: 0
|
||||
m_Height: 0
|
||||
m_CompleteImageSize: 0
|
||||
m_MipsStripped: 0
|
||||
m_TextureFormat: 1
|
||||
m_MipCount: 1
|
||||
m_IsReadable: 1
|
||||
m_IsPreProcessed: 0
|
||||
m_IgnoreMipmapLimit: 0
|
||||
m_MipmapLimitGroupName:
|
||||
m_StreamingMipmaps: 0
|
||||
m_StreamingMipmapsPriority: 0
|
||||
m_VTOnly: 0
|
||||
m_AlphaIsTransparency: 0
|
||||
m_ImageCount: 1
|
||||
m_TextureDimension: 2
|
||||
@ -335,9 +348,11 @@ Texture2D:
|
||||
m_WrapW: 0
|
||||
m_LightmapFormat: 0
|
||||
m_ColorSpace: 0
|
||||
m_PlatformBlob:
|
||||
image data: 0
|
||||
_typelessdata:
|
||||
m_StreamData:
|
||||
serializedVersion: 2
|
||||
offset: 0
|
||||
size: 0
|
||||
path:
|
||||
|
Loading…
x
Reference in New Issue
Block a user