All working but codex.

This commit is contained in:
2026-05-13 14:20:25 +01:00
parent c203f836b1
commit 602e1ec0d3
49 changed files with 186784 additions and 62239 deletions

BIN
Assets/Data/.DS_Store vendored

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 MiB

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@@ -0,0 +1,143 @@
fileFormatVersion: 2
guid: 30baef15ab2e64b6a801c78f734d048f
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 13
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 1
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 0
swizzle: 50462976
cookieLightType: 0
platformSettings:
- serializedVersion: 4
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: Android
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
- serializedVersion: 4
buildTarget: iOS
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: ca4658f5941b949028cea8a4644a4561
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 3ccd90dd742684f8ba9a10a17e40b87b
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,21 @@
fileFormatVersion: 2
guid: aeb1c529a2ccb49978d4fa2932a6cb77
TrueTypeFontImporter:
externalObjects: {}
serializedVersion: 4
fontSize: 16
forceTextureCase: -2
characterSpacing: 0
characterPadding: 1
includeFontData: 1
fontNames:
- Cormorant Garamond
fallbackFontReferences: []
customCharacters:
fontRenderingMode: 0
ascentCalculationMode: 1
useLegacyBoundsCalculation: 0
shouldRoundAdvanceValue: 1
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 97bb3839c413f42c5932360cf6b0a3fc
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d3c8386bbe4db4de0801cdcfecfcc852
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,28 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!114 &11400000
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 668f0266fce84811b2efce4a48adff09, type: 3}
m_Name: Codex
m_EditorClassIdentifier: BriarQueen.Framework::BriarQueen.Framework.Managers.Player.Data.ItemDataSo
_idType: 2
_itemKey: 0
_environmentKey: 2
_puzzleSlotKey: 0
_icon: {fileID: 0}
_itemName: Strange Book
_interaction:
rid: 4945117580700680460
references:
version: 2
RefIds:
- rid: 4945117580700680460
type: {class: NoOpItemInteraction, ns: BriarQueen.Framework.Managers.Interaction.Data, asm: BriarQueen.Framework}
data:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 07dcdc2b7fb6b488793fcb1cb7261cd3
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 11400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -94,6 +94,7 @@ MonoBehaviour:
_lockedInteractText:
_locked: 0
_cursorStyle: 4
_soundEffectOnClick: 0
CanvasGroup: {fileID: 0}
--- !u!1 &2546645184983875302
GameObject:
@@ -189,6 +190,7 @@ MonoBehaviour:
_lockedInteractText:
_locked: 0
_cursorStyle: 6
_soundEffectOnClick: 0
CanvasGroup: {fileID: 0}
--- !u!1 &4421245674168000992
GameObject:
@@ -258,6 +260,7 @@ RectTransform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 4576823656230343716}
- {fileID: 7088472163317892184}
m_Father: {fileID: 6339280219726500310}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
@@ -303,6 +306,42 @@ MonoBehaviour:
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!1 &5427156575764192652
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 7088472163317892184}
m_Layer: 5
m_Name: Interactions
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &7088472163317892184
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5427156575764192652}
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: 4911006826862735992}
m_Father: {fileID: 7300298623626277452}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 100, y: 100}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1 &7628546449707446757
GameObject:
m_ObjectHideFlags: 0
@@ -420,6 +459,113 @@ MonoBehaviour:
m_EditorClassIdentifier: BriarQueen.Framework::BriarQueen.Framework.Managers.Levels.Data.BaseLevel
_levelKey: 1
_levelName: At the Car
Pickups: []
Pickups:
- {fileID: 2979208422284585002}
CodexTriggers: []
Puzzles: []
_raycaster: {fileID: 5838140475631316327}
--- !u!1 &9044384593066319242
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4911006826862735992}
- component: {fileID: 2426398793036763882}
- component: {fileID: 4686401616898843419}
- component: {fileID: 2979208422284585002}
- component: {fileID: 2155989015062251532}
m_Layer: 5
m_Name: Codex
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4911006826862735992
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9044384593066319242}
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: 7088472163317892184}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
m_AnchorMax: {x: 0.5, y: 0.5}
m_AnchoredPosition: {x: 533, y: -464}
m_SizeDelta: {x: 156, y: 132}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2426398793036763882
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9044384593066319242}
m_CullTransparentMesh: 1
--- !u!114 &4686401616898843419
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9044384593066319242}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: fe87c0e1cc204ed48ad3b37840f39efc, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.Image
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_Sprite: {fileID: 21300000, guid: 30baef15ab2e64b6a801c78f734d048f, type: 3}
m_Type: 0
m_PreserveAspect: 0
m_FillCenter: 1
m_FillMethod: 4
m_FillAmount: 1
m_FillClockwise: 1
m_FillOrigin: 0
m_UseSpriteMesh: 0
m_PixelsPerUnitMultiplier: 1
--- !u!114 &2979208422284585002
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9044384593066319242}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 9207909e92b24dd0a8b2ed9836ce1134, type: 3}
m_Name:
m_EditorClassIdentifier: BriarQueen.Game::BriarQueen.Game.Items.KeyItems.CodexBook
_itemData: {fileID: 11400000, guid: 07dcdc2b7fb6b488793fcb1cb7261cd3, type: 2}
_interactableTooltip:
_pickupText:
_canvasGroup: {fileID: 2155989015062251532}
--- !u!225 &2155989015062251532
CanvasGroup:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 9044384593066319242}
m_Enabled: 1
m_Alpha: 1
m_Interactable: 1
m_BlocksRaycasts: 1
m_IgnoreParentGroups: 0

View File

@@ -562,6 +562,7 @@ MonoBehaviour:
_currentSave:
SaveVersion: 0.0.2-alpha
SaveFileName:
CodexUnlocked: 0
InventoryData: []
CollectedItems: []
RemovedItems: []

View File

@@ -67,8 +67,8 @@ MonoBehaviour:
m_Calls: []
m_text: Delete
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
@@ -417,8 +417,8 @@ MonoBehaviour:
m_Calls: []
m_text: Create Save Data.
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_fontAsset: {fileID: 11400000, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_sharedMaterial: {fileID: 4574445937968986710, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
@@ -554,8 +554,8 @@ MonoBehaviour:
m_Calls: []
m_text:
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_fontAsset: {fileID: 11400000, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_sharedMaterial: {fileID: 4574445937968986710, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
@@ -863,8 +863,8 @@ MonoBehaviour:
m_Calls: []
m_text:
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_fontAsset: {fileID: 11400000, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_sharedMaterial: {fileID: 4574445937968986710, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
@@ -1068,3 +1068,5 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier: BriarQueen.UI::BriarQueen.UI.Menus.Components.UnderlineButton
_label: {fileID: 8582300275547234308}
_contextLabel: {fileID: 0}
_contextText:

View File

@@ -19,3 +19,4 @@ MonoBehaviour:
- {fileID: 11400000, guid: 1a7a083158210477983fb2377074f358, type: 2}
_environmentInteractables:
- {fileID: 11400000, guid: 82a811edfc83e4c1f9610c319285009d, type: 2}
- {fileID: 11400000, guid: 07dcdc2b7fb6b488793fcb1cb7261cd3, type: 2}

File diff suppressed because it is too large Load Diff

View File

@@ -569,8 +569,8 @@ MonoBehaviour:
m_Calls: []
m_text: Enter text...
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
@@ -1766,15 +1766,15 @@ MonoBehaviour:
m_Calls: []
m_text: Press Start
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_fontAsset: {fileID: 11400000, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_sharedMaterial: {fileID: 4574445937968986710, guid: 4c986c17e63da4bc3bf90fa23663b8dd, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
m_fontColor32:
serializedVersion: 2
rgba: 4294967295
m_fontColor: {r: 1, g: 1, b: 1, a: 1}
rgba: 4291019744
m_fontColor: {r: 0.8773585, g: 0.76561946, b: 0.76561946, a: 1}
m_enableVertexGradient: 0
m_colorMode: 3
m_fontColorGradient:
@@ -2095,8 +2095,8 @@ MonoBehaviour:
m_Calls: []
m_text: "Input Save Name\u200B"
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: 3ccd90dd742684f8ba9a10a17e40b87b, type: 2}
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
@@ -4178,8 +4178,8 @@ MonoBehaviour:
m_Calls: []
m_text: Delete 'Profile'?
m_isRightToLeft: 0
m_fontAsset: {fileID: 11400000, guid: c74ac0bcb27d8486da7434fc14a8d3aa, type: 2}
m_sharedMaterial: {fileID: 6576895709950921952, guid: c74ac0bcb27d8486da7434fc14a8d3aa, type: 2}
m_fontAsset: {fileID: 11400000, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_sharedMaterial: {fileID: 2180264, guid: 8f586378b4e144a9851e7b34d9b748ee, type: 2}
m_fontSharedMaterials: []
m_fontMaterial: {fileID: 0}
m_fontMaterials: []
@@ -4360,6 +4360,8 @@ MonoBehaviour:
m_Name:
m_EditorClassIdentifier: BriarQueen.UI::BriarQueen.UI.Menus.Components.UnderlineButton
_label: {fileID: 1367252155}
_contextLabel: {fileID: 0}
_contextText:
--- !u!1 &1971403710
GameObject:
m_ObjectHideFlags: 0

View File

@@ -383,85 +383,6 @@ Transform:
m_Children: []
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &676988440
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 676988443}
- component: {fileID: 676988442}
- component: {fileID: 676988441}
m_Layer: 0
m_Name: EventSystem
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &676988441
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 676988440}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 01614664b831546d2ae94a42149d80ac, type: 3}
m_Name:
m_EditorClassIdentifier: Unity.InputSystem::UnityEngine.InputSystem.UI.InputSystemUIInputModule
m_SendPointerHoverToParent: 1
m_MoveRepeatDelay: 0.5
m_MoveRepeatRate: 0.1
m_XRTrackingOrigin: {fileID: 0}
m_ActionsAsset: {fileID: -944628639613478452, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_PointAction: {fileID: -1654692200621890270, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MoveAction: {fileID: -8784545083839296357, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_SubmitAction: {fileID: 392368643174621059, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_CancelAction: {fileID: 7727032971491509709, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_LeftClickAction: {fileID: 3001919216989983466, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_MiddleClickAction: {fileID: -2185481485913320682, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_RightClickAction: {fileID: -4090225696740746782, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_ScrollWheelAction: {fileID: 6240969308177333660, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDevicePositionAction: {fileID: 6564999863303420839, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_TrackedDeviceOrientationAction: {fileID: 7970375526676320489, guid: ca9f5fa95ffab41fb9a615ab714db018, type: 3}
m_DeselectOnBackgroundClick: 1
m_PointerBehavior: 0
m_CursorLockBehavior: 0
m_ScrollDeltaPerTick: 6
--- !u!114 &676988442
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 676988440}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 76c392e42b5098c458856cdf6ecaaaa1, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.EventSystems.EventSystem
m_FirstSelected: {fileID: 0}
m_sendNavigationEvents: 1
m_DragThreshold: 10
--- !u!4 &676988443
Transform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 676988440}
serializedVersion: 2
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: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1684932629
GameObject:
m_ObjectHideFlags: 0
@@ -513,4 +434,3 @@ SceneRoots:
- {fileID: 203844589}
- {fileID: 1684932631}
- {fileID: 290940349}
- {fileID: 676988443}

View File

@@ -23,6 +23,7 @@ and wonderful, and perhaps, just perhaps, discover herself in the process.
8. **PrimeTween** - Tweening is done using the PrimeTween Library. Each class that has a Sequence should also have a cancellation token.
9. **Tokens** - Cancellation Tokens should be re-used where possible.
10. **Versions** - We're using C# 9 with Unity 6.3
11. **Workflow** - You're not to make any code changes until you've shown me the proposed changes, I'll then either approve, deny, or modify them before you make the change.
## Documentation

View File

@@ -15,6 +15,7 @@ namespace BriarQueen.Data.Identifiers
{
None = 0,
C1CarNewspaper,
Codex,
}
public enum PuzzleSlotKey

View File

@@ -6,11 +6,11 @@ namespace BriarQueen.Data.Identifiers
{
ReturnToPreviousLevel,
UsingItemsTogether,
HideHUDKeyboard,
HideHUD,
ExitItems,
MultipleUseItems,
DarkRooms,
CodexKeyboard,
Codex,
HiddenItems,
ResetPuzzles,
Tools,
@@ -32,7 +32,7 @@ namespace BriarQueen.Data.Identifiers
"Select one item, then click another to use them together."
},
{
TutorialPopupID.HideHUDKeyboard,
TutorialPopupID.HideHUD,
"Press '{Hide_HUD}' to hide the HUD."
},
{
@@ -48,7 +48,7 @@ namespace BriarQueen.Data.Identifiers
"Dark rooms can hide important details. Use light to reveal them."
},
{
TutorialPopupID.CodexKeyboard,
TutorialPopupID.Codex,
"The Codex is used to collect any documents you encounter. Press '{Codex}' to open it."
},
{

View File

@@ -159,6 +159,8 @@ namespace BriarQueen.Framework.Managers.Interaction
if (_currentHovered != null)
ClearHover().Forget();
Debug.Log($"[InteractManager] SetExclusiveRaycaster set to {raycaster.gameObject.name}.");
}
/// <summary>
@@ -170,6 +172,8 @@ namespace BriarQueen.Framework.Managers.Interaction
if (_currentHovered != null)
ClearHover().Forget();
Debug.Log($"[InteractManager] Cleared exclusive raycaster.");
}
public void Initialize()
@@ -375,7 +379,6 @@ namespace BriarQueen.Framework.Managers.Interaction
return;
if (_currentHovered != null)
{
try
{
await _currentHovered.ExitHover();
@@ -383,19 +386,20 @@ namespace BriarQueen.Framework.Managers.Interaction
catch
{
}
}
_currentHovered = next;
_eventCoordinator.Publish(new HoverInteractableChangedEvent(_currentHovered));
_eventCoordinator.Publish(
new HoverInteractableChangedEvent(_currentHovered));
var cursor = _currentHovered?.ApplicableCursorStyle
?? UICursorService.CursorStyle.Default;
var cursor =
_currentHovered?.ApplicableCursorStyle
?? UICursorService.CursorStyle.Default;
_eventCoordinator.Publish(new CursorStyleChangeEvent(cursor));
_eventCoordinator.Publish(
new CursorStyleChangeEvent(cursor));
if (_currentHovered != null)
{
try
{
await _currentHovered.EnterHover();
@@ -403,7 +407,6 @@ namespace BriarQueen.Framework.Managers.Interaction
catch
{
}
}
}
private async UniTask ClearHover()
@@ -438,7 +441,6 @@ namespace BriarQueen.Framework.Managers.Interaction
return;
_currentHovered.OnInteract(_selectedItem).Forget();
}
private void OnRightClickReceived(OnRightClickEvent obj)

View File

@@ -37,6 +37,8 @@ namespace BriarQueen.Framework.Managers.Levels
public bool Initialized { get; private set; }
public BaseLevel CurrentLevel => _currentLevel;
[Inject]
public LevelManager(
AddressableManager addressableManager,

View File

@@ -253,8 +253,6 @@ namespace BriarQueen.Framework.Managers.Player
}
}
_tutorialService.DisplayTutorial(TutorialPopupID.CodexKeyboard);
_eventCoordinator.PublishImmediate(new RequestGameSaveEvent());
_eventCoordinator.Publish(new CodexChangedEvent(entry.EntryType));
}
@@ -437,6 +435,8 @@ namespace BriarQueen.Framework.Managers.Player
Debug.Log($"[PlayerManager] Final InventoryData count = {save.InventoryData.Count}");
save.CodexUnlocked = CodexUnlocked();
save.DiscoveredCodexEntries ??= new List<CodexSaveData>();
save.DiscoveredCodexEntries.Clear();

View File

@@ -12,6 +12,7 @@ using BriarQueen.Framework.Managers.UI.Events;
using BriarQueen.Framework.Services.Settings;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.UI;
using VContainer;
namespace BriarQueen.Framework.Managers.UI

View File

@@ -22,15 +22,9 @@ namespace BriarQueen.Game.Items.Environment.General.Book
internal CanvasGroup CanvasGroup => _canvasGroup;
private void Start()
{
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
}
private void OnDestroy()
{
_eventCoordinator.Unsubscribe<OnRightClickEvent>(OnRightClickPressed);
_interactManager.ClearExclusiveRaycaster();
}
[Inject]

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: fa07dbddba49468ba81f3751a90773b5
timeCreated: 1778599317

View File

@@ -0,0 +1,28 @@
using BriarQueen.Data.Identifiers;
using BriarQueen.Framework.Managers.Levels.Data;
using BriarQueen.Framework.Managers.Player.Data;
using BriarQueen.Framework.Managers.UI;
using Cysharp.Threading.Tasks;
namespace BriarQueen.Game.Items.KeyItems
{
public class CodexBook : BaseItem
{
public override UICursorService.CursorStyle ApplicableCursorStyle => UICursorService.CursorStyle.Pickup;
public async override UniTask OnInteract(ItemDataSo item = null)
{
if (PlayerManager.CodexUnlocked())
{
await Remove();
return;
}
PlayerManager.UnlockCodex();
TutorialService.DisplayTutorial(TutorialPopupID.Codex);
await Remove();
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 9207909e92b24dd0a8b2ed9836ce1134
timeCreated: 1778599317

View File

@@ -1,40 +0,0 @@
using System;
using BriarQueen.Data.Identifiers;
using UnityEngine;
using UnityEngine.UI;
namespace BriarQueen.UI.Codex
{
public class CodexCategoryButton : MonoBehaviour
{
[SerializeField]
private Button _button;
public CodexType Category { get; private set; }
private void Awake()
{
if (_button != null)
_button.onClick.AddListener(HandleClicked);
}
private void OnDestroy()
{
if (_button != null)
_button.onClick.RemoveListener(HandleClicked);
}
public event Action<CodexType> OnCategoryClicked;
public void Initialize(CodexType category)
{
Category = category;
}
private void HandleClicked()
{
OnCategoryClicked?.Invoke(Category);
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 2cfb06e8e46d402e86eb8dc6e9f6c96e
timeCreated: 1773684333

View File

@@ -10,6 +10,7 @@ using BriarQueen.Framework.Managers.Player.Data;
using BriarQueen.Framework.Managers.UI.Base;
using BriarQueen.Framework.Registries;
using BriarQueen.Framework.Services.Destruction;
using BriarQueen.UI.Components;
using BriarQueen.UI.Menus;
using BriarQueen.UI.Menus.Components;
using Cysharp.Threading.Tasks;
@@ -25,31 +26,29 @@ namespace BriarQueen.UI.Codex
{
public class CodexWindow : MonoBehaviour, IUIWindow, IUIBackHandler
{
// ── Root ──────────────────────────────────────────────────────
[Header("Root UI")]
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private RectTransform _windowRect;
// ── Left panel — header ───────────────────────────────────────
[Header("Content")]
[SerializeField] private CanvasGroup _backgroundGroup; // Direct child — faded instead of root
[Header("Left Panel — Header")]
[SerializeField] private TextMeshProUGUI _leftPanelTitleText;
[SerializeField] private CanvasGroup _leftPanelTitleGroup;
// ── Left panel — categories ───────────────────────────────────
[Header("Left Panel — Categories")]
[SerializeField] private CanvasGroup _categoriesGroup;
[SerializeField] private CodexCategoryButton _booksButton;
[SerializeField] private CodexCategoryButton _cluesButton;
[SerializeField] private CodexCategoryButton _photosButton;
[SerializeField] private UnderlineButton _booksButton;
[SerializeField] private UnderlineButton _cluesButton;
[SerializeField] private UnderlineButton _photosButton;
// ── Left panel — locations ────────────────────────────────────
[Header("Left Panel — Locations")]
[SerializeField] private CanvasGroup _locationListGroup;
[SerializeField] private RectTransform _locationListContainer;
[SerializeField] private VerticalScrollbar _locationScrollbar;
[SerializeField] private Button _backToCategoriesButton;
// ── Left panel — entries ──────────────────────────────────────
[Header("Left Panel — Entries")]
[SerializeField] private CanvasGroup _entryListGroup;
[SerializeField] private RectTransform _entryListContainer;
@@ -57,24 +56,20 @@ namespace BriarQueen.UI.Codex
[SerializeField] private Button _backToLocationsButton;
[SerializeField] private UnderlineButtonGroup _entryButtonGroup;
// ── Right panel — display ─────────────────────────────────────
[Header("Right Panel — Display")]
[SerializeField] private CanvasGroup _displayGroup;
[SerializeField] private RectTransform _displayLayoutRoot;
[SerializeField] private CanvasGroup _rightPanelGroup;
[SerializeField] private RectTransform _rightPanelRoot;
[SerializeField] private TextMeshProUGUI _titleText;
[SerializeField] private CanvasGroup _titleGroup;
[SerializeField] private CanvasGroup _contentGroup;
[SerializeField] private RectTransform _contentScrollContainer;
[SerializeField] private VerticalScrollbar _contentScrollbar;
[SerializeField] private TextMeshProUGUI _bodyText;
[SerializeField] private TextMeshProUGUI _photoDescription;
[SerializeField] private CanvasGroup _displayAreaGroup;
[SerializeField] private ScrollableTextBox _bodyText;
[SerializeField] private ScrollableTextBox _photoDescription;
[SerializeField] private TextMeshProUGUI _polaroidWriting;
[SerializeField] private Image _polaroid;
[SerializeField] private Image _displayImage;
[SerializeField] private GameObject _contentRoot;
[SerializeField] private GameObject _displayAreaRoot;
[SerializeField] private GameObject _emptyStateRoot;
// ── Tween settings ────────────────────────────────────────────
[Header("Tween Settings")]
[SerializeField] private TweenSettings _windowTweenSettings = new()
{
@@ -117,7 +112,6 @@ namespace BriarQueen.UI.Codex
[Header("Internal")]
[SerializeField] private GraphicRaycaster _graphicRaycaster;
// ── Runtime state ─────────────────────────────────────────────
private enum LeftPanelState { Categories, Locations, Entries }
private LeftPanelState _leftPanelState = LeftPanelState.Categories;
@@ -161,11 +155,59 @@ namespace BriarQueen.UI.Codex
public bool IsModal => true;
public WindowType WindowType => WindowType.CodexWindow;
// ── Raycaster ─────────────────────────────────────────────────
private void TryRegisterRaycaster()
{
Debug.Log($"[CodexWindow] TryRegisterRaycaster " +
$"registered={_raycasterRegistered} " +
$"interactManager={_interactManager != null} " +
$"raycaster={_graphicRaycaster != null}");
Debug.Log("[CodexWindow] Try register raycaster.");
if (_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.AddUIRaycaster(_graphicRaycaster);
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
Debug.Log("[CodexWindow] Registered raycaster.");
}
private void TryUnregisterRaycaster()
{
Debug.Log("[CodexWindow] Try unregister raycaster.");
if (!_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.RemoveUIRaycaster(_graphicRaycaster);
_interactManager.ClearExclusiveRaycaster();
_raycasterRegistered = false;
Debug.Log("[CodexWindow] Raycaster unregistered.");
}
// ── Unity lifecycle ───────────────────────────────────────────
private void Awake()
{
SetCanvasGroupImmediate(_canvasGroup, 0f, false);
if (_canvasGroup != null)
{
_canvasGroup.alpha = 0f;
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
}
// Background group controls visual fading
if (_backgroundGroup != null)
{
_backgroundGroup.alpha = 0f;
_backgroundGroup.blocksRaycasts = false;
_backgroundGroup.interactable = false;
}
if (_windowRect != null)
_windowRect.localScale = Vector3.one * _hiddenScale;
@@ -177,29 +219,26 @@ namespace BriarQueen.UI.Codex
SetLeftPanelTitleImmediate("Codex");
}
private void Start()
private async UniTaskVoid Start()
{
InitializeCategoryButtons();
_started = true;
CacheButtonReferences();
await EnsurePoolsReady();
}
private void OnEnable()
{
BindCategoryButtons();
BindNavButtons();
if (_started)
TryRegisterRaycaster();
}
private void OnDisable()
{
UnbindCategoryButtons();
UnbindNavButtons();
TryUnregisterRaycaster();
ReleaseAllLocationButtons();
ReleaseAllEntryButtons();
CancelAllOperations();
_interactManager?.ClearExclusiveRaycaster();
}
private void OnDestroy()
@@ -207,25 +246,31 @@ namespace BriarQueen.UI.Codex
CancelAllOperations();
_locationButtonPool?.Dispose();
_entryButtonPool?.Dispose();
TryUnregisterRaycaster();
}
// ── IUIWindow ─────────────────────────────────────────────────
public async UniTask Show()
{
CacheButtonReferences();
ResetOperationCts();
gameObject.SetActive(true);
TryRegisterRaycaster();
if (!_started)
await UniTask.WaitUntil(() => _started,
cancellationToken: this.GetCancellationTokenOnDestroy());
if (_canvasGroup != null)
{
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
}
await EnsurePoolsReady();
if (_backgroundGroup != null)
{
_backgroundGroup.alpha = 0f;
_backgroundGroup.blocksRaycasts = false;
_backgroundGroup.interactable = false;
}
ResetOperationCts();
gameObject.SetActive(true);
SetCanvasGroupImmediate(_canvasGroup, 0f, false);
if (_windowRect != null)
_windowRect.localScale = Vector3.one * _hiddenScale;
@@ -236,7 +281,7 @@ namespace BriarQueen.UI.Codex
SetLeftPanelTitleImmediate("Codex");
_windowSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_canvasGroup, new TweenSettings<float>
.Group(Tween.Alpha(_backgroundGroup, new TweenSettings<float>
{
startValue = 0f,
endValue = 1f,
@@ -251,26 +296,54 @@ namespace BriarQueen.UI.Codex
try
{
await _windowSequence.ToUniTask(cancellationToken: _operationCts.Token);
}
catch (OperationCanceledException) { return; }
finally { _windowSequence = default; }
var canvasTask = Tween.Alpha(_canvasGroup, new TweenSettings<float>
{
startValue = 0f,
endValue = 1f,
settings = _windowTweenSettings
}).ToUniTask();
var backgroundTask = _windowSequence.ToUniTask();
await UniTask.WhenAll(canvasTask, backgroundTask).AttachExternalCancellation(_operationCts.Token);
_backgroundGroup.blocksRaycasts = true;
_backgroundGroup.interactable = true;
}
catch (OperationCanceledException)
{
return;
}
finally
{
_windowSequence = default;
}
_canvasGroup.interactable = true;
_canvasGroup.blocksRaycasts = true;
_canvasGroup.alpha = 1f;
SetCanvasGroupImmediate(_canvasGroup, 1f, true);
await TransitionToCategories(instant: true);
Debug.Log($"[CodexWindow] Codex Window Show Complete.");
}
public async UniTask Hide()
{
TryUnregisterRaycaster();
Debug.Log($"[CodexWindow] Codex Window Hide Started.");
ResetOperationCts();
SetCanvasGroupInteractivity(_canvasGroup, false);
if (_canvasGroup != null)
{
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
}
TryUnregisterRaycaster();
_windowSequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_canvasGroup, new TweenSettings<float>
.Group(Tween.Alpha(_backgroundGroup, new TweenSettings<float>
{
startValue = _canvasGroup.alpha,
startValue = _backgroundGroup != null ? _backgroundGroup.alpha : 1f,
endValue = 0f,
settings = _windowTweenSettings
}))
@@ -288,7 +361,15 @@ namespace BriarQueen.UI.Codex
catch (OperationCanceledException) { return; }
finally { _windowSequence = default; }
if (_canvasGroup != null)
{
_canvasGroup.alpha = 0f;
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
}
gameObject.SetActive(false);
Debug.Log($"[CodexWindow] Codex Window Hide Complete.");
}
// ── IUIBackHandler ────────────────────────────────────────────
@@ -297,19 +378,10 @@ namespace BriarQueen.UI.Codex
{
switch (_leftPanelState)
{
case LeftPanelState.Entries:
NavigateBackToLocations().Forget();
return true;
case LeftPanelState.Locations:
NavigateBackToCategories().Forget();
return true;
case LeftPanelState.Categories:
return false;
default:
return false;
case LeftPanelState.Entries: NavigateBackToLocations().Forget(); return true;
case LeftPanelState.Locations: NavigateBackToCategories().Forget(); return true;
case LeftPanelState.Categories: return false;
default: return false;
}
}
@@ -415,7 +487,6 @@ namespace BriarQueen.UI.Codex
{
if (_entryButtonGroup != null)
_entryButtonGroup.RemoveButton(btn.UnderlineButton);
btn.OnEntryClicked -= OnEntryClicked;
btn.SetSelected(false);
btn.gameObject.SetActive(false);
@@ -432,30 +503,15 @@ namespace BriarQueen.UI.Codex
// ── Navigation ────────────────────────────────────────────────
private void OnCategoryClicked(CodexType category)
{
NavigateToLocations(category).Forget();
}
private void OnCluesClicked(UnderlineButton _) => NavigateToLocations(CodexType.PuzzleClue).Forget();
private void OnDocumentsClicked(UnderlineButton _) => NavigateToLocations(CodexType.DocumentEntry).Forget();
private void OnLocationClicked(Location location)
{
NavigateToEntries(location).Forget();
}
private void OnPhotosClicked(UnderlineButton _) => NavigateToLocations(CodexType.Photo).Forget();
private void OnEntryClicked(CodexEntrySo entry)
{
DisplayEntry(entry).Forget();
}
private void OnBackToCategoriesClicked()
{
NavigateBackToCategories().Forget();
}
private void OnBackToLocationsClicked()
{
NavigateBackToLocations().Forget();
}
private void OnLocationClicked(Location location) => NavigateToEntries(location).Forget();
private void OnEntryClicked(CodexEntrySo entry) => DisplayEntry(entry).Forget();
private void OnBackToCategoriesClicked() => NavigateBackToCategories().Forget();
private void OnBackToLocationsClicked() => NavigateBackToLocations().Forget();
// ── Left panel transitions ────────────────────────────────────
@@ -494,7 +550,6 @@ namespace BriarQueen.UI.Codex
await FadeLeftPanelTitle(GetCategoryDisplayName(category));
await FadeOutCurrentLeftPanel();
await BuildLocationButtons(token);
token.ThrowIfCancellationRequested();
_leftPanelState = LeftPanelState.Locations;
@@ -502,7 +557,6 @@ namespace BriarQueen.UI.Codex
await RefreshLayout(_locationListContainer);
RestoreLocationScroll();
await FadePanelIn(_locationListGroup);
await FadeOutDisplay();
ShowEmptyDisplay();
}
@@ -524,7 +578,6 @@ namespace BriarQueen.UI.Codex
await FadeLeftPanelTitle(GetLocationDisplayName(location));
await FadePanelOut(_locationListGroup);
await BuildEntryButtons(token);
token.ThrowIfCancellationRequested();
_leftPanelState = LeftPanelState.Entries;
@@ -532,7 +585,6 @@ namespace BriarQueen.UI.Codex
await RefreshLayout(_entryListContainer);
RestoreEntryScroll();
await FadePanelIn(_entryListGroup);
await FadeOutDisplay();
ShowEmptyDisplay();
}
@@ -542,7 +594,6 @@ namespace BriarQueen.UI.Codex
private async UniTask NavigateBackToCategories()
{
ResetOperationCts();
try
{
await FadeOutDisplay();
@@ -565,7 +616,6 @@ namespace BriarQueen.UI.Codex
await FadeLeftPanelTitle(GetCategoryDisplayName(_currentCategory));
await FadePanelOut(_entryListGroup);
ReleaseAllEntryButtons();
token.ThrowIfCancellationRequested();
_leftPanelState = LeftPanelState.Locations;
@@ -573,7 +623,6 @@ namespace BriarQueen.UI.Codex
await RefreshLayout(_locationListContainer);
RestoreLocationScroll();
await FadePanelIn(_locationListGroup);
await FadeOutDisplay();
ShowEmptyDisplay();
}
@@ -584,15 +633,9 @@ namespace BriarQueen.UI.Codex
{
switch (_leftPanelState)
{
case LeftPanelState.Categories:
await FadePanelOut(_categoriesGroup);
break;
case LeftPanelState.Locations:
await FadePanelOut(_locationListGroup);
break;
case LeftPanelState.Entries:
await FadePanelOut(_entryListGroup);
break;
case LeftPanelState.Categories: await FadePanelOut(_categoriesGroup); break;
case LeftPanelState.Locations: await FadePanelOut(_locationListGroup); break;
case LeftPanelState.Entries: await FadePanelOut(_entryListGroup); break;
}
}
@@ -600,11 +643,12 @@ namespace BriarQueen.UI.Codex
private void SetLeftPanelTitleImmediate(string title)
{
if (_leftPanelTitleText != null) _leftPanelTitleText.text = title;
if (_leftPanelTitleText != null) _leftPanelTitleText.text = title;
if (_leftPanelTitleGroup != null)
{
_leftPanelTitleGroup.alpha = 1f;
_leftPanelTitleGroup.gameObject.SetActive(true);
_leftPanelTitleGroup.alpha = 1f;
_leftPanelTitleGroup.interactable = true;
_leftPanelTitleGroup.blocksRaycasts = true;
}
}
@@ -617,7 +661,6 @@ namespace BriarQueen.UI.Codex
}
StopLeftPanelTitleTween();
var token = _operationCts?.Token ?? this.GetCancellationTokenOnDestroy();
_leftPanelTitleSequence = Sequence.Create(useUnscaledTime: true)
@@ -663,10 +706,8 @@ namespace BriarQueen.UI.Codex
_ => string.Empty
};
private static string GetLocationDisplayName(Location location)
{
return location.ToString().Replace("_", " ");
}
private static string GetLocationDisplayName(Location location) =>
location.ToString().Replace("_", " ");
// ── Display area ──────────────────────────────────────────────
@@ -679,7 +720,7 @@ namespace BriarQueen.UI.Codex
try
{
if (_currentEntry != null && _displayGroup.alpha > 0.001f)
if (_currentEntry != null && _rightPanelGroup.alpha > 0.001f)
await FadeOutDisplay();
token.ThrowIfCancellationRequested();
@@ -687,10 +728,9 @@ namespace BriarQueen.UI.Codex
_currentEntry = entry;
_lastEntryByCategory[_currentCategory] = entry.UniqueID;
UpdateEntryButtonSelection();
ApplyEntryToDisplay(entry);
await RefreshLayout(_displayLayoutRoot);
await RefreshLayout(_rightPanelRoot);
SetTitleVisible(false);
SetContentVisible(false);
@@ -718,9 +758,9 @@ namespace BriarQueen.UI.Codex
private async UniTask FadeInTitle(CancellationToken token)
{
if (_titleGroup == null) return;
_titleGroup.alpha = 0f;
_titleGroup.gameObject.SetActive(true);
_titleGroup.alpha = 0f;
_titleGroup.interactable = true;
_titleGroup.blocksRaycasts = true;
await Tween.Alpha(_titleGroup, new TweenSettings<float>
{
@@ -734,31 +774,31 @@ namespace BriarQueen.UI.Codex
private async UniTask FadeInContent(CancellationToken token)
{
if (_contentGroup == null) return;
if (_displayAreaGroup == null) return;
_displayAreaGroup.alpha = 0f;
_displayAreaGroup.interactable = true;
_displayAreaGroup.blocksRaycasts = true;
_contentGroup.alpha = 0f;
_contentGroup.gameObject.SetActive(true);
await Tween.Alpha(_contentGroup, new TweenSettings<float>
await Tween.Alpha(_displayAreaGroup, new TweenSettings<float>
{
startValue = 0f,
endValue = 1f,
settings = _contentFadeSettings
}).ToUniTask(cancellationToken: token);
_contentGroup.alpha = 1f;
_displayAreaGroup.alpha = 1f;
}
private async UniTask FadeOutDisplay()
{
if (_displayGroup == null || _displayGroup.alpha < 0.001f) return;
if (_rightPanelGroup == null || _rightPanelGroup.alpha < 0.001f) return;
StopDisplayTween();
_displaySequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_displayGroup, new TweenSettings<float>
.Group(Tween.Alpha(_rightPanelGroup, new TweenSettings<float>
{
startValue = _displayGroup.alpha,
startValue = _rightPanelGroup.alpha,
endValue = 0f,
settings = _contentFadeSettings
}));
@@ -777,15 +817,17 @@ namespace BriarQueen.UI.Codex
private void SetTitleVisible(bool visible)
{
if (_titleGroup == null) return;
_titleGroup.alpha = visible ? 1f : 0f;
_titleGroup.gameObject.SetActive(visible);
_titleGroup.alpha = visible ? 1f : 0f;
_titleGroup.interactable = visible;
_titleGroup.blocksRaycasts = visible;
}
private void SetContentVisible(bool visible)
{
if (_contentGroup == null) return;
_contentGroup.alpha = visible ? 1f : 0f;
_contentGroup.gameObject.SetActive(visible);
if (_displayAreaGroup == null) return;
_displayAreaGroup.alpha = visible ? 1f : 0f;
_displayAreaGroup.interactable = visible;
_displayAreaGroup.blocksRaycasts = visible;
}
// ── Panel fade helpers ────────────────────────────────────────
@@ -796,7 +838,6 @@ namespace BriarQueen.UI.Codex
StopLeftPanelTween();
group.alpha = 0f;
group.gameObject.SetActive(true);
group.blocksRaycasts = false;
group.interactable = false;
@@ -825,7 +866,12 @@ namespace BriarQueen.UI.Codex
{
if (group == null || group.alpha < 0.001f)
{
SetPanelImmediate(group, false);
if (group != null)
{
group.alpha = 0f;
group.interactable = false;
group.blocksRaycasts = false;
}
return;
}
@@ -849,7 +895,9 @@ namespace BriarQueen.UI.Codex
catch (OperationCanceledException) { return; }
finally { _leftPanelSequence = default; }
SetPanelImmediate(group, false);
group.alpha = 0f;
group.interactable = false;
group.blocksRaycasts = false;
}
// ── Button building ───────────────────────────────────────────
@@ -872,10 +920,8 @@ namespace BriarQueen.UI.Codex
foreach (var location in locations)
{
token.ThrowIfCancellationRequested();
var button = _locationButtonPool.Get();
if (button == null) continue;
button.Initialize(location);
button.OnLocationClicked += OnLocationClicked;
_activeLocationButtons.Add(button);
@@ -901,14 +947,11 @@ namespace BriarQueen.UI.Codex
foreach (var entry in entries)
{
token.ThrowIfCancellationRequested();
var button = _entryButtonPool.Get();
if (button == null) continue;
button.Initialize(entry);
button.OnEntryClicked += OnEntryClicked;
_activeEntryButtons.Add(button);
if (_entryButtonGroup != null && button.UnderlineButton != null)
_entryButtonGroup.AddButton(button.UnderlineButton);
}
@@ -923,14 +966,13 @@ namespace BriarQueen.UI.Codex
{
if (entry == null) { ClearDisplay(); return; }
if (_titleText != null)
_titleText.text = entry.Title;
if (_titleText != null) _titleText.text = entry.Title;
var isPhoto = entry.EntryType == CodexType.Photo || entry.IsPhotoOverride;
var showImage = isPhoto && entry.DisplayImage != null;
var showText = !string.IsNullOrWhiteSpace(entry.BodyText) || entry.IsBodyTextOverride;
var showPhotoDesc = isPhoto && !string.IsNullOrWhiteSpace(entry.PhotoDescription);
var showPolaroid = isPhoto && !string.IsNullOrWhiteSpace(entry.PolaroidWriting);
var showPhotoDesc = isPhoto && !string.IsNullOrWhiteSpace(entry.PhotoDescription);
if (_polaroid != null)
_polaroid.gameObject.SetActive(isPhoto);
@@ -942,36 +984,36 @@ namespace BriarQueen.UI.Codex
_displayImage.gameObject.SetActive(showImage);
}
if (_photoDescription != null)
{
_photoDescription.text = showPhotoDesc ? entry.PhotoDescription : string.Empty;
_photoDescription.gameObject.SetActive(showPhotoDesc);
}
if (_polaroidWriting != null)
{
_polaroidWriting.text = showPolaroid ? entry.PolaroidWriting : string.Empty;
_polaroidWriting.gameObject.SetActive(showPolaroid);
}
if (_photoDescription != null)
{
if (showPhotoDesc) { _photoDescription.gameObject.SetActive(true); _photoDescription.SetText(entry.PhotoDescription); }
else { _photoDescription.Clear(); _photoDescription.gameObject.SetActive(false); }
}
if (_bodyText != null)
{
_bodyText.text = showText ? entry.BodyText : string.Empty;
_bodyText.gameObject.SetActive(showText);
if (showText) { _bodyText.gameObject.SetActive(true); _bodyText.SetText(entry.BodyText); }
else { _bodyText.Clear(); _bodyText.gameObject.SetActive(false); }
}
SetEmptyStateVisible(false);
if (_contentRoot != null) _contentRoot.SetActive(true);
if (_displayAreaRoot != null) _displayAreaRoot.SetActive(true);
}
private void ClearDisplay()
{
if (_titleText != null) _titleText.text = string.Empty;
if (_bodyText != null) { _bodyText.text = string.Empty; _bodyText.gameObject.SetActive(false); }
if (_polaroid != null) _polaroid.gameObject.SetActive(false);
if (_displayImage != null) { _displayImage.sprite = null; _displayImage.enabled = false; _displayImage.gameObject.SetActive(false); }
if (_photoDescription != null) { _photoDescription.text = string.Empty; _photoDescription.gameObject.SetActive(false); }
if (_polaroidWriting != null) { _polaroidWriting.text = string.Empty; _polaroidWriting.gameObject.SetActive(false); }
if (_titleText != null) _titleText.text = string.Empty;
if (_bodyText != null) { _bodyText.Clear(); _bodyText.gameObject.SetActive(false); }
if (_photoDescription != null) { _photoDescription.Clear(); _photoDescription.gameObject.SetActive(false); }
if (_polaroid != null) _polaroid.gameObject.SetActive(false);
if (_displayImage != null) { _displayImage.sprite = null; _displayImage.enabled = false; _displayImage.gameObject.SetActive(false); }
if (_polaroidWriting != null) { _polaroidWriting.text = string.Empty; _polaroidWriting.gameObject.SetActive(false); }
}
// ── Selection state ───────────────────────────────────────────
@@ -981,13 +1023,10 @@ namespace BriarQueen.UI.Codex
foreach (var button in _activeEntryButtons)
{
if (button == null) continue;
var isSelected = _currentEntry != null &&
button.Entry != null &&
button.Entry.UniqueID == _currentEntry.UniqueID;
button.SetSelected(isSelected);
if (_entryButtonGroup != null && button.UnderlineButton != null && isSelected)
_entryButtonGroup.SelectButton(button.UnderlineButton);
}
@@ -1051,25 +1090,18 @@ namespace BriarQueen.UI.Codex
// ── Binding ───────────────────────────────────────────────────
private void InitializeCategoryButtons()
{
if (_booksButton != null) _booksButton.Initialize(CodexType.DocumentEntry);
if (_cluesButton != null) _cluesButton.Initialize(CodexType.PuzzleClue);
if (_photosButton != null) _photosButton.Initialize(CodexType.Photo);
}
private void BindCategoryButtons()
{
if (_booksButton != null) _booksButton.OnCategoryClicked += OnCategoryClicked;
if (_cluesButton != null) _cluesButton.OnCategoryClicked += OnCategoryClicked;
if (_photosButton != null) _photosButton.OnCategoryClicked += OnCategoryClicked;
if (_booksButton != null) _booksButton.SelectionRequested += OnDocumentsClicked;
if (_cluesButton != null) _cluesButton.SelectionRequested += OnCluesClicked;
if (_photosButton != null) _photosButton.SelectionRequested += OnPhotosClicked;
}
private void UnbindCategoryButtons()
{
if (_booksButton != null) _booksButton.OnCategoryClicked -= OnCategoryClicked;
if (_cluesButton != null) _cluesButton.OnCategoryClicked -= OnCategoryClicked;
if (_photosButton != null) _photosButton.OnCategoryClicked -= OnCategoryClicked;
if (_booksButton != null) _booksButton.SelectionRequested -= OnDocumentsClicked;
if (_cluesButton != null) _cluesButton.SelectionRequested -= OnCluesClicked;
if (_photosButton != null) _photosButton.SelectionRequested -= OnPhotosClicked;
}
private void BindNavButtons()
@@ -1088,24 +1120,6 @@ namespace BriarQueen.UI.Codex
_backToLocationsButton.onClick.RemoveListener(OnBackToLocationsClicked);
}
// ── Raycaster ─────────────────────────────────────────────────
private void TryRegisterRaycaster()
{
if (_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.AddUIRaycaster(_graphicRaycaster);
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
}
private void TryUnregisterRaycaster()
{
if (!_raycasterRegistered || _interactManager == null || _graphicRaycaster == null) return;
_interactManager.RemoveUIRaycaster(_graphicRaycaster);
_interactManager.ClearExclusiveRaycaster();
_raycasterRegistered = false;
}
// ── Layout ────────────────────────────────────────────────────
private async UniTask RefreshLayout(RectTransform root)
@@ -1142,7 +1156,6 @@ namespace BriarQueen.UI.Codex
group.alpha = visible ? 1f : 0f;
group.interactable = visible;
group.blocksRaycasts = visible;
group.gameObject.SetActive(visible);
}
private static void SetCanvasGroupImmediate(CanvasGroup group, float alpha, bool interactable)
@@ -1162,17 +1175,16 @@ namespace BriarQueen.UI.Codex
private void SetDisplayImmediate(bool visible)
{
if (_displayGroup == null) return;
_displayGroup.alpha = visible ? 1f : 0f;
_displayGroup.interactable = visible;
_displayGroup.blocksRaycasts = visible;
_displayGroup.gameObject.SetActive(visible);
if (_rightPanelGroup == null) return;
_rightPanelGroup.alpha = visible ? 1f : 0f;
_rightPanelGroup.interactable = visible;
_rightPanelGroup.blocksRaycasts = visible;
}
private void SetEmptyStateVisible(bool visible)
{
if (_emptyStateRoot != null) _emptyStateRoot.SetActive(visible);
if (_contentRoot != null) _contentRoot.SetActive(!visible);
if (_emptyStateRoot != null) _emptyStateRoot.SetActive(visible);
if (_displayAreaRoot != null) _displayAreaRoot.SetActive(!visible);
}
// ── CTS helpers ───────────────────────────────────────────────

View File

@@ -0,0 +1,144 @@
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace BriarQueen.UI.Components
{
[ExecuteAlways]
public class ScrollableTextBox : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI _text;
[SerializeField] private RectTransform _content;
[SerializeField] private BriarQueen.UI.Menus.VerticalScrollbar _scrollbar;
private RectTransform _textRect;
private LayoutElement _layoutElement;
private void Awake()
{
Init();
}
private void OnValidate()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.delayCall += () =>
{
if (this == null) return;
Init();
if (_text != null && !string.IsNullOrEmpty(_text.text))
ApplyTextHeight();
};
#endif
}
private void Init()
{
if (_text != null)
{
_textRect = _text.GetComponent<RectTransform>();
_layoutElement = _text.GetComponent<LayoutElement>();
if (_layoutElement == null)
_layoutElement = _text.gameObject.AddComponent<LayoutElement>();
}
}
private void ApplyTextHeight()
{
_text.ForceMeshUpdate();
var height = _text.preferredHeight;
if (_layoutElement != null)
_layoutElement.preferredHeight = height;
if (_textRect != null)
{
var delta = _textRect.sizeDelta;
delta.y = height;
_textRect.sizeDelta = delta;
}
if (_content != null)
{
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
}
}
public void SetText(string content)
{
if (_text == null) return;
_text.text = content;
_text.ForceMeshUpdate();
var height = _text.preferredHeight;
if (_layoutElement != null)
_layoutElement.preferredHeight = height;
if (_textRect != null)
{
var delta = _textRect.sizeDelta;
delta.y = height;
_textRect.sizeDelta = delta;
}
// Also resize Content to match so scrollbar measures correctly
if (_content != null)
{
var delta = _content.sizeDelta;
delta.y = height;
_content.sizeDelta = delta;
var pos = _content.anchoredPosition;
pos.y = 0f;
_content.anchoredPosition = pos;
}
if (Application.isPlaying)
StartCoroutine(RebuildNextFrame());
else
_scrollbar?.Rebuild();
}
private System.Collections.IEnumerator RebuildNextFrame()
{
yield return null;
Canvas.ForceUpdateCanvases();
LayoutRebuilder.ForceRebuildLayoutImmediate(_content);
yield return null;
_scrollbar?.Rebuild();
_scrollbar?.SetNormalized(1f);
}
public void Clear()
{
if (_text == null) return;
_text.text = string.Empty;
if (_layoutElement != null)
_layoutElement.preferredHeight = 0f;
if (_textRect != null)
{
var sd = _textRect.sizeDelta;
sd.y = 0f;
_textRect.sizeDelta = sd;
}
if (_content != null)
{
var pos = _content.anchoredPosition;
pos.y = 0f;
_content.anchoredPosition = pos;
}
_scrollbar?.Rebuild();
}
public void ScrollToTop() => _scrollbar?.SetNormalized(1f);
public void ScrollToBottom() => _scrollbar?.SetNormalized(0f);
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: c3727dc2fa2f418f82fcfae0993856cb
timeCreated: 1778584851

View File

@@ -15,11 +15,17 @@ namespace BriarQueen.UI.Menus.Components
IDeselectHandler
{
[Header("References")]
[SerializeField] private TextMeshProUGUI _label;
[SerializeField] protected TextMeshProUGUI _label;
private Button _button;
private UnderlineButtonGroup _group;
private bool _isHovered;
[SerializeField]
protected TextMeshProUGUI _contextLabel;
[SerializeField]
protected string _contextText;
protected Button _button;
protected UnderlineButtonGroup _group;
protected bool _isHovered;
public event Action<UnderlineButton> SelectionRequested;
public event Action<UnderlineButton> HoverEntered;
@@ -30,13 +36,14 @@ namespace BriarQueen.UI.Menus.Components
// True when this button is registered with a group
public bool IsGrouped => _group != null;
private void Awake()
protected virtual void Awake()
{
_button = GetComponent<Button>();
SetUnderline(false);
}
private void OnDisable()
protected virtual void OnDisable()
{
_isHovered = false;
SetUnderline(false);
@@ -68,6 +75,8 @@ namespace BriarQueen.UI.Menus.Components
HoverEntered?.Invoke(this);
else
RefreshStandaloneState();
UpdateContextText();
}
public void OnPointerExit(PointerEventData eventData)
@@ -78,10 +87,13 @@ namespace BriarQueen.UI.Menus.Components
HoverExited?.Invoke(this);
else
RefreshStandaloneState();
UpdateContextText();
}
public void OnPointerClick(PointerEventData eventData)
{
Debug.Log($"[UnderlineButton] OnPointerClick {gameObject.name}");
if (_button != null && !_button.interactable) return;
SelectionRequested?.Invoke(this);
}
@@ -102,6 +114,8 @@ namespace BriarQueen.UI.Menus.Components
IsSelected = true;
RefreshStandaloneState();
}
UpdateContextText();
}
public void OnDeselect(BaseEventData eventData)
@@ -115,6 +129,8 @@ namespace BriarQueen.UI.Menus.Components
IsSelected = false;
RefreshStandaloneState();
}
UpdateContextText();
}
// ── Public API ────────────────────────────────────────────────
@@ -154,5 +170,16 @@ namespace BriarQueen.UI.Menus.Components
SetUnderline(IsSelected || _isHovered);
}
private void UpdateContextText()
{
if (_contextLabel == null)
return;
if(IsSelected || _isHovered)
_contextLabel.text = _contextText;
else
_contextLabel.text = string.Empty;
}
}
}

View File

@@ -5,11 +5,14 @@ using BriarQueen.Framework.Events.UI;
using BriarQueen.Framework.Managers.Audio;
using BriarQueen.Framework.Managers.Interaction;
using BriarQueen.Framework.Managers.IO;
using BriarQueen.Framework.Managers.Levels;
using BriarQueen.Framework.Managers.UI.Base;
using BriarQueen.Framework.Managers.UI.Events;
using BriarQueen.Framework.Services.Game;
using BriarQueen.UI.Menus.Components;
using Cysharp.Threading.Tasks;
using PrimeTween;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.UI;
@@ -20,226 +23,392 @@ namespace BriarQueen.UI.Menus
public class PauseMenuWindow : MonoBehaviour, IUIWindow
{
[Header("Root UI")]
[SerializeField]
private CanvasGroup _canvasGroup;
[SerializeField] private CanvasGroup _canvasGroup;
[SerializeField] private RectTransform _windowRect;
[SerializeField]
private RectTransform _windowRect;
[Header("Background")]
[SerializeField] private CanvasGroup _backgroundGroup;
[Header("Transient Info")]
[SerializeField] private TextMeshProUGUI _levelName;
[Header("Buttons")]
[SerializeField]
private Button _resumeButton;
[SerializeField] private UnderlineButton _resumeButton;
[SerializeField] private UnderlineButton _saveButton;
[SerializeField] private UnderlineButton _settingsButton;
[SerializeField] private UnderlineButton _exitButton;
[SerializeField] private UnderlineButton _quitToDesktopButton;
[SerializeField]
private Button _saveButton;
[SerializeField]
private Button _settingsButton;
[SerializeField]
private Button _exitButton;
[SerializeField]
private Button _quitToDesktopButton;
[Header("Layout")]
[SerializeField] private CanvasGroup _buttonsGroup;
[Header("Selection")]
[SerializeField]
private Selectable _firstSelectedOnOpen;
[SerializeField] private Selectable _firstSelectedOnOpen;
[Header("Tween Settings")]
[SerializeField]
private TweenSettings _tweenSettings = new()
[SerializeField] private TweenSettings _backgroundFadeSettings = new()
{
duration = 0.25f,
ease = Ease.OutQuad,
duration = 0.4f,
ease = Ease.OutQuad,
useUnscaledTime = true
};
[SerializeField] private TweenSettings _buttonFadeSettings = new()
{
duration = 0.25f,
ease = Ease.OutQuad,
useUnscaledTime = true
};
[Header("Scale")]
[SerializeField]
private float _hiddenScale = 0.85f;
[SerializeField] private float _hiddenScale = 0.85f;
[Header("Internal")]
[SerializeField]
private GraphicRaycaster _graphicRaycaster;
[SerializeField] private GraphicRaycaster _graphicRaycaster;
private AudioManager _audioManager;
private CancellationTokenSource _cts;
private EventCoordinator _eventCoordinator;
private GameService _gameService;
private InteractManager _interactManager;
private SaveManager _saveManager;
private LevelManager _levelManager;
private CancellationTokenSource _cts;
private Sequence _sequence;
private bool _raycasterRegistered;
public bool IsModal => true;
public WindowType WindowType => WindowType.PauseMenuWindow;
private void TryRegisterRaycaster()
{
if (_raycasterRegistered)
return;
if (_interactManager == null || _graphicRaycaster == null)
return;
_interactManager.AddUIRaycaster(_graphicRaycaster);
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
}
private void TryUnregisterRaycaster()
{
if (!_raycasterRegistered)
return;
if (_interactManager == null || _graphicRaycaster == null)
return;
_interactManager.RemoveUIRaycaster(_graphicRaycaster);
_interactManager.ClearExclusiveRaycaster();
_raycasterRegistered = false;
}
// ── Unity lifecycle ───────────────────────────────────────────
private void Awake()
{
// Start hidden by default
if (_canvasGroup != null)
{
_canvasGroup.alpha = 0f;
_canvasGroup.alpha = 0f;
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
_canvasGroup.interactable = false;
}
if (_windowRect != null)
_windowRect.localScale = Vector3.one * _hiddenScale;
_windowRect.localScale = Vector3.one;
SetGroupImmediate(_backgroundGroup, 0f);
HideButtons();
}
private void OnEnable()
{
if (_resumeButton != null) _resumeButton.onClick.AddListener(OnResumeButtonClick);
if (_saveButton != null) _saveButton.onClick.AddListener(OnSaveButtonClick);
if (_settingsButton != null) _settingsButton.onClick.AddListener(OnSettingsButtonClick);
if (_exitButton != null) _exitButton.onClick.AddListener(OnExitButtonClick);
if (_quitToDesktopButton != null) _quitToDesktopButton.onClick.AddListener(OnQuitToDesktopButtonClick);
_interactManager.SetExclusiveRaycaster(_graphicRaycaster);
BindButtons();
}
private void OnDisable()
{
if (_resumeButton != null) _resumeButton.onClick.RemoveListener(OnResumeButtonClick);
if (_saveButton != null) _saveButton.onClick.RemoveListener(OnSaveButtonClick);
if (_settingsButton != null) _settingsButton.onClick.RemoveListener(OnSettingsButtonClick);
if (_exitButton != null) _exitButton.onClick.RemoveListener(OnExitButtonClick);
if (_quitToDesktopButton != null) _quitToDesktopButton.onClick.RemoveListener(OnQuitToDesktopButtonClick);
_interactManager.ClearExclusiveRaycaster();
UnbindButtons();
}
private void OnDestroy()
{
StopAndResetCancellation();
TryUnregisterRaycaster();
}
// ── IUIWindow ─────────────────────────────────────────────────
public async UniTask Show()
{
if (_canvasGroup == null || _windowRect == null)
{
Debug.LogError("[PauseMenuWindow] Missing CanvasGroup or WindowRect reference.");
gameObject.SetActive(true);
return;
}
StopAndResetCancellation();
SetLevelName();
gameObject.SetActive(true);
TryRegisterRaycaster();
_canvasGroup.alpha = 0f;
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
_canvasGroup.interactable = false;
_windowRect.localScale = Vector3.one * _hiddenScale;
var alpha = new TweenSettings<float>
{
startValue = 0f,
endValue = 1f,
settings = _tweenSettings
};
var scale = new TweenSettings<Vector3>
{
startValue = Vector3.one * _hiddenScale,
endValue = Vector3.one,
settings = _tweenSettings
};
_sequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_canvasGroup, alpha))
.Group(Tween.Scale(_windowRect, scale));
SetGroupImmediate(_backgroundGroup, 0f);
HideButtons();
try
{
await _sequence.ToUniTask(cancellationToken: _cts.Token);
var fadeWindowTask = FadeGroup(_canvasGroup, 1f, _backgroundFadeSettings, _cts.Token);
var fadeBackgroundTask = FadeGroup(_backgroundGroup, 1f, _backgroundFadeSettings, _cts.Token);
await UniTask.WhenAll(fadeWindowTask, fadeBackgroundTask);
_backgroundGroup.blocksRaycasts = true;
_backgroundGroup.interactable = true;
_buttonsGroup.blocksRaycasts = true;
_buttonsGroup.interactable = true;
await FadeGroup(_buttonsGroup, 1f, _buttonFadeSettings, _cts.Token);
}
catch (OperationCanceledException)
{
return;
}
finally
{
_sequence = default;
}
_canvasGroup.alpha = 1f;
_windowRect.localScale = Vector3.one;
_canvasGroup.blocksRaycasts = true;
_canvasGroup.interactable = true;
SelectDefault();
_canvasGroup.interactable = true;
}
public async UniTask Hide()
{
if (_canvasGroup == null || _windowRect == null)
{
gameObject.SetActive(false);
return;
}
StopAndResetCancellation();
// Block clicks immediately
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
_canvasGroup.interactable = false;
var alpha = new TweenSettings<float>
{
startValue = _canvasGroup.alpha,
endValue = 0f,
settings = _tweenSettings
};
var scale = new TweenSettings<Vector3>
{
startValue = _windowRect.localScale,
endValue = Vector3.one * _hiddenScale,
settings = _tweenSettings
};
_sequence = Sequence.Create(useUnscaledTime: true)
.Group(Tween.Alpha(_canvasGroup, alpha))
.Group(Tween.Scale(_windowRect, scale));
TryUnregisterRaycaster();
try
{
await _sequence.ToUniTask(cancellationToken: _cts.Token);
await FadeGroup(_buttonsGroup, 0f, _buttonFadeSettings, _cts.Token);
await FadeGroup(_backgroundGroup, 0f, _backgroundFadeSettings, _cts.Token);
}
catch (OperationCanceledException)
{
return;
}
finally
{
_sequence = default;
}
_canvasGroup.alpha = 0f;
_windowRect.localScale = Vector3.one * _hiddenScale;
_resumeButton.SetSelectedState(false);
_saveButton.SetSelectedState(false);
_settingsButton.SetSelectedState(false);
_exitButton.SetSelectedState(false);
_quitToDesktopButton.SetSelectedState(false);
_canvasGroup.alpha = 0f;
_canvasGroup.blocksRaycasts = false;
_canvasGroup.interactable = false;
gameObject.SetActive(false);
}
// ── DI ────────────────────────────────────────────────────────
[Inject]
public void Construct(EventCoordinator eventCoordinator, SaveManager saveManager, GameService gameService,
InteractManager interactManager, AudioManager audioManager)
public void Construct(
EventCoordinator eventCoordinator,
SaveManager saveManager,
GameService gameService,
InteractManager interactManager,
AudioManager audioManager,
LevelManager levelManager)
{
_eventCoordinator = eventCoordinator;
_saveManager = saveManager;
_gameService = gameService;
_interactManager = interactManager;
_audioManager = audioManager;
_saveManager = saveManager;
_gameService = gameService;
_interactManager = interactManager;
_audioManager = audioManager;
_levelManager = levelManager;
}
// ── Level ─────────────────────────────────────────────────────
private void SetLevelName()
{
if (_levelManager == null || _levelName == null)
return;
var currentLevel = _levelManager.CurrentLevel;
if (!string.IsNullOrEmpty(currentLevel.LevelName))
_levelName.text = currentLevel.LevelName;
}
// ── Button binding ────────────────────────────────────────────
private void BindButtons()
{
if (_resumeButton != null)
_resumeButton.SelectionRequested += OnResumeClicked;
if (_saveButton != null)
_saveButton.SelectionRequested += OnSaveClicked;
if (_settingsButton != null)
_settingsButton.SelectionRequested += OnSettingsClicked;
if (_exitButton != null)
_exitButton.SelectionRequested += OnExitClicked;
if (_quitToDesktopButton != null)
_quitToDesktopButton.SelectionRequested += OnQuitToDesktopClicked;
}
private void UnbindButtons()
{
if (_resumeButton != null)
_resumeButton.SelectionRequested -= OnResumeClicked;
if (_saveButton != null)
_saveButton.SelectionRequested -= OnSaveClicked;
if (_settingsButton != null)
_settingsButton.SelectionRequested -= OnSettingsClicked;
if (_exitButton != null)
_exitButton.SelectionRequested -= OnExitClicked;
if (_quitToDesktopButton != null)
_quitToDesktopButton.SelectionRequested -= OnQuitToDesktopClicked;
}
// ── Button callbacks ──────────────────────────────────────────
private void OnResumeClicked(UnderlineButton _)
{
_eventCoordinator?.Publish(new PauseButtonClickedEvent());
}
private void OnSaveClicked(UnderlineButton _)
{
SaveGame().Forget();
}
private void OnSettingsClicked(UnderlineButton _)
{
_eventCoordinator?.Publish(new UIToggleSettingsWindow(true));
}
private void OnExitClicked(UnderlineButton _)
{
_eventCoordinator?.Publish(new FadeEvent(false, 1f));
ExitInternal().Forget();
}
private void OnQuitToDesktopClicked(UnderlineButton _)
{
QuitInternal().Forget();
}
// ── Internal async ────────────────────────────────────────────
private async UniTask ExitInternal()
{
await UniTask.Delay(TimeSpan.FromSeconds(1));
_audioManager?.StopAllAudio();
await SaveGame();
_eventCoordinator?.Publish(new PauseButtonClickedEvent());
await _gameService.LoadMainMenu();
}
private async UniTask QuitInternal()
{
_eventCoordinator?.Publish(new FadeEvent(false, 1f));
await UniTask.Delay(TimeSpan.FromSeconds(1));
await SaveGame();
_gameService?.QuitGame();
}
private async UniTask SaveGame()
{
if (_saveManager == null)
return;
await _saveManager.SaveGameDataLatest();
}
// ── Layout helpers ────────────────────────────────────────────
private void HideButtons()
{
SetGroupImmediate(_buttonsGroup, 0f);
}
private static void SetGroupImmediate(CanvasGroup group, float alpha)
{
if (group == null)
return;
group.alpha = alpha;
group.interactable = false;
group.blocksRaycasts = false;
}
private async UniTask FadeGroup(
CanvasGroup group,
float target,
TweenSettings settings,
CancellationToken token)
{
if (group == null)
return;
await Tween.Alpha(group, new TweenSettings<float>
{
startValue = group.alpha,
endValue = target,
settings = settings
}).ToUniTask(cancellationToken: token);
group.alpha = target;
}
// ── Selection ─────────────────────────────────────────────────
private void SelectDefault()
{
if (EventSystem.current == null)
return;
EventSystem.current.SetSelectedGameObject(null);
if (_firstSelectedOnOpen != null)
{
EventSystem.current.SetSelectedGameObject(
_firstSelectedOnOpen.gameObject);
}
else if (_resumeButton != null)
{
EventSystem.current.SetSelectedGameObject(
_resumeButton.gameObject);
}
Debug.Log(
$"[PauseMenuWindow] Selected: {EventSystem.current.currentSelectedGameObject}");
}
// ── CTS ───────────────────────────────────────────────────────
private void StopAndResetCancellation()
{
if (_sequence.isAlive)
@@ -256,77 +425,9 @@ namespace BriarQueen.UI.Menus
}
_cts.Dispose();
_cts = null;
}
_cts = new CancellationTokenSource();
}
private void OnResumeButtonClick()
{
_eventCoordinator?.Publish(new PauseButtonClickedEvent());
}
private void SelectDefault()
{
var selectable = _firstSelectedOnOpen != null ? _firstSelectedOnOpen : _resumeButton;
if (selectable == null)
{
return;
}
if (EventSystem.current != null)
{
EventSystem.current.SetSelectedGameObject(selectable.gameObject);
return;
}
selectable.Select();
}
private void OnSaveButtonClick()
{
SaveGame().Forget();
}
private void OnSettingsButtonClick()
{
_eventCoordinator.Publish(new UIToggleSettingsWindow(true));
}
private void OnExitButtonClick()
{
_eventCoordinator.Publish(new FadeEvent(false, 1f));
ExitButtonInternal().Forget();
}
private async UniTask ExitButtonInternal()
{
await UniTask.Delay(TimeSpan.FromSeconds(1));
_audioManager.StopAllAudio();
await SaveGame();
_eventCoordinator.Publish(new PauseButtonClickedEvent());
await _gameService.LoadMainMenu();
}
private void OnQuitToDesktopButtonClick()
{
QuitButtonInternal().Forget();
}
private async UniTask QuitButtonInternal()
{
_eventCoordinator.Publish(new FadeEvent(false, 1f));
await UniTask.Delay(TimeSpan.FromSeconds(1));
await SaveGame();
_gameService.QuitGame();
}
private async UniTask SaveGame()
{
if (_saveManager == null) return;
await _saveManager.SaveGameDataLatest();
// TODO: Saved feedback popup/toast
}
}
}

View File

@@ -205,6 +205,7 @@ namespace BriarQueen.UI.Menus
{
StopAndResetCancellation();
CancelAndDisposePanelCts();
TryUnregisterRaycaster();
if (_applyButton != null) _applyButton.onClick.RemoveListener(OnApplyClicked);
if (_backButton != null) _backButton.onClick.RemoveListener(OnBackClicked);
@@ -915,7 +916,6 @@ namespace BriarQueen.UI.Menus
return;
_interactManager.AddUIRaycaster(_graphicRaycaster);
_interactManager?.SetExclusiveRaycaster(_graphicRaycaster);
_raycasterRegistered = true;
}
@@ -928,7 +928,6 @@ namespace BriarQueen.UI.Menus
return;
_interactManager.RemoveUIRaycaster(_graphicRaycaster);
_interactManager?.ClearExclusiveRaycaster();
_raycasterRegistered = false;
}
}

View File

@@ -17,51 +17,28 @@ namespace BriarQueen.UI.Menus
private static readonly Vector3[] Corners = new Vector3[4];
[Header("Hierarchy")]
[SerializeField]
private RectTransform _viewport;
[SerializeField]
private RectTransform _content;
[SerializeField]
private RectTransform _trackRect;
[SerializeField]
private RectTransform _handleRect;
[SerializeField]
private Image _scrollBarImage;
[SerializeField] private RectTransform _viewport;
[SerializeField] private RectTransform _content;
[SerializeField] private RectTransform _trackRect;
[SerializeField] private RectTransform _handleRect;
[SerializeField] private Image _scrollBarImage;
[Header("Scroll Settings")]
[SerializeField]
private float _wheelPixels = 80f;
[SerializeField]
private float _padSpeed = 900f;
[SerializeField]
private float _inputSystemWheelScale = 0.05f;
[SerializeField] private float _wheelPixels = 80f;
[SerializeField] private float _padSpeed = 900f;
[SerializeField] private float _inputSystemWheelScale = 0.05f;
[Header("Handle")]
[SerializeField]
private bool _useCustomHandleSizing;
[SerializeField]
private float _minHandleHeight = 24f;
[SerializeField] private bool _useCustomHandleSizing;
[SerializeField] private float _minHandleHeight = 24f;
[Header("Alignment")]
[SerializeField]
private bool _centerContentWhenNotScrollable = true;
[SerializeField]
private float _topInset = 6f;
[SerializeField]
private float _bottomInset = 6f;
[SerializeField] private bool _centerContentWhenNotScrollable = true;
[SerializeField] private float _topInset = 6f;
[SerializeField] private float _bottomInset = 6f;
[Header("Track")]
[SerializeField]
private bool _hideTrackWhenNotScrollable = true;
[SerializeField] private bool _hideTrackWhenNotScrollable = true;
#if UNITY_EDITOR
[Header("Editor Debug")]
@@ -70,7 +47,7 @@ namespace BriarQueen.UI.Menus
private float _debugNormalized;
#endif
private bool _isScrollable;
private bool _isScrollable;
private float _scrollRange;
private Camera _uiCamera;
@@ -108,11 +85,14 @@ namespace BriarQueen.UI.Menus
if (!TryGetContentBounds(out var top, out var bottom))
return;
var contentHeight = top - bottom;
var contentHeight = top - bottom;
var viewportHeight = _viewport.rect.height - _topInset - _bottomInset;
_isScrollable = contentHeight > viewportHeight;
_scrollRange = Mathf.Max(0f, contentHeight - viewportHeight);
_scrollRange = Mathf.Max(0f, contentHeight - viewportHeight);
Debug.Log($"[Scrollbar] OnValidate — contentHeight:{contentHeight} viewportHeight:{viewportHeight} isScrollable:{_isScrollable} scrollRange:{_scrollRange}");
Normalized = Mathf.Clamp01(_debugNormalized);
if (_centerContentWhenNotScrollable && !_isScrollable)
@@ -155,11 +135,13 @@ namespace BriarQueen.UI.Menus
if (!TryGetContentBounds(out var top, out var bottom))
return;
var contentHeight = top - bottom;
var contentHeight = top - bottom;
var viewportHeight = _viewport.rect.height - _topInset - _bottomInset;
_isScrollable = contentHeight > viewportHeight;
_scrollRange = Mathf.Max(0f, contentHeight - viewportHeight);
_scrollRange = Mathf.Max(0f, contentHeight - viewportHeight);
Debug.Log($"[Scrollbar] Rebuild — contentHeight:{contentHeight} viewportHeight:{viewportHeight} isScrollable:{_isScrollable} scrollRange:{_scrollRange}");
if (_centerContentWhenNotScrollable && !_isScrollable)
{
@@ -179,6 +161,8 @@ namespace BriarQueen.UI.Menus
{
Normalized = Mathf.Clamp01(normalized);
Debug.Log($"[Scrollbar] SetNormalized:{normalized} isScrollable:{_isScrollable} scrollRange:{_scrollRange}");
if (!_isScrollable)
return;
@@ -193,13 +177,13 @@ namespace BriarQueen.UI.Menus
private void CenterContent(float top, float bottom)
{
var contentCenter = (top + bottom) * 0.5f;
var contentCenter = (top + bottom) * 0.5f;
var viewportCenter = (_viewport.rect.yMin + _viewport.rect.yMax) * 0.5f;
var delta = viewportCenter - contentCenter;
var position = _content.anchoredPosition;
position.y += delta;
position.y += delta;
_content.anchoredPosition = position;
}
@@ -222,13 +206,13 @@ namespace BriarQueen.UI.Menus
first.GetWorldCorners(Corners);
var childTop = _viewport.InverseTransformPoint(Corners[1]).y;
var childTop = _viewport.InverseTransformPoint(Corners[1]).y;
var targetTop = _viewport.rect.yMax - _topInset;
var delta = targetTop - childTop;
var position = _content.anchoredPosition;
position.y += delta;
position.y += delta;
_content.anchoredPosition = position;
}
@@ -238,7 +222,7 @@ namespace BriarQueen.UI.Menus
return;
var current = Normalized * _scrollRange;
var next = Mathf.Clamp(current + pixels, 0f, _scrollRange);
var next = Mathf.Clamp(current + pixels, 0f, _scrollRange);
Normalized = _scrollRange > 0f ? next / _scrollRange : 0f;
SetNormalized(Normalized);
@@ -258,7 +242,7 @@ namespace BriarQueen.UI.Menus
var min = _trackRect.rect.yMin + halfHandleHeight;
var max = _trackRect.rect.yMax - halfHandleHeight;
var y = Mathf.Clamp(localPoint.y, min, max);
var y = Mathf.Clamp(localPoint.y, min, max);
var normalized = 1f - Mathf.InverseLerp(min, max, y);
SetNormalized(normalized);
@@ -284,8 +268,9 @@ namespace BriarQueen.UI.Menus
private void SetContentY(float y)
{
Debug.Log($"[Scrollbar] SetContentY:{y}");
var position = _content.anchoredPosition;
position.y = y;
position.y = y;
_content.anchoredPosition = position;
#if UNITY_EDITOR
@@ -308,22 +293,15 @@ namespace BriarQueen.UI.Menus
return;
}
if (_useCustomHandleSizing)
{
var ratio = Mathf.Clamp01(_viewport.rect.height / (_scrollRange + _viewport.rect.height));
var height = Mathf.Max(_trackRect.rect.height * ratio, _minHandleHeight);
_handleRect.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, height);
}
var half = _handleRect.rect.height * 0.5f;
var min = _trackRect.rect.yMin + half;
var max = _trackRect.rect.yMax - half;
var yPos = Mathf.Lerp(max, min, Normalized);
var min = _trackRect.rect.yMin + half;
var max = _trackRect.rect.yMax - half;
var y = Mathf.Lerp(max, min, Normalized);
Debug.Log($"[Scrollbar] UpdateHandle — half:{half} trackYMin:{_trackRect.rect.yMin} trackYMax:{_trackRect.rect.yMax} min:{min} max:{max} yPos:{yPos} Normalized:{Normalized}");
var position = _handleRect.anchoredPosition;
position.y = y;
position.y = yPos;
_handleRect.anchoredPosition = position;
}
@@ -341,7 +319,7 @@ namespace BriarQueen.UI.Menus
private bool TryGetContentBounds(out float top, out float bottom)
{
top = float.MinValue;
top = float.MinValue;
bottom = float.MaxValue;
var found = false;
@@ -357,13 +335,15 @@ namespace BriarQueen.UI.Menus
for (var c = 0; c < 4; c++)
{
var local = _viewport.InverseTransformPoint(Corners[c]);
top = Mathf.Max(top, local.y);
top = Mathf.Max(top, local.y);
bottom = Mathf.Min(bottom, local.y);
}
found = true;
Debug.Log($"[Scrollbar] Child: {child.name} top:{top} bottom:{bottom} height:{top - bottom}");
}
Debug.Log($"[Scrollbar] Found:{found} ContentHeight:{top - bottom} ViewportHeight:{_viewport.rect.height}");
return found;
}
}