Compare commits

...

6 Commits

Author SHA1 Message Date
98883bd382 Merge branch 'main' into DamianBranch 2025-11-10 11:10:14 +01:00
474941f421 Reffitting of the scrapbook 2025-11-10 11:10:04 +01:00
Michal Pikulski
75cd70a18a Play intro audio only once 2025-11-10 11:09:06 +01:00
e82ec90723 WIP Scrapbook rezising 2025-11-10 10:47:00 +01:00
Michal Pikulski
252cb99884 Update icons in minigame 2025-11-10 10:41:38 +01:00
3f548c3ed4 Update HUD updates, moving scattered prefabs into a central HUD manager (#53)
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: #53
2025-11-09 21:41:39 +00:00
21 changed files with 12333 additions and 10575 deletions

View File

@@ -15,7 +15,7 @@ MonoBehaviour:
m_DefaultGroup: 6f3207429a65b3e4b83935ac19791077
m_currentHash:
serializedVersion: 2
Hash: f08b6489862aaf7bfceb29f571e2ef6c
Hash: 589e22fe6cd2fe0e25d89bd44a35bcbc
m_OptimizeCatalogSize: 0
m_BuildRemoteCatalog: 0
m_CatalogRequestsTimeout: 0

View File

@@ -154,10 +154,10 @@ RectTransform:
m_LocalScale: {x: 0, y: 0, z: 0}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 3194400469127591113}
- {fileID: 6565376648640168889}
- {fileID: 5539807896859420487}
- {fileID: 4167457363450270236}
- {fileID: 3864057818161790164}
m_Father: {fileID: 3475216782073696103}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -715,6 +715,171 @@ MonoBehaviour:
m_EditorClassIdentifier: AppleHillsScripts::UI.HudMenuButton
pagePrefab: {fileID: 7668937303613647057, guid: fe049e0d73eadd7479140c8e7bd10efe, type: 3}
buttonName: PauseMenuButton
--- !u!1 &4599222264323240281
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3864057818161790164}
- component: {fileID: 5271824036850954050}
- component: {fileID: 8081783206361873868}
- component: {fileID: 5548642987123338363}
- component: {fileID: 3058107077406709872}
- component: {fileID: 587711432829270645}
m_Layer: 5
m_Name: Icon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3864057818161790164
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4599222264323240281}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 0.99999, y: 0.99999, z: 0.99999}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 2474710976069581060}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 1}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: -50, y: -50}
m_SizeDelta: {x: 200, y: 200}
m_Pivot: {x: 1, y: 1}
--- !u!222 &5271824036850954050
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4599222264323240281}
m_CullTransparentMesh: 1
--- !u!114 &8081783206361873868
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4599222264323240281}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: -1
--- !u!114 &5548642987123338363
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4599222264323240281}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
m_Name:
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
lottieFile: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
customResolution: 0
resWidth: 250
resHeight: 250
stateName: Idle
resetAfterFinished: 0
autoPlay: 1
loop: 1
--- !u!114 &3058107077406709872
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4599222264323240281}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 8081783206361873868}
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 0}
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
m_MethodName: OpenAppSwitcher
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &587711432829270645
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4599222264323240281}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e29407f14afc4428a48d3d1b4245b210, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.HudMenuButton
pagePrefab: {fileID: 1498581815400593087, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
buttonName: RamaSjang Button
--- !u!1 &5113586844274188410
GameObject:
m_ObjectHideFlags: 0
@@ -1018,8 +1183,9 @@ MonoBehaviour:
portraitObject: {fileID: 2258532551510216878}
cinematicsParentObject: {fileID: 5598823553633962789}
CinematicBackground: {fileID: 1256355336041814197}
appSwitcher: {fileID: 3087409191859087859}
eagleEye: {fileID: 8093509920149135307}
ramaSjangButton: {fileID: 4599222264323240281}
scrabBookButton: {fileID: 2880351836456325619}
cinematicSprites: {fileID: 0}
cinematicBackgroundSprites: {fileID: 0}
currentCinematicPlayer: {fileID: 0}
@@ -1422,161 +1588,6 @@ GameObject:
m_CorrespondingSourceObject: {fileID: 6980564769726958139, guid: 428a0feafda9d6d4e87ecf43ad41dc20, type: 3}
m_PrefabInstance: {fileID: 1192924796845315568}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &4473383355500896076
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 2474710976069581060}
m_Modifications:
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_AnchorMax.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalScale.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalScale.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalScale.z
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 1498581815400593087, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_Name
value: AppSwitcher
objectReference: {fileID: 0}
- target: {fileID: 1702317823502492223, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_PresetInfoIsWorld
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4404111907760364827, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_IsActive
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7920249735731934357, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_Texture
value:
objectReference: {fileID: 0}
- target: {fileID: 8490254979303535795, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
propertyPath: m_Texture
value:
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents:
- targetCorrespondingSourceObject: {fileID: 6784053660381911346, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
insertIndex: -1
addedObject: {fileID: 1247411094983283289}
m_SourcePrefab: {fileID: 100100000, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
--- !u!1 &3087409191859087859 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 1498581815400593087, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
m_PrefabInstance: {fileID: 4473383355500896076}
m_PrefabAsset: {fileID: 0}
--- !u!224 &3194400469127591113 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 1315170081792486277, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
m_PrefabInstance: {fileID: 4473383355500896076}
m_PrefabAsset: {fileID: 0}
--- !u!1 &6931438578476385918 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 6784053660381911346, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
m_PrefabInstance: {fileID: 4473383355500896076}
m_PrefabAsset: {fileID: 0}
--- !u!114 &1247411094983283289
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6931438578476385918}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 494d0aedce9744308499355006071138, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.DummyInput
--- !u!1001 &6191884954105193926
PrefabInstance:
m_ObjectHideFlags: 0

View File

@@ -135,13 +135,13 @@ AnimatorStateMachine:
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -7925442279578022247}
m_Position: {x: 400, y: 370, z: 0}
m_Position: {x: 410, y: 370, z: 0}
- serializedVersion: 1
m_State: {fileID: -892202757677891130}
m_Position: {x: -20, y: 260, z: 0}
- serializedVersion: 1
m_State: {fileID: 1937208649765278840}
m_Position: {x: 489.1548, y: 156.18289, z: 0}
m_Position: {x: 490, y: 150, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []

View File

@@ -120,6 +120,44 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &879012544333199198
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8293076336493130222}
m_Layer: 5
m_Name: Rainbows
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8293076336493130222
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 879012544333199198}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6108475066390421500}
- {fileID: 6717870941799174515}
- {fileID: 4136733570236406132}
m_Father: {fileID: 1315170081792486277}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &904161782565348054
GameObject:
m_ObjectHideFlags: 0
@@ -166,7 +204,7 @@ RectTransform:
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 200}
m_SizeDelta: {x: 1550, y: 700}
m_SizeDelta: {x: 1550, y: 750}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!223 &4291423916360628965
Canvas:
@@ -252,7 +290,7 @@ MonoBehaviour:
m_StartCorner: 0
m_StartAxis: 0
m_CellSize: {x: 350, y: 350}
m_Spacing: {x: 50, y: 0}
m_Spacing: {x: 50, y: 50}
m_Constraint: 2
m_ConstraintCount: 2
--- !u!114 &7425566603516801919
@@ -281,7 +319,6 @@ GameObject:
- component: {fileID: 6669614972729775195}
- component: {fileID: 2981106092574900430}
- component: {fileID: 8074691980395114238}
- component: {fileID: 1630362919770549177}
m_Layer: 5
m_Name: AppSwitcher
m_TagString: Untagged
@@ -301,8 +338,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 6108475066390421500}
- {fileID: 1495118611075801417}
- {fileID: 8293076336493130222}
- {fileID: 808554455652734252}
- {fileID: 2831878373711017175}
m_Father: {fileID: 0}
@@ -364,36 +400,14 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: bac6124b3ada8a048a0b87a729a22312, type: 3}
m_Name:
m_EditorClassIdentifier: '::'
iconIdle: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
iconEstablish: {fileID: 4900000, guid: 975218623da47f8428c484d886554a6c, type: 3}
rainbowEstablish: {fileID: 4900000, guid: 622be2ef9d5e27d45a9deaf7ed805f5f, type: 3}
rainbowRemove: {fileID: 4900000, guid: 589505308c5daf449800f30dd4b92ce7, type: 3}
rainbow: {fileID: 5382650426034128680}
icon: {fileID: 6784053660381911346}
PageName:
transitionDuration: 0.3
rainbowIn: {fileID: 5382650426034128680}
rainbowOut: {fileID: 3983328028282460839}
gameLayoutContainer: {fileID: 904161782565348054}
exitButton: {fileID: 8427602740714176801}
--- !u!95 &1630362919770549177
Animator:
serializedVersion: 7
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1498581815400593087}
m_Enabled: 1
m_Avatar: {fileID: 0}
m_Controller: {fileID: 9100000, guid: fc380d833ededb441a23b106de60bedd, type: 2}
m_CullingMode: 0
m_UpdateMode: 2
m_ApplyRootMotion: 0
m_LinearVelocityBlending: 0
m_StabilizeFeet: 0
m_AnimatePhysics: 0
m_WarningMessage:
m_HasTransformHierarchy: 1
m_AllowConstantClipSamplingOptimization: 1
m_KeepAnimatorStateOnDisable: 0
m_WriteDefaultValuesOnDisable: 0
rectMask: {fileID: 7425566603516801919}
slideDuration: 0.6
--- !u!1 &2426870979657684456
GameObject:
m_ObjectHideFlags: 0
@@ -514,6 +528,99 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &3983328028282460839
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6717870941799174515}
- component: {fileID: 6334910097310371923}
- component: {fileID: 8821021733826365168}
- component: {fileID: 9163925342151684341}
m_Layer: 5
m_Name: RainbowOut
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6717870941799174515
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3983328028282460839}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 8293076336493130222}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6334910097310371923
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3983328028282460839}
m_CullTransparentMesh: 1
--- !u!114 &8821021733826365168
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3983328028282460839}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: -1
--- !u!114 &9163925342151684341
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3983328028282460839}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
m_Name:
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
lottieFile: {fileID: 4900000, guid: 589505308c5daf449800f30dd4b92ce7, type: 3}
customResolution: 0
resWidth: 250
resHeight: 250
stateName:
resetAfterFinished: 0
autoPlay: 0
loop: 0
--- !u!1 &4270065472017787841
GameObject:
m_ObjectHideFlags: 0
@@ -664,7 +771,7 @@ RectTransform:
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 6108475066390421500}
m_Father: {fileID: 8293076336493130222}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
@@ -842,7 +949,7 @@ GameObject:
- component: {fileID: 7920249735731934357}
- component: {fileID: 3566391948883171773}
m_Layer: 5
m_Name: Rainbow
m_Name: RainbowIn
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
@@ -855,13 +962,12 @@ RectTransform:
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5382650426034128680}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalRotation: {x: -0, y: -0, z: -0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4136733570236406132}
m_Father: {fileID: 1315170081792486277}
m_Children: []
m_Father: {fileID: 8293076336493130222}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 1, y: 1}
@@ -1043,156 +1149,6 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &6784053660381911346
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1495118611075801417}
- component: {fileID: 9118909078554628244}
- component: {fileID: 8490254979303535795}
- component: {fileID: 4316986085632541161}
- component: {fileID: 6597789131808754055}
m_Layer: 5
m_Name: Icon
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1495118611075801417
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6784053660381911346}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 1, y: 1, z: 1}
m_ConstrainProportionsScale: 0
m_Children: []
m_Father: {fileID: 1315170081792486277}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 1, y: 1}
m_AnchorMax: {x: 1, y: 1}
m_AnchoredPosition: {x: -50, y: -50}
m_SizeDelta: {x: 200, y: 200}
m_Pivot: {x: 1, y: 1}
--- !u!222 &9118909078554628244
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6784053660381911346}
m_CullTransparentMesh: 1
--- !u!114 &8490254979303535795
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6784053660381911346}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 1344c3c82d62a2a41a3576d8abb8e3ea, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.RawImage
m_Material: {fileID: 0}
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_RaycastTarget: 1
m_RaycastPadding: {x: 0, y: 0, z: 0, w: 0}
m_Maskable: 1
m_OnCullStateChanged:
m_PersistentCalls:
m_Calls: []
m_Texture: {fileID: 0}
m_UVRect:
serializedVersion: 2
x: 0
y: 0
width: 1
height: -1
--- !u!114 &4316986085632541161
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6784053660381911346}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 2fd09147b9e9d42a48d6ddc915ddc3d2, type: 3}
m_Name:
m_EditorClassIdentifier: SkiaSharp.Unity::SkiaSharp.Unity.SkottiePlayerV2
lottieFile: {fileID: 4900000, guid: 50e22b5bb8a496840952f2563758c13c, type: 3}
customResolution: 0
resWidth: 250
resHeight: 250
stateName: Idle
resetAfterFinished: 0
autoPlay: 1
loop: 1
--- !u!114 &6597789131808754055
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6784053660381911346}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 4e29b1a8efbd4b44bb3f3716e73f07ff, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Button
m_Navigation:
m_Mode: 3
m_WrapAround: 0
m_SelectOnUp: {fileID: 0}
m_SelectOnDown: {fileID: 0}
m_SelectOnLeft: {fileID: 0}
m_SelectOnRight: {fileID: 0}
m_Transition: 1
m_Colors:
m_NormalColor: {r: 1, g: 1, b: 1, a: 1}
m_HighlightedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_PressedColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 1}
m_SelectedColor: {r: 0.9607843, g: 0.9607843, b: 0.9607843, a: 1}
m_DisabledColor: {r: 0.78431374, g: 0.78431374, b: 0.78431374, a: 0.5019608}
m_ColorMultiplier: 1
m_FadeDuration: 0.1
m_SpriteState:
m_HighlightedSprite: {fileID: 0}
m_PressedSprite: {fileID: 0}
m_SelectedSprite: {fileID: 0}
m_DisabledSprite: {fileID: 0}
m_AnimationTriggers:
m_NormalTrigger: Normal
m_HighlightedTrigger: Highlighted
m_PressedTrigger: Pressed
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 8490254979303535795}
m_OnClick:
m_PersistentCalls:
m_Calls:
- m_Target: {fileID: 8074691980395114238}
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
m_MethodName: OpenAppSwitcher
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
m_IntArgument: 0
m_FloatArgument: 0
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!1 &7713997083397969887
GameObject:
m_ObjectHideFlags: 0
@@ -1565,6 +1521,7 @@ GameObject:
- component: {fileID: 5972191288640444065}
- component: {fileID: 236099612463072939}
- component: {fileID: 447310668687539451}
- component: {fileID: 6704345904811573523}
m_Layer: 5
m_Name: CloseUIButton
m_TagString: Untagged
@@ -1675,7 +1632,7 @@ MonoBehaviour:
m_Calls:
- m_Target: {fileID: 8074691980395114238}
m_TargetAssemblyTypeName: AppSwitcher, AppleHillsScripts
m_MethodName: CloseAppSwitcher
m_MethodName: OnBackPressed
m_Mode: 1
m_Arguments:
m_ObjectArgument: {fileID: 0}
@@ -1685,3 +1642,15 @@ MonoBehaviour:
m_StringArgument:
m_BoolArgument: 0
m_CallState: 2
--- !u!114 &6704345904811573523
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8427602740714176801}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 494d0aedce9744308499355006071138, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.DummyInput

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -453761,6 +453761,10 @@ PrefabInstance:
propertyPath: m_PlayOnAwake
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8545106365577783398, guid: ead4e790fa3a1924ebd1586c93cd5479, type: 3}
propertyPath: isOneTime
value: 1
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []

File diff suppressed because it is too large Load Diff

View File

@@ -469,6 +469,34 @@ namespace Core.Lifecycle
LogDebug($"Restored scene data to {restoredCount} components");
}
/// <summary>
/// Broadcasts scene restore completed event to all registered components.
/// Called AFTER all OnSceneRestoreRequested calls complete.
/// </summary>
public void BroadcastSceneRestoreCompleted()
{
LogDebug("Broadcasting SceneRestoreCompleted");
// Create a copy to avoid collection modification during iteration
var componentsCopy = new List<ManagedBehaviour>(managedAwakeList);
foreach (var component in componentsCopy)
{
if (component == null) continue;
try
{
component.InvokeSceneRestoreCompleted();
}
catch (Exception ex)
{
Debug.LogError($"[LifecycleManager] Exception during scene restore completed for {component.SaveId}: {ex}");
}
}
LogDebug("SceneRestoreCompleted broadcast complete");
}
/// <summary>
/// Broadcasts global restore request to all registered components that opt-in.
/// Distributes serialized data to matching components by SaveId.

View File

@@ -89,6 +89,7 @@ namespace Core.Lifecycle
public void InvokeSceneReady() => OnSceneReady();
public string InvokeSceneSaveRequested() => OnSceneSaveRequested();
public void InvokeSceneRestoreRequested(string data) => OnSceneRestoreRequested(data);
public void InvokeSceneRestoreCompleted() => OnSceneRestoreCompleted();
public string InvokeGlobalSaveRequested() => OnGlobalSaveRequested();
public void InvokeGlobalRestoreRequested(string data) => OnGlobalRestoreRequested(data);
public void InvokeManagedDestroy() => OnManagedDestroy();
@@ -202,6 +203,10 @@ namespace Core.Lifecycle
/// Called during scene transitions to restore scene-specific state.
/// Receives previously serialized data (from OnSceneSaveRequested).
///
/// IMPORTANT: This method MUST be synchronous. Do not use coroutines or async/await.
/// OnSceneRestoreCompleted is called immediately after all restore calls complete,
/// so any async operations would still be running when it fires.
///
/// TIMING:
/// - Called AFTER scene load, during OnSceneReady phase
/// - Frequency: Every scene transition
@@ -212,6 +217,29 @@ namespace Core.Lifecycle
// Default: no-op
}
/// <summary>
/// Called after all scene restore operations complete.
/// Does NOT receive data - use OnSceneRestoreRequested for that.
///
/// GUARANTEE:
/// - ALWAYS called after scene load, whether there's save data or not
/// - All OnSceneRestoreRequested() calls have RETURNED (but async operations may still be running)
/// - Safe for synchronous restore operations (JSON deserialization, setting fields, etc.)
///
/// TIMING:
/// - Called AFTER all OnSceneRestoreRequested calls complete (or immediately if no save data exists)
/// - Frequency: Every scene transition
/// - Use for: Post-restore initialization, first-time initialization, triggering events after state is restored
///
/// COMMON PATTERN:
/// Use this to perform actions that depend on whether data was restored or not.
/// Example: Play one-time audio only if it hasn't been played before (_hasPlayed == false).
/// </summary>
protected virtual void OnSceneRestoreCompleted()
{
// Default: no-op
}
/// <summary>
/// Called once on game boot to restore global persistent state.
/// Receives data that was saved via OnGlobalSaveRequested.

View File

@@ -504,9 +504,19 @@ namespace Core.SaveLoad
/// </summary>
public void RestoreSceneData()
{
if (Lifecycle.LifecycleManager.Instance == null)
{
Logging.Warning("[SaveLoadManager] LifecycleManager not available for scene restore");
return;
}
if (currentSaveData == null || currentSaveData.participantStates == null)
{
Logging.Debug("[SaveLoadManager] No scene data to restore");
Logging.Debug("[SaveLoadManager] No scene data to restore (first visit or no save data)");
// Still broadcast restore completed so components can initialize properly
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreCompleted();
Logging.Debug($"[SaveLoadManager] Scene restore completed (no data)");
return;
}
@@ -520,11 +530,12 @@ namespace Core.SaveLoad
}
// Restore scene data via LifecycleManager
if (Lifecycle.LifecycleManager.Instance != null)
{
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreRequested(saveDataDict);
Logging.Debug($"[SaveLoadManager] Broadcast scene restore to LifecycleManager");
}
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreRequested(saveDataDict);
Logging.Debug($"[SaveLoadManager] Broadcast scene restore to LifecycleManager");
// Broadcast scene restore completed - ALWAYS called, whether there's data or not
Lifecycle.LifecycleManager.Instance.BroadcastSceneRestoreCompleted();
Logging.Debug($"[SaveLoadManager] Scene restore completed");
}
/// <summary>

View File

@@ -1,22 +1,80 @@
using UnityEngine;
using UnityEngine.Audio;
using System;
using Core.Lifecycle;
public class LevelAudioObject : MonoBehaviour
[Serializable]
public class LevelAudioObjectSaveData
{
public bool hasPlayed;
}
public class LevelAudioObject : ManagedBehaviour
{
[Header("Audio Settings")]
public AppleAudioSource narratorAudioSource;
public AudioResource firstNarration;
[Header("Playback Settings")]
[Tooltip("If true, the audio will only play once and never again after being played")]
public bool isOneTime;
// Start is called once before the first execution of Update after the MonoBehaviour is created
void Start()
private bool _hasPlayed;
#region ManagedBehaviour Overrides
public override bool AutoRegisterForSave => isOneTime; // Only save if one-time audio
protected override string OnSceneSaveRequested()
{
PlayNarrationAudio();
if (!isOneTime)
return null; // No need to save if not one-time
LevelAudioObjectSaveData saveData = new LevelAudioObjectSaveData
{
hasPlayed = _hasPlayed
};
return JsonUtility.ToJson(saveData);
}
void PlayNarrationAudio()
protected override void OnSceneRestoreRequested(string serializedData)
{
if (!isOneTime || string.IsNullOrEmpty(serializedData))
return;
try
{
LevelAudioObjectSaveData saveData = JsonUtility.FromJson<LevelAudioObjectSaveData>(serializedData);
_hasPlayed = saveData.hasPlayed;
}
catch (Exception e)
{
Debug.LogWarning($"[LevelAudioObject] Failed to restore audio state: {e.Message}");
}
}
protected override void OnSceneRestoreCompleted()
{
if (isOneTime && !_hasPlayed)
{
PlayNarrationAudio();
}
}
#endregion
private void PlayNarrationAudio()
{
if (narratorAudioSource == null || firstNarration == null)
{
Debug.LogWarning($"[LevelAudioObject] Missing audio source or narration resource on {gameObject.name}");
return;
}
narratorAudioSource.audioSource.resource = firstNarration;
narratorAudioSource.Play(0);
_hasPlayed = true;
}
}

View File

@@ -1,89 +1,122 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using SkiaSharp.Unity;
using Input;
using AppleHills.Core;
using UI.Core;
using Pixelplacement;
using Pixelplacement.TweenSystem;
using UI;
using UnityEngine.Events;
public class AppSwitcher : MonoBehaviour
public class AppSwitcher : UIPage
{
public TextAsset iconIdle;
public TextAsset iconEstablish;
public TextAsset rainbowEstablish;
public TextAsset rainbowRemove;
public GameObject rainbow;
public GameObject icon;
public GameObject rainbowIn;
public GameObject rainbowOut;
public GameObject gameLayoutContainer;
public GameObject exitButton;
public RectMask2D rectMask;
[Header("Slide Animation Settings")]
public float slideDuration = 0.5f;
private SkottiePlayerV2 rainbowInPlayer;
private SkottiePlayerV2 rainbowOutPlayer;
private TweenBase slideInTween;
private TweenBase slideOutTween;
private SkottiePlayerV2 iconPlayer;
private SkottiePlayerV2 rainbowPlayer;
private Animator animator;
private void OnEnable()
protected override void OnManagedAwake()
{
iconPlayer = icon.GetComponentInChildren<SkottiePlayerV2>();
rainbowPlayer = rainbow.GetComponentInChildren<SkottiePlayerV2>();
animator = GetComponent<Animator>();
rainbow.SetActive(false);
base.OnManagedAwake();
PageName = "AppSwitcher";
rainbowInPlayer = rainbowIn.GetComponent<SkottiePlayerV2>();
rainbowOutPlayer = rainbowOut.GetComponent<SkottiePlayerV2>();
if (rectMask == null)
{
rectMask = GetComponent<RectMask2D>();
}
// Initially hide both
rainbowIn.SetActive(true);
exitButton.SetActive(false);
}
public void OpenAppSwitcher()
protected override void DoTransitionIn(Action onComplete)
{
PlayerHudManager.Instance.HideAllHudExcept(gameObject);
rainbow.SetActive(true);
//Activate players
rainbow.SetActive(true);
gameLayoutContainer.SetActive(true);
// Play establishing animations
rainbowPlayer.LoadAnimation(rainbowEstablish.text);
rainbowPlayer.PlayAnimation(false);
rainbowPlayer.loop = false;
gameLayoutContainer.SetActive(true);
animator.Play("GamesReveal");
// Show the exit button
exitButton.SetActive(true);
// Set input mode to UI
QuickAccess.Instance.PlayerController.InterruptMoveTo();
InputManager.Instance.SetInputMode(InputMode.UI);
gameLayoutContainer.SetActive(true);
rainbowPlayer.OnAnimationFinished += AnimFinished;
// Hide rainbow out, show rainbow in
rainbowOut.SetActive(false);
// Play animation on rainbow in without resetting state
rainbowInPlayer.PlayAnimation(true);
// Slide in animation - tween padding.left from 1700 to 0
slideInTween = TweenPaddingLeft(1700f, 0f, Tween.EaseOut, () =>
{
onComplete?.Invoke();
rainbowOut.SetActive(true);
exitButton.SetActive(true);
});
}
public void CloseAppSwitcher()
protected override void DoTransitionOut(Action onComplete)
{
rainbowPlayer.resetAfterFinished = true;
rainbowPlayer.LoadAnimation(rainbowRemove.text);
rainbowPlayer.PlayAnimation(false);
rainbowPlayer.loop = false;
animator.Play("GamesHide");
// Set input mode to game and ui
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
rainbowIn.SetActive(false);
// Play animation on rainbow out with resetting state
rainbowOutPlayer.PlayAnimation(true);
// Hide the exit button
exitButton.SetActive(false);
PlayerHudManager.Instance.ShowAllHud();
// Slide out animation - tween padding.left from 0 to 1700
slideOutTween = TweenPaddingLeft(0f, 1700f, Tween.EaseIn, () => {
gameLayoutContainer.SetActive(false);
rainbowIn.SetActive(true);
onComplete?.Invoke();
InputManager.Instance.SetInputMode(InputMode.GameAndUI);
});
}
public void GamesHiddenAnimationEvent()
{
rainbow.SetActive(false);
gameLayoutContainer.SetActive(false);
}
private void AnimFinished(string str)
{
/// <summary>
/// Tweens the left padding of the rectMask from startValue to endValue.
/// </summary>
private TweenBase TweenPaddingLeft(float startValue, float endValue, AnimationCurve easeCurve, Action onComplete)
{
// Set starting position
Vector4 startPadding = rectMask.padding;
startPadding.x = startValue;
rectMask.padding = startPadding;
return Tween.Value(
startValue,
endValue,
(value) => {
Vector4 padding = rectMask.padding;
padding.x = value;
rectMask.padding = padding;
},
slideDuration,
0f, // no delay
easeCurve,
Tween.LoopType.None,
null, // onStart
onComplete
);
}
protected override void OnDestroy()
{
base.OnDestroy();
// Clean up tweens
slideInTween?.Stop();
slideOutTween?.Stop();
}
}

View File

@@ -165,15 +165,6 @@ namespace UI.CardSystem
UIPageController.Instance.PopPage();
}
}
// If album exits while in Overworld, show AppSwitcher. If not, keep it hidden.
if (PlayerHudManager.Instance.currentUIMode == PlayerHudManager.UIMode.Overworld)
{
PlayerHudManager.Instance.ToggleAppSwitcher(true);
}
else
{
PlayerHudManager.Instance.ToggleAppSwitcher(false);
}
}
private void OnBoosterCountChanged(int newCount)

View File

@@ -70,11 +70,8 @@ namespace UI.CardSystem
if (albumViewPage != null)
{
UIPageController.Instance.PushPage(albumViewPage);
PlayerHudManager.Instance.appSwitcher.SetActive(false);
}
}
PlayerHudManager.Instance.ToggleAppSwitcher(false);
// If we're already on the album main page, do nothing
}
private void OnPageChanged(UIPage currentPage)

View File

@@ -10,7 +10,8 @@ namespace UI.CardSystem
/// <summary>
/// Singleton UI component for granting booster packs from minigames.
/// Displays a booster pack with glow effect, waits for user to click continue,
/// then animates the pack flying to bottom-left corner before granting the reward.
/// then shows the scrapbook button and animates the pack flying to it before granting the reward.
/// The scrapbook button is automatically hidden after the animation completes.
/// </summary>
public class MinigameBoosterGiver : MonoBehaviour
{
@@ -187,23 +188,61 @@ namespace UI.CardSystem
yield break;
}
// Calculate bottom-left corner position in local space
RectTransform canvasRect = GetComponentInParent<Canvas>()?.GetComponent<RectTransform>();
Vector3 targetPosition;
if (canvasRect != null)
// Show scrapbook button temporarily using HUD visibility context
PlayerHudManager.HudVisibilityContext hudContext = null;
GameObject scrapbookButton = null;
scrapbookButton = PlayerHudManager.Instance.GetScrabookButton();
if (scrapbookButton != null)
{
// Convert bottom-left corner with offset to local position
Vector2 bottomLeft = new Vector2(-canvasRect.rect.width / 2f, -canvasRect.rect.height / 2f);
targetPosition = bottomLeft + targetBottomLeftOffset;
hudContext = PlayerHudManager.Instance.ShowElementTemporarily(scrapbookButton);
}
else
{
// Fallback if no canvas found
targetPosition = _boosterInitialPosition + new Vector3(-500f, -500f, 0f);
Debug.LogWarning("[MinigameBoosterGiver] Scrapbook button not found in PlayerHudManager.");
}
// Tween to bottom-left corner
// Calculate target position - use scrapbook button position if available
Vector3 targetPosition;
if (scrapbookButton != null)
{
// Get the scrapbook button's position in the same coordinate space as boosterImage
RectTransform scrapbookRect = scrapbookButton.GetComponent<RectTransform>();
if (scrapbookRect != null)
{
// Convert scrapbook button's world position to local position relative to boosterImage's parent
Canvas canvas = GetComponentInParent<Canvas>();
if (canvas != null && canvas.renderMode == RenderMode.ScreenSpaceOverlay)
{
// For overlay canvas, convert screen position to local position
Vector2 screenPos = RectTransformUtility.WorldToScreenPoint(null, scrapbookRect.position);
RectTransformUtility.ScreenPointToLocalPointInRectangle(
boosterImage.parent as RectTransform,
screenPos,
null,
out Vector2 localPoint);
targetPosition = localPoint;
}
else
{
// For world space or camera canvas
targetPosition = boosterImage.parent.InverseTransformPoint(scrapbookRect.position);
}
}
else
{
Debug.LogWarning("[MinigameBoosterGiver] Scrapbook button has no RectTransform, using fallback position.");
targetPosition = GetFallbackPosition();
}
}
else
{
// Fallback to bottom-left corner
targetPosition = GetFallbackPosition();
}
// Tween to scrapbook button position
Tween.LocalPosition(boosterImage, targetPosition, disappearDuration, 0f, Tween.EaseInBack);
// Scale down
@@ -224,6 +263,9 @@ namespace UI.CardSystem
Debug.LogWarning("[MinigameBoosterGiver] CardSystemManager not found, cannot grant booster pack.");
}
// Hide scrapbook button by disposing the context
hudContext?.Dispose();
// Hide the visual
if (visualContainer != null)
{
@@ -237,6 +279,22 @@ namespace UI.CardSystem
// Clear sequence reference
_currentSequence = null;
}
private Vector3 GetFallbackPosition()
{
RectTransform canvasRect = GetComponentInParent<Canvas>()?.GetComponent<RectTransform>();
if (canvasRect != null)
{
// Convert bottom-left corner with offset to local position
Vector2 bottomLeft = new Vector2(-canvasRect.rect.width / 2f, -canvasRect.rect.height / 2f);
return bottomLeft + targetBottomLeftOffset;
}
else
{
// Ultimate fallback if no canvas found
return _boosterInitialPosition + new Vector3(-500f, -500f, 0f);
}
}
}
}

View File

@@ -190,23 +190,35 @@ namespace UI.Core
{
if (_pageStack.Count <= 0) return;
// Hide and pop current page
// Pop current page from stack
UIPage currentPage = _pageStack.Pop();
currentPage.TransitionOut();
// Show previous page if there is one
if (_pageStack.Count > 0)
// Subscribe to transition out completion event
Action onTransitionComplete = null;
onTransitionComplete = () =>
{
UIPage previousPage = _pageStack.Peek();
previousPage.TransitionIn();
OnPageChanged?.Invoke(previousPage);
Logging.Debug($"[UIPageController] Popped to previous page: {previousPage.PageName}");
}
else
{
OnPageChanged?.Invoke(null);
Logging.Debug("[UIPageController] Popped last page, no pages left in stack");
}
// Unsubscribe to prevent memory leaks
currentPage.OnTransitionOutCompleted -= onTransitionComplete;
// Fire OnPageChanged AFTER transition completes
if (_pageStack.Count > 0)
{
UIPage previousPage = _pageStack.Peek();
previousPage.TransitionIn();
OnPageChanged?.Invoke(previousPage);
Logging.Debug($"[UIPageController] Popped to previous page: {previousPage.PageName}");
}
else
{
OnPageChanged?.Invoke(null);
Logging.Debug("[UIPageController] Popped last page, no pages left in stack");
}
};
currentPage.OnTransitionOutCompleted += onTransitionComplete;
// Start the transition out animation
currentPage.TransitionOut();
}
/// <summary>

View File

@@ -7,6 +7,7 @@ using UnityEngine.Playables;
using UnityEngine.UI;
using System.Linq;
using System.Collections.Generic;
using System;
namespace UI
{
@@ -19,6 +20,73 @@ namespace UI
{
public enum UIMode { Overworld, Puzzle, Minigame, HideAll };
/// <summary>
/// Context object for managing temporary HUD element visibility.
/// Automatically restores previous visibility state when disposed.
/// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementTemporarily(myButton)) { ... }
/// </summary>
public class HudVisibilityContext : IDisposable
{
private readonly GameObject _element;
private readonly bool _previousState;
private bool _disposed;
internal HudVisibilityContext(GameObject element, bool show)
{
_element = element;
_previousState = element.activeSelf;
_element.SetActive(show);
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
if (_element != null)
{
_element.SetActive(_previousState);
}
}
}
/// <summary>
/// Multi-element visibility context for managing multiple HUD elements at once.
/// Automatically restores previous visibility states when disposed.
/// </summary>
public class MultiHudVisibilityContext : IDisposable
{
private readonly List<(GameObject element, bool previousState)> _elements;
private bool _disposed;
internal MultiHudVisibilityContext(IEnumerable<GameObject> elements, bool show)
{
_elements = new List<(GameObject, bool)>();
foreach (var element in elements)
{
if (element != null)
{
_elements.Add((element, element.activeSelf));
element.SetActive(show);
}
}
}
public void Dispose()
{
if (_disposed) return;
_disposed = true;
foreach (var (element, previousState) in _elements)
{
if (element != null)
{
element.SetActive(previousState);
}
}
}
}
public UIMode currentUIMode;
[Header("HUD Management")]
@@ -31,9 +99,9 @@ namespace UI
public GameObject CinematicBackground;
[Header("HUD Elements")]
public GameObject appSwitcher;
public GameObject eagleEye;
public GameObject ramaSjangButton;
public GameObject scrabBookButton;
[HideInInspector] public Image cinematicSprites;
[HideInInspector] public Image cinematicBackgroundSprites;
@@ -64,12 +132,6 @@ namespace UI
UnityEngine.Debug.LogError("[PlayerHudManager] UIPageController not found on same GameObject!");
}
// Get AppSwitcher component reference
if (appSwitcher != null)
{
_appSwitcherComponent = appSwitcher.GetComponent<AppSwitcher>();
}
InitializeReferences();
}
@@ -164,53 +226,17 @@ namespace UI
switch (sceneName)
{
case "AppleHillsOverworld":
UpdateUIMode(UIMode.Overworld);
currentUIMode = UIMode.Overworld;
break;
case "Quarry":
UpdateUIMode(UIMode.Puzzle);
currentUIMode = UIMode.Puzzle;
break;
case "DivingForPictures":
UpdateUIMode(UIMode.Minigame);
break;
}
}
public void UpdateUIMode(UIMode mode)
{
switch (mode)
{
case UIMode.Overworld:
// Update currentUIMode var
currentUIMode = UIMode.Overworld;
// Show app switcher
appSwitcher.SetActive(true);
// Hide eagle eye
eagleEye.SetActive(false);
break;
case UIMode.Puzzle:
// Update currentUIMode var
currentUIMode = UIMode.Puzzle;
// Hide app switcher
appSwitcher.SetActive(false);
// show eagle eye
eagleEye.SetActive(true);
break;
case UIMode.Minigame:
// Update currentUIMode var
currentUIMode = UIMode.Minigame;
// Hide app switcher
appSwitcher.SetActive(false);
// Hide birds eye
eagleEye.SetActive(false);
break;
}
}
public void ToggleAppSwitcher(bool boo)
{
appSwitcher.SetActive(boo);
ShowAllHud();
}
/// <summary>
@@ -263,14 +289,50 @@ namespace UI
return;
}
// Set visibility for all HUD children
foreach (Transform child in hudButtonsContainer)
{
child.gameObject.SetActive(visible);
}
ApplyUIModeOverrides(visible);
Logging.Debug($"[PlayerHudManager] {(visible ? "Shown" : "Hidden")} all HUD elements");
}
/// <summary>
/// Applies UI mode-specific visibility rules (e.g., hiding eagleEye in certain modes)
/// </summary>
private void ApplyUIModeOverrides(bool visible)
{
switch (currentUIMode)
{
case UIMode.Overworld:
if (visible)
{
eagleEye.SetActive(false);
}
break;
case UIMode.Puzzle:
if (visible)
{
ramaSjangButton.SetActive(false);
}
break;
case UIMode.Minigame:
if (visible)
{
eagleEye.SetActive(false);
ramaSjangButton.SetActive(false);
scrabBookButton.SetActive(false);
}
break;
case UIMode.HideAll:
break;
}
}
/// <summary>
/// Automatically manages HUD visibility based on page stack state
/// </summary>
@@ -328,6 +390,64 @@ namespace UI
UnityEngine.Debug.LogError("[PlayerHudManager] Cannot push page - UIPageController not found!");
}
}
#region HUD Element Getters
public GameObject GetEagleEye() => eagleEye;
public GameObject GetRamaSjangButton() => ramaSjangButton;
public GameObject GetScrabookButton() => scrabBookButton;
#endregion
#region Context-Based Visibility Management
/// <summary>
/// Temporarily shows a HUD element. Returns a context object that restores the previous state when disposed.
/// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementTemporarily(myButton)) { /* element is visible */ }
/// </summary>
public HudVisibilityContext ShowElementTemporarily(GameObject element)
{
if (element == null)
{
Logging.Warning("[PlayerHudManager] Attempted to show null element");
return null;
}
return new HudVisibilityContext(element, true);
}
/// <summary>
/// Temporarily hides a HUD element. Returns a context object that restores the previous state when disposed.
/// Usage: using (var ctx = PlayerHudManager.Instance.HideElementTemporarily(myButton)) { /* element is hidden */ }
/// </summary>
public HudVisibilityContext HideElementTemporarily(GameObject element)
{
if (element == null)
{
Logging.Warning("[PlayerHudManager] Attempted to hide null element");
return null;
}
return new HudVisibilityContext(element, false);
}
/// <summary>
/// Temporarily shows multiple HUD elements. Returns a context object that restores all previous states when disposed.
/// Usage: using (var ctx = PlayerHudManager.Instance.ShowElementsTemporarily(button1, button2, button3)) { /* elements are visible */ }
/// </summary>
public MultiHudVisibilityContext ShowElementsTemporarily(params GameObject[] elements)
{
return new MultiHudVisibilityContext(elements, true);
}
/// <summary>
/// Temporarily hides multiple HUD elements. Returns a context object that restores all previous states when disposed.
/// Usage: using (var ctx = PlayerHudManager.Instance.HideElementsTemporarily(button1, button2, button3)) { /* elements are hidden */ }
/// </summary>
public MultiHudVisibilityContext HideElementsTemporarily(params GameObject[] elements)
{
return new MultiHudVisibilityContext(elements, false);
}
#endregion
}
}