Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
SSBookMinigames
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
SSBookMinigames
Commits
c336f670
Commit
c336f670
authored
Feb 22, 2026
by
Mahmoud Aglan
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
SAAAAADDDD START WORKING
parent
9833ad6e
Changes
30
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
30 changed files
with
26831 additions
and
21411 deletions
+26831
-21411
Hakawaty.asset
My project/Assets/Hakawaty.asset
+26441
-20304
CsBotController.cs
...roject/Assets/ScienceStreet/CS/Scripts/CsBotController.cs
+7
-8
CsDemoBuilder.cs
My project/Assets/ScienceStreet/CS/Scripts/CsDemoBuilder.cs
+21
-30
CsGameManager.cs
My project/Assets/ScienceStreet/CS/Scripts/CsGameManager.cs
+10
-20
CsOptionDraggable.cs
...ject/Assets/ScienceStreet/CS/Scripts/CsOptionDraggable.cs
+21
-31
CsPrefabBuilder.cs
...roject/Assets/ScienceStreet/CS/Scripts/CsPrefabBuilder.cs
+16
-54
CsUIManager.cs
My project/Assets/ScienceStreet/CS/Scripts/CsUIManager.cs
+4
-19
CsWordButton.cs
My project/Assets/ScienceStreet/CS/Scripts/CsWordButton.cs
+9
-13
McqDemoBuilder.cs
...roject/Assets/ScienceStreet/MCQ/Scripts/McqDemoBuilder.cs
+19
-27
McqGameManager.cs
...roject/Assets/ScienceStreet/MCQ/Scripts/McqGameManager.cs
+2
-8
McqGateController.cs
...ect/Assets/ScienceStreet/MCQ/Scripts/McqGateController.cs
+8
-10
McqPrefabBuilder.cs
...ject/Assets/ScienceStreet/MCQ/Scripts/McqPrefabBuilder.cs
+12
-47
McqQuestionDisplay.cs
...ct/Assets/ScienceStreet/MCQ/Scripts/McqQuestionDisplay.cs
+6
-7
McqUIManager.cs
My project/Assets/ScienceStreet/MCQ/Scripts/McqUIManager.cs
+3
-10
SSApiManager.cs
...oject/Assets/ScienceStreet/Shared/Scripts/SSApiManager.cs
+4
-27
SSAudioManager.cs
...ect/Assets/ScienceStreet/Shared/Scripts/SSAudioManager.cs
+8
-15
SSColorPalette.cs
...ect/Assets/ScienceStreet/Shared/Scripts/SSColorPalette.cs
+28
-31
SSDataModels.cs
...oject/Assets/ScienceStreet/Shared/Scripts/SSDataModels.cs
+6
-15
SSFontManager.cs
...ject/Assets/ScienceStreet/Shared/Scripts/SSFontManager.cs
+3
-5
SSGameSession.cs
...ject/Assets/ScienceStreet/Shared/Scripts/SSGameSession.cs
+7
-15
SSParticleManager.cs
.../Assets/ScienceStreet/Shared/Scripts/SSParticleManager.cs
+6
-11
TfDemoBuilder.cs
My project/Assets/ScienceStreet/TF/Scripts/TfDemoBuilder.cs
+28
-37
TfHandController.cs
...oject/Assets/ScienceStreet/TF/Scripts/TfHandController.cs
+12
-15
TfPrefabBuilder.cs
...roject/Assets/ScienceStreet/TF/Scripts/TfPrefabBuilder.cs
+10
-42
TfProductionLine.cs
...oject/Assets/ScienceStreet/TF/Scripts/TfProductionLine.cs
+15
-16
TfQuestionScreen.cs
...oject/Assets/ScienceStreet/TF/Scripts/TfQuestionScreen.cs
+19
-24
TfUIManager.cs
My project/Assets/ScienceStreet/TF/Scripts/TfUIManager.cs
+18
-31
collectcodebase.sh
My project/Assets/ScienceStreet/collectcodebase.sh
+0
-529
cs_comments_backup_20260222_185359.meta
...ets/ScienceStreet/cs_comments_backup_20260222_185359.meta
+2
-1
LiberationSans SDF - Fallback.asset
...ces/Fonts & Materials/LiberationSans SDF - Fallback.asset
+86
-9
No files found.
My project/Assets/Hakawaty.asset
View file @
c336f670
This diff is collapsed.
Click to expand it.
My project/Assets/ScienceStreet/CS/Scripts/CsBotController.cs
View file @
c336f670
...
...
@@ -20,7 +20,7 @@ namespace com.al_arcade.cs
var
shader
=
Shader
.
Find
(
"Universal Render Pipeline/Lit"
)
??
Shader
.
Find
(
"Standard"
)
??
Shader
.
Find
(
"Unlit/Color"
);
// ── Body ─────────────────────────────────────────────────
_body
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Capsule
);
_body
.
name
=
"Body"
;
_body
.
transform
.
SetParent
(
transform
);
...
...
@@ -30,7 +30,7 @@ namespace com.al_arcade.cs
_bodyMat
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Primary
};
_body
.
GetComponent
<
Renderer
>().
material
=
_bodyMat
;
// ── Head ─────────────────────────────────────────────────
_head
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Sphere
);
_head
.
name
=
"Head"
;
_head
.
transform
.
SetParent
(
transform
);
...
...
@@ -40,7 +40,7 @@ namespace com.al_arcade.cs
_headMat
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Accent
};
_head
.
GetComponent
<
Renderer
>().
material
=
_headMat
;
// ── Eyes ─────────────────────────────────────────────────
var
eyeMat
=
new
Material
(
shader
)
{
color
=
Color
.
white
};
var
pupilMat
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
TextDark
};
...
...
@@ -65,7 +65,7 @@ namespace com.al_arcade.cs
pupil
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
pupilMat
);
}
// ── Mouth ────────────────────────────────────────────────
_mouth
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
_mouth
.
name
=
"Mouth"
;
_mouth
.
transform
.
SetParent
(
_head
.
transform
);
...
...
@@ -75,7 +75,7 @@ namespace com.al_arcade.cs
_mouthMat
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Danger
};
_mouth
.
GetComponent
<
Renderer
>().
material
=
_mouthMat
;
// ── Arms ─────────────────────────────────────────────────
for
(
int
side
=
-
1
;
side
<=
1
;
side
+=
2
)
{
var
arm
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Capsule
);
...
...
@@ -89,7 +89,7 @@ namespace com.al_arcade.cs
new
Material
(
shader
)
{
color
=
SSColorPalette
.
PrimaryDark
};
}
// ── Feet ─────────────────────────────────────────────────
for
(
int
side
=
-
1
;
side
<=
1
;
side
+=
2
)
{
var
foot
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
...
...
@@ -160,7 +160,6 @@ namespace com.al_arcade.cs
}
}
// ── Reactions ────────────────────────────────────────────────
public
void
PlayHappy
()
{
...
...
@@ -183,7 +182,7 @@ namespace com.al_arcade.cs
.
OnComplete
(()
=>
_headMat
.
DOColor
(
SSColorPalette
.
Accent
,
0.4f
));
}
// Reset mouth after delay
DOTween
.
Sequence
().
SetDelay
(
1f
).
OnComplete
(()
=>
{
if
(
_mouth
==
null
)
return
;
...
...
My project/Assets/ScienceStreet/CS/Scripts/CsDemoBuilder.cs
View file @
c336f670
...
...
@@ -44,7 +44,7 @@ namespace com.al_arcade.cs
Debug
.
Log
(
" Correct-the-Sentence Game"
);
Debug
.
Log
(
"═══════════════════════════════════════════"
);
// ── EventSystem ──────────────────────────────────────────
if
(
FindObjectOfType
<
EventSystem
>()
==
null
)
{
var
es
=
new
GameObject
(
"EventSystem"
);
...
...
@@ -52,7 +52,7 @@ namespace com.al_arcade.cs
es
.
AddComponent
<
StandaloneInputModule
>();
}
// ── Managers ─────────────────────────────────────────────
SSApiManager
.
EnsureInstance
();
SSAudioManager
.
EnsureInstance
();
SSParticleManager
.
EnsureInstance
();
...
...
@@ -64,49 +64,49 @@ namespace com.al_arcade.cs
session
.
classCode
=
classCode
;
yield
return
null
;
// ── Scene ────────────────────────────────────────────────
BuildScene
();
yield
return
null
;
// ── Camera ───────────────────────────────────────────────
SetupCamera
();
yield
return
null
;
// ── Bot ──────────────────────────────────────────────────
var
botObj
=
new
GameObject
(
"Bot"
);
botObj
.
transform
.
position
=
new
Vector3
(
0
,
0
,
0
);
_bot
=
botObj
.
AddComponent
<
CsBotController
>();
_bot
.
Build
();
yield
return
null
;
// ── Word Container ───────────────────────────────────────
var
wordContainer
=
new
GameObject
(
"WordContainer"
);
wordContainer
.
transform
.
position
=
Vector3
.
zero
;
yield
return
null
;
// ── UI ───────────────────────────────────────────────────
var
uiObj
=
new
GameObject
(
"CsUI"
);
_uiManager
=
uiObj
.
AddComponent
<
CsUIManager
>();
_uiManager
.
BuildUI
();
// ★ FIX: Initialize the UnityEvent if null
if
(
_uiManager
.
onRestartClicked
==
null
)
_uiManager
.
onRestartClicked
=
new
UnityEvent
();
yield
return
null
;
// ── Game Manager ─────────────────────────────────────────
var
gmObj
=
new
GameObject
(
"CsGameManager"
);
_gm
=
gmObj
.
AddComponent
<
CsGameManager
>();
_gm
.
bot
=
_bot
;
_gm
.
uiManager
=
_uiManager
;
_gm
.
wordContainer
=
wordContainer
.
transform
;
// ★ FIX: Safe listener via named method
_uiManager
.
onRestartClicked
.
AddListener
(
OnRestartClicked
);
yield
return
null
;
// ── Lighting ─────────────────────────────────────────────
SetupLighting
();
yield
return
null
;
...
...
@@ -118,16 +118,13 @@ namespace com.al_arcade.cs
yield
return
new
WaitForSeconds
(
0.5f
);
// ── Start ────────────────────────────────────────────────
if
(
useOfflineTestData
)
_gm
.
StartWithQuestions
(
GetTestQuestions
());
else
_gm
.
StartGame
();
}
// ════════════════════════════════════════════════════════════
// RESTART HANDLER
// ════════════════════════════════════════════════════════════
private
void
OnRestartClicked
()
{
...
...
@@ -135,9 +132,6 @@ namespace com.al_arcade.cs
if
(
_gm
!=
null
)
_gm
.
StartGame
();
}
// ════════════════════════════════════════════════════════════
// SCENE
// ════════════════════════════════════════════════════════════
private
void
BuildScene
()
{
...
...
@@ -146,7 +140,7 @@ namespace com.al_arcade.cs
var
shader
=
GetShader
();
// Ground
var
ground
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
ground
.
name
=
"Ground"
;
ground
.
transform
.
position
=
new
Vector3
(
0
,
-
0.05f
,
0
);
...
...
@@ -154,7 +148,7 @@ namespace com.al_arcade.cs
ground
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
40
,
40
,
65
,
255
)
};
// Circular platform
var
platform
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cylinder
);
platform
.
name
=
"Platform"
;
platform
.
transform
.
position
=
new
Vector3
(
0
,
0.05f
,
0
);
...
...
@@ -163,7 +157,7 @@ namespace com.al_arcade.cs
platform
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Primary
,
0.6f
)
};
// Outer ring with pulse
var
ring
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cylinder
);
ring
.
name
=
"Ring"
;
ring
.
transform
.
position
=
new
Vector3
(
0
,
0.04f
,
0
);
...
...
@@ -175,7 +169,7 @@ namespace com.al_arcade.cs
ringMat
.
DOFade
(
0.1f
,
1.5f
).
SetEase
(
Ease
.
InOutSine
)
.
SetLoops
(-
1
,
LoopType
.
Yoyo
);
// Background decorations
for
(
int
i
=
0
;
i
<
20
;
i
++)
{
var
deco
=
GameObject
.
CreatePrimitive
(
...
...
@@ -213,7 +207,7 @@ namespace com.al_arcade.cs
.
SetLoops
(-
1
,
LoopType
.
Incremental
).
SetEase
(
Ease
.
Linear
);
}
// Grid lines on ground
for
(
float
x
=
-
9
;
x
<=
9
;
x
+=
3
)
{
var
line
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
...
...
@@ -235,7 +229,7 @@ namespace com.al_arcade.cs
{
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Primary
,
0.08f
)
};
}
// Floor label
var
floorText
=
new
GameObject
(
"FloorLabel"
);
floorText
.
transform
.
position
=
new
Vector3
(
0
,
0.02f
,
-
3
);
floorText
.
transform
.
rotation
=
Quaternion
.
Euler
(
90
,
0
,
0
);
...
...
@@ -276,7 +270,7 @@ namespace com.al_arcade.cs
dirLight
.
intensity
=
0.9f
;
dirLight
.
shadows
=
LightShadows
.
Soft
;
// Accent light on bot
var
accent
=
new
GameObject
(
"AccentLight"
);
var
aLight
=
accent
.
AddComponent
<
Light
>();
aLight
.
type
=
LightType
.
Point
;
...
...
@@ -285,7 +279,7 @@ namespace com.al_arcade.cs
aLight
.
intensity
=
0.8f
;
aLight
.
color
=
SSColorPalette
.
Accent
;
// Blue back light
var
back
=
new
GameObject
(
"BackLight"
);
var
bLight
=
back
.
AddComponent
<
Light
>();
bLight
.
type
=
LightType
.
Point
;
...
...
@@ -298,9 +292,6 @@ namespace com.al_arcade.cs
RenderSettings
.
ambientLight
=
new
Color32
(
40
,
42
,
60
,
255
);
}
// ════════════════════════════════════════════════════════════
// TEST DATA
// ════════════════════════════════════════════════════════════
private
CsQuestion
[]
GetTestQuestions
()
{
...
...
@@ -418,4 +409,4 @@ namespace com.al_arcade.cs
??
Shader
.
Find
(
"Unlit/Color"
);
}
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/CS/Scripts/CsGameManager.cs
View file @
c336f670
...
...
@@ -29,7 +29,7 @@ namespace com.al_arcade.cs
public
CsUIManager
uiManager
;
public
Transform
wordContainer
;
// State
private
CsGameState
_state
=
CsGameState
.
Idle
;
private
CsQuestion
[]
_questions
;
private
int
_currentIndex
;
...
...
@@ -52,9 +52,6 @@ namespace com.al_arcade.cs
Instance
=
this
;
}
// ═══════════════════════════════════════════════════════════
// PUBLIC API
// ═══════════════════════════════════════════════════════════
public
void
StartGame
()
=>
StartCoroutine
(
StartGameRoutine
());
...
...
@@ -112,9 +109,6 @@ namespace com.al_arcade.cs
_onOptionDropped
?.
Invoke
(
isCorrectOption
);
}
// ═══════════════════════════════════════════════════════════
// GAME FLOW
// ═══════════════════════════════════════════════════════════
private
IEnumerator
StartGameRoutine
()
{
...
...
@@ -277,9 +271,6 @@ namespace com.al_arcade.cs
yield
return
new
WaitForSeconds
(
0.8f
);
}
// ═══════════════════════════════════════════════════════════
// WORD SPAWNING — ★ Dynamic sizing, no overlaps
// ═══════════════════════════════════════════════════════════
private
void
SpawnWords
(
CsQuestion
question
)
{
...
...
@@ -288,23 +279,23 @@ namespace com.al_arcade.cs
int
wordCount
=
question
.
words
.
Length
;
// ★ Calculate total width needed based on actual text lengths
float
padding
=
0.6f
;
// extra padding per word card
float
gapBetween
=
0.25f
;
// gap between cards
float
charWidth
=
0.32f
;
// approx width per character
float
padding
=
0.6f
;
float
gapBetween
=
0.25f
;
float
charWidth
=
0.32f
;
float
[]
wordWidths
=
new
float
[
wordCount
];
float
totalWidth
=
0
;
for
(
int
i
=
0
;
i
<
wordCount
;
i
++)
{
float
w
=
question
.
words
[
i
].
word_text
.
Length
*
charWidth
+
padding
;
w
=
Mathf
.
Max
(
w
,
1.0f
);
// minimum width
w
=
Mathf
.
Max
(
w
,
1.0f
);
wordWidths
[
i
]
=
w
;
totalWidth
+=
w
;
}
totalWidth
+=
(
wordCount
-
1
)
*
gapBetween
;
// ★ If total width exceeds max, scale everything down
float
maxAllowedWidth
=
14f
;
float
scaleFactor
=
1f
;
if
(
totalWidth
>
maxAllowedWidth
)
...
...
@@ -315,12 +306,12 @@ namespace com.al_arcade.cs
wordWidths
[
i
]
*=
scaleFactor
;
}
// Base position above bot
Vector3
basePos
=
bot
!=
null
?
bot
.
transform
.
position
+
Vector3
.
up
*
3.5f
:
Vector3
.
up
*
4f
;
// ★ RTL layout: start from right edge
float
startX
=
totalWidth
/
2f
;
float
currentX
=
startX
;
...
...
@@ -339,7 +330,7 @@ namespace com.al_arcade.cs
wb
.
Setup
(
word
.
word_text
,
word
.
is_wrong
,
i
,
wordWidths
[
i
],
scaleFactor
);
_wordButtons
.
Add
(
wb
);
// Entrance animation
wordObj
.
transform
.
localScale
=
Vector3
.
zero
;
wordObj
.
transform
.
DOScale
(
Vector3
.
one
,
0.4f
)
.
SetDelay
(
i
*
0.08f
)
...
...
@@ -378,7 +369,6 @@ namespace com.al_arcade.cs
_wordClickLocked
=
false
;
}
// ── Victory ──────────────────────────────────────────────────
private
IEnumerator
VictorySequence
()
{
...
...
My project/Assets/ScienceStreet/CS/Scripts/CsOptionDraggable.cs
View file @
c336f670
...
...
@@ -23,7 +23,7 @@ namespace com.al_arcade.cs
private
CsWordButton
_targetWord
;
private
CanvasGroup
_canvasGroup
;
// ★ Drag offset: distance from pointer to rect center at grab time
private
Vector2
_dragOffset
;
private
bool
_originalPosCaptured
;
private
Camera
_canvasCamera
;
...
...
@@ -38,20 +38,20 @@ namespace com.al_arcade.cs
_rect
=
GetComponent
<
RectTransform
>();
if
(
_rect
==
null
)
_rect
=
gameObject
.
AddComponent
<
RectTransform
>();
// ★ CanvasGroup so we can make it not block raycasts while dragging
_canvasGroup
=
gameObject
.
AddComponent
<
CanvasGroup
>();
// Determine canvas camera (null for ScreenSpaceOverlay)
_canvasCamera
=
null
;
if
(
_canvas
!=
null
&&
_canvas
.
renderMode
!=
RenderMode
.
ScreenSpaceOverlay
)
_canvasCamera
=
_canvas
.
worldCamera
;
// Background
_bg
=
gameObject
.
AddComponent
<
Image
>();
_bg
.
color
=
SSColorPalette
.
Card
;
_bg
.
raycastTarget
=
true
;
// Text
var
textObj
=
new
GameObject
(
"Text"
);
textObj
.
transform
.
SetParent
(
transform
,
false
);
var
textRect
=
textObj
.
AddComponent
<
RectTransform
>();
...
...
@@ -72,41 +72,37 @@ namespace com.al_arcade.cs
_text
.
fontSizeMax
=
22
;
SSFontManager
.
Apply
(
_text
);
// Entrance animation
transform
.
localScale
=
Vector3
.
one
*
0.5f
;
transform
.
DOScale
(
Vector3
.
one
,
0.3f
).
SetEase
(
Ease
.
OutBack
);
_originalPosCaptured
=
false
;
}
// ════════════════════════════════════════════════════════════
// DRAG HANDLERS — ★ Cursor-accurate positioning
// ════════════════════════════════════════════════════════════
public
void
OnBeginDrag
(
PointerEventData
eventData
)
{
// ★ Capture the original anchored position for return-to-origin
_originalAnchoredPos
=
_rect
.
anchoredPosition
;
_originalPosCaptured
=
true
;
// ★ Calculate offset: where the pointer is relative to the rect's center
// so the card doesn't jump — it stays exactly where you grabbed it
Vector2
localPointerPos
;
RectTransformUtility
.
ScreenPointToLocalPointInRectangle
(
_rect
.
parent
as
RectTransform
,
// parent rect
eventData
.
position
,
// screen pointer
_canvasCamera
,
// camera (null for overlay)
_rect
.
parent
as
RectTransform
,
eventData
.
position
,
_canvasCamera
,
out
localPointerPos
);
_dragOffset
=
_rect
.
anchoredPosition
-
localPointerPos
;
// Visual feedback
_bg
.
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Primary
,
0.3f
);
DOTween
.
Kill
(
transform
,
"optScale"
);
transform
.
DOScale
(
Vector3
.
one
*
1.08f
,
0.12f
).
SetId
(
"optScale"
);
transform
.
SetAsLastSibling
();
// ★ Let raycasts pass through while dragging (optional, helps with drop detection)
_canvasGroup
.
blocksRaycasts
=
false
;
var
audio
=
SSAudioManager
.
Instance
;
...
...
@@ -117,7 +113,7 @@ namespace com.al_arcade.cs
{
if
(
_rect
==
null
||
_canvas
==
null
)
return
;
// ★ Convert screen pointer to local position in parent
Vector2
localPointerPos
;
RectTransformUtility
.
ScreenPointToLocalPointInRectangle
(
_rect
.
parent
as
RectTransform
,
...
...
@@ -125,16 +121,16 @@ namespace com.al_arcade.cs
_canvasCamera
,
out
localPointerPos
);
// ★ Apply with the initial offset so the card stays under the finger
_rect
.
anchoredPosition
=
localPointerPos
+
_dragOffset
;
}
public
void
OnEndDrag
(
PointerEventData
eventData
)
{
// Re-enable raycasts
_canvasGroup
.
blocksRaycasts
=
true
;
// ★ Check if dropped near the target word
bool
droppedOnTarget
=
false
;
if
(
_targetWord
!=
null
&&
Camera
.
main
!=
null
)
{
...
...
@@ -151,7 +147,7 @@ namespace com.al_arcade.cs
if
(
IsCorrect
)
{
// Snap to target and disappear
DOTween
.
Kill
(
transform
);
transform
.
DOScale
(
Vector3
.
zero
,
0.3f
)
.
SetEase
(
Ease
.
InBack
)
...
...
@@ -163,14 +159,14 @@ namespace com.al_arcade.cs
}
else
{
// Wrong — shake then return
DOTween
.
Kill
(
transform
,
"optShake"
);
transform
.
DOShakePosition
(
0.3f
,
10f
,
15
).
SetId
(
"optShake"
);
}
}
}
// ★ Return to original position (always, unless correct + destroyed)
ReturnToOrigin
();
}
...
...
@@ -188,9 +184,6 @@ namespace com.al_arcade.cs
}
}
// ════════════════════════════════════════════════════════════
// HOVER
// ════════════════════════════════════════════════════════════
public
void
OnPointerEnter
(
PointerEventData
eventData
)
{
...
...
@@ -205,9 +198,6 @@ namespace com.al_arcade.cs
_bg
.
DOColor
(
SSColorPalette
.
Card
,
0.15f
).
SetId
(
"optHover"
);
}
// ════════════════════════════════════════════════════════════
// CLEANUP
// ════════════════════════════════════════════════════════════
private
void
OnDestroy
()
{
...
...
@@ -216,4 +206,4 @@ namespace com.al_arcade.cs
if
(
_bg
!=
null
)
DOTween
.
Kill
(
_bg
);
}
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/CS/Scripts/CsPrefabBuilder.cs
View file @
c336f670
This diff is collapsed.
Click to expand it.
My project/Assets/ScienceStreet/CS/Scripts/CsUIManager.cs
View file @
c336f670
...
...
@@ -28,9 +28,6 @@ namespace com.al_arcade.cs
[
Header
(
"Events"
)]
public
UnityEvent
onRestartClicked
;
// ════════════════════════════════════════════════════════════
// BUILD
// ════════════════════════════════════════════════════════════
public
void
BuildUI
()
{
...
...
@@ -61,14 +58,13 @@ namespace com.al_arcade.cs
_feedbackGroup
.
alpha
=
0
;
}
// ── Game HUD ─────────────────────────────────────────────────
private
void
BuildGameHUD
(
Transform
parent
)
{
var
go
=
MkFull
(
parent
,
"GameUI"
);
_gameUI
=
go
.
AddComponent
<
CanvasGroup
>();
// Top bar
var
topBar
=
new
GameObject
(
"TopBar"
);
topBar
.
transform
.
SetParent
(
go
.
transform
,
false
);
var
tbr
=
topBar
.
AddComponent
<
RectTransform
>();
...
...
@@ -93,7 +89,7 @@ namespace com.al_arcade.cs
_streakText
.
color
=
SSColorPalette
.
Warning
;
_streakText
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
// Progress bar
var
pbg
=
MkFull
(
go
.
transform
,
"ProgressBg"
);
var
pr
=
pbg
.
GetComponent
<
RectTransform
>();
pr
.
anchorMin
=
new
Vector2
(
0.25f
,
1
);
pr
.
anchorMax
=
new
Vector2
(
0.75f
,
1
);
...
...
@@ -115,7 +111,7 @@ namespace com.al_arcade.cs
_progressText
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
_progressText
.
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.5f
);
// Hint
_hintText
=
MkTxt
(
go
.
transform
,
"Hint"
,
""
,
18
,
new
Vector2
(
0.5f
,
0
),
new
Vector2
(
0
,
200
),
new
Vector2
(
600
,
40
));
_hintText
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
...
...
@@ -123,7 +119,6 @@ namespace com.al_arcade.cs
_hintText
.
fontStyle
=
TMPro
.
FontStyles
.
Italic
;
}
// ── Options Panel ────────────────────────────────────────────
private
void
BuildOptionsPanel
(
Transform
parent
)
{
...
...
@@ -155,7 +150,6 @@ namespace com.al_arcade.cs
.
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Accent
,
0.6f
);
}
// ── Feedback Overlay ─────────────────────────────────────────
private
void
BuildFeedbackOverlay
(
Transform
parent
)
{
...
...
@@ -185,7 +179,6 @@ namespace com.al_arcade.cs
_feedbackText
.
enableWordWrapping
=
true
;
}
// ── Loading ──────────────────────────────────────────────────
private
void
BuildLoadingPanel
(
Transform
parent
)
{
...
...
@@ -199,7 +192,6 @@ namespace com.al_arcade.cs
_loadingText
.
color
=
Color
.
white
;
}
// ── Error ────────────────────────────────────────────────────
private
void
BuildErrorPanel
(
Transform
parent
)
{
...
...
@@ -214,7 +206,6 @@ namespace com.al_arcade.cs
_errorText
.
enableWordWrapping
=
true
;
}
// ── Results ──────────────────────────────────────────────────
private
void
BuildResultsPanel
(
Transform
parent
)
{
...
...
@@ -241,7 +232,7 @@ namespace com.al_arcade.cs
_resultStats
.
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.7f
);
_resultStats
.
enableWordWrapping
=
true
;
// Restart button
var
btn
=
new
GameObject
(
"RestartBtn"
);
btn
.
transform
.
SetParent
(
go
.
transform
,
false
);
var
br
=
btn
.
AddComponent
<
RectTransform
>();
...
...
@@ -264,9 +255,6 @@ namespace com.al_arcade.cs
bt
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
}
// ════════════════════════════════════════════════════════════
// PUBLIC METHODS
// ════════════════════════════════════════════════════════════
public
void
ShowGameUI
()
{
_gameUI
.
gameObject
.
SetActive
(
true
);
_gameUI
.
DOFade
(
1f
,
0.3f
);
}
...
...
@@ -333,7 +321,6 @@ namespace com.al_arcade.cs
}
}
// ── Options ──────────────────────────────────────────────────
public
void
ShowOptions
(
CsOption
[]
options
,
CsWordButton
targetWord
)
{
...
...
@@ -387,7 +374,6 @@ namespace com.al_arcade.cs
_activeOptions
.
Clear
();
}
// ── Loading / Error / Results ────────────────────────────────
public
void
ShowLoading
(
string
msg
)
{
_loadingUI
.
gameObject
.
SetActive
(
true
);
if
(
_loadingText
!=
null
)
_loadingText
.
arabicText
=
msg
;
_loadingUI
.
DOFade
(
1f
,
0.3f
);
}
...
...
@@ -440,7 +426,6 @@ namespace com.al_arcade.cs
ClearOptions
();
}
// ── Helpers ──────────────────────────────────────────────────
private
GameObject
MkFull
(
Transform
p
,
string
n
)
{
...
...
My project/Assets/ScienceStreet/CS/Scripts/CsWordButton.cs
View file @
c336f670
...
...
@@ -22,9 +22,7 @@ namespace com.al_arcade.cs
private
float
_cardWidth
;
private
float
_cardHeight
=
0.8f
;
/// <summary>
/// Setup with explicit width and optional scale factor to prevent overlaps.
/// </summary>
public
void
Setup
(
string
text
,
bool
isWrong
,
int
index
,
float
cardWidth
=
-
1f
,
float
scaleFactor
=
1f
)
{
...
...
@@ -32,7 +30,7 @@ namespace com.al_arcade.cs
IsWrong
=
isWrong
;
Index
=
index
;
// ★ If width not provided, calculate from text
if
(
cardWidth
<=
0
)
_cardWidth
=
text
.
Length
*
0.32f
+
0.6f
;
else
...
...
@@ -49,7 +47,7 @@ namespace com.al_arcade.cs
var
shader
=
Shader
.
Find
(
"Universal Render Pipeline/Lit"
)
??
Shader
.
Find
(
"Standard"
)
??
Shader
.
Find
(
"Unlit/Color"
);
// ── Background card ──────────────────────────────────────
_background
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
_background
.
name
=
"WordBg"
;
_background
.
transform
.
SetParent
(
transform
);
...
...
@@ -60,11 +58,11 @@ namespace com.al_arcade.cs
_bgMaterial
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
NeutralWord
};
_background
.
GetComponent
<
Renderer
>().
material
=
_bgMaterial
;
// ── Text ─────────────────────────────────────────────────
var
textObj
=
new
GameObject
(
"WordText"
);
textObj
.
transform
.
SetParent
(
transform
);
textObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
0
,
-
0.05f
);
// ★ Face camera (identity rotation — parent handles billboard in LateUpdate if needed)
textObj
.
transform
.
localRotation
=
Quaternion
.
identity
;
_text
=
textObj
.
AddComponent
<
ArabicTextMeshPro
>();
...
...
@@ -81,11 +79,11 @@ namespace com.al_arcade.cs
_text
.
overflowMode
=
TMPro
.
TextOverflowModes
.
Ellipsis
;
SSFontManager
.
Apply
(
_text
);
// ── Collider (matches card exactly) ──────────────────────
_collider
=
GetComponent
<
BoxCollider
>();
_collider
.
size
=
new
Vector3
(
_cardWidth
,
_cardHeight
,
0.2f
);
// ── Shadow ───────────────────────────────────────────────
var
shadow
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
shadow
.
name
=
"Shadow"
;
shadow
.
transform
.
SetParent
(
transform
);
...
...
@@ -120,7 +118,7 @@ namespace com.al_arcade.cs
if
(
_bgMaterial
!=
null
)
DOTween
.
Kill
(
_bgMaterial
);
}
// ── Billboard towards camera ─────────────────────────────────
private
void
LateUpdate
()
{
if
(
Camera
.
main
==
null
)
return
;
...
...
@@ -130,7 +128,6 @@ namespace com.al_arcade.cs
transform
.
rotation
=
Quaternion
.
LookRotation
(
awayFromCam
);
}
// ── Mouse Interaction ────────────────────────────────────────
private
void
OnMouseEnter
()
{
...
...
@@ -158,7 +155,6 @@ namespace com.al_arcade.cs
CsGameManager
.
Instance
.
OnWordClicked
(
this
);
}
// ── Public Methods ───────────────────────────────────────────
public
void
Highlight
(
bool
isWrongWord
)
{
...
...
@@ -173,7 +169,7 @@ namespace com.al_arcade.cs
if
(
_text
!=
null
)
_text
.
color
=
Color
.
white
;
transform
.
DOPunchScale
(
Vector3
.
one
*
0.2f
,
0.4f
,
8
,
0.3f
);
// Pulsing glow
DOTween
.
Sequence
()
.
Append
(
_bgMaterial
.
DOColor
(
Color
.
Lerp
(
targetColor
,
Color
.
white
,
0.3f
),
0.5f
))
.
Append
(
_bgMaterial
.
DOColor
(
targetColor
,
0.5f
))
...
...
My project/Assets/ScienceStreet/MCQ/Scripts/McqDemoBuilder.cs
View file @
c336f670
...
...
@@ -46,7 +46,7 @@ namespace com.al_arcade.mcq
{
Debug
.
Log
(
"══════ MCQ Runner Demo Builder ══════"
);
// ── EventSystem ──────────────────────────────────────────
if
(
FindObjectOfType
<
EventSystem
>()
==
null
)
{
var
es
=
new
GameObject
(
"EventSystem"
);
...
...
@@ -54,7 +54,7 @@ namespace com.al_arcade.mcq
es
.
AddComponent
<
StandaloneInputModule
>();
}
// ── Managers ─────────────────────────────────────────────
SSApiManager
.
EnsureInstance
();
SSAudioManager
.
EnsureInstance
();
SSParticleManager
.
EnsureInstance
();
...
...
@@ -66,31 +66,31 @@ namespace com.al_arcade.mcq
session
.
classCode
=
classCode
;
yield
return
null
;
// ── Scene ────────────────────────────────────────────────
BuildScene
();
yield
return
null
;
// ── Player ───────────────────────────────────────────────
BuildPlayer
();
yield
return
null
;
// ── Question Display ─────────────────────────────────────
BuildQuestionDisplay
();
yield
return
null
;
// ── UI ───────────────────────────────────────────────────
BuildUI
();
yield
return
null
;
// ── Game Manager ─────────────────────────────────────────
BuildGameManager
();
yield
return
null
;
// ── Camera ───────────────────────────────────────────────
SetupCamera
();
yield
return
null
;
// ── Lighting ─────────────────────────────────────────────
SetupLighting
();
yield
return
null
;
...
...
@@ -98,16 +98,13 @@ namespace com.al_arcade.mcq
yield
return
new
WaitForSeconds
(
0.3f
);
// ── Start ────────────────────────────────────────────────
if
(
useOfflineTestData
)
_gm
.
StartWithQuestions
(
GetTestQuestions
());
else
_gm
.
StartGame
();
}
// ════════════════════════════════════════════════════════════
// BUILD METHODS
// ════════════════════════════════════════════════════════════
private
void
BuildScene
()
{
...
...
@@ -116,7 +113,7 @@ namespace com.al_arcade.mcq
var
shader
=
GetLitShader
();
// Road (centered at x=0, extends along +Z)
var
road
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
road
.
name
=
"Road"
;
road
.
transform
.
position
=
new
Vector3
(
0
,
-
0.05f
,
200
);
...
...
@@ -124,7 +121,7 @@ namespace com.al_arcade.mcq
road
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
60
,
60
,
80
,
255
)
};
// Lane dividers
for
(
int
i
=
-
1
;
i
<=
1
;
i
+=
2
)
{
var
line
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
...
...
@@ -136,7 +133,7 @@ namespace com.al_arcade.mcq
{
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Accent
,
0.4f
)
};
}
// Center dashes
for
(
float
z
=
0
;
z
<
400
;
z
+=
4
)
{
var
dash
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
...
...
@@ -148,7 +145,7 @@ namespace com.al_arcade.mcq
{
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.2f
)
};
}
// Side decorations
for
(
int
side
=
-
1
;
side
<=
1
;
side
+=
2
)
{
for
(
float
z
=
0
;
z
<
400
;
z
+=
20
)
...
...
@@ -167,7 +164,7 @@ namespace com.al_arcade.mcq
}
}
// Horizon
var
horizon
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
horizon
.
name
=
"Horizon"
;
horizon
.
transform
.
position
=
new
Vector3
(
0
,
2f
,
500
);
...
...
@@ -207,7 +204,7 @@ namespace com.al_arcade.mcq
_uiManager
=
obj
.
AddComponent
<
McqUIManager
>();
_uiManager
.
BuildUI
();
// ★ FIX: Initialize the UnityEvent if null
if
(
_uiManager
.
onRestartClicked
==
null
)
_uiManager
.
onRestartClicked
=
new
UnityEvent
();
}
...
...
@@ -221,7 +218,7 @@ namespace com.al_arcade.mcq
_gm
.
uiManager
=
_uiManager
;
_gm
.
gateParent
=
new
GameObject
(
"Gates"
).
transform
;
// ★ FIX: Safe listener — all refs captured after they exist
_uiManager
.
onRestartClicked
.
AddListener
(
OnRestartClicked
);
}
...
...
@@ -272,9 +269,6 @@ namespace com.al_arcade.mcq
RenderSettings
.
ambientMode
=
UnityEngine
.
Rendering
.
AmbientMode
.
Flat
;
}
// ════════════════════════════════════════════════════════════
// TEST DATA
// ════════════════════════════════════════════════════════════
private
McqQuestion
[]
GetTestQuestions
()
{
...
...
@@ -306,9 +300,7 @@ namespace com.al_arcade.mcq
}
}
// ════════════════════════════════════════════════════════════════
// Camera follow — 3rd-person runner (behind + above)
// ════════════════════════════════════════════════════════════════
public
class
McqCameraFollow
:
MonoBehaviour
{
public
Transform
target
;
...
...
@@ -328,4 +320,4 @@ namespace com.al_arcade.mcq
Time
.
deltaTime
*
smoothSpeed
);
}
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/MCQ/Scripts/McqGameManager.cs
View file @
c336f670
...
...
@@ -62,7 +62,6 @@ namespace com.al_arcade.mcq
Instance
=
this
;
}
// ── Public API ───────────────────────────────────────────────
public
void
StartGame
()
=>
StartCoroutine
(
StartGameRoutine
());
...
...
@@ -90,7 +89,6 @@ namespace com.al_arcade.mcq
if
(
questionDisplay
!=
null
)
questionDisplay
.
Hide
();
}
// ── Game Flow ────────────────────────────────────────────────
private
IEnumerator
StartGameRoutine
()
{
...
...
@@ -202,7 +200,7 @@ namespace com.al_arcade.mcq
_state
=
McqGameState
.
AnswerFeedback
;
yield
return
ProcessAnswer
(
answered
&&
wasCorrect
);
// Cleanup gates
foreach
(
var
gate
in
_activeGates
)
{
if
(
gate
!=
null
)
...
...
@@ -272,9 +270,6 @@ namespace com.al_arcade.mcq
yield
return
new
WaitForSeconds
(
feedbackDisplayTime
);
}
// ══════════════════════════════════════════════════════════
// GATE SPAWNING — always road-center X=0
// ══════════════════════════════════════════════════════════
private
void
SpawnGates
(
McqQuestion
question
)
{
...
...
@@ -284,7 +279,7 @@ namespace com.al_arcade.mcq
float
playerZ
=
player
!=
null
?
player
.
transform
.
position
.
z
:
0f
;
// ★ Gates spawn relative to ROAD center (x=0), NOT player x
Vector3
basePos
=
new
Vector3
(
0f
,
0f
,
playerZ
+
gateSpawnDistance
);
float
totalWidth
=
(
answers
.
Length
-
1
)
*
gateSpacing
;
...
...
@@ -315,7 +310,6 @@ namespace com.al_arcade.mcq
return
gate
;
}
// ── Feedback ─────────────────────────────────────────────────
private
void
ShowCorrectFeedback
(
int
points
)
{
...
...
My project/Assets/ScienceStreet/MCQ/Scripts/McqGateController.cs
View file @
c336f670
...
...
@@ -42,11 +42,11 @@ namespace com.al_arcade.mcq
{
var
shader
=
GetShader
();
// ── Pillars ──────────────────────────────────────────────
CreatePillar
(
Vector3
.
left
*
(
GateWidth
/
2f
),
"LeftPillar"
,
shader
);
CreatePillar
(
Vector3
.
right
*
(
GateWidth
/
2f
),
"RightPillar"
,
shader
);
// ── Top bar ──────────────────────────────────────────────
var
topBar
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
topBar
.
name
=
"TopBar"
;
topBar
.
transform
.
SetParent
(
transform
);
...
...
@@ -56,7 +56,7 @@ namespace com.al_arcade.mcq
var
topMat
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Primary
};
topBar
.
GetComponent
<
Renderer
>().
material
=
topMat
;
// ── Answer panel — on the +Z side (back wall of gate archway) ──
_backPanel
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
_backPanel
.
name
=
"AnswerPanel"
;
_backPanel
.
transform
.
SetParent
(
transform
);
...
...
@@ -66,12 +66,12 @@ namespace com.al_arcade.mcq
_panelMaterial
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
GateDefault
};
_backPanel
.
GetComponent
<
Renderer
>().
material
=
_panelMaterial
;
// ── Text label — identity rotation, readable from -Z (camera side) ──
var
textObj
=
new
GameObject
(
"AnswerLabel"
);
textObj
.
transform
.
SetParent
(
transform
);
textObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
GateHeight
/
2f
,
GateDepth
/
2f
-
0.08f
);
// ★ NO Euler(0,180,0) — TMP 3D text is readable from -Z by default,
// camera is behind player at -Z. Identity rotation = correct.
textObj
.
transform
.
localRotation
=
Quaternion
.
identity
;
_label
=
textObj
.
AddComponent
<
ArabicTextMeshPro
>();
...
...
@@ -88,13 +88,13 @@ namespace com.al_arcade.mcq
_label
.
overflowMode
=
TMPro
.
TextOverflowModes
.
Ellipsis
;
SSFontManager
.
Apply
(
_label
);
// ── Trigger collider ─────────────────────────────────────
_collider
=
gameObject
.
AddComponent
<
BoxCollider
>();
_collider
.
isTrigger
=
true
;
_collider
.
center
=
new
Vector3
(
0
,
GateHeight
/
2f
,
0
);
_collider
.
size
=
new
Vector3
(
GateWidth
,
GateHeight
,
GateDepth
);
// ── Floor highlight ──────────────────────────────────────
var
floor
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
floor
.
name
=
"FloorHighlight"
;
floor
.
transform
.
SetParent
(
transform
);
...
...
@@ -147,7 +147,6 @@ namespace com.al_arcade.mcq
if
(
_label
!=
null
)
DOTween
.
Kill
(
_label
.
transform
);
}
// ── Collision ────────────────────────────────────────────────
private
void
OnTriggerEnter
(
Collider
other
)
{
...
...
@@ -157,7 +156,6 @@ namespace com.al_arcade.mcq
onPlayerEnter
?.
Invoke
(
GateIndex
);
}
// ── Feedback Animations ──────────────────────────────────────
public
void
PlayCorrectAnimation
()
{
...
...
My project/Assets/ScienceStreet/MCQ/Scripts/McqPrefabBuilder.cs
View file @
c336f670
This diff is collapsed.
Click to expand it.
My project/Assets/ScienceStreet/MCQ/Scripts/McqQuestionDisplay.cs
View file @
c336f670
...
...
@@ -25,7 +25,7 @@ namespace com.al_arcade.mcq
var
shader
=
Shader
.
Find
(
"Universal Render Pipeline/Lit"
)
??
Shader
.
Find
(
"Standard"
)
??
Shader
.
Find
(
"Unlit/Color"
);
// Background panel (Cube)
_panel
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
_panel
.
name
=
"QuestionPanel"
;
_panel
.
transform
.
SetParent
(
transform
);
...
...
@@ -36,7 +36,7 @@ namespace com.al_arcade.mcq
{
color
=
new
Color
(
0.12f
,
0.12f
,
0.5f
,
0.95f
)
};
_panel
.
GetComponent
<
Renderer
>().
material
=
panelMat
;
// Accent bar
var
bar
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
bar
.
name
=
"AccentBar"
;
bar
.
transform
.
SetParent
(
_panel
.
transform
);
...
...
@@ -46,8 +46,7 @@ namespace com.al_arcade.mcq
bar
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Accent
};
// ★ Question text — identity local rotation
// Parent will billboard to face camera
var
textObj
=
new
GameObject
(
"QuestionText"
);
textObj
.
transform
.
SetParent
(
transform
);
textObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
0.2f
,
-
0.06f
);
...
...
@@ -65,7 +64,7 @@ namespace com.al_arcade.mcq
_questionText
.
overflowMode
=
TMPro
.
TextOverflowModes
.
Ellipsis
;
SSFontManager
.
Apply
(
_questionText
);
// Source text
var
srcObj
=
new
GameObject
(
"SourceText"
);
srcObj
.
transform
.
SetParent
(
transform
);
srcObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
-
0.85f
,
-
0.06f
);
...
...
@@ -104,14 +103,14 @@ namespace com.al_arcade.mcq
{
if
(
_playerTransform
==
null
)
return
;
// ★ Follow player, stay between player and gates
Vector3
targetPos
=
_playerTransform
.
position
+
Vector3
.
up
*
floatHeight
+
Vector3
.
forward
*
forwardOffset
;
transform
.
position
=
Vector3
.
Lerp
(
transform
.
position
,
targetPos
,
Time
.
deltaTime
*
followSpeed
);
// ★ Billboard: face away from camera so text (-Z face) faces camera
if
(
Camera
.
main
!=
null
)
{
Vector3
awayFromCam
=
transform
.
position
-
Camera
.
main
.
transform
.
position
;
...
...
My project/Assets/ScienceStreet/MCQ/Scripts/McqUIManager.cs
View file @
c336f670
...
...
@@ -27,9 +27,6 @@ namespace com.al_arcade.mcq
[
Header
(
"Events"
)]
public
UnityEvent
onRestartClicked
;
// ════════════════════════════════════════════════════════════
// BUILD
// ════════════════════════════════════════════════════════════
public
void
BuildUI
()
{
...
...
@@ -82,7 +79,7 @@ namespace com.al_arcade.mcq
new
Vector2
(
200
,
-
15
),
24
,
TMPro
.
TextAlignmentOptions
.
TopLeft
);
_streakText
.
color
=
SSColorPalette
.
Warning
;
// Hearts
_heartIcons
=
new
Image
[
5
];
for
(
int
i
=
0
;
i
<
5
;
i
++)
{
...
...
@@ -98,7 +95,7 @@ namespace com.al_arcade.mcq
h
.
SetActive
(
false
);
}
// Progress bar
var
progBg
=
MakeImg
(
go
.
transform
,
"ProgressBg"
,
new
Vector2
(
0
,
0
),
new
Vector2
(
1
,
0
),
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.1f
));
...
...
@@ -208,7 +205,7 @@ namespace com.al_arcade.mcq
new
Vector2
(
200
,
0
),
24
);
_resultStreak
.
color
=
SSColorPalette
.
Accent
;
// Restart button
var
btnObj
=
new
GameObject
(
"RestartBtn"
);
btnObj
.
transform
.
SetParent
(
go
.
transform
,
false
);
var
br
=
btnObj
.
AddComponent
<
RectTransform
>();
...
...
@@ -229,9 +226,6 @@ namespace com.al_arcade.mcq
btnTxt
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
}
// ══════════════════════════════════════════════════════════
// PUBLIC
// ══════════════════════════════════════════════════════════
public
void
ShowGameUI
()
{
...
...
@@ -377,7 +371,6 @@ namespace com.al_arcade.mcq
_feedbackUI
.
alpha
=
0
;
}
// ── Helpers ──────────────────────────────────────────────────
private
GameObject
MakePanel
(
Transform
p
,
string
n
,
Vector2
amin
,
Vector2
amax
)
{
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSApiManager.cs
View file @
c336f670
// ============================================================================
// Science Street — API Manager (Singleton)
// Handles all communication with the PHP backend
// ============================================================================
using
System
;
using
System.Collections
;
using
System.Collections.Generic
;
...
...
@@ -21,7 +19,7 @@ namespace com.al_arcade.shared
[
SerializeField
]
private
int
timeoutSeconds
=
15
;
// ── Singleton Setup ──────────────────────────────────────────
private
void
Awake
()
{
if
(
Instance
!=
null
&&
Instance
!=
this
)
...
...
@@ -33,7 +31,7 @@ namespace com.al_arcade.shared
DontDestroyOnLoad
(
gameObject
);
}
// ── Ensure Instance Exists ───────────────────────────────────
public
static
SSApiManager
EnsureInstance
()
{
if
(
Instance
!=
null
)
return
Instance
;
...
...
@@ -43,9 +41,6 @@ namespace com.al_arcade.shared
return
Instance
;
}
// ════════════════════════════════════════════════════════════
// GENERIC REQUEST
// ════════════════════════════════════════════════════════════
public
IEnumerator
GetRequest
(
string
action
,
Dictionary
<
string
,
string
>
parameters
,
...
...
@@ -79,9 +74,6 @@ namespace com.al_arcade.shared
onSuccess
?.
Invoke
(
json
);
}
// ════════════════════════════════════════════════════════════
// PING
// ════════════════════════════════════════════════════════════
public
IEnumerator
Ping
(
Action
<
bool
>
onResult
)
{
...
...
@@ -90,9 +82,6 @@ namespace com.al_arcade.shared
err
=>
onResult
?.
Invoke
(
false
));
}
// ════════════════════════════════════════════════════════════
// VALIDATE CLASS CODE
// ════════════════════════════════════════════════════════════
public
IEnumerator
ValidateClassCode
(
string
code
,
Action
<
ClassInfo
>
onSuccess
,
...
...
@@ -120,9 +109,6 @@ namespace com.al_arcade.shared
onError
);
}
// ════════════════════════════════════════════════════════════
// GET GRADES
// ════════════════════════════════════════════════════════════
public
IEnumerator
GetGrades
(
Action
<
GradeInfo
[
]>
onSuccess
,
Action
<
string
>
onError
)
...
...
@@ -146,9 +132,6 @@ namespace com.al_arcade.shared
onError
);
}
// ════════════════════════════════════════════════════════════
// FETCH MCQ QUESTIONS
// ════════════════════════════════════════════════════════════
public
IEnumerator
FetchMcq
(
string
buildType
,
string
classCode
,
int
count
,
int
gradeId
,
...
...
@@ -183,9 +166,6 @@ namespace com.al_arcade.shared
onError
);
}
// ════════════════════════════════════════════════════════════
// FETCH T/F QUESTIONS
// ════════════════════════════════════════════════════════════
public
IEnumerator
FetchTf
(
string
buildType
,
string
classCode
,
int
count
,
int
gradeId
,
...
...
@@ -220,9 +200,6 @@ namespace com.al_arcade.shared
onError
);
}
// ════════════════════════════════════════════════════════════
// FETCH CS QUESTIONS
// ════════════════════════════════════════════════════════════
public
IEnumerator
FetchCs
(
string
buildType
,
string
classCode
,
int
count
,
int
gradeId
,
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSAudioManager.cs
View file @
c336f670
// ============================================================================
// Science Street — Audio Manager
// Plays SFX with optional AudioClip references.
// Works silently if no clips are assigned.
// ============================================================================
using
UnityEngine
;
using
System.Collections.Generic
;
...
...
@@ -77,7 +74,6 @@ namespace com.al_arcade.shared
return
src
;
}
// ── Play Methods ─────────────────────────────────────────────
public
void
Play
(
AudioClip
clip
,
float
volumeScale
=
1f
,
float
pitch
=
1f
)
{
...
...
@@ -104,10 +100,7 @@ namespace com.al_arcade.shared
public
void
PlayCheer
(
float
vol
=
1f
)
=>
Play
(
sfxCheer
,
vol
);
public
void
PlayCountdown
(
float
vol
=
0.8f
)
=>
Play
(
sfxCountdown
,
vol
);
/// <summary>
/// Plays a generated procedural beep (no AudioClip needed).
/// Useful for demo/prototype mode.
/// </summary>
public
void
PlayProceduralBeep
(
float
frequency
=
440f
,
float
duration
=
0.1f
,
float
volume
=
0.3f
)
{
...
...
@@ -119,7 +112,7 @@ namespace com.al_arcade.shared
for
(
int
i
=
0
;
i
<
sampleCount
;
i
++)
{
float
t
=
(
float
)
i
/
sampleRate
;
float
envelope
=
1f
-
((
float
)
i
/
sampleCount
);
// fade out
float
envelope
=
1f
-
((
float
)
i
/
sampleCount
);
data
[
i
]
=
Mathf
.
Sin
(
2f
*
Mathf
.
PI
*
frequency
*
t
)
*
envelope
*
volume
;
}
...
...
@@ -135,10 +128,10 @@ namespace com.al_arcade.shared
public
void
PlayClickBeep
()
=>
PlayProceduralBeep
(
660f
,
0.05f
,
0.15f
);
public
void
PlaySuccessJingle
()
{
// Three ascending tones
PlayProceduralBeep
(
523f
,
0.12f
,
0.2f
);
// C5
StartCoroutine
(
DelayedBeep
(
660f
,
0.12f
,
0.1f
));
// E5
StartCoroutine
(
DelayedBeep
(
784f
,
0.2f
,
0.2f
));
// G5
PlayProceduralBeep
(
523f
,
0.12f
,
0.2f
);
StartCoroutine
(
DelayedBeep
(
660f
,
0.12f
,
0.1f
));
StartCoroutine
(
DelayedBeep
(
784f
,
0.2f
,
0.2f
));
}
public
void
PlayFailBuzz
()
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSColorPalette.cs
View file @
c336f670
// ============================================================================
// Science Street — Shared Color Palette
// AL-Arcade Game Dev Team
// ============================================================================
using
UnityEngine
;
namespace
com.al_arcade.shared
{
/// <summary>
/// Central color definitions matching the Science Street brand.
/// </summary>
public
static
class
SSColorPalette
{
// ── Brand Colors ─────────────────────────────────────────────
public
static
readonly
Color
Primary
=
new
Color32
(
48
,
48
,
208
,
255
);
// #3030D0
public
static
readonly
Color
PrimaryDark
=
new
Color32
(
32
,
32
,
168
,
255
);
// #2020A8
public
static
readonly
Color
PrimaryLight
=
new
Color32
(
80
,
80
,
220
,
255
);
// #5050DC
public
static
readonly
Color
Accent
=
new
Color32
(
254
,
215
,
0
,
255
);
// #FED700
public
static
readonly
Color
AccentDark
=
new
Color32
(
212
,
180
,
0
,
255
);
// #D4B400
// ── Feedback Colors ──────────────────────────────────────────
public
static
readonly
Color
Success
=
new
Color32
(
16
,
185
,
129
,
255
);
// #10B981
public
static
readonly
Color
SuccessLight
=
new
Color32
(
209
,
250
,
229
,
255
);
// #D1FAE5
public
static
readonly
Color
Danger
=
new
Color32
(
239
,
68
,
68
,
255
);
// #EF4444
public
static
readonly
Color
DangerLight
=
new
Color32
(
254
,
226
,
226
,
255
);
// #FEE2E2
public
static
readonly
Color
Warning
=
new
Color32
(
245
,
158
,
11
,
255
);
// #F59E0B
public
static
readonly
Color
Info
=
new
Color32
(
59
,
130
,
246
,
255
);
// #3B82F6
// ── UI Colors ────────────────────────────────────────────────
public
static
readonly
Color
Background
=
new
Color32
(
238
,
240
,
248
,
255
);
// #EEF0F8
public
static
readonly
Color
Primary
=
new
Color32
(
48
,
48
,
208
,
255
);
public
static
readonly
Color
PrimaryDark
=
new
Color32
(
32
,
32
,
168
,
255
);
public
static
readonly
Color
PrimaryLight
=
new
Color32
(
80
,
80
,
220
,
255
);
public
static
readonly
Color
Accent
=
new
Color32
(
254
,
215
,
0
,
255
);
public
static
readonly
Color
AccentDark
=
new
Color32
(
212
,
180
,
0
,
255
);
public
static
readonly
Color
Success
=
new
Color32
(
16
,
185
,
129
,
255
);
public
static
readonly
Color
SuccessLight
=
new
Color32
(
209
,
250
,
229
,
255
);
public
static
readonly
Color
Danger
=
new
Color32
(
239
,
68
,
68
,
255
);
public
static
readonly
Color
DangerLight
=
new
Color32
(
254
,
226
,
226
,
255
);
public
static
readonly
Color
Warning
=
new
Color32
(
245
,
158
,
11
,
255
);
public
static
readonly
Color
Info
=
new
Color32
(
59
,
130
,
246
,
255
);
public
static
readonly
Color
Background
=
new
Color32
(
238
,
240
,
248
,
255
);
public
static
readonly
Color
Card
=
Color
.
white
;
public
static
readonly
Color
TextDark
=
new
Color32
(
26
,
26
,
46
,
255
);
// #1A1A2E
public
static
readonly
Color
TextMuted
=
new
Color32
(
107
,
114
,
128
,
255
);
// #6B7280
public
static
readonly
Color
Border
=
new
Color32
(
229
,
231
,
235
,
255
);
// #E5E7EB
public
static
readonly
Color
TextDark
=
new
Color32
(
26
,
26
,
46
,
255
);
public
static
readonly
Color
TextMuted
=
new
Color32
(
107
,
114
,
128
,
255
);
public
static
readonly
Color
Border
=
new
Color32
(
229
,
231
,
235
,
255
);
// ── Game-specific ────────────────────────────────────────────
public
static
readonly
Color
GateCorrect
=
new
Color32
(
16
,
185
,
129
,
255
);
public
static
readonly
Color
GateWrong
=
new
Color32
(
239
,
68
,
68
,
255
);
public
static
readonly
Color
GateDefault
=
new
Color32
(
80
,
80
,
220
,
255
);
public
static
readonly
Color
TrueGreen
=
new
Color32
(
34
,
197
,
94
,
255
);
// #22C55E
public
static
readonly
Color
FalseRed
=
new
Color32
(
239
,
68
,
68
,
255
);
// #EF4444
public
static
readonly
Color
TrueGreen
=
new
Color32
(
34
,
197
,
94
,
255
);
public
static
readonly
Color
FalseRed
=
new
Color32
(
239
,
68
,
68
,
255
);
public
static
readonly
Color
WrongWord
=
new
Color32
(
239
,
68
,
68
,
255
);
public
static
readonly
Color
CorrectWord
=
new
Color32
(
16
,
185
,
129
,
255
);
public
static
readonly
Color
NeutralWord
=
new
Color32
(
248
,
249
,
252
,
255
);
// ── Helpers ──────────────────────────────────────────────────
public
static
Color
WithAlpha
(
Color
c
,
float
a
)
{
return
new
Color
(
c
.
r
,
c
.
g
,
c
.
b
,
a
);
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSDataModels.cs
View file @
c336f670
// ============================================================================
// Science Street — Shared Data Models
// JSON deserialization targets for API responses
// ============================================================================
using
System
;
using
UnityEngine
;
using
Newtonsoft.Json
;
namespace
com.al_arcade.shared
{
// ── API Wrapper Responses ────────────────────────────────────────
[
Serializable
]
public
class
ApiResponse
<
T
>
...
...
@@ -37,7 +35,6 @@ namespace com.al_arcade.shared
public
ClassInfo
classInfo
;
}
// ── Core Data Types ──────────────────────────────────────────────
[
Serializable
]
public
class
GradeInfo
...
...
@@ -58,30 +55,26 @@ namespace com.al_arcade.shared
public
string
teacher_name
;
}
// ── MCQ ──────────────────────────────────────────────────────────
[
Serializable
]
public
class
McqQuestion
{
public
string
id
;
public
string
question_text
;
public
string
answer1
;
// always correct
public
string
answer1
;
public
string
answer2
;
public
string
answer3
;
public
string
answer4
;
public
string
source
;
public
string
grade_name
;
/// <summary>
/// Returns all 4 answers shuffled. Sets correctIndex to the
/// position of the correct answer in the shuffled array.
/// </summary>
public
string
[]
GetShuffledAnswers
(
out
int
correctIndex
)
{
string
[]
arr
=
{
answer1
,
answer2
,
answer3
,
answer4
};
string
correct
=
answer1
;
// Fisher-Yates shuffle
for
(
int
i
=
arr
.
Length
-
1
;
i
>
0
;
i
--)
{
int
j
=
UnityEngine
.
Random
.
Range
(
0
,
i
+
1
);
...
...
@@ -93,7 +86,6 @@ namespace com.al_arcade.shared
}
}
// ── True/False ───────────────────────────────────────────────────
[
Serializable
]
public
class
TfQuestion
...
...
@@ -105,7 +97,6 @@ namespace com.al_arcade.shared
public
string
grade_name
;
}
// ── Correct Sentence ─────────────────────────────────────────────
[
Serializable
]
public
class
CsQuestion
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSFontManager.cs
View file @
c336f670
...
...
@@ -2,10 +2,8 @@ using UnityEngine;
namespace
com.al_arcade.shared
{
/// <summary>
/// Global Arabic font manager. Set the font once from any DemoBuilder,
/// then all text components pick it up via Apply().
/// </summary>
public
static
class
SSFontManager
{
private
static
TMPro
.
TMP_FontAsset
_font
;
...
...
@@ -26,4 +24,4 @@ namespace com.al_arcade.shared
if
(
_font
!=
null
&&
tmp
!=
null
)
tmp
.
font
=
_font
;
}
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/Shared/Scripts/SSGameSession.cs
View file @
c336f670
// ============================================================================
// Science Street — Game Session Manager
// Holds current game session state (build type, class code, etc.)
// ============================================================================
using
System
;
using
System.Collections
;
using
UnityEngine
;
...
...
@@ -23,14 +21,14 @@ namespace com.al_arcade.shared
[
Tooltip
(
"Number of questions to fetch"
)]
public
int
questionCount
=
10
;
// ── Runtime State (Teacher Build) ────────────────────────────
[
HideInInspector
]
public
string
classCode
=
""
;
[
HideInInspector
]
public
string
className
=
""
;
[
HideInInspector
]
public
string
teacherName
=
""
;
[
HideInInspector
]
public
string
gradeName
=
""
;
[
HideInInspector
]
public
bool
isClassValidated
=
false
;
// ── Events ───────────────────────────────────────────────────
[
Header
(
"Events"
)]
public
UnityEvent
onSessionReady
;
public
UnityEvent
<
string
>
onSessionError
;
...
...
@@ -55,9 +53,7 @@ namespace com.al_arcade.shared
return
Instance
;
}
/// <summary>
/// Validates a teacher class code. On success, stores all class info.
/// </summary>
public
IEnumerator
ValidateAndStartTeacherSession
(
string
code
,
Action
onSuccess
,
Action
<
string
>
onError
)
{
...
...
@@ -89,9 +85,7 @@ namespace com.al_arcade.shared
});
}
/// <summary>
/// Starts a Science Street (public) session.
/// </summary>
public
void
StartSciStreetSession
(
int
grade
=
0
)
{
buildType
=
"scistreet"
;
...
...
@@ -102,9 +96,7 @@ namespace com.al_arcade.shared
onSessionReady
?.
Invoke
();
}
/// <summary>
/// Resets the session to defaults.
/// </summary>
public
void
ResetSession
()
{
buildType
=
"scistreet"
;
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSParticleManager.cs
View file @
c336f670
// ============================================================================
// Science Street — Particle Effect Manager
// Creates particle effects programmatically. Works without any prefabs.
// ============================================================================
using
UnityEngine
;
using
System.Collections
;
using
System.Collections.Generic
;
...
...
@@ -41,7 +39,6 @@ namespace com.al_arcade.shared
return
Instance
;
}
// ── Public Play Methods ──────────────────────────────────────
public
void
PlayCorrectBurst
(
Vector3
position
)
{
...
...
@@ -105,7 +102,6 @@ namespace com.al_arcade.shared
PlayConfetti
(
pos
);
}
// ── Procedural Particle Creation ─────────────────────────────
private
void
PlayProceduralBurst
(
Vector3
pos
,
Color
startColor
,
Color
endColor
,
int
count
,
float
lifetime
)
...
...
@@ -141,7 +137,7 @@ namespace com.al_arcade.shared
new
Keyframe
(
0f
,
1f
),
new
Keyframe
(
1f
,
0f
)));
// Use default material
var
renderer
=
go
.
GetComponent
<
ParticleSystemRenderer
>();
renderer
.
material
=
GetParticleMaterial
();
...
...
@@ -169,7 +165,7 @@ namespace com.al_arcade.shared
main
.
loop
=
false
;
main
.
duration
=
0.2f
;
// Random color from our palette
var
gradient
=
new
Gradient
();
gradient
.
SetKeys
(
new
[]
{
...
...
@@ -208,7 +204,6 @@ namespace com.al_arcade.shared
Destroy
(
go
,
5f
);
}
// ── Helpers ──────────────────────────────────────────────────
private
void
SpawnPrefab
(
ParticleSystem
prefab
,
Vector3
pos
)
{
...
...
@@ -225,7 +220,7 @@ namespace com.al_arcade.shared
{
if
(
_cachedMat
!=
null
)
return
_cachedMat
;
// Try to find the default particle shader
Shader
shader
=
Shader
.
Find
(
"Particles/Standard Unlit"
);
if
(
shader
==
null
)
shader
=
Shader
.
Find
(
"Universal Render Pipeline/Particles/Unlit"
);
if
(
shader
==
null
)
shader
=
Shader
.
Find
(
"Mobile/Particles/Alpha Blended"
);
...
...
@@ -233,7 +228,7 @@ namespace com.al_arcade.shared
if
(
shader
==
null
)
shader
=
Shader
.
Find
(
"Unlit/Color"
);
_cachedMat
=
new
Material
(
shader
);
_cachedMat
.
SetFloat
(
"_Mode"
,
2
);
// Fade
_cachedMat
.
SetFloat
(
"_Mode"
,
2
);
return
_cachedMat
;
}
}
...
...
My project/Assets/ScienceStreet/TF/Scripts/TfDemoBuilder.cs
View file @
c336f670
This diff is collapsed.
Click to expand it.
My project/Assets/ScienceStreet/TF/Scripts/TfHandController.cs
View file @
c336f670
...
...
@@ -43,13 +43,13 @@ namespace com.al_arcade.tf
float
side
=
isLeft
?
-
1f
:
1f
;
var
shader
=
GetShader
();
// ── Hand root ────────────────────────────────────────────
hand
=
new
GameObject
(
isLeft
?
"LeftHand"
:
"RightHand"
);
hand
.
transform
.
SetParent
(
transform
);
hand
.
transform
.
localPosition
=
new
Vector3
(
side
*
0.35f
,
-
0.3f
,
0.55f
);
hand
.
transform
.
localRotation
=
Quaternion
.
Euler
(
12f
,
-
side
*
8f
,
side
*
4f
);
// ── Arm (smaller, more proportional) ─────────────────────
var
arm
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Capsule
);
arm
.
name
=
"Arm"
;
arm
.
transform
.
SetParent
(
hand
.
transform
);
...
...
@@ -59,7 +59,7 @@ namespace com.al_arcade.tf
arm
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
255
,
220
,
180
,
255
)
};
// ── Button (sized for close-up FPS view) ─────────────────
btn
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cylinder
);
btn
.
name
=
isLeft
?
"TrueButton"
:
"FalseButton"
;
btn
.
transform
.
SetParent
(
hand
.
transform
);
...
...
@@ -73,17 +73,17 @@ namespace com.al_arcade.tf
};
btn
.
GetComponent
<
Renderer
>().
material
=
mat
;
// ── Label — ★ small font, tight rect, on top of button ───
var
labelObj
=
new
GameObject
(
"Label"
);
labelObj
.
transform
.
SetParent
(
btn
.
transform
);
labelObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
0.8f
,
0
);
labelObj
.
transform
.
localRotation
=
Quaternion
.
Euler
(
90
,
0
,
0
);
// ★ Scale the label container down so the text is proportional
labelObj
.
transform
.
localScale
=
new
Vector3
(
0.6f
,
0.6f
,
0.6f
);
label
=
labelObj
.
AddComponent
<
ArabicTextMeshPro
>();
label
.
arabicText
=
isLeft
?
"صح ✓"
:
"خطأ ✗"
;
// ★ fontSize 2 in a small world-space rect = readable not giant
label
.
fontSize
=
2.2f
;
label
.
fontSizeMin
=
1.5f
;
label
.
fontSizeMax
=
2.5f
;
...
...
@@ -91,12 +91,12 @@ namespace com.al_arcade.tf
label
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
label
.
color
=
Color
.
white
;
label
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
// ★ Tight rect so text doesn't overflow
label
.
rectTransform
.
sizeDelta
=
new
Vector2
(
1.2f
,
0.5f
);
label
.
overflowMode
=
TMPro
.
TextOverflowModes
.
Overflow
;
SSFontManager
.
Apply
(
label
);
// ── Glow ring ────────────────────────────────────────────
var
ring
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cylinder
);
ring
.
name
=
"GlowRing"
;
ring
.
transform
.
SetParent
(
btn
.
transform
);
...
...
@@ -110,7 +110,6 @@ namespace com.al_arcade.tf
};
}
// ── Idle Animation ───────────────────────────────────────────
private
void
StartIdleAnimation
()
{
...
...
@@ -139,7 +138,6 @@ namespace com.al_arcade.tf
_idleSeq
=
null
;
}
// ── Input ────────────────────────────────────────────────────
public
void
SetReady
(
bool
ready
)
=>
_isReady
=
ready
;
...
...
@@ -161,14 +159,14 @@ namespace com.al_arcade.tf
var
restPos
=
isTrue
?
_leftRestPos
:
_rightRestPos
;
var
btnBaseScale
=
isTrue
?
_leftBtnBaseScale
:
_rightBtnBaseScale
;
// ★ Kill ALL tweens, reset to known state
KillIdleTween
();
DOTween
.
Kill
(
hand
.
transform
);
DOTween
.
Kill
(
btn
.
transform
);
hand
.
transform
.
localPosition
=
restPos
;
btn
.
transform
.
localScale
=
btnBaseScale
;
// ★ Press animation — always returns to restPos
var
pressSeq
=
DOTween
.
Sequence
();
pressSeq
.
Append
(
hand
.
transform
.
DOLocalMoveY
(
restPos
.
y
+
0.06f
,
0.07f
)
...
...
@@ -181,7 +179,7 @@ namespace com.al_arcade.tf
.
SetEase
(
Ease
.
OutBounce
));
pressSeq
.
OnComplete
(()
=>
StartIdleAnimation
());
// ★ Button squash (Y axis is thickness for cylinder)
btn
.
transform
.
DOScaleY
(
btnBaseScale
.
y
*
0.3f
,
0.05f
)
.
SetEase
(
Ease
.
InQuad
)
.
OnComplete
(()
=>
...
...
@@ -195,7 +193,6 @@ namespace com.al_arcade.tf
TfGameManager
.
Instance
.
SubmitAnswer
(
isTrue
);
}
// ── Feedback ─────────────────────────────────────────────────
public
void
PlayCorrectFeedback
(
bool
wasTrue
)
{
...
...
@@ -270,4 +267,4 @@ namespace com.al_arcade.tf
Shader
.
Find
(
"Universal Render Pipeline/Lit"
)
??
Shader
.
Find
(
"Standard"
)
??
Shader
.
Find
(
"Unlit/Color"
);
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/TF/Scripts/TfPrefabBuilder.cs
View file @
c336f670
...
...
@@ -12,9 +12,7 @@ namespace com.al_arcade.tf
[
AddComponentMenu
(
"Science Street/TF Prefab Builder"
)]
public
class
TfPrefabBuilder
:
MonoBehaviour
{
// ════════════════════════════════════════════════════════════
// SCENE
// ════════════════════════════════════════════════════════════
[
Header
(
"Scene Environment"
)]
[
Tooltip
(
"Your full factory environment prefab."
)]
...
...
@@ -26,18 +24,12 @@ namespace com.al_arcade.tf
[
SerializeField
]
private
float
cameraFOV
=
55f
;
[
SerializeField
]
private
Color
cameraBgColor
=
new
Color32
(
70
,
80
,
110
,
255
);
// ════════════════════════════════════════════════════════════
// LIGHTING
// ════════════════════════════════════════════════════════════
[
Header
(
"Lighting"
)]
[
SerializeField
]
private
GameObject
directionalLightPrefab
;
[
SerializeField
]
private
GameObject
[]
extraLightPrefabs
;
[
SerializeField
]
private
Color
ambientColor
=
new
Color32
(
75
,
78
,
95
,
255
);
// ════════════════════════════════════════════════════════════
// PRODUCTION LINE
// ════════════════════════════════════════════════════════════
[
Header
(
"Production Line"
)]
[
Tooltip
(
"Your production line prefab. MUST have TfProductionLine.\n"
+
...
...
@@ -45,9 +37,6 @@ namespace com.al_arcade.tf
[
SerializeField
]
private
GameObject
productionLinePrefab
;
[
SerializeField
]
private
Vector3
productionLinePosition
=
new
Vector3
(
0
,
0
,
2
);
// ════════════════════════════════════════════════════════════
// QUESTION SCREEN
// ════════════════════════════════════════════════════════════
[
Header
(
"Question Screen"
)]
[
Tooltip
(
"Your question screen prefab. MUST have TfQuestionScreen.\n"
+
...
...
@@ -55,27 +44,18 @@ namespace com.al_arcade.tf
[
SerializeField
]
private
GameObject
questionScreenPrefab
;
[
SerializeField
]
private
Vector3
questionScreenPosition
=
new
Vector3
(
0
,
5f
,
12f
);
// ════════════════════════════════════════════════════════════
// HANDS
// ════════════════════════════════════════════════════════════
[
Header
(
"Hands / Buttons"
)]
[
Tooltip
(
"Your hands prefab. MUST have TfHandController.\n"
+
"If null, procedural hands are created."
)]
[
SerializeField
]
private
GameObject
handsPrefab
;
// ════════════════════════════════════════════════════════════
// UI
// ════════════════════════════════════════════════════════════
[
Header
(
"UI Canvas"
)]
[
Tooltip
(
"Your Canvas prefab. MUST have TfUIManager with all references wired.\n"
+
"If null, procedural UI is created."
)]
[
SerializeField
]
private
GameObject
canvasPrefab
;
// ════════════════════════════════════════════════════════════
// AUDIO
// ════════════════════════════════════════════════════════════
[
Header
(
"Audio — SFX Clips"
)]
[
SerializeField
]
private
AudioClip
sfxCorrect
;
...
...
@@ -87,9 +67,6 @@ namespace com.al_arcade.tf
[
SerializeField
]
private
AudioClip
sfxPop
;
[
SerializeField
]
private
AudioClip
sfxSlam
;
// ════════════════════════════════════════════════════════════
// PARTICLES
// ════════════════════════════════════════════════════════════
[
Header
(
"Particles"
)]
[
SerializeField
]
private
ParticleSystem
correctBurstParticle
;
...
...
@@ -98,16 +75,10 @@ namespace com.al_arcade.tf
[
SerializeField
]
private
ParticleSystem
sparksParticle
;
[
SerializeField
]
private
ParticleSystem
starBurstParticle
;
// ════════════════════════════════════════════════════════════
// FONT
// ════════════════════════════════════════════════════════════
[
Header
(
"Arabic Font"
)]
[
SerializeField
]
private
TMP_FontAsset
arabicFont
;
// ════════════════════════════════════════════════════════════
// GAME SETTINGS
// ════════════════════════════════════════════════════════════
[
Header
(
"Game Settings"
)]
[
SerializeField
]
private
string
buildType
=
"scistreet"
;
...
...
@@ -120,9 +91,6 @@ namespace com.al_arcade.tf
[
Header
(
"Debug"
)]
[
SerializeField
]
private
bool
useOfflineTestData
=
false
;
// ════════════════════════════════════════════════════════════
// RUNTIME
// ════════════════════════════════════════════════════════════
private
TfGameManager
_gm
;
private
TfHandController
_handController
;
...
...
@@ -159,20 +127,20 @@ namespace com.al_arcade.tf
session
.
classCode
=
classCode
;
yield
return
null
;
// ── Camera ───────────────────────────────────────────
SetupCamera
();
yield
return
null
;
// ── Environment ──────────────────────────────────────
if
(
environmentPrefab
!=
null
)
Instantiate
(
environmentPrefab
,
Vector3
.
zero
,
Quaternion
.
identity
);
yield
return
null
;
// ── Lighting ─────────────────────────────────────────
SetupLighting
();
yield
return
null
;
// ── Production Line ──────────────────────────────────
if
(
productionLinePrefab
!=
null
)
{
var
lineObj
=
Instantiate
(
productionLinePrefab
,
...
...
@@ -194,7 +162,7 @@ namespace com.al_arcade.tf
}
yield
return
null
;
// ── Question Screen ──────────────────────────────────
if
(
questionScreenPrefab
!=
null
)
{
var
screenObj
=
Instantiate
(
questionScreenPrefab
,
...
...
@@ -215,7 +183,7 @@ namespace com.al_arcade.tf
}
yield
return
null
;
// ── Hands ────────────────────────────────────────────
if
(
handsPrefab
!=
null
)
{
var
handsObj
=
Instantiate
(
handsPrefab
);
...
...
@@ -235,7 +203,7 @@ namespace com.al_arcade.tf
}
yield
return
null
;
// ── UI ───────────────────────────────────────────────
if
(
canvasPrefab
!=
null
)
{
var
canvasObj
=
Instantiate
(
canvasPrefab
);
...
...
@@ -258,7 +226,7 @@ namespace com.al_arcade.tf
_uiManager
.
onRestartClicked
=
new
UnityEvent
();
yield
return
null
;
// ── Game Manager ─────────────────────────────────────
var
gmObj
=
new
GameObject
(
"TfGameManager"
);
_gm
=
gmObj
.
AddComponent
<
TfGameManager
>();
_gm
.
handController
=
_handController
;
...
...
@@ -348,4 +316,4 @@ namespace com.al_arcade.tf
};
}
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/TF/Scripts/TfProductionLine.cs
View file @
c336f670
...
...
@@ -21,7 +21,7 @@ namespace com.al_arcade.tf
float
totalLength
=
stepsToWin
*
stepDistance
+
10f
;
var
shader
=
GetShader
();
// ── Belt surface ─────────────────────────────────────────
var
belt
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
belt
.
name
=
"Belt"
;
belt
.
transform
.
SetParent
(
transform
);
...
...
@@ -31,7 +31,7 @@ namespace com.al_arcade.tf
belt
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
55
,
55
,
65
,
255
)
};
// ── Belt top highlight ───────────────────────────────────
var
beltTop
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
beltTop
.
name
=
"BeltTop"
;
beltTop
.
transform
.
SetParent
(
transform
);
...
...
@@ -41,7 +41,7 @@ namespace com.al_arcade.tf
beltTop
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
70
,
70
,
80
,
255
)
};
// ── Rollers ──────────────────────────────────────────────
int
rc
=
Mathf
.
CeilToInt
(
totalLength
/
2f
);
_rollers
=
new
GameObject
[
rc
];
for
(
int
i
=
0
;
i
<
rc
;
i
++)
...
...
@@ -58,7 +58,7 @@ namespace com.al_arcade.tf
_rollers
[
i
]
=
r
;
}
// ── Side rails ───────────────────────────────────────────
for
(
int
s
=
-
1
;
s
<=
1
;
s
+=
2
)
{
var
rail
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
...
...
@@ -71,7 +71,7 @@ namespace com.al_arcade.tf
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Primary
};
}
// ── Legs ─────────────────────────────────────────────────
for
(
float
z
=
1
;
z
<
totalLength
;
z
+=
4f
)
{
for
(
int
s
=
-
1
;
s
<=
1
;
s
+=
2
)
...
...
@@ -87,12 +87,12 @@ namespace com.al_arcade.tf
}
}
// ── Progress markers ─────────────────────────────────────
for
(
int
i
=
0
;
i
<
stepsToWin
;
i
++)
{
float
mz
=
(
i
+
1
)
*
stepDistance
;
// Line marker
var
marker
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
marker
.
name
=
$"Marker_
{
i
}
"
;
marker
.
transform
.
SetParent
(
transform
);
...
...
@@ -105,13 +105,13 @@ namespace com.al_arcade.tf
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Accent
,
0.5f
)
};
// Step label — facing camera
var
labelObj
=
new
GameObject
(
"StepLabel"
);
labelObj
.
transform
.
SetParent
(
marker
.
transform
);
labelObj
.
transform
.
position
=
marker
.
transform
.
position
+
new
Vector3
(
1.6f
,
0.5f
,
0
);
// Billboard toward camera
Vector3
away
=
labelObj
.
transform
.
position
-
cameraPos
;
away
.
y
=
0
;
if
(
away
.
sqrMagnitude
>
0.01f
)
...
...
@@ -119,7 +119,7 @@ namespace com.al_arcade.tf
var
lbl
=
labelObj
.
AddComponent
<
ArabicTextMeshPro
>();
lbl
.
arabicText
=
$"✦
{
i
+
1
}
"
;
// ★ Small readable size
lbl
.
fontSize
=
2f
;
lbl
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
lbl
.
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Accent
,
0.7f
);
...
...
@@ -127,7 +127,7 @@ namespace com.al_arcade.tf
SSFontManager
.
Apply
(
lbl
);
}
// ── End zone ─────────────────────────────────────────────
float
endZ
=
stepsToWin
*
stepDistance
+
2f
;
var
ez
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
ez
.
name
=
"EndZone"
;
...
...
@@ -138,7 +138,7 @@ namespace com.al_arcade.tf
ez
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Success
,
0.35f
)
};
// ── Product ──────────────────────────────────────────────
_product
=
new
GameObject
(
"Product"
);
_product
.
transform
.
SetParent
(
transform
);
_product
.
transform
.
localPosition
=
new
Vector3
(
0
,
0.7f
,
0
);
...
...
@@ -152,7 +152,7 @@ namespace com.al_arcade.tf
_productMat
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Accent
};
box
.
GetComponent
<
Renderer
>().
material
=
_productMat
;
// Stripe on box
var
stripe
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
stripe
.
name
=
"Stripe"
;
stripe
.
transform
.
SetParent
(
_product
.
transform
);
...
...
@@ -162,7 +162,7 @@ namespace com.al_arcade.tf
stripe
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
Primary
};
// Star on top
var
star
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Sphere
);
star
.
name
=
"Star"
;
star
.
transform
.
SetParent
(
_product
.
transform
);
...
...
@@ -175,7 +175,6 @@ namespace com.al_arcade.tf
_currentZ
=
0
;
}
// ── Movement ─────────────────────────────────────────────────
public
IEnumerator
MoveForward
(
float
dist
)
{
...
...
@@ -265,4 +264,4 @@ namespace com.al_arcade.tf
Shader
.
Find
(
"Universal Render Pipeline/Lit"
)
??
Shader
.
Find
(
"Standard"
)
??
Shader
.
Find
(
"Unlit/Color"
);
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/TF/Scripts/TfQuestionScreen.cs
View file @
c336f670
...
...
@@ -15,15 +15,13 @@ namespace com.al_arcade.tf
private
Material
_feedbackMat
;
private
GameObject
_feedbackPanel
;
/// <summary>
/// Build screen at position, rotated to face cameraPos.
/// </summary>
public
void
Build
(
Vector3
position
,
Vector3
cameraPos
)
{
transform
.
position
=
position
;
var
shader
=
GetShader
();
// ── Frame ────────────────────────────────────────────────
var
frame
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
frame
.
name
=
"Frame"
;
frame
.
transform
.
SetParent
(
transform
);
...
...
@@ -33,7 +31,7 @@ namespace com.al_arcade.tf
frame
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
25
,
25
,
35
,
255
)
};
// ── Screen border highlight ──────────────────────────────
var
borderGlow
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
borderGlow
.
name
=
"BorderGlow"
;
borderGlow
.
transform
.
SetParent
(
transform
);
...
...
@@ -43,7 +41,7 @@ namespace com.al_arcade.tf
borderGlow
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Primary
,
0.3f
)
};
// ── Screen surface ───────────────────────────────────────
var
surface
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
surface
.
name
=
"Surface"
;
surface
.
transform
.
SetParent
(
transform
);
...
...
@@ -53,7 +51,7 @@ namespace com.al_arcade.tf
_screenMat
=
new
Material
(
shader
)
{
color
=
new
Color32
(
15
,
15
,
50
,
255
)
};
surface
.
GetComponent
<
Renderer
>().
material
=
_screenMat
;
// ── Pole ─────────────────────────────────────────────────
var
pole
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cylinder
);
pole
.
name
=
"Pole"
;
pole
.
transform
.
SetParent
(
transform
);
...
...
@@ -63,7 +61,7 @@ namespace com.al_arcade.tf
pole
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
70
,
70
,
85
,
255
)
};
// ── Pole base ────────────────────────────────────────────
var
poleBase
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cylinder
);
poleBase
.
name
=
"PoleBase"
;
poleBase
.
transform
.
SetParent
(
transform
);
...
...
@@ -73,7 +71,7 @@ namespace com.al_arcade.tf
poleBase
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
new
Color32
(
60
,
60
,
75
,
255
)
};
// ── Question text ★ z = -0.25 (pushed out toward camera) ─
var
textObj
=
new
GameObject
(
"QuestionText"
);
textObj
.
transform
.
SetParent
(
transform
);
textObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
0.25f
,
-
0.25f
);
...
...
@@ -84,7 +82,7 @@ namespace com.al_arcade.tf
_questionText
.
color
=
Color
.
white
;
_questionText
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
_questionText
.
enableAutoSizing
=
true
;
// ★ Sensible font range for a 7-unit-wide screen at ~12m distance
_questionText
.
fontSizeMin
=
1.8f
;
_questionText
.
fontSizeMax
=
3.8f
;
_questionText
.
rectTransform
.
sizeDelta
=
new
Vector2
(
6.2f
,
2.2f
);
...
...
@@ -92,7 +90,7 @@ namespace com.al_arcade.tf
_questionText
.
overflowMode
=
TMPro
.
TextOverflowModes
.
Ellipsis
;
SSFontManager
.
Apply
(
_questionText
);
// ── Source text ──────────────────────────────────────────
var
srcObj
=
new
GameObject
(
"SourceText"
);
srcObj
.
transform
.
SetParent
(
transform
);
srcObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
-
1.15f
,
-
0.25f
);
...
...
@@ -105,7 +103,7 @@ namespace com.al_arcade.tf
_sourceText
.
rectTransform
.
sizeDelta
=
new
Vector2
(
6f
,
0.5f
);
SSFontManager
.
Apply
(
_sourceText
);
// ── Feedback panel (overlays question) ───────────────────
_feedbackPanel
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
_feedbackPanel
.
name
=
"FeedbackPanel"
;
_feedbackPanel
.
transform
.
SetParent
(
transform
);
...
...
@@ -122,14 +120,14 @@ namespace com.al_arcade.tf
fbObj
.
transform
.
SetParent
(
_feedbackPanel
.
transform
);
fbObj
.
transform
.
localPosition
=
new
Vector3
(
0
,
0
,
-
0.15f
);
fbObj
.
transform
.
localRotation
=
Quaternion
.
identity
;
// ★ Scale container so feedback text isn't giant
// FeedbackPanel is 6.6 wide but we want text around 3 units
fbObj
.
transform
.
localScale
=
new
Vector3
(
0.5f
,
0.5f
,
1f
);
_feedbackText
=
fbObj
.
AddComponent
<
ArabicTextMeshPro
>();
_feedbackText
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
_feedbackText
.
color
=
Color
.
white
;
// ★ Moderate feedback font size
_feedbackText
.
fontSize
=
4f
;
_feedbackText
.
fontSizeMin
=
2.5f
;
_feedbackText
.
fontSizeMax
=
5f
;
...
...
@@ -140,7 +138,7 @@ namespace com.al_arcade.tf
_feedbackText
.
arabicText
=
""
;
SSFontManager
.
Apply
(
_feedbackText
);
// ── Accent strips (top + bottom) ─────────────────────────
var
topStrip
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Cube
);
topStrip
.
name
=
"TopStrip"
;
topStrip
.
transform
.
SetParent
(
transform
);
...
...
@@ -159,7 +157,7 @@ namespace com.al_arcade.tf
botStrip
.
GetComponent
<
Renderer
>().
material
=
new
Material
(
shader
)
{
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
Accent
,
0.5f
)
};
// ── Status indicator lights ──────────────────────────────
for
(
int
i
=
-
1
;
i
<=
1
;
i
+=
2
)
{
var
light
=
GameObject
.
CreatePrimitive
(
PrimitiveType
.
Sphere
);
...
...
@@ -174,18 +172,17 @@ namespace com.al_arcade.tf
};
}
// ★ Rotate entire screen so -Z faces camera
Vector3
awayFromCamera
=
transform
.
position
-
cameraPos
;
awayFromCamera
.
y
=
0
;
if
(
awayFromCamera
.
sqrMagnitude
>
0.01f
)
transform
.
rotation
=
Quaternion
.
LookRotation
(
awayFromCamera
);
}
// ── Show Question ────────────────────────────────────────────
public
void
ShowQuestion
(
string
text
,
string
source
=
""
)
{
// Hide feedback
if
(
_feedbackMat
!=
null
)
{
DOTween
.
Kill
(
_feedbackMat
,
"fbMat"
);
...
...
@@ -207,7 +204,7 @@ namespace com.al_arcade.tf
if
(
_sourceText
!=
null
)
_sourceText
.
arabicText
=
!
string
.
IsNullOrEmpty
(
source
)
?
$"📖
{
source
}
"
:
""
;
// Screen flash effect
if
(
_screenMat
!=
null
)
{
DOTween
.
Kill
(
_screenMat
,
"screenFlash"
);
...
...
@@ -219,7 +216,6 @@ namespace com.al_arcade.tf
}
}
// ── Show Feedback ────────────────────────────────────────────
public
void
ShowFeedback
(
bool
correct
,
int
streak
)
{
...
...
@@ -246,7 +242,6 @@ namespace com.al_arcade.tf
}
}
// ── Clear ────────────────────────────────────────────────────
public
void
Clear
()
{
...
...
@@ -264,4 +259,4 @@ namespace com.al_arcade.tf
Shader
.
Find
(
"Universal Render Pipeline/Lit"
)
??
Shader
.
Find
(
"Standard"
)
??
Shader
.
Find
(
"Unlit/Color"
);
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/TF/Scripts/TfUIManager.cs
View file @
c336f670
...
...
@@ -21,9 +21,6 @@ namespace com.al_arcade.tf
[
Header
(
"Events"
)]
public
UnityEvent
onRestartClicked
;
// ════════════════════════════════════════════════════════════
// BUILD — all sizes tuned for 1920×1080 reference
// ════════════════════════════════════════════════════════════
public
void
BuildUI
()
{
...
...
@@ -50,14 +47,13 @@ namespace com.al_arcade.tf
_resultsUI
.
alpha
=
0
;
_resultsUI
.
gameObject
.
SetActive
(
false
);
}
// ── Game HUD ─────────────────────────────────────────────────
private
void
BuildGameHUD
(
Transform
parent
)
{
var
go
=
MkPanel
(
parent
,
"GameUI"
);
_gameUI
=
go
.
AddComponent
<
CanvasGroup
>();
// ── Top bar ──────────────────────────────────────────────
var
topBarObj
=
new
GameObject
(
"TopBar"
);
topBarObj
.
transform
.
SetParent
(
go
.
transform
,
false
);
var
tbr
=
topBarObj
.
AddComponent
<
RectTransform
>();
...
...
@@ -69,26 +65,26 @@ namespace com.al_arcade.tf
topBarObj
.
AddComponent
<
Image
>().
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
PrimaryDark
,
0.82f
);
// Score — top-left
_scoreText
=
MkTxt
(
topBarObj
.
transform
,
"Score"
,
"0"
,
32
,
new
Vector2
(
0
,
0.5f
),
new
Vector2
(
36
,
6
),
new
Vector2
(
180
,
44
));
_scoreText
.
color
=
SSColorPalette
.
Accent
;
_scoreText
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
_scoreText
.
alignment
=
TMPro
.
TextAlignmentOptions
.
MidlineLeft
;
// Score label
var
scoreLbl
=
MkTxt
(
topBarObj
.
transform
,
"ScoreLbl"
,
"النقاط"
,
14
,
new
Vector2
(
0
,
0.5f
),
new
Vector2
(
36
,
-
20
),
new
Vector2
(
100
,
22
));
scoreLbl
.
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.5f
);
scoreLbl
.
alignment
=
TMPro
.
TextAlignmentOptions
.
MidlineLeft
;
// Streak — center
_streakText
=
MkTxt
(
topBarObj
.
transform
,
"Streak"
,
""
,
26
,
new
Vector2
(
0.5f
,
0.5f
),
new
Vector2
(
0
,
0
),
new
Vector2
(
200
,
44
));
_streakText
.
color
=
SSColorPalette
.
Warning
;
_streakText
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
// ── Progress bar ─────────────────────────────────────────
var
progBg
=
new
GameObject
(
"ProgressBg"
);
progBg
.
transform
.
SetParent
(
go
.
transform
,
false
);
var
pr
=
progBg
.
AddComponent
<
RectTransform
>();
...
...
@@ -111,13 +107,13 @@ namespace com.al_arcade.tf
_progressFill
=
fill
.
AddComponent
<
Image
>();
_progressFill
.
color
=
SSColorPalette
.
Accent
;
// Progress label
_progressLabel
=
MkTxt
(
go
.
transform
,
"ProgLbl"
,
"0 / 5"
,
16
,
new
Vector2
(
0.5f
,
1
),
new
Vector2
(
0
,
-
98
),
new
Vector2
(
200
,
22
));
_progressLabel
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
_progressLabel
.
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.55f
);
// ── Bottom hint ──────────────────────────────────────────
var
hintObj
=
new
GameObject
(
"HintBg"
);
hintObj
.
transform
.
SetParent
(
go
.
transform
,
false
);
var
hbr
=
hintObj
.
AddComponent
<
RectTransform
>();
...
...
@@ -136,7 +132,6 @@ namespace com.al_arcade.tf
hint
.
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.5f
);
}
// ── Loading ──────────────────────────────────────────────────
private
void
BuildLoadingPanel
(
Transform
parent
)
{
...
...
@@ -150,14 +145,13 @@ namespace com.al_arcade.tf
_loadingText
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
_loadingText
.
color
=
Color
.
white
;
// Spinner dots
var
dots
=
MkTxt
(
go
.
transform
,
"Dots"
,
"● ● ●"
,
18
,
new
Vector2
(
0.5f
,
0.5f
),
new
Vector2
(
0
,
-
36
),
new
Vector2
(
200
,
30
));
dots
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
dots
.
color
=
SSColorPalette
.
Accent
;
}
// ── Error ────────────────────────────────────────────────────
private
void
BuildErrorPanel
(
Transform
parent
)
{
...
...
@@ -173,18 +167,17 @@ namespace com.al_arcade.tf
_errorText
.
enableWordWrapping
=
true
;
}
// ── Results ──────────────────────────────────────────────────
private
void
BuildResultsPanel
(
Transform
parent
)
{
var
go
=
MkPanel
(
parent
,
"ResultsUI"
);
_resultsUI
=
go
.
AddComponent
<
CanvasGroup
>();
// Semi-transparent background
var
bg
=
go
.
AddComponent
<
Image
>();
bg
.
color
=
SSColorPalette
.
WithAlpha
(
SSColorPalette
.
PrimaryDark
,
0.94f
);
// Card panel (centered box)
var
card
=
new
GameObject
(
"Card"
);
card
.
transform
.
SetParent
(
go
.
transform
,
false
);
var
cr
=
card
.
AddComponent
<
RectTransform
>();
...
...
@@ -194,33 +187,33 @@ namespace com.al_arcade.tf
var
cardImg
=
card
.
AddComponent
<
Image
>();
cardImg
.
color
=
SSColorPalette
.
WithAlpha
(
new
Color32
(
30
,
30
,
55
,
255
),
0.95f
);
// Title
_resultTitle
=
MkTxt
(
card
.
transform
,
"Title"
,
"تم التصنيع! 🎉"
,
42
,
new
Vector2
(
0.5f
,
1
),
new
Vector2
(
0
,
-
50
),
new
Vector2
(
500
,
55
));
_resultTitle
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
_resultTitle
.
color
=
SSColorPalette
.
Accent
;
_resultTitle
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
// Score
_resultScore
=
MkTxt
(
card
.
transform
,
"Score"
,
"0"
,
56
,
new
Vector2
(
0.5f
,
1
),
new
Vector2
(
0
,
-
130
),
new
Vector2
(
300
,
70
));
_resultScore
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
_resultScore
.
color
=
Color
.
white
;
_resultScore
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
// Score label
MkTxt
(
card
.
transform
,
"ScoreLbl"
,
"النقاط"
,
16
,
new
Vector2
(
0.5f
,
1
),
new
Vector2
(
0
,
-
185
),
new
Vector2
(
100
,
25
))
.
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.4f
);
// Stats
_resultStats
=
MkTxt
(
card
.
transform
,
"Stats"
,
""
,
20
,
new
Vector2
(
0.5f
,
0.5f
),
new
Vector2
(
0
,
10
),
new
Vector2
(
450
,
60
));
_resultStats
.
alignment
=
TMPro
.
TextAlignmentOptions
.
Center
;
_resultStats
.
color
=
SSColorPalette
.
WithAlpha
(
Color
.
white
,
0.65f
);
_resultStats
.
enableWordWrapping
=
true
;
// Restart button
var
btnObj
=
new
GameObject
(
"RestartBtn"
);
btnObj
.
transform
.
SetParent
(
card
.
transform
,
false
);
var
br
=
btnObj
.
AddComponent
<
RectTransform
>();
...
...
@@ -251,9 +244,6 @@ namespace com.al_arcade.tf
btnTxt
.
fontStyle
=
TMPro
.
FontStyles
.
Bold
;
}
// ════════════════════════════════════════════════════════════
// PUBLIC METHODS
// ════════════════════════════════════════════════════════════
public
void
ShowGameUI
()
{
...
...
@@ -325,7 +315,7 @@ namespace com.al_arcade.tf
if
(
_resultStats
!=
null
)
_resultStats
.
arabicText
=
$"✓ صحيح:
{
correct
}
| ✗ خطأ:
{
wrong
}
"
;
// Animated entrance
var
seq
=
DOTween
.
Sequence
();
seq
.
Append
(
_resultsUI
.
DOFade
(
1
,
0.4f
));
if
(
_resultTitle
!=
null
)
...
...
@@ -340,7 +330,7 @@ namespace com.al_arcade.tf
seq
.
Append
(
_resultScore
.
transform
.
DOScale
(
1
,
0.35f
).
SetEase
(
Ease
.
OutBack
));
// Count-up
int
ds
=
0
;
DOTween
.
To
(()
=>
ds
,
x
=>
{
...
...
@@ -358,9 +348,6 @@ namespace com.al_arcade.tf
if
(
_resultsUI
!=
null
)
_resultsUI
.
gameObject
.
SetActive
(
false
);
}
// ════════════════════════════════════════════════════════════
// HELPERS
// ════════════════════════════════════════════════════════════
private
GameObject
MkPanel
(
Transform
p
,
string
n
)
{
...
...
@@ -391,4 +378,4 @@ namespace com.al_arcade.tf
return
t
;
}
}
}
\ No newline at end of file
}
My project/Assets/ScienceStreet/collectcodebase.sh
deleted
100644 → 0
View file @
9833ad6e
This diff is collapsed.
Click to expand it.
My project/Assets/ScienceStreet/c
ollectcodebase.sh
.meta
→
My project/Assets/ScienceStreet/c
s_comments_backup_20260222_185359
.meta
View file @
c336f670
fileFormatVersion: 2
guid: 5fe070f9e16c540beb7eae4411def4a3
guid: 172cb1724b3354adbba5be5427c4ab94
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
...
...
My project/Assets/TextMesh Pro/Resources/Fonts & Materials/LiberationSans SDF - Fallback.asset
View file @
c336f670
This diff is collapsed.
Click to expand it.
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment