Compare commits

..

21 Commits

Author SHA1 Message Date
Michal Pikulski
7aca1a17ac Stash work 2025-11-17 08:39:41 +01:00
Michal Pikulski
78aafb9275 Almost working card state machine 2025-11-16 20:35:54 +01:00
Michal Pikulski
6fe7d012fc Updates to testing scene 2025-11-15 20:37:02 +01:00
Michal Pikulski
b2c47d4e4f Stash scene changes 2025-11-15 20:37:02 +01:00
Michal Pikulski
755082c67d Updates to card testing scene 2025-11-15 20:37:02 +01:00
Michal Pikulski
4e7f774386 Stash half-assed work on testing scene 2025-11-15 20:37:02 +01:00
Michal Pikulski
39d5890db4 Fix up card flows, align with the old 1:1 2025-11-15 20:37:01 +01:00
Michal Pikulski
a6471ede45 Make cards use settings 2025-11-15 20:37:01 +01:00
Michal Pikulski
4fdbbb0aa8 Add roadmap docs 2025-11-15 20:37:01 +01:00
Michal Pikulski
1fdff3450b Update the card kerfufle 2025-11-15 20:37:01 +01:00
06cc3bde3b Merge pull request 'DamianBranch' (#58) from DamianBranch into main
Reviewed-on: #58
2025-11-14 09:30:49 +00:00
9cc112e5f0 Update Quarry.unity 2025-11-14 10:30:05 +01:00
DamianCorazza
19be64a75f Butterfly Distraction 2025-11-14 00:04:33 +01:00
c08fc4a720 WIP Butterfly can be set free, now only missing forcing the couple to look. 2025-11-13 16:23:52 +01:00
c3639bbb93 Added the Flying Butterfly WIP 2025-11-12 16:25:32 +01:00
Michal Pikulski
612ca7eae8 Interactables documentaiton 2025-11-11 15:55:38 +01:00
acf46c701e Last life cycle refactor updates + add comprehensive documentation (#57)
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: #57
2025-11-11 12:32:36 +00:00
fe2eb0a280 Merge remote-tracking branch 'origin/kill-json-player' 2025-11-11 10:06:23 +01:00
0aa2270e1a Lifecycle System Refactor & Logging Centralization (#56)
## ManagedBehaviour System Refactor

- **Sealed `Awake()`** to prevent override mistakes that break singleton registration
- **Added `OnManagedAwake()`** for early initialization (fires during registration)
- **Renamed lifecycle hook:** `OnManagedAwake()` → `OnManagedStart()` (fires after boot, mirrors Unity's Awake→Start)
- **40 files migrated** to new pattern (2 core, 38 components)
- Eliminated all fragile `private new void Awake()` patterns
- Zero breaking changes - backward compatible

## Centralized Logging System

- **Automatic tagging** via `CallerMemberName` and `CallerFilePath` - logs auto-tagged as `[ClassName][MethodName] message`
- **Unified API:** Single `Logging.Debug/Info/Warning/Error()` replaces custom `LogDebugMessage()` implementations
- **~90 logging call sites** migrated across 10 files
- **10 redundant helper methods** removed
- All logs broadcast via `Logging.OnLogEntryAdded` event for real-time monitoring

## Custom Log Console (Editor Window)

- **Persistent filter popups** for multi-selection (classes, methods, log levels) - windows stay open during selection
- **Search** across class names, methods, and message content
- **Time range filter** with MinMaxSlider
- **Export** filtered logs to timestamped `.txt` files
- **Right-click context menu** for quick filtering and copy actions
- **Visual improvements:** White text, alternating row backgrounds, color-coded log levels
- **Multiple instances** supported for simultaneous system monitoring
- Open via `AppleHills > Custom Log Console`

Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com>
Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com>
Reviewed-on: #56
2025-11-11 08:48:29 +00:00
MacBuilder
d647bb5707 Target eliminated, good job 47 2025-11-10 15:55:28 +01:00
MacBuilder
dec7ced2d1 Began killing json 2025-11-10 14:57:42 +01:00
190 changed files with 28802 additions and 3755 deletions

3
.gitignore vendored
View File

@@ -104,3 +104,6 @@ InitTestScene*.unity*
.vscode/launch.json
.vscode/settings.json
.idea/.idea.AppleHillsProduction/.idea/indexLayout.xml
# WIP docs
/docs/wip/

View File

@@ -30,6 +30,11 @@ MonoBehaviour:
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 533a675687aa04146bfb69b8c9be7a6b
m_Address: Settings/CardSystemSettings
m_ReadOnly: 0
m_SerializedLabels: []
FlaggedDuringContentUpdateRestriction: 0
- m_GUID: 8f5195fb013895049a19488fd4d8f2a1
m_Address: Settings/InteractionSettings
m_ReadOnly: 0

View File

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

View File

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

View File

@@ -0,0 +1,194 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1102 &-7123694714182698348
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Butterfly_Trapped
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
- {fileID: -3401047733442852747}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 95de8fd6297091e48ad4e98af36895ee, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1102 &-5852692507557025309
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Butterfly_Flight
m_Speed: 1
m_CycleOffset: 0
m_Transitions:
- {fileID: 4242574681130237058}
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 5e5d09518a311b9448ad34766ea05a01, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1101 &-3401047733442852747
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: BrokeOut
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: -5852692507557025309}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0
m_TransitionOffset: 0
m_ExitTime: 0.75
m_HasExitTime: 1
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1
--- !u!91 &9100000
AnimatorController:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Butterfly
serializedVersion: 5
m_AnimatorParameters:
- m_Name: IsFree
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 9100000}
- m_Name: BrokeOut
m_Type: 9
m_DefaultFloat: 0
m_DefaultInt: 0
m_DefaultBool: 0
m_Controller: {fileID: 9100000}
m_AnimatorLayers:
- serializedVersion: 5
m_Name: Base Layer
m_StateMachine: {fileID: 200773854421593538}
m_Mask: {fileID: 0}
m_Motions: []
m_Behaviours: []
m_BlendingMode: 0
m_SyncedLayerIndex: -1
m_DefaultWeight: 0
m_IKPass: 0
m_SyncedLayerAffectsTiming: 0
m_Controller: {fileID: 9100000}
--- !u!1107 &200773854421593538
AnimatorStateMachine:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Base Layer
m_ChildStates:
- serializedVersion: 1
m_State: {fileID: -5852692507557025309}
m_Position: {x: 240, y: 240, z: 0}
- serializedVersion: 1
m_State: {fileID: 3280735923797652806}
m_Position: {x: 450, y: 240, z: 0}
- serializedVersion: 1
m_State: {fileID: -7123694714182698348}
m_Position: {x: 30, y: 240, z: 0}
m_ChildStateMachines: []
m_AnyStateTransitions: []
m_EntryTransitions: []
m_StateMachineTransitions: {}
m_StateMachineBehaviours: []
m_AnyStatePosition: {x: 50, y: 160, z: 0}
m_EntryPosition: {x: 50, y: 200, z: 0}
m_ExitPosition: {x: 660, y: 250, z: 0}
m_ParentStateMachinePosition: {x: 800, y: 20, z: 0}
m_DefaultState: {fileID: -7123694714182698348}
--- !u!1102 &3280735923797652806
AnimatorState:
serializedVersion: 6
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Butterfly_Free
m_Speed: 1
m_CycleOffset: 0
m_Transitions: []
m_StateMachineBehaviours: []
m_Position: {x: 50, y: 50, z: 0}
m_IKOnFeet: 0
m_WriteDefaultValues: 1
m_Mirror: 0
m_SpeedParameterActive: 0
m_MirrorParameterActive: 0
m_CycleOffsetParameterActive: 0
m_TimeParameterActive: 0
m_Motion: {fileID: 7400000, guid: 0327201d9a45c4b4e8630d83f5db7b02, type: 2}
m_Tag:
m_SpeedParameter:
m_MirrorParameter:
m_CycleOffsetParameter:
m_TimeParameter:
--- !u!1101 &4242574681130237058
AnimatorStateTransition:
m_ObjectHideFlags: 1
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name:
m_Conditions:
- m_ConditionMode: 1
m_ConditionEvent: IsFree
m_EventTreshold: 0
m_DstStateMachine: {fileID: 0}
m_DstState: {fileID: 3280735923797652806}
m_Solo: 0
m_Mute: 0
m_IsExit: 0
serializedVersion: 3
m_TransitionDuration: 0
m_TransitionOffset: 0
m_ExitTime: 0.75
m_HasExitTime: 1
m_HasFixedDuration: 1
m_InterruptionSource: 0
m_OrderedInterruption: 1
m_CanTransitionToSelf: 1

View File

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -0,0 +1,223 @@
fileFormatVersion: 2
guid: d5bbe5b893ed9bc43b303a0e5c712a09
TextureImporter:
internalIDToNameTable:
- first:
213: 4530433918361379743
second: Butterfly_0
- first:
213: 4699623745766655208
second: Butterfly_1
- first:
213: -265841166610147798
second: Butterfly_2
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: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
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:
- serializedVersion: 2
name: Butterfly_0
rect:
serializedVersion: 2
x: 0
y: 0
width: 256
height: 321
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: f93af4e35a55fde30800000000000000
internalID: 4530433918361379743
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: Butterfly_1
rect:
serializedVersion: 2
x: 256
y: 0
width: 256
height: 321
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: 8e48968a5ea683140800000000000000
internalID: 4699623745766655208
vertices: []
indices:
edges: []
weights: []
- serializedVersion: 2
name: Butterfly_2
rect:
serializedVersion: 2
x: 512
y: 0
width: 256
height: 321
alignment: 0
pivot: {x: 0.5, y: 0.5}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: a26d6811eda8f4cf0800000000000000
internalID: -265841166610147798
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID: 2094ca25d42e30840bdbb20c96ca89f6
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries:
- key: SpriteEditor.SliceSettings
value: '{"sliceOnImport":false,"gridCellCount":{"x":1.0,"y":1.0},"gridSpriteSize":{"x":256.0,"y":321.0},"gridSpriteOffset":{"x":0.0,"y":0.0},"gridSpritePadding":{"x":0.0,"y":0.0},"pivot":{"x":0.5,"y":0.5},"pivotPixels":{"x":0.0,"y":0.0},"autoSlicingMethod":0,"spriteAlignment":0,"pivotUnitMode":0,"slicingType":1,"keepEmptyRects":false,"isAlternate":false}'
nameFileIdTable:
Butterfly_0: 4530433918361379743
Butterfly_1: 4699623745766655208
Butterfly_2: -265841166610147798
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,620 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Butterfly_Flight
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.3
value: {x: 0, y: 0, z: -21.435}
inSlope: {x: 0, y: 0, z: -42.74739}
outSlope: {x: 0, y: 0, z: -42.74739}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.76666665
value: {x: 0, y: 0, z: -32.773}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1.0333333
value: {x: 0, y: 0, z: -9.69}
inSlope: {x: 0, y: 0, z: 63.431614}
outSlope: {x: 0, y: 0, z: 63.431614}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1.2833333
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path:
m_PositionCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.3
value: {x: 0, y: 0.1, z: 0}
inSlope: {x: 0, y: 0.45000002, z: 0}
outSlope: {x: 0, y: 0.45000002, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.6666667
value: {x: 0, y: 0.3, z: 0}
inSlope: {x: 0, y: 1.0714287, z: 0}
outSlope: {x: 0, y: 1.0714287, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.76666665
value: {x: 0, y: 0.6, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.98333335
value: {x: 0, y: 0.3, z: 0}
inSlope: {x: 0, y: -1.1612904, z: 0}
outSlope: {x: 0, y: -1.1612904, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1.2833333
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path:
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 0.3
value: {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 0.6666667
value: {fileID: -265841166610147798, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 0.98333335
value: {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 1.2833333
value: {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 1
script: {fileID: 0}
typeID: 4
customType: 0
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 0
attribute: 4
script: {fileID: 0}
typeID: 4
customType: 4
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: -265841166610147798, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1.3
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.6666667
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.98333335
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.x
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0.1
inSlope: 0.45000002
outSlope: 0.45000002
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.6666667
value: 0.3
inSlope: 1.0714287
outSlope: 1.0714287
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.98333335
value: 0.3
inSlope: -1.1612904
outSlope: -1.1612904
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.y
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.6666667
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.98333335
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.z
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.0333333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.x
path:
classID: 4
script: {fileID: 0}
flags: 16
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.0333333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.y
path:
classID: 4
script: {fileID: 0}
flags: 16
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: -21.435
inSlope: -42.74739
outSlope: -42.74739
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: -32.773
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.0333333
value: -9.69
inSlope: 63.431614
outSlope: 63.431614
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.z
path:
classID: 4
script: {fileID: 0}
flags: 16
m_EulerEditorCurves:
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.x
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.y
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.z
path:
classID: 4
script: {fileID: 0}
flags: 0
m_HasGenericRootTransform: 1
m_HasMotionFloatCurves: 0
m_Events: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 5e5d09518a311b9448ad34766ea05a01
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,620 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!74 &7400000
AnimationClip:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: Butterfly_Free
serializedVersion: 7
m_Legacy: 0
m_Compressed: 0
m_UseHighQualityCurve: 1
m_RotationCurves: []
m_CompressedRotationCurves: []
m_EulerCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.3
value: {x: 0, y: 0, z: -21.435}
inSlope: {x: 0, y: 0, z: -42.74739}
outSlope: {x: 0, y: 0, z: -42.74739}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.76666665
value: {x: 0, y: 0, z: -32.773}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1.0333333
value: {x: 0, y: 0, z: -9.69}
inSlope: {x: 0, y: 0, z: 63.431614}
outSlope: {x: 0, y: 0, z: 63.431614}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1.2833333
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path:
m_PositionCurves:
- curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.3
value: {x: 0, y: 0.1, z: 0}
inSlope: {x: 0, y: 0.45000002, z: 0}
outSlope: {x: 0, y: 0.45000002, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.6666667
value: {x: 0, y: 0.3, z: 0}
inSlope: {x: 0, y: 1.0714287, z: 0}
outSlope: {x: 0, y: 1.0714287, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.76666665
value: {x: 0, y: 0.6, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 0.98333335
value: {x: 0, y: 0.3, z: 0}
inSlope: {x: 0, y: -1.1612904, z: 0}
outSlope: {x: 0, y: -1.1612904, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
- serializedVersion: 3
time: 1.2833333
value: {x: 0, y: 0, z: 0}
inSlope: {x: 0, y: 0, z: 0}
outSlope: {x: 0, y: 0, z: 0}
tangentMode: 0
weightedMode: 0
inWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
outWeight: {x: 0.33333334, y: 0.33333334, z: 0.33333334}
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
path:
m_ScaleCurves: []
m_FloatCurves: []
m_PPtrCurves:
- serializedVersion: 2
curve:
- time: 0
value: {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 0.3
value: {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 0.6666667
value: {fileID: -265841166610147798, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 0.98333335
value: {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- time: 1.2833333
value: {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
attribute: m_Sprite
path:
classID: 212
script: {fileID: 0}
flags: 2
m_SampleRate: 60
m_WrapMode: 0
m_Bounds:
m_Center: {x: 0, y: 0, z: 0}
m_Extent: {x: 0, y: 0, z: 0}
m_ClipBindingConstant:
genericBindings:
- serializedVersion: 2
path: 0
attribute: 1
script: {fileID: 0}
typeID: 4
customType: 0
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 0
attribute: 4
script: {fileID: 0}
typeID: 4
customType: 4
isPPtrCurve: 0
isIntCurve: 0
isSerializeReferenceCurve: 0
- serializedVersion: 2
path: 0
attribute: 0
script: {fileID: 0}
typeID: 212
customType: 23
isPPtrCurve: 1
isIntCurve: 0
isSerializeReferenceCurve: 0
pptrCurveMapping:
- {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: -265841166610147798, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: 4699623745766655208, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
- {fileID: 4530433918361379743, guid: d5bbe5b893ed9bc43b303a0e5c712a09, type: 3}
m_AnimationClipSettings:
serializedVersion: 2
m_AdditiveReferencePoseClip: {fileID: 0}
m_AdditiveReferencePoseTime: 0
m_StartTime: 0
m_StopTime: 1.3
m_OrientationOffsetY: 0
m_Level: 0
m_CycleOffset: 0
m_HasAdditiveReferencePose: 0
m_LoopTime: 1
m_LoopBlend: 0
m_LoopBlendOrientation: 0
m_LoopBlendPositionY: 0
m_LoopBlendPositionXZ: 0
m_KeepOriginalOrientation: 0
m_KeepOriginalPositionY: 1
m_KeepOriginalPositionXZ: 0
m_HeightFromFeet: 0
m_Mirror: 0
m_EditorCurves:
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.6666667
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.98333335
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.x
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0.1
inSlope: 0.45000002
outSlope: 0.45000002
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.6666667
value: 0.3
inSlope: 1.0714287
outSlope: 1.0714287
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0.6
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.98333335
value: 0.3
inSlope: -1.1612904
outSlope: -1.1612904
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.y
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.6666667
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.98333335
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalPosition.z
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.0333333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.x
path:
classID: 4
script: {fileID: 0}
flags: 16
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.0333333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.y
path:
classID: 4
script: {fileID: 0}
flags: 16
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve:
- serializedVersion: 3
time: 0
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.3
value: -21.435
inSlope: -42.74739
outSlope: -42.74739
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 0.76666665
value: -32.773
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.0333333
value: -9.69
inSlope: 63.431614
outSlope: 63.431614
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
- serializedVersion: 3
time: 1.2833333
value: 0
inSlope: 0
outSlope: 0
tangentMode: 136
weightedMode: 0
inWeight: 0.33333334
outWeight: 0.33333334
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: localEulerAnglesRaw.z
path:
classID: 4
script: {fileID: 0}
flags: 16
m_EulerEditorCurves:
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.x
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.y
path:
classID: 4
script: {fileID: 0}
flags: 0
- serializedVersion: 2
curve:
serializedVersion: 2
m_Curve: []
m_PreInfinity: 2
m_PostInfinity: 2
m_RotationOrder: 4
attribute: m_LocalEulerAngles.z
path:
classID: 4
script: {fileID: 0}
flags: 0
m_HasGenericRootTransform: 1
m_HasMotionFloatCurves: 0
m_Events: []

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0327201d9a45c4b4e8630d83f5db7b02
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 95de8fd6297091e48ad4e98af36895ee
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 7400000
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,43 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: SPiderweb
m_Shader: {fileID: 10753, guid: 0000000000000000f000000000000000, type: 0}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 4
m_EnableInstancingVariants: 0
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _AlphaTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 2800000, guid: 0c9ec27b671ec814fb53bee78443c9c9, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- PixelSnap: 0
- _EnableExternalAlpha: 0
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _Flip: {r: 1, g: 1, b: 1, a: 1}
- _RendererColor: {r: 1, g: 1, b: 1, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 74a21ef39c3a86548804ca284dd6995a
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 0c9ec27b671ec814fb53bee78443c9c9
TextureImporter:
internalIDToNameTable:
- first:
213: -8296513218426820769
second: SPiderweb_0
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: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
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
spriteSheet:
serializedVersion: 2
sprites:
- serializedVersion: 2
name: SPiderweb_0
rect:
serializedVersion: 2
x: 2
y: 0
width: 254
height: 255
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: f5726554f2ddcdc80800000000000000
internalID: -8296513218426820769
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
SPiderweb_0: -8296513218426820769
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@@ -0,0 +1,156 @@
fileFormatVersion: 2
guid: 57224356af3d045dbbf8b420e13b4b10
TextureImporter:
internalIDToNameTable:
- first:
213: 2364528222304962155
second: ramasjang_icon_0
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: 1
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 2
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: 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:
- serializedVersion: 2
name: ramasjang_icon_0
rect:
serializedVersion: 2
x: 4
y: 5
width: 334
height: 334
alignment: 0
pivot: {x: 0, y: 0}
border: {x: 0, y: 0, z: 0, w: 0}
customData:
outline: []
physicsShape: []
tessellationDetail: -1
bones: []
spriteID: b668fdfe3ed70d020800000000000000
internalID: 2364528222304962155
vertices: []
indices:
edges: []
weights: []
outline: []
customData:
physicsShape: []
bones: []
spriteID:
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
spriteCustomMetadata:
entries: []
nameFileIdTable:
ramasjang_icon_0: 2364528222304962155
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: cb41c852d70c4066bf510792ee19b3f5
timeCreated: 1762866335

View File

@@ -0,0 +1,748 @@
using System.Collections.Generic;
using System.Linq;
using UnityEditor;
using UnityEngine;
using Interactions;
using System.Reflection;
using System;
namespace AppleHills.Editor.InteractionSystem
{
/// <summary>
/// Editor utility for managing and debugging interactable objects in the scene.
/// Provides scene object locator, inspector editing, and runtime debugging capabilities.
/// </summary>
public class InteractableEditorWindow : EditorWindow
{
// Tab management
private int _selectedTab = 0;
private readonly string[] _tabNames = { "Scene", "Debug" };
// Scene interactables tracking
private List<InteractableBase> _sceneInteractables = new List<InteractableBase>();
private InteractableBase _selectedInteractable;
private GameObject _selectedGameObject;
// UI state
private Vector2 _listScrollPosition;
private Vector2 _inspectorScrollPosition;
private Vector2 _debugScrollPosition;
private string _searchQuery = "";
// Runtime state
private bool _isPlaying = false;
// Editor for selected interactable
private UnityEditor.Editor _cachedEditor;
// Available interactable types for adding
private static readonly Type[] AvailableInteractableTypes = new Type[]
{
typeof(OneClickInteraction),
typeof(Pickup),
typeof(ItemSlot),
typeof(SaveableInteractable),
typeof(InteractableBase)
};
[MenuItem("AppleHills/Interactable Editor")]
public static void ShowWindow()
{
var window = GetWindow<InteractableEditorWindow>("Interactable Editor");
window.minSize = new Vector2(900, 600);
window.Show();
}
private void OnEnable()
{
RefreshSceneInteractables();
// Register for scene and selection changes
UnityEditor.SceneManagement.EditorSceneManager.sceneOpened += OnSceneOpened;
UnityEditor.SceneManagement.EditorSceneManager.sceneClosed += OnSceneClosed;
Selection.selectionChanged += OnSelectionChanged;
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
EditorApplication.hierarchyChanged += OnHierarchyChanged;
}
private void OnDisable()
{
UnityEditor.SceneManagement.EditorSceneManager.sceneOpened -= OnSceneOpened;
UnityEditor.SceneManagement.EditorSceneManager.sceneClosed -= OnSceneClosed;
Selection.selectionChanged -= OnSelectionChanged;
EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
EditorApplication.hierarchyChanged -= OnHierarchyChanged;
// Clean up cached editor
if (_cachedEditor != null)
{
DestroyImmediate(_cachedEditor);
_cachedEditor = null;
}
}
private void OnSceneOpened(UnityEngine.SceneManagement.Scene scene, UnityEditor.SceneManagement.OpenSceneMode mode)
{
RefreshSceneInteractables();
}
private void OnSceneClosed(UnityEngine.SceneManagement.Scene scene)
{
RefreshSceneInteractables();
}
private void OnHierarchyChanged()
{
RefreshSceneInteractables();
}
private void OnSelectionChanged()
{
// Check if selected object has changed
if (Selection.activeGameObject != null && Selection.activeGameObject != _selectedGameObject)
{
var interactable = Selection.activeGameObject.GetComponent<InteractableBase>();
if (interactable != null)
{
// GameObject has an interactable - select it
SelectInteractable(interactable);
}
else
{
// GameObject doesn't have an interactable - track it for add menu
_selectedGameObject = Selection.activeGameObject;
_selectedInteractable = null;
// Clear cached editor
if (_cachedEditor != null)
{
DestroyImmediate(_cachedEditor);
_cachedEditor = null;
}
}
Repaint();
}
else if (Selection.activeGameObject == null)
{
// Nothing selected - clear selection
_selectedGameObject = null;
_selectedInteractable = null;
if (_cachedEditor != null)
{
DestroyImmediate(_cachedEditor);
_cachedEditor = null;
}
Repaint();
}
}
private void OnPlayModeStateChanged(PlayModeStateChange state)
{
_isPlaying = EditorApplication.isPlaying;
if (_isPlaying)
{
RefreshSceneInteractables();
}
Repaint();
}
private void OnGUI()
{
DrawHeader();
_selectedTab = GUILayout.Toolbar(_selectedTab, _tabNames);
EditorGUILayout.Space();
switch (_selectedTab)
{
case 0: // Scene tab
DrawSceneTab();
break;
case 1: // Debug tab
DrawDebugTab();
break;
}
}
#region Header UI
private void DrawHeader()
{
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
if (GUILayout.Button("Refresh", EditorStyles.toolbarButton, GUILayout.Width(60)))
{
RefreshSceneInteractables();
}
GUILayout.FlexibleSpace();
// Tab-specific toolbar options
if (_selectedTab == 0) // Scene tab
{
EditorGUILayout.LabelField($"Found: {_sceneInteractables.Count} interactables", EditorStyles.toolbarButton, GUILayout.Width(150));
}
else if (_selectedTab == 1) // Debug tab
{
EditorGUILayout.LabelField(_isPlaying ? "Runtime Active" : "Editor Mode", EditorStyles.toolbarButton, GUILayout.Width(100));
}
EditorGUILayout.EndHorizontal();
}
#endregion
#region Scene Tab
private void DrawSceneTab()
{
EditorGUILayout.BeginHorizontal();
// Left panel - interactable list
EditorGUILayout.BeginVertical(GUILayout.Width(300));
DrawInteractableListPanel();
EditorGUILayout.EndVertical();
// Separator
EditorGUILayout.Space(5);
// Right panel - inspector/editor
EditorGUILayout.BeginVertical();
DrawInspectorPanel();
EditorGUILayout.EndVertical();
EditorGUILayout.EndHorizontal();
}
private void DrawInteractableListPanel()
{
// Search field
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
_searchQuery = EditorGUILayout.TextField(_searchQuery, EditorStyles.toolbarSearchField);
if (GUILayout.Button("×", EditorStyles.toolbarButton, GUILayout.Width(20)) && !string.IsNullOrEmpty(_searchQuery))
{
_searchQuery = "";
GUI.FocusControl(null);
}
EditorGUILayout.EndHorizontal();
_listScrollPosition = EditorGUILayout.BeginScrollView(_listScrollPosition);
// Filter interactables by search query
var filteredInteractables = string.IsNullOrEmpty(_searchQuery)
? _sceneInteractables
: _sceneInteractables.Where(i => i != null && i.gameObject.name.ToLower().Contains(_searchQuery.ToLower())).ToList();
if (filteredInteractables.Count == 0)
{
EditorGUILayout.HelpBox("No interactables found in scene", MessageType.Info);
}
else
{
foreach (var interactable in filteredInteractables)
{
if (interactable == null) continue;
if (DrawInteractableListItem(interactable))
{
SelectInteractable(interactable);
}
}
}
EditorGUILayout.EndScrollView();
}
private bool DrawInteractableListItem(InteractableBase interactable)
{
bool isSelected = interactable == _selectedInteractable;
Color originalColor = GUI.backgroundColor;
if (isSelected)
GUI.backgroundColor = new Color(0.3f, 0.5f, 0.8f);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
GUI.backgroundColor = originalColor;
EditorGUILayout.BeginHorizontal();
// Interactable info
EditorGUILayout.BeginVertical();
EditorGUILayout.LabelField(interactable.gameObject.name, EditorStyles.boldLabel);
EditorGUILayout.LabelField(interactable.GetType().Name, EditorStyles.miniLabel);
// Show additional info for specific types
if (interactable is Pickup pickup && pickup.itemData != null)
{
EditorGUILayout.LabelField($"Item: {pickup.itemData.itemName}", EditorStyles.miniLabel);
}
else if (interactable is ItemSlot slot && slot.itemData != null)
{
EditorGUILayout.LabelField($"Slot: {slot.itemData.itemName}", EditorStyles.miniLabel);
}
EditorGUILayout.EndVertical();
GUILayout.FlexibleSpace();
// Ping button
if (GUILayout.Button("Ping", GUILayout.Width(50)))
{
EditorGUIUtility.PingObject(interactable.gameObject);
Selection.activeGameObject = interactable.gameObject;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.EndVertical();
Rect itemRect = GUILayoutUtility.GetLastRect();
bool wasClicked = Event.current.type == EventType.MouseDown && Event.current.button == 0
&& itemRect.Contains(Event.current.mousePosition);
if (wasClicked)
{
Event.current.Use();
}
return wasClicked;
}
private void DrawInspectorPanel()
{
_inspectorScrollPosition = EditorGUILayout.BeginScrollView(_inspectorScrollPosition);
if (_selectedInteractable == null && _selectedGameObject == null)
{
EditorGUILayout.HelpBox("Select an interactable from the list or in the scene hierarchy", MessageType.Info);
}
else if (_selectedGameObject != null && _selectedInteractable == null)
{
// Selected object doesn't have an interactable - show add menu
DrawAddInteractableMenu();
}
else if (_selectedInteractable != null)
{
// Draw custom inspector for the selected interactable
DrawInteractableInspector();
}
EditorGUILayout.EndScrollView();
}
private void DrawAddInteractableMenu()
{
EditorGUILayout.HelpBox($"GameObject '{_selectedGameObject.name}' doesn't have an Interactable component", MessageType.Info);
EditorGUILayout.Space();
EditorGUILayout.LabelField("Add Interactable Component:", EditorStyles.boldLabel);
foreach (var interactableType in AvailableInteractableTypes)
{
if (GUILayout.Button($"Add {interactableType.Name}", GUILayout.Height(30)))
{
Undo.RecordObject(_selectedGameObject, $"Add {interactableType.Name}");
var component = _selectedGameObject.AddComponent(interactableType) as InteractableBase;
EditorUtility.SetDirty(_selectedGameObject);
SelectInteractable(component);
RefreshSceneInteractables();
}
}
}
private void DrawInteractableInspector()
{
// Header
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Editing:", EditorStyles.boldLabel, GUILayout.Width(60));
EditorGUILayout.LabelField(_selectedInteractable.gameObject.name, EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
if (GUILayout.Button("Ping", GUILayout.Width(50)))
{
EditorGUIUtility.PingObject(_selectedInteractable.gameObject);
Selection.activeGameObject = _selectedInteractable.gameObject;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// Draw default inspector using Editor
if (_cachedEditor == null || _cachedEditor.target != _selectedInteractable)
{
if (_cachedEditor != null)
{
DestroyImmediate(_cachedEditor);
}
_cachedEditor = UnityEditor.Editor.CreateEditor(_selectedInteractable);
}
if (_cachedEditor != null)
{
EditorGUI.BeginChangeCheck();
_cachedEditor.OnInspectorGUI();
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(_selectedInteractable);
}
}
EditorGUILayout.Space();
// Additional info section
DrawAdditionalInfo();
}
private void DrawAdditionalInfo()
{
EditorGUILayout.LabelField("Additional Information", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
// Show component information
EditorGUILayout.LabelField("Type:", _selectedInteractable.GetType().Name);
// Show attached actions
var actions = _selectedInteractable.GetComponents<InteractionActionBase>();
if (actions.Length > 0)
{
EditorGUILayout.LabelField($"Actions: {actions.Length}");
EditorGUI.indentLevel++;
foreach (var action in actions)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(action.GetType().Name, EditorStyles.miniLabel);
if (GUILayout.Button("Ping", GUILayout.Width(50)))
{
EditorGUIUtility.PingObject(action);
}
EditorGUILayout.EndHorizontal();
}
EditorGUI.indentLevel--;
}
// Show specific type info
if (_selectedInteractable is Pickup pickup)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Pickup Info:", EditorStyles.boldLabel);
if (pickup.itemData != null)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Item Data:", GUILayout.Width(100));
EditorGUILayout.ObjectField(pickup.itemData, typeof(PickupItemData), false);
if (GUILayout.Button("Ping", GUILayout.Width(50)))
{
EditorGUIUtility.PingObject(pickup.itemData);
}
EditorGUILayout.EndHorizontal();
}
}
else if (_selectedInteractable is ItemSlot slot)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField("Slot Info:", EditorStyles.boldLabel);
if (slot.itemData != null)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Slot Data:", GUILayout.Width(100));
EditorGUILayout.ObjectField(slot.itemData, typeof(PickupItemData), false);
if (GUILayout.Button("Ping", GUILayout.Width(50)))
{
EditorGUIUtility.PingObject(slot.itemData);
}
EditorGUILayout.EndHorizontal();
}
if (_isPlaying)
{
var slottedObject = slot.GetSlottedObject();
if (slottedObject != null)
{
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField("Slotted Object:", GUILayout.Width(100));
EditorGUILayout.ObjectField(slottedObject, typeof(GameObject), true);
if (GUILayout.Button("Ping", GUILayout.Width(50)))
{
EditorGUIUtility.PingObject(slottedObject);
}
EditorGUILayout.EndHorizontal();
}
}
}
EditorGUILayout.EndVertical();
}
#endregion
#region Debug Tab
private void DrawDebugTab()
{
if (!_isPlaying)
{
EditorGUILayout.HelpBox("Enter Play Mode to debug interactables at runtime", MessageType.Info);
return;
}
_debugScrollPosition = EditorGUILayout.BeginScrollView(_debugScrollPosition);
EditorGUILayout.LabelField("Scene Interactables", EditorStyles.boldLabel);
EditorGUILayout.HelpBox("Test interactions and trigger individual events", MessageType.Info);
EditorGUILayout.Space();
foreach (var interactable in _sceneInteractables)
{
if (interactable == null) continue;
DrawDebugInteractableItem(interactable);
}
EditorGUILayout.EndScrollView();
}
private void DrawDebugInteractableItem(InteractableBase interactable)
{
EditorGUILayout.BeginVertical(EditorStyles.helpBox);
// Header
EditorGUILayout.BeginHorizontal();
EditorGUILayout.LabelField(interactable.gameObject.name, EditorStyles.boldLabel);
EditorGUILayout.LabelField($"({interactable.GetType().Name})", EditorStyles.miniLabel);
GUILayout.FlexibleSpace();
if (GUILayout.Button("Ping", GUILayout.Width(50)))
{
EditorGUIUtility.PingObject(interactable.gameObject);
Selection.activeGameObject = interactable.gameObject;
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// Interaction buttons
EditorGUILayout.LabelField("Trigger Interaction:", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Full Interaction", GUILayout.Height(25)))
{
TriggerFullInteraction(interactable);
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.Space();
// Event buttons
EditorGUILayout.LabelField("Trigger Individual Events:", EditorStyles.boldLabel);
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Started"))
{
TriggerEvent(interactable, "OnInteractionStarted");
TriggerUnityEvent(interactable, "interactionStarted");
}
if (GUILayout.Button("Arrived"))
{
TriggerEvent(interactable, "OnInteractingCharacterArrived");
TriggerUnityEvent(interactable, "characterArrived");
}
if (GUILayout.Button("Do Interaction"))
{
TriggerEvent(interactable, "DoInteraction");
}
EditorGUILayout.EndHorizontal();
EditorGUILayout.BeginHorizontal();
if (GUILayout.Button("Complete (Success)"))
{
TriggerEventWithParam(interactable, "OnInteractionFinished", true);
TriggerUnityEventWithParam(interactable, "interactionComplete", true);
}
if (GUILayout.Button("Complete (Fail)"))
{
TriggerEventWithParam(interactable, "OnInteractionFinished", false);
TriggerUnityEventWithParam(interactable, "interactionComplete", false);
}
if (GUILayout.Button("Interrupted"))
{
TriggerUnityEvent(interactable, "interactionInterrupted");
}
EditorGUILayout.EndHorizontal();
// Show registered actions
var actions = interactable.GetComponents<InteractionActionBase>();
if (actions.Length > 0)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField($"Registered Actions ({actions.Length}):", EditorStyles.boldLabel);
foreach (var action in actions)
{
EditorGUILayout.BeginHorizontal(EditorStyles.helpBox);
EditorGUILayout.LabelField(action.GetType().Name);
if (action.respondToEvents != null && action.respondToEvents.Count > 0)
{
string events = string.Join(", ", action.respondToEvents);
EditorGUILayout.LabelField($"Events: {events}", EditorStyles.miniLabel);
}
EditorGUILayout.EndHorizontal();
}
}
EditorGUILayout.EndVertical();
EditorGUILayout.Space();
}
#endregion
#region Data Management
private void RefreshSceneInteractables()
{
_sceneInteractables.Clear();
// Find all interactables in the scene
var allInteractables = FindObjectsByType<InteractableBase>(FindObjectsSortMode.None);
_sceneInteractables.AddRange(allInteractables);
// Sort by name for easier browsing
_sceneInteractables.Sort((a, b) =>
{
if (a == null || b == null) return 0;
return string.Compare(a.gameObject.name, b.gameObject.name, StringComparison.Ordinal);
});
}
private void SelectInteractable(InteractableBase interactable)
{
_selectedInteractable = interactable;
_selectedGameObject = interactable?.gameObject;
// Clear cached editor to force recreation
if (_cachedEditor != null)
{
DestroyImmediate(_cachedEditor);
_cachedEditor = null;
}
}
#endregion
#region Debug Helpers
private void TriggerFullInteraction(InteractableBase interactable)
{
if (!_isPlaying || interactable == null) return;
// Simulate a tap on the interactable
Vector3 worldPos = interactable.transform.position;
interactable.OnTap(new Vector2(worldPos.x, worldPos.y));
Debug.Log($"[Interactable Editor] Triggered full interaction on {interactable.gameObject.name}");
}
private void TriggerEvent(InteractableBase interactable, string methodName)
{
if (!_isPlaying || interactable == null) return;
Type type = interactable.GetType();
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
try
{
method.Invoke(interactable, null);
Debug.Log($"[Interactable Editor] Invoked {methodName} on {interactable.gameObject.name}");
}
catch (Exception e)
{
Debug.LogError($"[Interactable Editor] Error invoking {methodName}: {e.Message}");
}
}
else
{
Debug.LogWarning($"[Interactable Editor] Method {methodName} not found on {type.Name}");
}
}
private void TriggerEventWithParam(InteractableBase interactable, string methodName, object param)
{
if (!_isPlaying || interactable == null) return;
Type type = interactable.GetType();
MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (method != null)
{
try
{
method.Invoke(interactable, new object[] { param });
Debug.Log($"[Interactable Editor] Invoked {methodName}({param}) on {interactable.gameObject.name}");
}
catch (Exception e)
{
Debug.LogError($"[Interactable Editor] Error invoking {methodName}: {e.Message}");
}
}
else
{
Debug.LogWarning($"[Interactable Editor] Method {methodName} not found on {type.Name}");
}
}
private void TriggerUnityEvent(InteractableBase interactable, string fieldName)
{
if (!_isPlaying || interactable == null) return;
Type type = interactable.GetType();
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && field.GetValue(interactable) is UnityEngine.Events.UnityEventBase unityEvent)
{
// Use reflection to invoke the protected Invoke method
MethodInfo invokeMethod = unityEvent.GetType().GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (invokeMethod != null)
{
invokeMethod.Invoke(unityEvent, null);
Debug.Log($"[Interactable Editor] Invoked UnityEvent {fieldName} on {interactable.gameObject.name}");
}
}
}
private void TriggerUnityEventWithParam(InteractableBase interactable, string fieldName, bool param)
{
if (!_isPlaying || interactable == null) return;
Type type = interactable.GetType();
FieldInfo field = type.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (field != null && field.GetValue(interactable) is UnityEngine.Events.UnityEvent<bool> unityEvent)
{
unityEvent.Invoke(param);
Debug.Log($"[Interactable Editor] Invoked UnityEvent<bool> {fieldName}({param}) on {interactable.gameObject.name}");
}
}
#endregion
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 3045d5bcf3e04203bfe060f80d8913ca
timeCreated: 1762866335

View File

@@ -560,6 +560,15 @@ namespace AppleHills.Editor.PuzzleSystem
EditorGUILayout.BeginHorizontal(EditorStyles.toolbar);
EditorGUILayout.LabelField($"Current Level: {_runtimeLevelData.levelId}", EditorStyles.boldLabel);
GUILayout.FlexibleSpace();
// Unlock All button
if (GUILayout.Button("Unlock All", EditorStyles.toolbarButton, GUILayout.Width(100)))
{
UnlockAllPuzzles();
}
EditorGUILayout.EndHorizontal();
_debugScrollPosition = EditorGUILayout.BeginScrollView(_debugScrollPosition);
@@ -870,6 +879,121 @@ namespace AppleHills.Editor.PuzzleSystem
UpdateRuntimeData();
}
private void UnlockAllPuzzles()
{
if (!_isPlaying || _runtimeLevelData == null) return;
PuzzleManager puzzleManager = Object.FindFirstObjectByType<PuzzleManager>();
if (puzzleManager == null)
{
Debug.LogError("[Puzzle Editor] Cannot find PuzzleManager in scene");
return;
}
Debug.Log("[Puzzle Editor] Starting to unlock all puzzles...");
// Get all steps from the level data
List<PuzzleStepSO> allSteps = new List<PuzzleStepSO>(_runtimeLevelData.allSteps);
// Track which steps we've processed
HashSet<string> processedSteps = new HashSet<string>();
bool madeProgress = true;
int maxIterations = 100; // Safety limit to prevent infinite loops
int iteration = 0;
// Keep iterating until no more steps can be unlocked/completed
while (madeProgress && iteration < maxIterations)
{
madeProgress = false;
iteration++;
foreach (var step in allSteps)
{
if (step == null || processedSteps.Contains(step.stepId))
continue;
// Check if already completed
if (puzzleManager.IsPuzzleStepCompleted(step.stepId))
{
processedSteps.Add(step.stepId);
continue;
}
// Check if step is unlocked or can be unlocked
bool isUnlocked = puzzleManager.IsStepUnlocked(step);
if (!isUnlocked)
{
// Try to unlock it if dependencies are met
// We need to check if all dependencies are completed
bool canUnlock = CanUnlockStep(step, puzzleManager);
if (canUnlock)
{
// Unlock the step using reflection
System.Type managerType = puzzleManager.GetType();
System.Reflection.MethodInfo unlockMethod = managerType.GetMethod("UnlockStep",
System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.Public |
System.Reflection.BindingFlags.NonPublic);
if (unlockMethod != null)
{
unlockMethod.Invoke(puzzleManager, new object[] { step });
Debug.Log($"[Puzzle Editor] Unlocked step: {step.stepId}");
isUnlocked = true;
}
}
}
// If unlocked, complete it
if (isUnlocked && !puzzleManager.IsPuzzleStepCompleted(step.stepId))
{
puzzleManager.MarkPuzzleStepCompleted(step);
Debug.Log($"[Puzzle Editor] Completed step: {step.stepId}");
processedSteps.Add(step.stepId);
madeProgress = true;
}
}
}
if (iteration >= maxIterations)
{
Debug.LogWarning($"[Puzzle Editor] Reached maximum iterations ({maxIterations}). Some steps may not have been completed.");
}
Debug.Log($"[Puzzle Editor] Unlock all complete. Processed {processedSteps.Count} steps in {iteration} iterations.");
// Update runtime data to reflect all changes
UpdateRuntimeData();
}
/// <summary>
/// Checks if a step can be unlocked by verifying all its dependencies are completed
/// </summary>
private bool CanUnlockStep(PuzzleStepSO step, PuzzleManager puzzleManager)
{
if (step == null || _runtimeLevelData == null) return false;
// Initial steps can always be unlocked
if (_runtimeLevelData.IsInitialStep(step))
return true;
// Check if all dependencies are completed
if (_runtimeLevelData.stepDependencies.TryGetValue(step.stepId, out string[] dependencies))
{
foreach (var depId in dependencies)
{
if (!puzzleManager.IsPuzzleStepCompleted(depId))
{
return false;
}
}
}
return true;
}
#endregion
}
}

View File

@@ -10,7 +10,7 @@ namespace AppleHills.Core.Settings.Editor
{
private Vector2 scrollPosition;
private List<BaseSettings> allSettings = new List<BaseSettings>();
private string[] tabNames = new string[] { "Player & Follower", "Interaction & Items", "Diving Minigame" };
private string[] tabNames = new string[] { "Player & Follower", "Interaction & Items", "Diving Minigame", "Card System" };
private int selectedTab = 0;
private Dictionary<string, SerializedObject> serializedSettingsObjects = new Dictionary<string, SerializedObject>();
private GUIStyle headerStyle;
@@ -48,6 +48,7 @@ namespace AppleHills.Core.Settings.Editor
CreateSettingsIfMissing<PlayerFollowerSettings>("PlayerFollowerSettings");
CreateSettingsIfMissing<InteractionSettings>("InteractionSettings");
CreateSettingsIfMissing<DivingMinigameSettings>("DivingMinigameSettings");
CreateSettingsIfMissing<CardSystemSettings>("CardSystemSettings");
}
private void CreateSettingsIfMissing<T>(string fileName) where T : BaseSettings
@@ -114,6 +115,9 @@ namespace AppleHills.Core.Settings.Editor
case 2: // Minigames
DrawSettingsEditor<DivingMinigameSettings>();
break;
case 3: // Card System
DrawSettingsEditor<CardSystemSettings>();
break;
}
EditorGUILayout.EndScrollView();

View File

@@ -725,10 +725,9 @@ GameObject:
m_Component:
- component: {fileID: 3864057818161790164}
- component: {fileID: 5271824036850954050}
- component: {fileID: 8081783206361873868}
- component: {fileID: 5548642987123338363}
- component: {fileID: 3058107077406709872}
- component: {fileID: 587711432829270645}
- component: {fileID: 4189849640380816173}
m_Layer: 5
m_Name: Icon
m_TagString: Untagged
@@ -763,53 +762,6 @@ CanvasRenderer:
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
@@ -850,7 +802,7 @@ MonoBehaviour:
m_SelectedTrigger: Selected
m_DisabledTrigger: Disabled
m_Interactable: 1
m_TargetGraphic: {fileID: 8081783206361873868}
m_TargetGraphic: {fileID: 0}
m_OnClick:
m_PersistentCalls:
m_Calls:
@@ -880,6 +832,36 @@ MonoBehaviour:
m_EditorClassIdentifier: AppleHillsScripts::UI.HudMenuButton
pagePrefab: {fileID: 1498581815400593087, guid: ccd858c7962d48147b0233c1bf1382f5, type: 3}
buttonName: RamaSjang Button
--- !u!114 &4189849640380816173
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: 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: 2364528222304962155, guid: 57224356af3d045dbbf8b420e13b4b10, 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!1 &5113586844274188410
GameObject:
m_ObjectHideFlags: 0

View File

@@ -255,11 +255,8 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 0a0d74ee1aa43b54ab5d08005bdd9b16, type: 3}
m_Name:
m_EditorClassIdentifier: '::'
getDistractedMin: 5
getDistractedMax: 8
getFlirtyMin: 4
getFlirtyMax: 5
fakeChocolate: {fileID: 2391935521422290070}
realChocolate: {fileID: 0}
distractedAudioClips: {fileID: 6418180475301049370, guid: 956d8d84e8dd1de4e94ba48c041dc6ec, type: 2}
angryAudioClips: {fileID: 6418180475301049370, guid: 22e6e844862e5b94989b572cb70c1eff, type: 2}
feederClips: {fileID: 6418180475301049370, guid: 2e607d3f32c25a14ea074850dd2f8ac5, type: 2}

View File

@@ -148,8 +148,6 @@ RectTransform:
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}
@@ -402,8 +400,8 @@ MonoBehaviour:
m_EditorClassIdentifier: '::'
PageName:
transitionDuration: 0.3
rainbowIn: {fileID: 5382650426034128680}
rainbowOut: {fileID: 3983328028282460839}
rainbowIn: {fileID: 0}
rainbowOut: {fileID: 0}
gameLayoutContainer: {fileID: 904161782565348054}
exitButton: {fileID: 8427602740714176801}
rectMask: {fileID: 7425566603516801919}
@@ -528,99 +526,6 @@ 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
@@ -936,99 +841,6 @@ MonoBehaviour:
m_OnClick:
m_PersistentCalls:
m_Calls: []
--- !u!1 &5382650426034128680
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 6108475066390421500}
- component: {fileID: 2398693306920598044}
- component: {fileID: 7920249735731934357}
- component: {fileID: 3566391948883171773}
m_Layer: 5
m_Name: RainbowIn
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &6108475066390421500
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5382650426034128680}
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 &2398693306920598044
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5382650426034128680}
m_CullTransparentMesh: 1
--- !u!114 &7920249735731934357
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5382650426034128680}
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 &3566391948883171773
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5382650426034128680}
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: 622be2ef9d5e27d45a9deaf7ed805f5f, type: 3}
customResolution: 0
resWidth: 250
resHeight: 250
stateName:
resetAfterFinished: 0
autoPlay: 0
loop: 0
--- !u!1 &5867455130109727138
GameObject:
m_ObjectHideFlags: 0

View File

@@ -470,14 +470,9 @@ MonoBehaviour:
canvasGroup: {fileID: 2448231841641732440}
exitButton: {fileID: 1436816358814431354}
book: {fileID: 2685537002028647152}
zoneTabs:
- {fileID: 6429946768665127855}
- {fileID: 9183285670530916085}
- {fileID: 994625896264652594}
- {fileID: 6982294778394446152}
- {fileID: 185814890104990467}
tabContainer: {fileID: 0}
bottomRightSlots: {fileID: 3356256732385166000}
albumCardPlacementPrefab: {fileID: 1275563675283742273, guid: aca553283b12f314795f62d785d01912, type: 3}
cardPrefab: {fileID: 7504168507910195884, guid: c1795924899c08343a189300904ed424, type: 3}
cardEnlargedBackdrop: {fileID: 0}
cardEnlargedContainer: {fileID: 0}
boosterPackButtons:
@@ -1834,28 +1829,6 @@ PrefabInstance:
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
--- !u!114 &185814890104990467 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 3088623090806397146, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
m_PrefabInstance: {fileID: 2902811845053789145}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ff50caabb55742bc8d24a6ddffeda815, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.BookTabButton
--- !u!114 &994625896264652594 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 2703643042664441067, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
m_PrefabInstance: {fileID: 2902811845053789145}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ff50caabb55742bc8d24a6ddffeda815, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.BookTabButton
--- !u!114 &1436816358814431354 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 4303263265458260899, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
@@ -1898,36 +1871,3 @@ RectTransform:
m_CorrespondingSourceObject: {fileID: 9009119031401934516, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
m_PrefabInstance: {fileID: 2902811845053789145}
m_PrefabAsset: {fileID: 0}
--- !u!114 &6429946768665127855 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 8174905762612418678, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
m_PrefabInstance: {fileID: 2902811845053789145}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ff50caabb55742bc8d24a6ddffeda815, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.BookTabButton
--- !u!114 &6982294778394446152 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 5237338805622422161, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
m_PrefabInstance: {fileID: 2902811845053789145}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ff50caabb55742bc8d24a6ddffeda815, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.BookTabButton
--- !u!114 &9183285670530916085 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 6285140893977816364, guid: 0809b88801c54604aac49ad1d382a0e5, type: 3}
m_PrefabInstance: {fileID: 2902811845053789145}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: ff50caabb55742bc8d24a6ddffeda815, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.BookTabButton

View File

@@ -75,9 +75,8 @@ MonoBehaviour:
bottomRightSlots: {fileID: 415627682025321105}
centerOpeningSlot: {fileID: 3371630871680769077}
cardDisplayContainer: {fileID: 4830022034953347571}
flippableCardPrefab: {fileID: 9060030918047515996, guid: e16716863eca4704fbfabef5a699b5aa, type: 3}
cardPrefab: {fileID: 7504168507910195884, guid: c1795924899c08343a189300904ed424, type: 3}
cardSpacing: 500
cardRevealDelay: 0.5
boosterDisappearDuration: 0.5
impulseSource: {fileID: 4448843358972162772}
openingParticleSystem: {fileID: 0}

View File

@@ -106,7 +106,6 @@ RectTransform:
m_ConstrainProportionsScale: 0
m_Children:
- {fileID: 8880693373090345290}
- {fileID: 4420447191717448385}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0.5, y: 0.5}
@@ -135,10 +134,7 @@ MonoBehaviour:
occupantScale: {x: 1, y: 1, z: 1}
scaleTransitionDuration: 0.3
targetCardDefinition: {fileID: 0}
albumCardPrefab: {fileID: 3697348702925017591, guid: 1d8cc8d9238eec34b8e600e7050e2979, type: 3}
previewCardDisplay: {fileID: 2297523098913213162}
previewEnlargedScale: 2.5
previewScaleDuration: 0.3
cardPrefab: {fileID: 7504168507910195884, guid: c1795924899c08343a189300904ed424, type: 3}
--- !u!114 &5397984527285824388
MonoBehaviour:
m_ObjectHideFlags: 0
@@ -189,156 +185,3 @@ RectTransform:
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!1001 &1620637915280911112
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 8576570241677955255}
m_Modifications:
- target: {fileID: 790099756778783334, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 790099756778783334, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchoredPosition.x
value: -0.030929565
objectReference: {fileID: 0}
- target: {fileID: 790099756778783334, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchoredPosition.y
value: 6.3459015
objectReference: {fileID: 0}
- target: {fileID: 1802458852284665438, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_Pivot.x
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchorMax.x
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchorMax.y
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalRotation.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalRotation.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalRotation.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 4210468743547155963, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5533787515014034956, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_Name
value: Card
objectReference: {fileID: 0}
- target: {fileID: 7441149886460635393, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_fontSize
value: 44.3
objectReference: {fileID: 0}
- target: {fileID: 7619421269260494372, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchorMax.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7619421269260494372, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7619421269260494372, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 7619421269260494372, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
--- !u!114 &2297523098913213162 stripped
MonoBehaviour:
m_CorrespondingSourceObject: {fileID: 693510968212398562, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
m_PrefabInstance: {fileID: 1620637915280911112}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 0}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 72cb26621865420aa763a66c06eb7f6d, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.CardDisplay
--- !u!224 &4420447191717448385 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 3108957999325520329, guid: 6d6e64f153ccde149bede8e82351d3c4, type: 3}
m_PrefabInstance: {fileID: 1620637915280911112}
m_PrefabAsset: {fileID: 0}

View File

@@ -460,8 +460,8 @@ RectTransform:
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: 200, y: 400}
m_AnchoredPosition: {x: 0, y: 10.0297}
m_SizeDelta: {x: 200, y: 270}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!114 &693510968212398562
MonoBehaviour:

View File

@@ -1,145 +1,5 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &596098681536817216
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1571786155082116174}
- component: {fileID: 742236545385962389}
- component: {fileID: 1015397553690971809}
m_Layer: 0
m_Name: Image (4)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1571786155082116174
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 596098681536817216}
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: 4945390406745498856}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &742236545385962389
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 596098681536817216}
m_CullTransparentMesh: 1
--- !u!114 &1015397553690971809
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 596098681536817216}
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: 0.3301887, g: 0.054512277, b: 0.054512277, 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: 0}
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!1 &1938654216571238436
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4945390406745498856}
- component: {fileID: 1958069320772630622}
m_Layer: 0
m_Name: ProgressBar
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4945390406745498856
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1938654216571238436}
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: 4874164524383443800}
- {fileID: 2705687956353102842}
- {fileID: 8595097391291779023}
- {fileID: 1657266364921102667}
- {fileID: 1571786155082116174}
m_Father: {fileID: 1716378143019989539}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.5}
m_AnchorMax: {x: 0, y: 0.5}
m_AnchoredPosition: {x: -51, y: 0}
m_SizeDelta: {x: 30, y: 540}
m_Pivot: {x: 0, y: 0.5}
--- !u!114 &1958069320772630622
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1938654216571238436}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 8a8695521f0d02e499659fee002a26c2, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.GridLayoutGroup
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 4
m_StartCorner: 0
m_StartAxis: 0
m_CellSize: {x: 30, y: 85}
m_Spacing: {x: 0, y: 24}
m_Constraint: 0
m_ConstraintCount: 2
--- !u!1 &2592418251725585151
GameObject:
m_ObjectHideFlags: 0
@@ -387,306 +247,6 @@ MonoBehaviour:
m_hasFontAssetChanged: 0
m_baseMaterial: {fileID: 0}
m_maskOffset: {x: 0, y: 0, z: 0, w: 0}
--- !u!1 &3959939499314668069
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 4874164524383443800}
- component: {fileID: 7959593666515881701}
- component: {fileID: 9112354298372600889}
m_Layer: 0
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &4874164524383443800
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3959939499314668069}
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: 4945390406745498856}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &7959593666515881701
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3959939499314668069}
m_CullTransparentMesh: 1
--- !u!114 &9112354298372600889
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3959939499314668069}
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: 0.17215312, g: 0.745283, b: 0.05273228, 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: 0}
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!1 &4375456684676617836
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 8595097391291779023}
- component: {fileID: 1792934611570678913}
- component: {fileID: 7854260356177144129}
m_Layer: 0
m_Name: Image (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &8595097391291779023
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4375456684676617836}
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: 4945390406745498856}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &1792934611570678913
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4375456684676617836}
m_CullTransparentMesh: 1
--- !u!114 &7854260356177144129
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 4375456684676617836}
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: 0.7830189, g: 0.52323097, b: 0.1071111, 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: 0}
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!1 &5012786113167728906
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2705687956353102842}
- component: {fileID: 2691862621904947354}
- component: {fileID: 2540160443596924038}
m_Layer: 0
m_Name: Image (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2705687956353102842
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5012786113167728906}
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: 4945390406745498856}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &2691862621904947354
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5012786113167728906}
m_CullTransparentMesh: 1
--- !u!114 &2540160443596924038
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 5012786113167728906}
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: 0.96037734, g: 1, b: 0.10849059, 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: 0}
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!1 &7770052403090895892
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 1657266364921102667}
- component: {fileID: 4495020596553564454}
- component: {fileID: 6044785843654307484}
m_Layer: 0
m_Name: Image (3)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &1657266364921102667
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7770052403090895892}
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: 4945390406745498856}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &4495020596553564454
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7770052403090895892}
m_CullTransparentMesh: 1
--- !u!114 &6044785843654307484
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7770052403090895892}
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: 0.5283019, g: 0.2082011, b: 0.067283735, 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: 0}
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!1 &7979281912729275558
GameObject:
m_ObjectHideFlags: 0
@@ -1018,17 +578,237 @@ MonoBehaviour:
cardDisplay: {fileID: 6240953021224011525}
albumCard: {fileID: 4223766615757628380}
enableIdleHover: 1
idleHoverHeight: 10
idleHoverDuration: 1.5
hoverScaleMultiplier: 1.05
flipDuration: 0.6
flipScalePunch: 1.3
newCardText: {fileID: 3802662965106921097}
newCardIdleText: {fileID: 8335972675955266088}
repeatText: {fileID: 7979281912729275558}
progressBarContainer: {fileID: 1938654216571238436}
cardsToUpgrade: 5
enlargedScale: 1.5
--- !u!1001 &7640944115072447751
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
serializedVersion: 3
m_TransformParent: {fileID: 1716378143019989539}
m_Modifications:
- target: {fileID: 2111622773705306824, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2111622773705306824, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2111622773705306824, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2111622773705306824, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2111622773705306824, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 2111622773705306824, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3003501824762097247, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3003501824762097247, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3003501824762097247, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3003501824762097247, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3003501824762097247, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3003501824762097247, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_Pivot.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_Pivot.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMax.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMax.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMin.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMin.y
value: 0.5
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.x
value: 30
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.y
value: 540
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalPosition.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalRotation.w
value: 1
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalRotation.x
value: -0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalRotation.y
value: -0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalRotation.z
value: -0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.x
value: -51
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalEulerAnglesHint.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalEulerAnglesHint.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_LocalEulerAnglesHint.z
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5730442312475707133, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5730442312475707133, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5730442312475707133, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5730442312475707133, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5730442312475707133, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 5730442312475707133, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 8137280556209245475, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_Name
value: ProgressBar
objectReference: {fileID: 0}
- target: {fileID: 9004345790622233676, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9004345790622233676, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9004345790622233676, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9004345790622233676, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9004345790622233676, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9004345790622233676, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9212690411364735305, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMax.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9212690411364735305, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchorMin.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9212690411364735305, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9212690411364735305, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_SizeDelta.y
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9212690411364735305, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.x
value: 0
objectReference: {fileID: 0}
- target: {fileID: 9212690411364735305, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
propertyPath: m_AnchoredPosition.y
value: 0
objectReference: {fileID: 0}
m_RemovedComponents: []
m_RemovedGameObjects: []
m_AddedGameObjects: []
m_AddedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
--- !u!1 &1938654216571238436 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 8137280556209245475, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
m_PrefabInstance: {fileID: 7640944115072447751}
m_PrefabAsset: {fileID: 0}
--- !u!224 &4945390406745498856 stripped
RectTransform:
m_CorrespondingSourceObject: {fileID: 3362949153200116207, guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0, type: 3}
m_PrefabInstance: {fileID: 7640944115072447751}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &8943403053347003322
PrefabInstance:
m_ObjectHideFlags: 0

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: c1795924899c08343a189300904ed424
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,457 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!1 &134777372236185875
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9004345790622233676}
- component: {fileID: 6083117740009387041}
- component: {fileID: 4172992435994106779}
m_Layer: 0
m_Name: Image (3)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9004345790622233676
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 134777372236185875}
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: 3362949153200116207}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6083117740009387041
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 134777372236185875}
m_CullTransparentMesh: 1
--- !u!114 &4172992435994106779
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 134777372236185875}
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: 0.5283019, g: 0.2082011, b: 0.067283735, 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: 0}
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!1 &3430309536586437645
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 5730442312475707133}
- component: {fileID: 5715486817664040349}
- component: {fileID: 5281139373228085633}
m_Layer: 0
m_Name: Image (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &5730442312475707133
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3430309536586437645}
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: 3362949153200116207}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &5715486817664040349
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3430309536586437645}
m_CullTransparentMesh: 1
--- !u!114 &5281139373228085633
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 3430309536586437645}
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: 0.96037734, g: 1, b: 0.10849059, 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: 0}
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!1 &6247241022221525867
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 2111622773705306824}
- component: {fileID: 8280957220828309894}
- component: {fileID: 501559951267601478}
m_Layer: 0
m_Name: Image (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &2111622773705306824
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6247241022221525867}
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: 3362949153200116207}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &8280957220828309894
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6247241022221525867}
m_CullTransparentMesh: 1
--- !u!114 &501559951267601478
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6247241022221525867}
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: 0.7830189, g: 0.52323097, b: 0.1071111, 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: 0}
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!1 &6700953609979385634
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3003501824762097247}
- component: {fileID: 323201945338772450}
- component: {fileID: 1477044080931340606}
m_Layer: 0
m_Name: Image
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3003501824762097247
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6700953609979385634}
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: 3362949153200116207}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &323201945338772450
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6700953609979385634}
m_CullTransparentMesh: 1
--- !u!114 &1477044080931340606
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 6700953609979385634}
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: 0.17215312, g: 0.745283, b: 0.05273228, 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: 0}
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!1 &7084112357262466375
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 9212690411364735305}
- component: {fileID: 6937480786921270930}
- component: {fileID: 7214059074060303270}
m_Layer: 0
m_Name: Image (4)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &9212690411364735305
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7084112357262466375}
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: 3362949153200116207}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0}
m_AnchorMax: {x: 0, y: 0}
m_AnchoredPosition: {x: 0, y: 0}
m_SizeDelta: {x: 0, y: 0}
m_Pivot: {x: 0.5, y: 0.5}
--- !u!222 &6937480786921270930
CanvasRenderer:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7084112357262466375}
m_CullTransparentMesh: 1
--- !u!114 &7214059074060303270
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 7084112357262466375}
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: 0.3301887, g: 0.054512277, b: 0.054512277, 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: 0}
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!1 &8137280556209245475
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
- component: {fileID: 3362949153200116207}
- component: {fileID: 3792049735601548967}
- component: {fileID: 2438311102500089381}
m_Layer: 0
m_Name: ProgressBar
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!224 &3362949153200116207
RectTransform:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8137280556209245475}
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: 9212690411364735305}
- {fileID: 9004345790622233676}
- {fileID: 2111622773705306824}
- {fileID: 5730442312475707133}
- {fileID: 3003501824762097247}
m_Father: {fileID: 0}
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
m_AnchorMin: {x: 0, y: 0.5}
m_AnchorMax: {x: 0, y: 0.5}
m_AnchoredPosition: {x: -51, y: 0}
m_SizeDelta: {x: 30, y: 540}
m_Pivot: {x: 0, y: 0.5}
--- !u!114 &3792049735601548967
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8137280556209245475}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 59f8146938fff824cb5fd77236b75775, type: 3}
m_Name:
m_EditorClassIdentifier: UnityEngine.UI::UnityEngine.UI.VerticalLayoutGroup
m_Padding:
m_Left: 0
m_Right: 0
m_Top: 0
m_Bottom: 0
m_ChildAlignment: 4
m_Spacing: 5
m_ChildForceExpandWidth: 1
m_ChildForceExpandHeight: 1
m_ChildControlWidth: 1
m_ChildControlHeight: 1
m_ChildScaleWidth: 0
m_ChildScaleHeight: 0
m_ReverseArrangement: 1
--- !u!114 &2438311102500089381
MonoBehaviour:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 8137280556209245475}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: e91de41001c14101b8fa4216d6c7888b, type: 3}
m_Name:
m_EditorClassIdentifier: AppleHillsScripts::UI.CardSystem.ProgressBarController

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: e3ca4613f52caec4bb1b8d2d8a4aa6d0
PrefabImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

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,7 @@
fileFormatVersion: 2
guid: 0fce6399583b6ac43b5cf11a411b05dc
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -11,9 +11,6 @@
"OptimizedRope",
"AudioSourceEvents",
"NewAssembly",
"SkiaSharp.Unity",
"SkiaSharp.Editor",
"SkiaSharp",
"Unity.Cinemachine"
],
"includePlatforms": [],

View File

@@ -30,8 +30,6 @@ namespace Bootstrap
private float _sceneLoadingProgress = 0f;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
// Run very early - need to set up loading screen before other systems initialize
public override int ManagedAwakePriority => 5;
internal override void OnManagedAwake()
{
@@ -83,10 +81,8 @@ namespace Bootstrap
Invoke(nameof(StartLoadingMainMenu), minDelayAfterBoot);
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Manual cleanup for events
if (initialLoadingScreen != null)
{

View File

@@ -37,8 +37,6 @@ namespace Cinematics
public PlayableDirector playableDirector;
public override int ManagedAwakePriority => 170; // Cinematic systems
internal override void OnManagedAwake()
{
// Set instance immediately (early initialization)

View File

@@ -15,8 +15,6 @@ namespace Cinematics
private float _holdStartTime;
private bool _isHolding;
private bool _skipPerformed;
public override int ManagedAwakePriority => 180; // Cinematic UI
internal override void OnManagedStart()
{
@@ -32,10 +30,8 @@ namespace Cinematics
Logging.Debug("[SkipCinematic] Initialized");
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Clean up subscriptions
UnsubscribeFromCinematicsEvents();
}

View File

@@ -34,8 +34,6 @@ namespace Core
public event Action OnGamePaused;
public event Action OnGameResumed;
// ManagedBehaviour configuration
public override int ManagedAwakePriority => 10; // Core infrastructure - runs early
internal override void OnManagedAwake()
{
@@ -171,6 +169,7 @@ namespace Core
var playerSettings = SettingsProvider.Instance.LoadSettingsSynchronous<PlayerFollowerSettings>();
var interactionSettings = SettingsProvider.Instance.LoadSettingsSynchronous<InteractionSettings>();
var minigameSettings = SettingsProvider.Instance.LoadSettingsSynchronous<DivingMinigameSettings>();
var cardSystemSettings = SettingsProvider.Instance.LoadSettingsSynchronous<CardSystemSettings>();
// Register settings with service locator
if (playerSettings != null)
@@ -202,9 +201,19 @@ namespace Core
{
Debug.LogError("Failed to load MinigameSettings");
}
if (cardSystemSettings != null)
{
ServiceLocator.Register<ICardSystemSettings>(cardSystemSettings);
Logging.Debug("CardSystemSettings registered successfully");
}
else
{
Debug.LogError("Failed to load CardSystemSettings");
}
// Log success
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null;
_settingsLoaded = playerSettings != null && interactionSettings != null && minigameSettings != null && cardSystemSettings != null;
if (_settingsLoaded)
{
Logging.Debug("All settings loaded and registered with ServiceLocator");

View File

@@ -47,8 +47,6 @@ namespace Core
// Broadcasts when any two items are successfully combined
// Args: first item data, second item data, result item data
public event Action<PickupItemData, PickupItemData, PickupItemData> OnItemsCombined;
public override int ManagedAwakePriority => 75; // Item registry
internal override void OnManagedAwake()
{
@@ -67,10 +65,8 @@ namespace Core
ClearAllRegistrations();
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Ensure we clean up any subscriptions from registered items when the manager is destroyed
ClearAllRegistrations();
}

View File

@@ -6,12 +6,19 @@
/// </summary>
public enum LifecyclePhase
{
/// <summary>
/// Called immediately during registration (during Awake).
/// Use for early initialization such as setting singleton instances.
/// NOT ordered - fires whenever Unity calls this component's Awake().
/// </summary>
ManagedAwake,
/// <summary>
/// Called once per component after bootstrap completes.
/// Guaranteed to be called after all bootstrap resources are loaded.
/// For late-registered components, called immediately upon registration.
/// </summary>
ManagedAwake,
ManagedStart,
/// <summary>
/// Called before a scene is unloaded.

View File

@@ -59,11 +59,11 @@ namespace Core.Lifecycle
#region State Flags
private bool isBootComplete = false;
private bool isBootComplete;
private string currentSceneReady = "";
// Scene loading state tracking
private bool isLoadingScene = false;
private bool isLoadingScene;
private string sceneBeingLoaded = "";
private List<ManagedBehaviour> pendingSceneComponents = new List<ManagedBehaviour>();
@@ -120,17 +120,13 @@ namespace Core.Lifecycle
// Track which scene this component belongs to
componentScenes[component] = sceneName;
// ALWAYS add to managedAwakeList - this is the master list used for save/load
InsertSorted(managedAwakeList, component, component.ManagedAwakePriority);
// Register for all scene lifecycle hooks
InsertSorted(sceneUnloadingList, component, component.SceneUnloadingPriority);
InsertSorted(sceneReadyList, component, component.SceneReadyPriority);
InsertSorted(saveRequestedList, component, component.SavePriority);
InsertSorted(restoreRequestedList, component, component.RestorePriority);
InsertSorted(destroyList, component, component.DestroyPriority);
// Call OnManagedAwake immediately after registration (early initialization hook)
// Add to all lifecycle lists (order of registration determines execution order)
managedAwakeList.Add(component);
sceneUnloadingList.Add(component);
sceneReadyList.Add(component);
saveRequestedList.Add(component);
restoreRequestedList.Add(component);
destroyList.Add(component);
try
{
component.OnManagedAwake();
@@ -146,7 +142,7 @@ namespace Core.Lifecycle
// Check if we're currently loading a scene
if (isLoadingScene && sceneName == sceneBeingLoaded)
{
// Batch this component - will be processed in priority order when scene load completes
// Batch this component - will be processed when scene load completes
pendingSceneComponents.Add(component);
LogDebug($"Batched component for scene load: {component.gameObject.name} (Scene: {sceneName})");
}
@@ -282,10 +278,7 @@ namespace Core.Lifecycle
LogDebug($"Processing {pendingSceneComponents.Count} batched components for scene: {sceneBeingLoaded}");
// Sort by ManagedAwake priority (lower values first)
pendingSceneComponents.Sort((a, b) => a.ManagedAwakePriority.CompareTo(b.ManagedAwakePriority));
// Call OnManagedStart in priority order
// Call OnManagedStart in registration order
foreach (var component in pendingSceneComponents)
{
if (component == null) continue;
@@ -294,7 +287,7 @@ namespace Core.Lifecycle
{
component.OnManagedStart();
HandleAutoRegistrations(component);
LogDebug($"Processed batched component: {component.gameObject.name} (Priority: {component.ManagedAwakePriority})");
LogDebug($"Processed batched component: {component.gameObject.name}");
}
catch (Exception ex)
{
@@ -309,7 +302,7 @@ namespace Core.Lifecycle
}
/// <summary>
/// Broadcast OnSceneUnloading to components in the specified scene (reverse priority order).
/// Broadcast OnSceneUnloading to components in the specified scene.
/// </summary>
public void BroadcastSceneUnloading(string sceneName)
{
@@ -336,8 +329,8 @@ namespace Core.Lifecycle
}
/// <summary>
/// Broadcast OnSceneReady to components in the specified scene (priority order).
/// If scene loading mode is active, processes batched components first.
/// Broadcast OnSceneReady to components in the specified scene.
/// Processes batched components first, then calls OnSceneReady on all components in that scene.
/// </summary>
public void BroadcastSceneReady(string sceneName)
{
@@ -621,42 +614,6 @@ namespace Core.Lifecycle
#endregion
#region Helper Methods
/// <summary>
/// Insert component into list maintaining sorted order by priority.
/// Uses binary search for efficient insertion.
/// </summary>
private void InsertSorted(List<ManagedBehaviour> list, ManagedBehaviour component, int priority)
{
// Simple linear insertion for now (can optimize with binary search later if needed)
int index = 0;
for (int i = 0; i < list.Count; i++)
{
int existingPriority = GetPriorityForList(list[i], list);
if (priority < existingPriority)
{
index = i;
break;
}
index = i + 1;
}
list.Insert(index, component);
}
/// <summary>
/// Get the priority value for a component based on which list it's in.
/// </summary>
private int GetPriorityForList(ManagedBehaviour component, List<ManagedBehaviour> list)
{
if (list == managedAwakeList) return component.ManagedAwakePriority;
if (list == sceneUnloadingList) return component.SceneUnloadingPriority;
if (list == sceneReadyList) return component.SceneReadyPriority;
if (list == saveRequestedList) return component.SavePriority;
if (list == restoreRequestedList) return component.RestorePriority;
if (list == destroyList) return component.DestroyPriority;
return 100;
}
/// <summary>
/// Log debug message if debug logging is enabled.

View File

@@ -8,46 +8,6 @@ namespace Core.Lifecycle
/// </summary>
public abstract class ManagedBehaviour : MonoBehaviour
{
#region Priority Properties
/// <summary>
/// Priority for OnManagedStart (lower values execute first).
/// Default: 100
/// </summary>
public virtual int ManagedAwakePriority => 100;
/// <summary>
/// Priority for OnSceneUnloading (executed in reverse: higher values execute first).
/// Default: 100
/// </summary>
public virtual int SceneUnloadingPriority => 100;
/// <summary>
/// Priority for OnSceneReady (lower values execute first).
/// Default: 100
/// </summary>
public virtual int SceneReadyPriority => 100;
/// <summary>
/// Priority for OnSaveRequested (executed in reverse: higher values execute first).
/// Default: 100
/// </summary>
public virtual int SavePriority => 100;
/// <summary>
/// Priority for OnRestoreRequested (lower values execute first).
/// Default: 100
/// </summary>
public virtual int RestorePriority => 100;
/// <summary>
/// Priority for OnManagedDestroy (executed in reverse: higher values execute first).
/// Default: 100
/// </summary>
public virtual int DestroyPriority => 100;
#endregion
#region Configuration Properties
/// <summary>
@@ -67,14 +27,19 @@ namespace Core.Lifecycle
/// Unique identifier for this component in the save system.
/// Default: "SceneName/GameObjectName/ComponentType"
/// Override ONLY for special cases (e.g., singletons like "PlayerController", or custom IDs).
/// Cached on first access to avoid runtime allocation.
/// </summary>
public virtual string SaveId
{
get
{
string sceneName = gameObject.scene.IsValid() ? gameObject.scene.name : "UnknownScene";
string componentType = GetType().Name;
return $"{sceneName}/{gameObject.name}/{componentType}";
if (_cachedSaveId == null)
{
string sceneName = gameObject.scene.IsValid() ? gameObject.scene.name : "UnknownScene";
string componentType = GetType().Name;
_cachedSaveId = $"{sceneName}/{gameObject.name}/{componentType}";
}
return _cachedSaveId;
}
}
@@ -83,6 +48,7 @@ namespace Core.Lifecycle
#region Private Fields
private bool _isRegistered;
private string _cachedSaveId;
#endregion
@@ -107,13 +73,16 @@ namespace Core.Lifecycle
/// <summary>
/// Unity OnDestroy - automatically unregisters and cleans up.
/// IMPORTANT: Derived classes that override OnDestroy MUST call base.OnDestroy()
/// SEALED: Cannot be overridden. Use OnManagedDestroy() for custom cleanup logic.
/// </summary>
protected virtual void OnDestroy()
private void OnDestroy()
{
if (!_isRegistered)
return;
// Call managed destroy hook
OnManagedDestroy();
// Unregister from LifecycleManager
if (LifecycleManager.Instance != null)
{
@@ -149,7 +118,7 @@ namespace Core.Lifecycle
/// <summary>
/// Called once per component after bootstrap completes.
/// GUARANTEE: Bootstrap resources are available, all managers are initialized.
/// For boot-time components: Called during LifecycleManager.BroadcastManagedStart (priority ordered).
/// For boot-time components: Called during LifecycleManager.BroadcastManagedStart (registration order).
/// For late-registered components: Called immediately upon registration (bootstrap already complete).
/// Use for initialization that depends on other systems.
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
@@ -161,7 +130,6 @@ namespace Core.Lifecycle
/// <summary>
/// Called before the scene this component belongs to is unloaded.
/// Called in REVERSE priority order (higher values execute first).
/// Use for scene-specific cleanup.
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
/// </summary>
@@ -172,7 +140,6 @@ namespace Core.Lifecycle
/// <summary>
/// Called after the scene this component belongs to has finished loading.
/// Called in priority order (lower values execute first).
/// Use for scene-specific initialization.
/// NOTE: Internal visibility allows LifecycleManager to call directly. Override in derived classes.
/// </summary>
@@ -312,7 +279,6 @@ namespace Core.Lifecycle
/// <summary>
/// Called during OnDestroy before component is destroyed.
/// Called in REVERSE priority order (higher values execute first).
/// NOTE: Most cleanup is automatic (managed events, auto-registrations).
/// Only override if you need custom cleanup logic.
/// Internal visibility allows LifecycleManager to call directly. Override in derived classes.

View File

@@ -24,9 +24,6 @@ namespace AppleHills.Core
#endregion Singleton Setup
// Very early initialization - QuickAccess should be available immediately
public override int ManagedAwakePriority => 5;
#region Manager Instances
// Core Managers

View File

@@ -43,8 +43,6 @@ namespace Core.SaveLoad
public event Action<string> OnLoadCompleted;
public event Action OnParticipantStatesRestored;
// ManagedBehaviour configuration
public override int ManagedAwakePriority => 20; // After GameManager and SceneManagerService
internal override void OnManagedAwake()
{
@@ -95,10 +93,8 @@ namespace Core.SaveLoad
// ...existing code...
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy(); // Important: call base to unregister from LifecycleManager
if (_instance == this)
{
_instance = null;

View File

@@ -42,10 +42,8 @@ namespace Core
}
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
if (_director != null)
{
_director.stopped -= OnDirectorStopped;

View File

@@ -44,8 +44,6 @@ namespace Core
private LogVerbosity _logVerbosity = LogVerbosity.Debug;
private const string BootstrapSceneName = "BootstrapScene";
// ManagedBehaviour configuration
public override int ManagedAwakePriority => 15; // Core infrastructure, after GameManager
internal override void OnManagedAwake()
{
@@ -369,7 +367,7 @@ namespace Core
await LoadSceneAsync(newSceneName, progress);
CurrentGameplayScene = newSceneName;
// PHASE 10: Broadcast scene ready - processes batched components in priority order, then calls OnSceneReady
// PHASE 10: Broadcast scene ready - processes batched components, then calls OnSceneReady
Logging.Debug($"Broadcasting OnSceneReady for: {newSceneName}");
LifecycleManager.Instance?.BroadcastSceneReady(newSceneName);

View File

@@ -18,9 +18,6 @@ namespace Core
public GameObject orientationPromptPrefab;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
// ManagedBehaviour configuration
public override int ManagedAwakePriority => 70; // Platform-specific utility
internal override void OnManagedAwake()
{
// Set instance immediately (early initialization)
@@ -103,15 +100,13 @@ namespace Core
}
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
// Unsubscribe from events to prevent memory leaks
if (SceneManagerService.Instance != null)
{
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
}
base.OnDestroy(); // Important: call base
}
/// <summary>

View File

@@ -0,0 +1,102 @@
using UnityEngine;
namespace AppleHills.Core.Settings
{
/// <summary>
/// Settings for the card system - controls animations, interactions, and progression
/// </summary>
[CreateAssetMenu(fileName = "CardSystemSettings", menuName = "AppleHills/Settings/Card System", order = 4)]
public class CardSystemSettings : BaseSettings, ICardSystemSettings
{
[Header("Idle Hover Animations")]
[Tooltip("Height of the idle hover animation in pixels")]
[SerializeField] private float idleHoverHeight = 10f;
[Tooltip("Duration of one complete hover cycle in seconds")]
[SerializeField] private float idleHoverDuration = 1.5f;
[Tooltip("Scale multiplier when hovering over a card (1.05 = 5% larger)")]
[SerializeField] private float hoverScaleMultiplier = 1.05f;
[Header("Flip Animations")]
[Tooltip("Duration of the card flip animation in seconds")]
[SerializeField] private float flipDuration = 0.6f;
[Tooltip("Scale punch amount during flip (1.1 = 10% larger at peak)")]
[SerializeField] private float flipScalePunch = 1.1f;
[Header("Enlarge/Shrink Animations")]
[Tooltip("Scale for new cards when enlarged (1.5 = 150% of normal size)")]
[SerializeField] private float newCardEnlargedScale = 1.5f;
[Tooltip("Scale for album cards when enlarged (2.5 = 250% of normal size)")]
[SerializeField] private float albumCardEnlargedScale = 2.5f;
[Tooltip("Duration of scale animations in seconds")]
[SerializeField] private float scaleDuration = 0.3f;
[Header("Drag & Drop")]
[Tooltip("Scale multiplier when dragging a card (1.1 = 10% larger)")]
[SerializeField] private float dragScale = 1.1f;
[Header("Progression System")]
[Tooltip("Number of duplicate cards needed to upgrade rarity")]
[SerializeField] private int cardsToUpgrade = 5;
[Header("General Animation")]
[Tooltip("Default animation duration when not specified in seconds")]
[SerializeField] private float defaultAnimationDuration = 0.3f;
// ICardSystemSettings implementation - Idle Hover Animations
public float IdleHoverHeight => idleHoverHeight;
public float IdleHoverDuration => idleHoverDuration;
public float HoverScaleMultiplier => hoverScaleMultiplier;
// ICardSystemSettings implementation - Flip Animations
public float FlipDuration => flipDuration;
public float FlipScalePunch => flipScalePunch;
// ICardSystemSettings implementation - Enlarge/Shrink Animations
public float NewCardEnlargedScale => newCardEnlargedScale;
public float AlbumCardEnlargedScale => albumCardEnlargedScale;
public float ScaleDuration => scaleDuration;
// ICardSystemSettings implementation - Drag & Drop
public float DragScale => dragScale;
// ICardSystemSettings implementation - Progression System
public int CardsToUpgrade => cardsToUpgrade;
// ICardSystemSettings implementation - General Animation
public float DefaultAnimationDuration => defaultAnimationDuration;
public override void OnValidate()
{
base.OnValidate();
// Validate idle hover animations
idleHoverHeight = Mathf.Max(0f, idleHoverHeight);
idleHoverDuration = Mathf.Max(0.1f, idleHoverDuration);
hoverScaleMultiplier = Mathf.Max(1.0f, hoverScaleMultiplier);
// Validate flip animations
flipDuration = Mathf.Max(0.1f, flipDuration);
flipScalePunch = Mathf.Max(1.0f, flipScalePunch);
// Validate enlarge/shrink animations
newCardEnlargedScale = Mathf.Max(1.0f, newCardEnlargedScale);
albumCardEnlargedScale = Mathf.Max(1.0f, albumCardEnlargedScale);
scaleDuration = Mathf.Max(0.1f, scaleDuration);
// Validate drag & drop
dragScale = Mathf.Max(1.0f, dragScale);
// Validate progression system
cardsToUpgrade = Mathf.Max(1, cardsToUpgrade);
// Validate general animation
defaultAnimationDuration = Mathf.Max(0.1f, defaultAnimationDuration);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: ce6f8e26f4e74a9ab16c190529e67638
timeCreated: 1762934668

View File

@@ -128,9 +128,36 @@ namespace AppleHills.Core.Settings
float[] ViewfinderProgressThresholds { get; }
float PaddingFactor { get; }
float MaxSizePercent { get; }
float MinSizePercent { get; }
public float MinSizePercent { get; }
public PhotoInputModes PhotoInputMode { get; }
}
/// <summary>
/// Interface for card system settings
/// </summary>
public interface ICardSystemSettings
{
// Idle Hover Animations
float IdleHoverHeight { get; }
float IdleHoverDuration { get; }
float HoverScaleMultiplier { get; }
// Photo Input Settings
PhotoInputModes PhotoInputMode { get; }
// Flip Animations
float FlipDuration { get; }
float FlipScalePunch { get; }
// Enlarge/Shrink Animations
float NewCardEnlargedScale { get; }
float AlbumCardEnlargedScale { get; }
float ScaleDuration { get; }
// Drag & Drop
float DragScale { get; }
// Progression System
int CardsToUpgrade { get; }
// General Animation
float DefaultAnimationDuration { get; }
}
}

View File

@@ -0,0 +1,53 @@
using Pixelplacement;
using UnityEngine;
using Core.SaveLoad;
public class ButterFlyBehaviour : MonoBehaviour
{
public AppleMachine butterStateMachine;
public Spline butterflightSpline;
public Transform butterflyObject;
public float flightDuration = 2f;
public float flightDelay = 0f;
private const float AnchorThreshold = 0.05f;
private Animator butterflyAnimator;
// Called when entering the butterfly flight state
public void OnEnable()
{
if (butterflightSpline == null || butterflyObject == null)
{
Debug.LogWarning("ButterFlyBehaviour: Missing spline or butterfly object reference.");
return;
}
if (butterflyObject != null )
{
butterflyAnimator = butterflyObject.GetComponentInChildren<Animator>();
}
butterflyAnimator.SetTrigger("BrokeOut");
Tween.Spline(
butterflightSpline,
butterflyObject,
0,
1,
false,
flightDuration,
flightDelay,
Tween.EaseInOut,
Tween.LoopType.None, HandleTweenStarted, HandleTweenFinished
);
}
public void HandleTweenStarted()
{
}
public void HandleTweenFinished()
{
butterStateMachine.ChangeState("Free");
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f8cd0ca91dab0404daaa3fa1dc722658

View File

@@ -0,0 +1,13 @@
using Core.SaveLoad;
using Core;
using UnityEngine;
public class ButterFlyState : AppleMachine
{
public void stateSwitch(string StateName)
{
Logging.Debug("State Switch to: " + StateName);
ChangeState(StateName);
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b889d915f28f8ac4ebeb12013bcaa4ce

View File

@@ -0,0 +1,21 @@
using Pixelplacement;
using UnityEngine;
using Core.SaveLoad;
public class ButterflyFreeBehaviour : MonoBehaviour
{
public GameObject butterflyRef;
private Animator butterflyAnimator;
public PicnicBehaviour picnicRef;
public void OnEnable()
{
if (butterflyRef != null)
{
butterflyAnimator = butterflyRef.GetComponentInChildren<Animator>();
}
butterflyAnimator.SetTrigger("IsFree");
picnicRef.EnterDistractedState();
Debug.Log("ButterflyFreeBehaviour enabled");
}
}

View File

@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6821f70f6ac4b85418b15ce068ddc6da

View File

@@ -8,12 +8,6 @@ using UnityEngine.Audio;
public class PicnicBehaviour : ManagedBehaviour
{
[Header("Random Call Settings")]
public float getDistractedMin = 2f;
public float getDistractedMax = 5f;
public float getFlirtyMin = 1f;
public float getFlirtyMax = 3f;
private AppleMachine stateMachine;
private Animator animator;
@@ -32,6 +26,7 @@ public class PicnicBehaviour : ManagedBehaviour
// Runtime state tracking
private bool _fakeChocolateDestroyed;
private bool _isDistracted; // track current explicit state so it can be saved
internal override void OnManagedAwake()
{
@@ -48,28 +43,37 @@ public class PicnicBehaviour : ManagedBehaviour
}
else
{
StartCoroutine(StateCycleRoutine());
// Restore the saved state (distracted or chilling) and wait for external control to change states.
if (_isDistracted)
EnterDistractedState();
else
EnterChillingState();
}
}
private IEnumerator StateCycleRoutine()
// Manual state control methods (replaces automatic timer-based switching)
public void EnterDistractedState()
{
while (true)
{
// Distracted state
float distractedWait = UnityEngine.Random.Range(getDistractedMin, getDistractedMax);
stateMachine.ChangeState("Picnic PPL Distracted");
animator.SetBool("theyDistracted", true);
_audioSource.Stop();
yield return new WaitForSeconds(distractedWait);
if (stateMachine == null) stateMachine = GetComponent<AppleMachine>();
if (animator == null) animator = GetComponent<Animator>();
if (_audioSource == null) _audioSource = GetComponent<AppleAudioSource>();
// Chilling state
float chillingWait = UnityEngine.Random.Range(getFlirtyMin, getFlirtyMax);
stateMachine.ChangeState("Picnic PPL Chilling");
animator.SetBool("theyDistracted", false);
_audioSource.Stop();
yield return new WaitForSeconds(chillingWait);
}
_audioSource.Stop();
stateMachine.ChangeState("Picnic PPL Distracted");
animator.SetBool("theyDistracted", true);
_isDistracted = true;
}
public void EnterChillingState()
{
if (stateMachine == null) stateMachine = GetComponent<AppleMachine>();
if (animator == null) animator = GetComponent<Animator>();
if (_audioSource == null) _audioSource = GetComponent<AppleAudioSource>();
_audioSource.Stop();
stateMachine.ChangeState("Picnic PPL Chilling");
animator.SetBool("theyDistracted", false);
_isDistracted = false;
}
public void triedToStealChocolate()
@@ -122,7 +126,7 @@ public class PicnicBehaviour : ManagedBehaviour
internal override string OnSceneSaveRequested()
{
var state = new PicnicBehaviourState { fakeChocolateDestroyed = _fakeChocolateDestroyed };
var state = new PicnicBehaviourState { fakeChocolateDestroyed = _fakeChocolateDestroyed, isDistracted = _isDistracted };
return JsonUtility.ToJson(state);
}
@@ -136,6 +140,7 @@ public class PicnicBehaviour : ManagedBehaviour
if (state != null)
{
_fakeChocolateDestroyed = state.fakeChocolateDestroyed;
_isDistracted = state.isDistracted;
}
}
catch (Exception ex)
@@ -149,4 +154,5 @@ public class PicnicBehaviour : ManagedBehaviour
public class PicnicBehaviourState
{
public bool fakeChocolateDestroyed;
public bool isDistracted;
}

View File

@@ -43,8 +43,6 @@ namespace Data.CardSystem
public event Action<int> OnBoosterCountChanged;
public event Action<CardData> OnPendingCardAdded;
public event Action<CardData> OnCardPlacedInAlbum;
public override int ManagedAwakePriority => 60; // Data systems
internal override void OnManagedAwake()
{

View File

@@ -32,9 +32,6 @@ namespace Dialogue
public bool IsCompleted { get; private set; }
public string CurrentSpeakerName => dialogueGraph?.speakerName;
public override int ManagedAwakePriority => 150; // Dialogue systems
internal override void OnManagedStart()
{
// Get required components
@@ -184,10 +181,8 @@ namespace Dialogue
return null;
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Unregister from events
if (PuzzleManager.Instance != null)
PuzzleManager.Instance.OnStepCompleted -= OnAnyPuzzleStepCompleted;

View File

@@ -49,8 +49,6 @@ namespace Input
private ITouchInputConsumer defaultConsumer;
private bool isHoldActive;
private LogVerbosity _logVerbosity = LogVerbosity.Warning;
public override int ManagedAwakePriority => 25; // Input infrastructure
internal override void OnManagedAwake()
{
@@ -106,7 +104,7 @@ namespace Input
SwitchInputOnSceneLoaded(sceneName);
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
// Unsubscribe from SceneManagerService events
if (SceneManagerService.Instance != null)
@@ -114,7 +112,6 @@ namespace Input
SceneManagerService.Instance.SceneLoadCompleted -= OnSceneLoadCompleted;
}
base.OnDestroy();
// Input action cleanup happens automatically
}

View File

@@ -70,7 +70,6 @@ namespace Input
public override bool AutoRegisterForSave => true;
// Scene-specific SaveId - each level has its own player state
public override string SaveId => $"{gameObject.scene.name}/PlayerController";
public override int ManagedAwakePriority => 100; // Player controller
internal override void OnManagedStart()
{

View File

@@ -41,9 +41,6 @@ namespace Interactions
// Action component system
private List<InteractionActionBase> _registeredActions = new List<InteractionActionBase>();
// ManagedBehaviour configuration
public override int ManagedAwakePriority => 100; // Gameplay base classes
/// <summary>
/// Register an action component with this interactable

View File

@@ -287,10 +287,8 @@ namespace Interactions
ItemManager.Instance?.RegisterItemSlot(this);
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Unregister from slot manager
ItemManager.Instance?.UnregisterItemSlot(this);
}

View File

@@ -50,10 +50,8 @@ namespace Interactions
ItemManager.Instance?.RegisterPickup(this);
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Unregister from ItemManager
ItemManager.Instance?.UnregisterPickup(this);
}

View File

@@ -80,10 +80,8 @@ namespace Levels
}
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
if (PuzzleManager.Instance != null)
{
PuzzleManager.Instance.OnAllPuzzlesComplete -= HandleAllPuzzlesComplete;

View File

@@ -13,7 +13,6 @@ using UI.Core;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.Playables;
using Svg;
namespace Minigames.DivingForPictures
{
@@ -104,7 +103,6 @@ namespace Minigames.DivingForPictures
public static DivingGameManager Instance => _instance;
public override int ManagedAwakePriority => 190;
public override bool AutoRegisterPausable => true; // Automatic GameManager registration
internal override void OnManagedAwake()
@@ -162,10 +160,8 @@ namespace Minigames.DivingForPictures
}
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy(); // Handles auto-unregister from GameManager
// Unsubscribe from events when the manager is destroyed
PlayerCollisionBehavior.OnDamageTaken -= OnPlayerDamageTaken;
OnMonsterSpawned -= DoMonsterSpawned;

View File

@@ -106,8 +106,6 @@ public class FollowerController : ManagedBehaviour
private bool _hasRestoredHeldItem; // Track if held item restoration completed
private string _expectedHeldItemSaveId; // Expected saveId during restoration
public override int ManagedAwakePriority => 110; // Follower after player
internal override void OnManagedStart()
{
_aiPath = GetComponent<AIPath>();

View File

@@ -83,10 +83,8 @@ namespace PuzzleS
}
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
if (PuzzleManager.Instance != null && stepData != null)
{
PuzzleManager.Instance.UnregisterStepBehaviour(this);

View File

@@ -93,8 +93,6 @@ namespace PuzzleS
// Track pending unlocks for steps that were unlocked before their behavior registered
private HashSet<string> _pendingUnlocks = new HashSet<string>();
public override int ManagedAwakePriority => 80; // Puzzle systems
internal override void OnManagedAwake()
{
@@ -138,10 +136,8 @@ namespace PuzzleS
LoadPuzzlesForScene(sceneName);
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Unsubscribe from SceneManagerService events
if (SceneManagerService.Instance != null)
{

View File

@@ -40,8 +40,6 @@ public class AudioManager : ManagedBehaviour, IPausable
/// </summary>
public static AudioManager Instance => _instance;
// ManagedBehaviour configuration
public override int ManagedAwakePriority => 30; // Audio infrastructure
public override bool AutoRegisterPausable => true; // Auto-register as IPausable
internal override void OnManagedAwake()

View File

@@ -1,7 +1,6 @@
using System;
using UnityEngine;
using UnityEngine.UI;
using SkiaSharp.Unity;
using Input;
using AppleHills.Core;
using UI.Core;
@@ -11,8 +10,6 @@ using UI;
public class AppSwitcher : UIPage
{
public GameObject rainbowIn;
public GameObject rainbowOut;
public GameObject gameLayoutContainer;
public GameObject exitButton;
public RectMask2D rectMask;
@@ -20,8 +17,6 @@ public class AppSwitcher : UIPage
[Header("Slide Animation Settings")]
public float slideDuration = 0.5f;
private SkottiePlayerV2 rainbowInPlayer;
private SkottiePlayerV2 rainbowOutPlayer;
private TweenBase slideInTween;
private TweenBase slideOutTween;
@@ -30,16 +25,13 @@ public class AppSwitcher : UIPage
base.OnManagedAwake();
PageName = "AppSwitcher";
rainbowInPlayer = rainbowIn.GetComponent<SkottiePlayerV2>();
rainbowOutPlayer = rainbowOut.GetComponent<SkottiePlayerV2>();
if (rectMask == null)
{
rectMask = GetComponent<RectMask2D>();
}
// Initially hide both
rainbowIn.SetActive(true);
// Initially hide
exitButton.SetActive(false);
}
@@ -49,27 +41,19 @@ public class AppSwitcher : UIPage
gameLayoutContainer.SetActive(true);
// 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);
});
}
protected override void DoTransitionOut(Action onComplete)
{
rainbowIn.SetActive(false);
// Play animation on rainbow out with resetting state
rainbowOutPlayer.PlayAnimation(true);
// Hide the exit button
exitButton.SetActive(false);
@@ -77,7 +61,6 @@ public class AppSwitcher : UIPage
// 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);
});
@@ -110,10 +93,8 @@ public class AppSwitcher : UIPage
);
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Clean up tweens
slideInTween?.Stop();
slideOutTween?.Stop();

View File

@@ -1,193 +0,0 @@
using System;
using AppleHills.Data.CardSystem;
using Core;
using Pixelplacement;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UI.CardSystem
{
/// <summary>
/// Album card component that wraps CardDisplay.
/// Handles tap-to-enlarge and tap-to-shrink interactions for cards placed in album slots.
///
/// TODO: Consider refactoring to state machine pattern (PendingReveal, PlacedInSlot, Enlarged)
/// This would eliminate the need for separate AlbumPlacementCard wrapper and simplify the hierarchy.
/// See design discussion with state transitions for cleaner architecture.
/// </summary>
public class AlbumCard : MonoBehaviour, IPointerClickHandler
{
[Header("References")]
[SerializeField] private CardDisplay cardDisplay;
[Header("Enlarge Settings")]
[SerializeField] private float enlargedScale = 2.5f;
[SerializeField] private float scaleDuration = 0.3f;
// Events for AlbumViewPage to manage backdrop and reparenting
public event Action<AlbumCard> OnEnlargeRequested;
public event Action<AlbumCard> OnShrinkRequested;
private AlbumCardSlot _parentSlot;
private CardData _cardData;
private bool _isEnlarged;
private Vector3 _originalScale;
private Transform _originalParent;
private Vector3 _originalLocalPosition;
private Quaternion _originalLocalRotation;
private void Awake()
{
// Auto-find CardDisplay if not assigned
if (cardDisplay == null)
{
cardDisplay = GetComponentInChildren<CardDisplay>();
}
// Store original scale
_originalScale = transform.localScale;
}
/// <summary>
/// Setup card with data
/// </summary>
public void SetupCard(CardData data)
{
_cardData = data;
if (cardDisplay != null)
{
cardDisplay.SetupCard(data);
}
}
/// <summary>
/// Set the parent slot this card belongs to
/// </summary>
public void SetParentSlot(AlbumCardSlot slot)
{
_parentSlot = slot;
}
/// <summary>
/// Get the card data
/// </summary>
public CardData GetCardData()
{
return _cardData;
}
/// <summary>
/// Handle tap on card - request enlarge/shrink from parent page
/// Only process clicks when card is placed in a slot (not during reveal flow)
/// </summary>
public void OnPointerClick(PointerEventData eventData)
{
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] OnPointerClick on {name}, _parentSlot={((_parentSlot != null) ? _parentSlot.name : "NULL")}, _isEnlarged={_isEnlarged}, position={eventData.position}");
// During reveal flow (before placed in slot), forward clicks to parent FlippableCard
if (_parentSlot == null)
{
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - No parent slot, forwarding click to parent FlippableCard");
// Find parent FlippableCard and forward the click
FlippableCard parentFlippable = GetComponentInParent<FlippableCard>();
if (parentFlippable != null)
{
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Found parent FlippableCard, calling OnPointerClick");
parentFlippable.OnPointerClick(eventData);
}
else
{
Logging.Warning($"[CLICK-TRACE-ALBUMCARD] {name} - No parent FlippableCard found!");
}
return;
}
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Has parent slot, processing click");
if (_isEnlarged)
{
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Is enlarged, requesting shrink");
OnShrinkRequested?.Invoke(this);
}
else
{
Logging.Debug($"[CLICK-TRACE-ALBUMCARD] {name} - Is normal size, requesting enlarge");
OnEnlargeRequested?.Invoke(this);
}
}
/// <summary>
/// Enlarge card (called by AlbumViewPage after reparenting)
/// </summary>
public void EnlargeCard()
{
if (_isEnlarged) return;
_isEnlarged = true;
// Store original transform info for restoration
_originalParent = transform.parent;
_originalLocalPosition = transform.localPosition;
_originalLocalRotation = transform.localRotation;
// Scale up with snappy tween
Tween.LocalScale(transform, _originalScale * enlargedScale, scaleDuration, 0f, Tween.EaseOutBack);
}
/// <summary>
/// Shrink card back to original size (called by AlbumViewPage before reparenting back)
/// </summary>
/// <param name="onComplete">Optional callback to invoke when shrink animation completes</param>
public void ShrinkCard(System.Action onComplete = null)
{
if (!_isEnlarged) return;
_isEnlarged = false;
// Scale back down with snappy tween, invoke callback when done
Tween.LocalScale(transform, _originalScale, scaleDuration, 0f, Tween.EaseInBack,
completeCallback: () => onComplete?.Invoke());
}
/// <summary>
/// Get original parent for restoration
/// </summary>
public Transform GetOriginalParent()
{
return _originalParent;
}
/// <summary>
/// Get original local position for restoration
/// </summary>
public Vector3 GetOriginalLocalPosition()
{
return _originalLocalPosition;
}
/// <summary>
/// Get original local rotation for restoration
/// </summary>
public Quaternion GetOriginalLocalRotation()
{
return _originalLocalRotation;
}
/// <summary>
/// Check if card is currently enlarged
/// </summary>
public bool IsEnlarged => _isEnlarged;
/// <summary>
/// Force reset enlarged state (for cleanup scenarios like page closing)
/// </summary>
public void ForceResetEnlargedState()
{
_isEnlarged = false;
transform.localScale = _originalScale;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 258a530448814715b5ec19737df2a658
timeCreated: 1762505823

View File

@@ -7,8 +7,8 @@ using Pixelplacement;
using UI.Core;
using UI.DragAndDrop.Core;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using UnityEngine.Serialization;
namespace UI.CardSystem
{
@@ -30,7 +30,8 @@ namespace UI.CardSystem
[Header("Album Card Reveal")]
[SerializeField] private SlotContainer bottomRightSlots;
[SerializeField] private GameObject albumCardPlacementPrefab; // The wrapper prefab with flip/drag (AlbumPlacementCard)
[FormerlySerializedAs("albumCardPlacementPrefab")]
[SerializeField] private GameObject cardPrefab; // New Card prefab for placement
[Header("Card Enlarge System")]
[SerializeField] private GameObject cardEnlargedBackdrop; // Backdrop to block interactions
@@ -41,9 +42,11 @@ namespace UI.CardSystem
[SerializeField] private BoosterOpeningPage boosterOpeningPage;
private Input.InputMode _previousInputMode;
private List<AlbumCardPlacementDraggable> _activeCards = new List<AlbumCardPlacementDraggable>();
private List<StateMachine.Card> _activeCards = new List<StateMachine.Card>();
private const int MAX_VISIBLE_CARDS = 3;
private List<StateMachine.Card> _pendingCornerCards = new List<StateMachine.Card>();
private const int MAX_PENDING_CORNER = 3;
internal override void OnManagedStart()
{
// Discover zone tabs from container
@@ -149,7 +152,7 @@ namespace UI.CardSystem
}
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
// Unsubscribe from CardSystemManager
if (CardSystemManager.Instance != null)
@@ -181,9 +184,6 @@ namespace UI.CardSystem
// Clean up active cards
CleanupActiveCards();
// Call base implementation
base.OnDestroy();
}
private void OnExitButtonClicked()
@@ -342,24 +342,20 @@ namespace UI.CardSystem
// If there's an enlarged card in the container, return it to its slot
if (cardEnlargedContainer != null && cardEnlargedContainer.childCount > 0)
{
// Get all enlarged cards (should only be one, but just in case)
for (int i = cardEnlargedContainer.childCount - 1; i >= 0; i--)
{
Transform cardTransform = cardEnlargedContainer.GetChild(i);
AlbumCard albumCard = cardTransform.GetComponent<AlbumCard>();
if (albumCard != null && albumCard.IsEnlarged)
var card = cardTransform.GetComponent<StateMachine.Card>();
var state = cardTransform.GetComponentInChildren<StateMachine.States.CardAlbumEnlargedState>(true);
if (card != null && state != null)
{
// Force reset state and return to slot
Transform originalParent = albumCard.GetOriginalParent();
Transform originalParent = state.GetOriginalParent();
if (originalParent != null)
{
cardTransform.SetParent(originalParent, true);
cardTransform.localPosition = albumCard.GetOriginalLocalPosition();
cardTransform.localRotation = albumCard.GetOriginalLocalRotation();
cardTransform.localPosition = state.GetOriginalLocalPosition();
cardTransform.localRotation = state.GetOriginalLocalRotation();
}
albumCard.ForceResetEnlargedState();
}
}
}
@@ -413,17 +409,15 @@ namespace UI.CardSystem
/// </summary>
private void SpawnPendingCards()
{
if (CardSystemManager.Instance == null || bottomRightSlots == null || albumCardPlacementPrefab == null)
if (CardSystemManager.Instance == null || bottomRightSlots == null || cardPrefab == null)
return;
var pending = CardSystemManager.Instance.GetPendingRevealCards();
// Get unique cards only (by DefinitionId + Rarity)
// Filter out cards with CopiesOwned = 0 (shouldn't happen but guard against it)
var uniquePending = pending
.Where(c => c.CopiesOwned > 0) // Guard: exclude zero-count cards
.Where(c => c.CopiesOwned > 0)
.GroupBy(c => new { c.DefinitionId, c.Rarity })
.Select(g => g.First()) // Take first instance of each unique card
.Select(g => g.First())
.ToList();
int spawnCount = Mathf.Min(uniquePending.Count, MAX_VISIBLE_CARDS);
@@ -437,11 +431,10 @@ namespace UI.CardSystem
}
/// <summary>
/// Spawn a card in a specific slot
/// Spawn a card in a specific slot using the new Card prefab
/// </summary>
private void SpawnCardInSlot(int slotIndex, CardData cardData)
{
// Guard: Don't spawn cards with zero copies
if (cardData.CopiesOwned <= 0)
{
Logging.Warning($"[AlbumViewPage] Skipping spawn of card '{cardData.Name}' with {cardData.CopiesOwned} copies");
@@ -455,38 +448,190 @@ namespace UI.CardSystem
return;
}
// Instantiate card directly as child of the slot container (not the slot itself, not canvas root)
// This keeps it in the correct UI hierarchy
GameObject cardObj = Instantiate(albumCardPlacementPrefab, bottomRightSlots.transform);
AlbumCardPlacementDraggable cardPlacement = cardObj.GetComponent<AlbumCardPlacementDraggable>();
if (cardPlacement != null)
GameObject cardObj = Instantiate(cardPrefab, bottomRightSlots.transform);
var card = cardObj.GetComponent<StateMachine.Card>();
if (card != null)
{
// Setup card data
cardPlacement.SetupCard(cardData);
// Cards spawned here are already revealed and can be dragged into album
card.SetupForAlbumPlacement(cardData);
// Subscribe to events
cardPlacement.OnCardRevealed += OnCardRevealed;
cardPlacement.OnCardPlacedInAlbum += OnCardPlacedInAlbum;
// Assign to slot with animation (will apply size/position)
card.AssignToSlot(slot, true);
// NOW assign to slot - this will:
// 1. Reparent to slot
// 2. Apply slot's occupantSizeMode scaling
// 3. Animate to slot position
cardPlacement.AssignToSlot(slot, true);
// Track placement completion to clean up
card.OnPlacedInAlbumSlot += OnCardPlacedInAlbum;
// Track it
_activeCards.Add(cardPlacement);
_activeCards.Add(card);
Logging.Debug($"[AlbumViewPage] Spawned card '{cardData.Name}' (CopiesOwned: {cardData.CopiesOwned}) in slot {slotIndex}");
Logging.Debug($"[AlbumViewPage] Spawned pending card '{cardData.Name}' in slot {slotIndex}");
}
else
{
Logging.Warning($"[AlbumViewPage] Spawned card has no AlbumCardDraggable component!");
Logging.Warning($"[AlbumViewPage] Spawned card prefab missing Card component!");
Destroy(cardObj);
}
}
/// <summary>
/// Handle when a card is placed in an album slot from the pending list
/// Moves from pending to inventory, shuffles remaining, and spawns the next unique card.
/// </summary>
private void OnCardPlacedInAlbum(StateMachine.Card card, AlbumCardSlot slot)
{
if (card == null) return;
var data = card.CardData;
Logging.Debug($"[AlbumViewPage] Card placed in album slot: {data?.Name}");
// Move card from pending to inventory now
if (data != null && CardSystemManager.Instance != null)
{
CardSystemManager.Instance.MarkCardAsPlaced(data);
}
// Stop tracking and unsubscribe
card.OnPlacedInAlbumSlot -= OnCardPlacedInAlbum;
_activeCards.Remove(card);
// Shuffle remaining cards to front and spawn next
ShuffleCardsToFront();
TrySpawnNextCard();
}
/// <summary>
/// Shuffle active cards to occupy front slots
/// </summary>
private void ShuffleCardsToFront()
{
if (bottomRightSlots == null || _activeCards.Count == 0)
return;
List<DraggableObject> draggableList = _activeCards.Cast<DraggableObject>().ToList();
SlotContainerHelper.ShuffleToFront(bottomRightSlots, draggableList, animate: true);
}
/// <summary>
/// Try to spawn the next pending unique card
/// </summary>
private void TrySpawnNextCard()
{
if (CardSystemManager.Instance == null)
return;
if (_activeCards.Count >= MAX_VISIBLE_CARDS)
return;
var pending = CardSystemManager.Instance.GetPendingRevealCards();
var uniquePending = pending
.Where(c => c.CopiesOwned > 0)
.GroupBy(c => new { c.DefinitionId, c.Rarity })
.Select(g => g.First())
.ToList();
foreach (var cardData in uniquePending)
{
bool alreadySpawned = _activeCards.Any(c =>
c.CardData.DefinitionId == cardData.DefinitionId &&
c.CardData.Rarity == cardData.Rarity);
if (!alreadySpawned)
{
int nextSlotIndex = _activeCards.Count;
SpawnCardInSlot(nextSlotIndex, cardData);
break;
}
}
}
/// <summary>
/// Clean up all active pending cards
/// </summary>
private void CleanupActiveCards()
{
foreach (var card in _activeCards)
{
if (card != null && card.gameObject != null)
{
card.OnPlacedInAlbumSlot -= OnCardPlacedInAlbum;
Destroy(card.gameObject);
}
}
_activeCards.Clear();
}
#endregion
#region Card Enlarge System (Album Slots)
/// <summary>
/// Subscribe to a placed card's enlarged state events to manage backdrop and reparenting.
/// Called by AlbumCardSlot when it spawns an owned card in a slot.
/// </summary>
public void RegisterCardInAlbum(StateMachine.Card card)
{
if (card == null) return;
var enlargeState = card.GetStateComponent<StateMachine.States.CardAlbumEnlargedState>("AlbumEnlargedState");
if (enlargeState != null)
{
enlargeState.OnEnlargeRequested += OnCardEnlargeRequested;
enlargeState.OnShrinkRequested += OnCardShrinkRequested;
}
}
public void UnregisterCardInAlbum(StateMachine.Card card)
{
if (card == null) return;
var enlargeState = card.GetStateComponent<StateMachine.States.CardAlbumEnlargedState>("AlbumEnlargedState");
if (enlargeState != null)
{
enlargeState.OnEnlargeRequested -= OnCardEnlargeRequested;
enlargeState.OnShrinkRequested -= OnCardShrinkRequested;
}
}
private void OnCardEnlargeRequested(StateMachine.States.CardAlbumEnlargedState state)
{
if (state == null) return;
// Show backdrop
if (cardEnlargedBackdrop != null)
{
cardEnlargedBackdrop.SetActive(true);
}
// Reparent card root to enlarged container preserving world transform
if (cardEnlargedContainer != null)
{
var ctx = state.GetComponentInParent<StateMachine.CardContext>();
if (ctx != null)
{
ctx.RootTransform.SetParent(cardEnlargedContainer, true);
ctx.RootTransform.SetAsLastSibling();
}
}
}
private void OnCardShrinkRequested(StateMachine.States.CardAlbumEnlargedState state)
{
if (state == null) return;
// Hide backdrop
if (cardEnlargedBackdrop != null)
{
cardEnlargedBackdrop.SetActive(false);
}
// Reparent back to original parent and restore local transform
var ctx = state.GetComponentInParent<StateMachine.CardContext>();
if (ctx != null)
{
Transform originalParent = state.GetOriginalParent();
if (originalParent != null)
{
ctx.RootTransform.SetParent(originalParent, true);
ctx.RootTransform.localPosition = state.GetOriginalLocalPosition();
ctx.RootTransform.localRotation = state.GetOriginalLocalRotation();
}
}
}
#endregion
/// <summary>
/// Handle when a new card is added to pending queue
/// Only spawn if this unique card isn't already visualized
@@ -519,109 +664,6 @@ namespace UI.CardSystem
}
}
/// <summary>
/// Handle when a card is revealed (flipped)
/// </summary>
private void OnCardRevealed(AlbumCardPlacementDraggable cardPlacement, CardData cardData)
{
Logging.Debug($"[AlbumViewPage] Card revealed: {cardData.Name} (Zone: {cardData.Zone}, CopiesOwned: {cardData.CopiesOwned})");
// IMMEDIATELY move card from pending to inventory upon reveal
if (CardSystemManager.Instance != null)
{
CardSystemManager.Instance.MarkCardAsPlaced(cardData);
Logging.Debug($"[AlbumViewPage] Moved card '{cardData.Name}' from pending to inventory on reveal");
}
// Remove this card from active cards list
_activeCards.Remove(cardPlacement);
// Check if we're currently viewing the correct zone for this card
CardZone currentZone = GetCurrentZone();
if (currentZone != cardData.Zone)
{
// Card is from a different zone - navigate to its zone
Logging.Debug($"[AlbumViewPage] Card zone ({cardData.Zone}) doesn't match current zone ({currentZone}). Navigating to card's zone...");
NavigateToZone(cardData.Zone);
}
else
{
Logging.Debug($"[AlbumViewPage] Card zone ({cardData.Zone}) matches current zone - no navigation needed.");
}
// Shuffle remaining cards to front and spawn next unique card
ShuffleCardsToFront();
TrySpawnNextCard();
}
/// <summary>
/// Handle when a card is placed in the album (from AlbumCardDraggable)
/// Card data already moved to inventory in OnCardRevealed
/// This just handles cleanup
/// </summary>
private void OnCardPlacedInAlbum(AlbumCardPlacementDraggable cardPlacement, CardData cardData)
{
Logging.Debug($"[AlbumViewPage] Card placed in album slot: {cardData.Name}");
// Unsubscribe from events (card is now static in album)
cardPlacement.OnCardRevealed -= OnCardRevealed;
cardPlacement.OnCardPlacedInAlbum -= OnCardPlacedInAlbum;
// Note: Card already removed from _activeCards in OnCardRevealed
// Note: Shuffle and spawn already done in OnCardRevealed
}
/// <summary>
/// Shuffle active cards to occupy front slots
/// </summary>
private void ShuffleCardsToFront()
{
if (bottomRightSlots == null || _activeCards.Count == 0)
return;
// Convert to base DraggableObject list for helper method
List<DraggableObject> draggableList = _activeCards.Cast<DraggableObject>().ToList();
SlotContainerHelper.ShuffleToFront(bottomRightSlots, draggableList, animate: true);
}
/// <summary>
/// Try to spawn the next pending card
/// Only spawns unique cards (not duplicates)
/// </summary>
private void TrySpawnNextCard()
{
if (CardSystemManager.Instance == null)
return;
if (_activeCards.Count >= MAX_VISIBLE_CARDS)
return; // Already at max
var pending = CardSystemManager.Instance.GetPendingRevealCards();
// Get unique pending cards, excluding zero-count cards
var uniquePending = pending
.Where(c => c.CopiesOwned > 0) // Guard: exclude zero-count cards
.GroupBy(c => new { c.DefinitionId, c.Rarity })
.Select(g => g.First())
.ToList();
// Find first unique card that's not already spawned
foreach (var cardData in uniquePending)
{
bool alreadySpawned = _activeCards.Any(c =>
c.CardData.DefinitionId == cardData.DefinitionId &&
c.CardData.Rarity == cardData.Rarity);
if (!alreadySpawned)
{
int nextSlotIndex = _activeCards.Count;
SpawnCardInSlot(nextSlotIndex, cardData);
break;
}
}
}
/// <summary>
/// Find a slot by its SlotIndex property
/// </summary>
@@ -640,213 +682,86 @@ namespace UI.CardSystem
return null;
}
/// <summary>
/// Get the current zone based on book page
/// </summary>
public CardZone GetCurrentZone()
public void SpawnPendingCornerCards()
{
if (book == null || zoneTabs == null || zoneTabs.Length == 0)
if (cardPrefab == null || bottomRightSlots == null) return;
CleanupPendingCornerCards();
for (int i = 0; i < MAX_PENDING_CORNER; i++)
{
return CardZone.AppleHills; // Default
}
int currentPage = book.CurrentPaper;
// Find tab with matching target page
foreach (var tab in zoneTabs)
{
if (tab.TargetPage == currentPage)
var slot = FindSlotByIndex(i);
if (slot == null) break;
GameObject cardObj = Instantiate(cardPrefab, bottomRightSlots.transform);
var card = cardObj.GetComponent<StateMachine.Card>();
if (card != null)
{
return tab.Zone;
card.SetupForAlbumPending();
card.AssignToSlot(slot, true);
_pendingCornerCards.Add(card);
}
else
{
Destroy(cardObj);
}
}
// Fallback to first zone
return CardZone.NotApplicable;
}
/// <summary>
/// Get tab for a specific zone
/// </summary>
public BookTabButton GetTabForZone(CardZone zone)
private void CleanupPendingCornerCards()
{
if (zoneTabs == null)
foreach (var c in _pendingCornerCards)
{
return null;
if (c != null) Destroy(c.gameObject);
}
foreach (var tab in zoneTabs)
{
if (tab.Zone == zone)
{
return tab;
}
}
return null;
_pendingCornerCards.Clear();
}
/// <summary>
/// Navigate to a specific zone
/// </summary>
public void NavigateToZone(CardZone zone)
public void HandlePendingCardDragStart(StateMachine.Card cornerCard)
{
BookTabButton tab = GetTabForZone(zone);
if (tab != null)
// Select smart pending card data
var selected = SelectSmartPendingCard();
if (selected == null)
{
tab.ActivateTab();
return; // no pending data
}
cornerCard.Context.SetupCard(selected);
// Navigate album to page
int targetPage = FindPageForCard(selected);
if (targetPage >= 0)
{
NavigateToAlbumPage(targetPage);
}
// Begin flip state
cornerCard.ChangeState("FlippingPendingState");
}
/// <summary>
/// Clean up all active cards
/// </summary>
private void CleanupActiveCards()
private CardData SelectSmartPendingCard()
{
foreach (var card in _activeCards)
{
if (card != null && card.gameObject != null)
{
card.OnCardRevealed -= OnCardRevealed;
card.OnCardPlacedInAlbum -= OnCardPlacedInAlbum;
Destroy(card.gameObject);
}
}
_activeCards.Clear();
if (CardSystemManager.Instance == null) return null;
var pending = CardSystemManager.Instance.GetPendingRevealCards();
if (pending.Count == 0) return null;
// Try current page match
var pageDefs = GetDefinitionsOnCurrentPage();
var match = pending.Find(c => pageDefs.Contains(c.DefinitionId));
if (match != null) return match;
// Fallback random
int idx = Random.Range(0, pending.Count);
return pending[idx];
}
#endregion
#region Card Enlarge System
/// <summary>
/// Subscribe to album card events when a card is spawned in a slot
/// Call this when AlbumCardSlot spawns a card
/// </summary>
public void RegisterAlbumCard(AlbumCard albumCard)
private List<string> GetDefinitionsOnCurrentPage()
{
if (albumCard == null) return;
albumCard.OnEnlargeRequested += OnCardEnlargeRequested;
albumCard.OnShrinkRequested += OnCardShrinkRequested;
// Placeholder: gather from slots on current page
return new List<string>();
}
/// <summary>
/// Unsubscribe from album card events
/// </summary>
public void UnregisterAlbumCard(AlbumCard albumCard)
private int FindPageForCard(CardData data)
{
if (albumCard == null) return;
albumCard.OnEnlargeRequested -= OnCardEnlargeRequested;
albumCard.OnShrinkRequested -= OnCardShrinkRequested;
// Placeholder: map definition to page index
return -1;
}
/// <summary>
/// Handle card enlarge request - show backdrop and reparent card
/// </summary>
private void OnCardEnlargeRequested(AlbumCard card)
private void NavigateToAlbumPage(int pageIndex)
{
if (card == null) return;
Logging.Debug($"[AlbumViewPage] OnCardEnlargeRequested called for card: {card.name}, current parent: {card.transform.parent.name}");
// IMPORTANT: Call EnlargeCard FIRST to store original parent (the slot)
// BEFORE reparenting to the enlarged container
card.EnlargeCard();
// Show backdrop
if (cardEnlargedBackdrop != null)
{
cardEnlargedBackdrop.SetActive(true);
Logging.Debug($"[AlbumViewPage] Backdrop shown");
}
// NOW reparent card to enlarged container (above backdrop)
if (cardEnlargedContainer != null)
{
card.transform.SetParent(cardEnlargedContainer, true);
card.transform.SetAsLastSibling(); // Ensure on top
Logging.Debug($"[AlbumViewPage] Card reparented to enlarged container");
}
Logging.Debug($"[AlbumViewPage] Card enlarged: {card.GetCardData()?.Name}");
// Placeholder: call book/page flip controller
}
/// <summary>
/// Handle card shrink request - hide backdrop and reparent card back to slot
/// </summary>
private void OnCardShrinkRequested(AlbumCard card)
{
if (card == null) return;
// Trigger shrink animation
card.ShrinkCard();
// Hide backdrop
if (cardEnlargedBackdrop != null)
{
cardEnlargedBackdrop.SetActive(false);
}
// Reparent back to original parent (the slot)
Transform originalParent = card.GetOriginalParent();
if (originalParent != null)
{
card.transform.SetParent(originalParent, true);
card.transform.localPosition = card.GetOriginalLocalPosition();
card.transform.localRotation = card.GetOriginalLocalRotation();
}
Logging.Debug($"[AlbumViewPage] Card shrunk: {card.GetCardData()?.Name}");
}
/// <summary>
/// Show backdrop and reparent slot preview card for enlargement
/// </summary>
public void ShowSlotPreview(AlbumCardSlot slot, Transform previewCardTransform)
{
if (previewCardTransform == null)
return;
Logging.Debug($"[AlbumViewPage] ShowSlotPreview called for slot: {slot.name}");
// Show backdrop
if (cardEnlargedBackdrop != null)
{
cardEnlargedBackdrop.SetActive(true);
}
// Reparent preview card to enlarged container (above backdrop)
if (cardEnlargedContainer != null)
{
previewCardTransform.SetParent(cardEnlargedContainer, true);
previewCardTransform.SetAsLastSibling();
}
}
/// <summary>
/// Hide backdrop and trigger shrink animation for slot preview
/// </summary>
public void HideSlotPreview(AlbumCardSlot slot, Transform previewCardTransform, System.Action onComplete)
{
if (previewCardTransform == null)
return;
Logging.Debug($"[AlbumViewPage] HideSlotPreview called for slot: {slot.name}");
// Hide backdrop
if (cardEnlargedBackdrop != null)
{
cardEnlargedBackdrop.SetActive(false);
}
// Shrink preview card
Vector3 originalScale = previewCardTransform.localScale / 2.5f; // Assuming 2.5x is enlarged scale
Pixelplacement.Tween.LocalScale(previewCardTransform, originalScale, 0.3f, 0f, Pixelplacement.Tween.EaseInBack,
completeCallback: () => onComplete?.Invoke());
}
#endregion
}
}

View File

@@ -70,16 +70,13 @@ namespace UI.CardSystem
}
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
// Unsubscribe from CardSystemManager events to prevent memory leaks
if (CardSystemManager.Instance != null)
{
CardSystemManager.Instance.OnBoosterCountChanged -= OnBoosterCountChanged;
}
// Call base implementation
base.OnDestroy();
}
/// <summary>

View File

@@ -10,6 +10,7 @@ using UI.CardSystem.DragDrop;
using UI.DragAndDrop.Core;
using Unity.Cinemachine;
using UnityEngine;
using UnityEngine.Serialization;
using UnityEngine.UI;
namespace UI.CardSystem
@@ -30,8 +31,11 @@ namespace UI.CardSystem
[Header("Card Display")]
[SerializeField] private Transform cardDisplayContainer;
[SerializeField] private GameObject flippableCardPrefab; // Placeholder for card backs
[FormerlySerializedAs("flippableCardPrefab")]
[SerializeField] private GameObject cardPrefab; // New Card prefab using state machine
[SerializeField] private float cardSpacing = 150f;
[SerializeField] private float cardWidth = 400f;
[SerializeField] private float cardHeight = 540f;
[Header("Settings")]
[SerializeField] private float boosterDisappearDuration = 0.5f;
@@ -44,12 +48,12 @@ namespace UI.CardSystem
private BoosterPackDraggable _currentBoosterInCenter;
private List<BoosterPackDraggable> _activeBoostersInSlots = new List<BoosterPackDraggable>();
private List<GameObject> _currentRevealedCards = new List<GameObject>();
private List<StateMachine.Card> _currentCards = new List<StateMachine.Card>();
private CardData[] _currentCardData;
private int _revealedCardCount;
private int _cardsCompletedInteraction; // Track how many cards finished their new/repeat interaction
private StateMachine.Card _activeCard; // Currently selected/revealing card
private int _cardsCompletedInteraction; // Track how many cards finished their reveal flow
private bool _isProcessingOpening;
private const int MAX_VISIBLE_BOOSTERS = 3;
private FlippableCard _currentActiveCard; // The card currently awaiting interaction
private void Awake()
{
// Make sure we have a CanvasGroup for transitions
@@ -76,10 +80,8 @@ namespace UI.CardSystem
gameObject.SetActive(false);
}
protected override void OnDestroy()
internal override void OnManagedDestroy()
{
base.OnDestroy();
// Unsubscribe from dismiss button
if (_dismissButton != null)
{
@@ -516,8 +518,8 @@ namespace UI.CardSystem
// Update visible boosters (remove from end if we drop below thresholds)
UpdateVisibleBoosters();
// Show card backs
SpawnCardBacks(_currentCardData.Length);
// Show cards using new Card prefab
SpawnBoosterCards(_currentCardData);
// Wait for player to reveal all cards
bool isLastBooster = _availableBoosterCount <= 0;
@@ -526,10 +528,7 @@ namespace UI.CardSystem
// Check if this was the last booster pack
if (isLastBooster)
{
// Wait for all card animations to complete before transitioning
// WaitForCardReveals already includes: 0.5s wait + (cardCount * 0.5s stagger) + 0.5s animation + 0.5s final
// Total is: 1.5s + (cardCount * 0.5s)
// For 5 cards that's 4 seconds total, which should be enough
// See earlier comment for timing
Logging.Debug("[BoosterOpeningPage] Last booster opened, auto-transitioning to album main page");
if (UIPageController.Instance != null)
{
@@ -541,6 +540,122 @@ namespace UI.CardSystem
_isProcessingOpening = false;
}
/// <summary>
/// Spawn cards for booster opening flow using the new Card prefab and state machine.
/// </summary>
private void SpawnBoosterCards(CardData[] cards)
{
if (cardPrefab == null || cardDisplayContainer == null)
{
Logging.Warning("BoosterOpeningPage: Missing card prefab or container!");
return;
}
_currentRevealedCards.Clear();
_currentCards.Clear();
_cardsCompletedInteraction = 0;
_activeCard = null;
int count = cards.Length;
float totalWidth = (count - 1) * cardSpacing;
float startX = -totalWidth / 2f;
for (int i = 0; i < count; i++)
{
GameObject cardObj = Instantiate(cardPrefab, cardDisplayContainer);
RectTransform cardRect = cardObj.GetComponent<RectTransform>();
if (cardRect != null)
{
cardRect.anchoredPosition = new Vector2(startX + (i * cardSpacing), 0);
cardRect.sizeDelta = new Vector2(cardWidth, cardHeight); // Set card size
cardRect.localScale = Vector3.zero; // for pop-in
}
var card = cardObj.GetComponent<StateMachine.Card>();
var context = cardObj.GetComponent<StateMachine.CardContext>();
if (card != null && context != null)
{
// Setup card for booster reveal
// States will query CardSystemManager for current collection state as needed
context.SetupCard(cards[i]);
card.SetupForBoosterReveal(cards[i], false); // isNew parameter not used anymore
card.SetDraggingEnabled(false);
// Subscribe to CardDisplay click for selection
context.CardDisplay.OnCardClicked += (_) => OnCardClicked(card);
// Subscribe to reveal flow complete event
context.OnRevealFlowComplete += (ctx) => OnCardRevealComplete(card);
// Track the card
_currentCards.Add(card);
// Tween in
Tween.LocalScale(cardObj.transform, Vector3.one, 0.3f, i * 0.1f, Tween.EaseOutBack);
}
else
{
Logging.Warning($"[BoosterOpeningPage] Card component or context missing on spawned card {i}!");
}
_currentRevealedCards.Add(cardObj);
}
}
/// <summary>
/// Handle when a card is clicked - start reveal flow if conditions are met
/// </summary>
private void OnCardClicked(StateMachine.Card card)
{
// Only allow clicking idle cards when no other card is active
if (_activeCard == null && card.IsIdle && card.Context.IsClickable)
{
Logging.Debug($"[BoosterOpeningPage] Card {card.CardData?.Name} selected for reveal");
// Set as active and disable all other idle cards
_activeCard = card;
foreach (var otherCard in _currentCards)
{
if (otherCard != card && otherCard.IsIdle)
{
otherCard.Context.IsClickable = false;
}
}
// Click will route to IdleState automatically and trigger flip
}
}
/// <summary>
/// Handle when a card completes its reveal flow
/// </summary>
private void OnCardRevealComplete(StateMachine.Card card)
{
_cardsCompletedInteraction++;
Logging.Debug($"[BoosterOpeningPage] Card {card.CardData?.Name} reveal complete ({_cardsCompletedInteraction}/{_currentCardData.Length})");
// Add card to inventory NOW (after player saw it)
if (card.CardData != null)
{
Data.CardSystem.CardSystemManager.Instance.AddCardToInventoryDelayed(card.CardData);
}
// Clear active card and re-enable remaining idle cards
if (_activeCard == card)
{
_activeCard = null;
foreach (var otherCard in _currentCards)
{
if (otherCard.IsIdle)
{
otherCard.Context.IsClickable = true;
}
}
}
}
/// <summary>
/// Animate the booster pack disappearing
/// </summary>
@@ -571,249 +686,19 @@ namespace UI.CardSystem
}
/// <summary>
/// Spawn card back placeholders for revealing
/// </summary>
private void SpawnCardBacks(int count)
{
if (flippableCardPrefab == null || cardDisplayContainer == null)
{
Logging.Warning("BoosterOpeningPage: Missing card prefab or container!");
return;
}
_currentRevealedCards.Clear();
_revealedCardCount = 0;
_cardsCompletedInteraction = 0; // Reset interaction count
// Calculate positions
float totalWidth = (count - 1) * cardSpacing;
float startX = -totalWidth / 2f;
for (int i = 0; i < count; i++)
{
GameObject cardObj = Instantiate(flippableCardPrefab, cardDisplayContainer);
RectTransform cardRect = cardObj.GetComponent<RectTransform>();
if (cardRect != null)
{
cardRect.anchoredPosition = new Vector2(startX + (i * cardSpacing), 0);
}
// Get FlippableCard component and setup the card data
FlippableCard flippableCard = cardObj.GetComponent<FlippableCard>();
if (flippableCard != null)
{
// Setup the card data (stored but not revealed yet)
flippableCard.SetupCard(_currentCardData[i]);
// Subscribe to flip started event (to disable other cards IMMEDIATELY)
int cardIndex = i; // Capture for closure
flippableCard.OnFlipStarted += OnCardFlipStarted;
// Subscribe to reveal event to track when flipped
flippableCard.OnCardRevealed += (card, data) => OnCardRevealed(cardIndex);
// Subscribe to inactive click event (for jiggle effect)
flippableCard.OnClickedWhileInactive += OnCardClickedWhileInactive;
// Initially, all cards are clickable (for flipping)
flippableCard.SetClickable(true);
}
else
{
Logging.Warning($"[BoosterOpeningPage] FlippableCard component not found on card {i}!");
}
_currentRevealedCards.Add(cardObj);
// Animate cards flying in
cardRect.localScale = Vector3.zero;
Tween.LocalScale(cardRect, Vector3.one, 0.3f, i * 0.1f, Tween.EaseOutBack);
}
}
/// <summary>
/// Handle when a card flip starts (disable all other cards IMMEDIATELY)
/// </summary>
private void OnCardFlipStarted(FlippableCard flippingCard)
{
Logging.Debug($"[BoosterOpeningPage] Card flip started, disabling all other cards.");
// Disable ALL cards immediately to prevent multi-flip
foreach (GameObject cardObj in _currentRevealedCards)
{
FlippableCard card = cardObj.GetComponent<FlippableCard>();
if (card != null)
{
card.SetClickable(false);
}
}
}
/// <summary>
/// Handle card reveal (when flipped)
/// </summary>
private void OnCardRevealed(int cardIndex)
{
Logging.Debug($"[BoosterOpeningPage] Card {cardIndex} revealed!");
_revealedCardCount++;
// Get the flippable card and card data
FlippableCard flippableCard = _currentRevealedCards[cardIndex].GetComponent<FlippableCard>();
if (flippableCard == null)
{
Logging.Warning($"[BoosterOpeningPage] FlippableCard not found for card {cardIndex}!");
return;
}
CardData cardData = flippableCard.CardData;
// Check if this is a new card using CardSystemManager
bool isNew = Data.CardSystem.CardSystemManager.Instance.IsCardNew(cardData, out CardData existingCard);
if (isNew)
{
Logging.Debug($"[BoosterOpeningPage] Card '{cardData.Name}' is NEW!");
flippableCard.ShowAsNew();
}
else
{
// Check if card is already Legendary - if so, skip progress bar and auto-progress
if (existingCard.Rarity == AppleHills.Data.CardSystem.CardRarity.Legendary)
{
Logging.Debug($"[BoosterOpeningPage] Card '{cardData.Name}' is LEGENDARY - auto-progressing!");
// Add to inventory immediately and move to next card
Data.CardSystem.CardSystemManager.Instance.AddCardToInventoryDelayed(cardData);
_cardsCompletedInteraction++;
_revealedCardCount++; // This was already incremented earlier, but we need to track completion
EnableUnrevealedCards();
return; // Skip showing the card enlarged
}
int ownedCount = existingCard.CopiesOwned;
Logging.Debug($"[BoosterOpeningPage] Card '{cardData.Name}' is a REPEAT! Owned: {ownedCount}");
// Check if this card will trigger an upgrade (ownedCount + 1 >= threshold)
bool willUpgrade = (ownedCount + 1) >= flippableCard.CardsToUpgrade && existingCard.Rarity < AppleHills.Data.CardSystem.CardRarity.Legendary;
if (willUpgrade)
{
Logging.Debug($"[BoosterOpeningPage] This card will trigger upgrade! ({ownedCount + 1}/{flippableCard.CardsToUpgrade})");
// Show as repeat - progress bar will fill and auto-trigger upgrade
flippableCard.ShowAsRepeatWithUpgrade(ownedCount, existingCard);
}
else
{
// Normal repeat, no upgrade
flippableCard.ShowAsRepeat(ownedCount);
}
}
// Set this card as the active one (only this card is clickable now)
SetActiveCard(flippableCard);
// Subscribe to tap event to know when interaction is complete
flippableCard.OnCardTappedAfterReveal += (card) => OnCardCompletedInteraction(card, cardIndex);
}
/// <summary>
/// Handle when a card's interaction is complete (tapped after reveal)
/// </summary>
private void OnCardCompletedInteraction(FlippableCard card, int cardIndex)
{
Logging.Debug($"[BoosterOpeningPage] Card {cardIndex} interaction complete!");
// Add card to inventory NOW (after player saw it)
Data.CardSystem.CardSystemManager.Instance.AddCardToInventoryDelayed(card.CardData);
// Return card to normal size
card.ReturnToNormalSize();
// Increment completed interaction count
_cardsCompletedInteraction++;
// Clear active card
_currentActiveCard = null;
// Re-enable all unrevealed cards (they can be flipped now)
EnableUnrevealedCards();
Logging.Debug($"[BoosterOpeningPage] Cards completed interaction: {_cardsCompletedInteraction}/{_currentCardData.Length}");
}
/// <summary>
/// Set which card is currently active (only this card can be clicked)
/// </summary>
private void SetActiveCard(FlippableCard activeCard)
{
_currentActiveCard = activeCard;
// Disable all other cards
foreach (GameObject cardObj in _currentRevealedCards)
{
FlippableCard card = cardObj.GetComponent<FlippableCard>();
if (card != null)
{
// Only the active card is clickable
card.SetClickable(card == activeCard);
}
}
Logging.Debug($"[BoosterOpeningPage] Set active card. Only one card is now clickable.");
}
/// <summary>
/// Re-enable all unrevealed cards (allow them to be flipped)
/// </summary>
private void EnableUnrevealedCards()
{
foreach (GameObject cardObj in _currentRevealedCards)
{
FlippableCard card = cardObj.GetComponent<FlippableCard>();
if (card != null && !card.IsFlipped)
{
card.SetClickable(true);
}
}
Logging.Debug($"[BoosterOpeningPage] Re-enabled unrevealed cards for flipping.");
}
/// <summary>
/// Handle when a card is clicked while not active (jiggle the active card)
/// </summary>
private void OnCardClickedWhileInactive(FlippableCard inactiveCard)
{
Logging.Debug($"[BoosterOpeningPage] Inactive card clicked, jiggling active card.");
if (_currentActiveCard != null)
{
_currentActiveCard.Jiggle();
}
}
/// <summary>
/// Wait until all cards are revealed AND all interactions are complete
/// Wait until all cards complete their reveal flow
/// </summary>
private IEnumerator WaitForCardReveals()
{
// Wait until all cards are flipped
while (_revealedCardCount < _currentCardData.Length)
{
yield return null;
}
Logging.Debug($"[BoosterOpeningPage] All cards revealed! Waiting for interactions...");
// Wait until all cards have completed their new/repeat interaction
// Wait until all cards have completed their reveal flow
while (_cardsCompletedInteraction < _currentCardData.Length)
{
yield return null;
}
Logging.Debug($"[BoosterOpeningPage] All interactions complete! Animating cards to album...");
Logging.Debug($"[BoosterOpeningPage] All cards revealed! Animating cards to album...");
// All cards revealed and interacted with, wait a moment
// Small pause
yield return new WaitForSeconds(0.5f);
// Show album icon before cards start tweening to it
@@ -831,28 +716,20 @@ namespace UI.CardSystem
{
if (cardObj != null)
{
// Stagger each card with 0.5s delay
float delay = cardIndex * 0.5f;
// Animate to album icon position, then destroy
// Use world space position tween for root transform
Tween.Position(cardObj.transform, targetPosition, 0.5f, delay, Tween.EaseInBack);
Tween.LocalScale(cardObj.transform, Vector3.zero, 0.5f, delay, Tween.EaseInBack,
completeCallback: () => Destroy(cardObj));
completeCallback: () => { if (cardObj != null) Destroy(cardObj); });
cardIndex++;
}
}
// Wait for all animations to complete
// Last card starts at: (cardCount - 1) * 0.5s delay
// Last card finishes at: (cardCount - 1) * 0.5s + 0.5s animation duration = cardCount * 0.5s
float totalAnimationTime = _currentCardData.Length * 0.5f;
_currentRevealedCards.Clear();
_currentCards.Clear();
yield return new WaitForSeconds(totalAnimationTime);
// Album icon stays visible for next booster (will be hidden when next booster is placed)
}
/// <summary>

View File

@@ -0,0 +1,23 @@
using UnityEngine;
using UnityEngine.UI;
namespace UI.CardSystem
{
/// <summary>
/// Simple component representing card back visuals; toggle visibility.
/// </summary>
public class CardBack : MonoBehaviour
{
[SerializeField] private Image backImage;
public void Show()
{
gameObject.SetActive(true);
}
public void Hide()
{
gameObject.SetActive(false);
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 37d815ba7b02481786cc1953678a3e8e
timeCreated: 1763322207

View File

@@ -37,10 +37,7 @@ namespace UI.CardSystem
// Events
public event Action<CardDisplay> OnCardClicked;
// Preview mode tracking for click forwarding
private bool _isPreviewMode;
private AlbumCardSlot _previewSlot;
/// <summary>
/// Sets up the card display with the given card data
@@ -88,46 +85,7 @@ namespace UI.CardSystem
Logging.Debug($"[CardDisplay] Updated visuals for card: {cardData.Name} (Rarity: {cardData.Rarity}, Zone: {cardData.Zone})");
}
/// <summary>
/// Apply preview visuals - black tint to card image and question marks for name
/// Used for empty slot previews to show locked/unknown cards
/// </summary>
public void SetPreviewVisuals()
{
// Set card name to question marks
if (cardNameText != null)
{
cardNameText.text = "??????";
}
// Apply black non-opaque tint to card image
if (cardImage != null)
{
cardImage.color = Color.black;
}
Logging.Debug($"[CardDisplay] Applied preview visuals (black tint and ?????? name)");
}
/// <summary>
/// Reset preview visuals back to normal
/// </summary>
public void ClearPreviewVisuals()
{
// Restore normal card name
if (cardData != null && cardNameText != null)
{
cardNameText.text = cardData.Name ?? "Unknown Card";
}
// Reset card image color to white (normal)
if (cardImage != null)
{
cardImage.color = Color.white;
}
Logging.Debug($"[CardDisplay] Cleared preview visuals");
}
/// <summary>
/// Updates the card name text
@@ -281,50 +239,11 @@ namespace UI.CardSystem
}
/// <summary>
/// Enable preview mode - when clicked, forwards click to the associated slot
/// </summary>
public void SetPreviewMode(bool isEnabled, AlbumCardSlot slot = null)
{
_isPreviewMode = isEnabled;
_previewSlot = slot;
// Enable raycast targets on images so this CardDisplay can receive clicks
if (cardImage != null) cardImage.raycastTarget = isEnabled;
if (frameImage != null) frameImage.raycastTarget = isEnabled;
if (overlayImage != null) overlayImage.raycastTarget = isEnabled;
if (backgroundImage != null) backgroundImage.raycastTarget = isEnabled;
if (zoneShapeImage != null) zoneShapeImage.raycastTarget = isEnabled;
Logging.Debug($"[CardDisplay] Preview mode {(isEnabled ? "enabled" : "disabled")}, slot: {(slot != null ? slot.name : "NULL")}");
}
/// <summary>
/// Handle click on CardDisplay - forward to preview slot if in preview mode
/// Handle pointer click - simply emit the click event
/// </summary>
public void OnPointerClick(PointerEventData eventData)
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] OnPointerClick on {name}, _isPreviewMode={_isPreviewMode}, _previewSlot={((_previewSlot != null) ? _previewSlot.name : "NULL")}");
if (_isPreviewMode && _previewSlot != null)
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - In preview mode, calling DismissPreview on slot: {_previewSlot.name}");
_previewSlot.DismissPreview();
}
else
{
// Not in preview mode - forward click to parent AlbumCard (if it exists)
AlbumCard parentAlbumCard = GetComponentInParent<AlbumCard>();
if (parentAlbumCard != null)
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - Forwarding click to parent AlbumCard");
parentAlbumCard.OnPointerClick(eventData);
}
else
{
Logging.Debug($"[CLICK-TRACE-CARDDISPLAY] {name} - No parent AlbumCard, firing OnCardClicked event");
OnCardClicked?.Invoke(this);
}
}
OnCardClicked?.Invoke(this);
}
#if UNITY_EDITOR

View File

@@ -1,252 +0,0 @@
using System;
using System.Collections;
using AppleHills.Data.CardSystem;
using Core;
using Data.CardSystem;
using Pixelplacement;
using UI.DragAndDrop.Core;
using UnityEngine;
namespace UI.CardSystem
{
/// <summary>
/// Draggable card for album reveal system.
/// Handles both tap and drag-hold interactions for revealing cards.
/// Auto-snaps to matching album slot on release/tap.
/// </summary>
public class AlbumCardPlacementDraggable : DraggableObject
{
[Header("Album Card Settings")]
[SerializeField] private FlippableCard flippableCard;
[SerializeField] private float holdRevealDelay = 0.1f;
private CardData _cardData;
private bool _isRevealed = false;
private bool _isDragRevealing = false;
private bool _waitingForPlacementTap = false;
private Coroutine _holdRevealCoroutine;
private bool _isHolding = false; // Track if pointer is currently down
// Events
public event Action<AlbumCardPlacementDraggable, CardData> OnCardRevealed;
public event Action<AlbumCardPlacementDraggable, CardData> OnCardPlacedInAlbum;
public CardData CardData => _cardData;
public bool IsRevealed => _isRevealed;
public CardZone Zone => _cardData?.Zone ?? CardZone.AppleHills;
protected override void Initialize()
{
base.Initialize();
// Auto-find FlippableCard if not assigned
if (flippableCard == null)
{
flippableCard = GetComponent<FlippableCard>();
}
}
/// <summary>
/// Setup the card data (stores it but doesn't reveal until tapped/dragged)
/// </summary>
public void SetupCard(CardData data)
{
_cardData = data;
if (flippableCard != null)
{
flippableCard.SetupCard(data);
}
}
/// <summary>
/// Reveal the card (flip to show front)
/// </summary>
public void RevealCard()
{
if (_isRevealed)
{
return;
}
_isRevealed = true;
if (flippableCard != null)
{
flippableCard.FlipToReveal();
}
OnCardRevealed?.Invoke(this, _cardData);
}
/// <summary>
/// Snap to the matching album slot
/// </summary>
public void SnapToAlbumSlot()
{
if (_cardData == null)
{
Logging.Warning("[AlbumCardPlacementDraggable] Cannot snap to slot - no card data assigned.");
return;
}
// Find all album card slots in the scene
AlbumCardSlot[] allSlots = FindObjectsByType<AlbumCardSlot>(FindObjectsSortMode.None);
AlbumCardSlot matchingSlot = null;
foreach (var slot in allSlots)
{
if (slot.CanAcceptCard(_cardData))
{
matchingSlot = slot;
break;
}
}
if (matchingSlot != null)
{
SetDraggingEnabled(false);
// NEW FLOW: Extract AlbumCard FIRST, then tween it
if (flippableCard != null)
{
AlbumCard extractedCard = flippableCard.ExtractAlbumCard(matchingSlot.transform);
if (extractedCard != null)
{
// Notify slot that card was placed
matchingSlot.OnCardPlaced(extractedCard);
// NOW tween the extracted AlbumCard into position
TweenExtractedCardToSlot(extractedCard, () =>
{
// After animation completes
Logging.Debug($"[AlbumCardPlacementDraggable] Card placement animation complete for {_cardData.Name}");
// Notify that card was placed
OnCardPlacedInAlbum?.Invoke(this, _cardData);
// Destroy this wrapper (the AlbumPlacementCard)
Destroy(gameObject);
});
}
else
{
Logging.Warning("[AlbumCardPlacementDraggable] Failed to extract AlbumCard from wrapper!");
}
}
}
else
{
Logging.Warning($"[AlbumCardPlacementDraggable] Could not find matching slot for card '{_cardData.Name}' (Zone: {_cardData.Zone}, Index: {_cardData.CollectionIndex})");
}
}
/// <summary>
/// Tween the extracted AlbumCard into its slot position
/// Tweens from current size to slot size - AspectRatioFitter handles width
/// </summary>
private void TweenExtractedCardToSlot(AlbumCard card, System.Action onComplete)
{
Transform cardTransform = card.transform;
RectTransform cardRect = cardTransform as RectTransform;
if (cardRect != null)
{
// Get target height from slot
RectTransform slotRect = cardTransform.parent as RectTransform;
float targetHeight = slotRect != null ? slotRect.rect.height : cardRect.sizeDelta.y;
// Tween from current size to target size (AspectRatioFitter will adjust width)
Vector2 targetSize = new Vector2(cardRect.sizeDelta.x, targetHeight);
Tween.Size(cardRect, targetSize, snapDuration, 0f, Tween.EaseOutBack);
// Tween position and rotation to slot center
Tween.LocalPosition(cardRect, Vector3.zero, snapDuration, 0f, Tween.EaseOutBack);
Tween.LocalRotation(cardTransform, Quaternion.identity, snapDuration, 0f, Tween.EaseOutBack,
completeCallback: () =>
{
Logging.Debug($"[AlbumCardPlacementDraggable] Tween complete for extracted card {card.name}, final height: {cardRect.sizeDelta.y}");
onComplete?.Invoke();
});
}
else
{
// No RectTransform, just reset and call callback
cardTransform.localPosition = Vector3.zero;
cardTransform.localRotation = Quaternion.identity;
onComplete?.Invoke();
}
}
protected override void OnPointerDownHook()
{
base.OnPointerDownHook();
_isHolding = true;
// Start hold-reveal timer if card not yet revealed
if (!_isRevealed && _holdRevealCoroutine == null)
{
_holdRevealCoroutine = StartCoroutine(HoldRevealTimer());
}
}
protected override void OnPointerUpHook(bool longPress)
{
base.OnPointerUpHook(longPress);
_isHolding = false;
// Cancel hold timer if running
if (_holdRevealCoroutine != null)
{
StopCoroutine(_holdRevealCoroutine);
_holdRevealCoroutine = null;
}
else
{
}
// Handle tap (not dragged)
if (!_wasDragged)
{
if (!_isRevealed)
{
// First tap: reveal the card
RevealCard();
_waitingForPlacementTap = true;
}
else if (_waitingForPlacementTap)
{
// Second tap: snap to slot
_waitingForPlacementTap = false;
SnapToAlbumSlot();
}
else
{
}
}
else if (_isDragRevealing)
{
// Was drag-revealed, auto-snap on release
_isDragRevealing = false;
SnapToAlbumSlot();
}
}
/// <summary>
/// Coroutine to reveal card after holding for specified duration
/// </summary>
private IEnumerator HoldRevealTimer()
{
yield return new WaitForSeconds(holdRevealDelay);
// If still holding after delay, reveal the card
if (!_isRevealed && _isHolding)
{
RevealCard();
_isDragRevealing = true;
}
_holdRevealCoroutine = null;
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 706803638ea24880bae19c87d3851ce6
timeCreated: 1762470947

View File

@@ -3,7 +3,6 @@ using Core;
using Data.CardSystem;
using UI.DragAndDrop.Core;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UI.CardSystem
{
@@ -11,131 +10,21 @@ namespace UI.CardSystem
/// Specialized slot for album pages that only accepts a specific card.
/// Validates cards based on their CardDefinition.
/// Self-populates with owned cards when enabled.
/// Shows preview of target card when empty slot is tapped.
/// </summary>
public class AlbumCardSlot : DraggableSlot, IPointerClickHandler
public class AlbumCardSlot : DraggableSlot
{
[Header("Album Slot Configuration")]
[SerializeField] private CardDefinition targetCardDefinition; // Which card this slot accepts
[SerializeField] private GameObject albumCardPrefab; // Prefab to spawn when card is owned
[SerializeField] private GameObject cardPrefab; // Card prefab to spawn when card is owned
[Header("Preview Card (for empty slots)")]
[SerializeField] private CardDisplay previewCardDisplay; // Nested CardDisplay showing greyed-out preview
[SerializeField] private float previewEnlargedScale = 2.5f;
[SerializeField] private float previewScaleDuration = 0.3f;
private bool _isOccupiedPermanently = false;
private AlbumCard _placedCard;
private bool _isPreviewShowing = false;
private Vector3 _previewOriginalScale;
private void Awake()
{
// Store original scale of preview card
if (previewCardDisplay != null)
{
_previewOriginalScale = previewCardDisplay.transform.localScale;
// Hide preview card by default
previewCardDisplay.gameObject.SetActive(false);
}
}
/// <summary>
/// Set the target card this slot should accept
/// </summary>
public void SetTargetCard(CardDefinition definition)
{
targetCardDefinition = definition;
}
/// <summary>
/// Check if this slot can accept a specific card
/// </summary>
public bool CanAcceptCard(CardData cardData)
{
if (cardData == null || targetCardDefinition == null) return false;
if (_isOccupiedPermanently) return false;
// Card must match this slot's target definition
return cardData.DefinitionId == targetCardDefinition.Id;
}
/// <summary>
/// Called when a card is successfully placed in this slot
/// </summary>
public void OnCardPlaced(AlbumCard albumCard = null)
{
_isOccupiedPermanently = true;
if (albumCard != null)
{
_placedCard = albumCard;
albumCard.SetParentSlot(this);
// Register with AlbumViewPage for enlarge/shrink handling
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
if (albumPage != null)
{
albumPage.RegisterAlbumCard(albumCard);
}
}
}
/// <summary>
/// Check if this slot has a placed card
/// </summary>
public bool HasPlacedCard()
{
return _placedCard != null;
}
/// <summary>
/// Get the placed card (if any)
/// </summary>
public AlbumCard GetPlacedCard()
{
return _placedCard;
}
private StateMachine.Card _placedCard;
private void OnEnable()
{
// Check if we should spawn a card for this slot
CheckAndSpawnOwnedCard();
// Setup preview card display if slot is empty
SetupPreviewCard();
}
/// <summary>
/// Setup the preview card display to show target card with preview visuals
/// Preview stays hidden until user taps to show it
/// </summary>
private void SetupPreviewCard()
{
if (previewCardDisplay == null || targetCardDefinition == null)
return;
// Only setup preview if slot is empty
if (_isOccupiedPermanently || _placedCard != null)
{
// Hide preview if slot is occupied
previewCardDisplay.gameObject.SetActive(false);
return;
}
// Setup preview card data
CardData previewData = targetCardDefinition.CreateCardData();
previewData.Rarity = CardRarity.Normal; // Show as normal rarity
previewCardDisplay.SetupCard(previewData);
// Apply preview visuals (black tint and ?????? name)
previewCardDisplay.SetPreviewVisuals();
// Keep preview hidden - it'll show when user taps to enlarge
previewCardDisplay.gameObject.SetActive(false);
Logging.Debug($"[AlbumCardSlot] Setup preview card for {targetCardDefinition.Name} (hidden until tap)");
}
/// <summary>
/// Check if player owns the card for this slot and spawn it if so
@@ -147,13 +36,13 @@ namespace UI.CardSystem
return;
// Guard: don't spawn if already occupied
if (_isOccupiedPermanently || _placedCard != null)
if (_placedCard != null)
return;
// Guard: need prefab to spawn
if (albumCardPrefab == null)
if (cardPrefab == null)
{
Logging.Warning($"[AlbumCardSlot] No albumCardPrefab assigned for slot targeting {targetCardDefinition.name}");
Logging.Warning($"[AlbumCardSlot] No cardPrefab assigned for slot targeting {targetCardDefinition.name}");
return;
}
@@ -174,27 +63,26 @@ namespace UI.CardSystem
// Spawn card if owned
if (ownedCard != null)
{
SpawnAlbumCard(ownedCard);
SpawnCard(ownedCard);
}
}
/// <summary>
/// Spawn an AlbumCard in this slot
/// Spawn a Card in this slot using the PlacedInSlotState
/// </summary>
private void SpawnAlbumCard(CardData cardData)
private void SpawnCard(CardData cardData)
{
GameObject cardObj = Instantiate(albumCardPrefab, transform);
AlbumCard albumCard = cardObj.GetComponent<AlbumCard>();
GameObject cardObj = Instantiate(cardPrefab, transform);
var card = cardObj.GetComponent<StateMachine.Card>();
if (albumCard != null)
if (card != null)
{
albumCard.SetupCard(cardData);
albumCard.SetParentSlot(this);
_placedCard = albumCard;
_isOccupiedPermanently = true;
// Setup card for album slot (starts in PlacedInSlotState)
card.SetupForAlbumSlot(cardData, this);
_placedCard = card;
// Resize the card to match the slot size (same as placed cards)
RectTransform cardRect = albumCard.transform as RectTransform;
// Resize the card to match the slot size
RectTransform cardRect = card.transform as RectTransform;
RectTransform slotRect = transform as RectTransform;
if (cardRect != null && slotRect != null)
{
@@ -211,156 +99,22 @@ namespace UI.CardSystem
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
if (albumPage != null)
{
albumPage.RegisterAlbumCard(albumCard);
albumPage.RegisterCardInAlbum(card);
}
Logging.Debug($"[AlbumCardSlot] Spawned owned card '{cardData.Name}' ({cardData.Rarity}) in slot");
}
else
{
Logging.Warning($"[AlbumCardSlot] Spawned prefab has no AlbumCard component!");
Logging.Warning($"[AlbumCardSlot] Spawned prefab has no Card component!");
Destroy(cardObj);
}
}
/// <summary>
/// Get the target card definition for this slot
/// </summary>
public CardDefinition GetTargetCardDefinition()
{
return targetCardDefinition;
}
/// <summary>
/// Handle click on slot - show/hide preview if empty
/// </summary>
public void OnPointerClick(PointerEventData eventData)
{
Logging.Debug($"[CLICK-TRACE-SLOT] OnPointerClick on {name}, _isOccupiedPermanently={_isOccupiedPermanently}, _placedCard={((_placedCard != null) ? _placedCard.name : "NULL")}, _isPreviewShowing={_isPreviewShowing}, position={eventData.position}");
// Only handle clicks if slot is empty
if (_isOccupiedPermanently || _placedCard != null)
{
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - Slot is occupied, ignoring");
return;
}
// Only handle if we have a preview card setup
if (previewCardDisplay == null || targetCardDefinition == null)
{
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - No preview setup, ignoring");
return;
}
if (_isPreviewShowing)
{
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - Preview is showing, hiding it");
HidePreview();
}
else
{
Logging.Debug($"[CLICK-TRACE-SLOT] {name} - Preview is hidden, showing it");
ShowPreview();
}
}
/// <summary>
/// Show enlarged preview of target card
/// </summary>
private void ShowPreview()
{
if (_isPreviewShowing || previewCardDisplay == null)
return;
_isPreviewShowing = true;
// Show the preview card (already has preview visuals applied)
previewCardDisplay.gameObject.SetActive(true);
// Enable preview mode so clicks on CardDisplay forward to this slot
previewCardDisplay.SetPreviewMode(true, this);
// Reset to normal scale before enlarging
previewCardDisplay.transform.localScale = _previewOriginalScale;
// Get AlbumViewPage to show backdrop and reparent
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
if (albumPage != null)
{
albumPage.ShowSlotPreview(this, previewCardDisplay.transform);
}
// Scale up preview card
Pixelplacement.Tween.LocalScale(previewCardDisplay.transform, _previewOriginalScale * previewEnlargedScale,
previewScaleDuration, 0f, Pixelplacement.Tween.EaseOutBack);
Logging.Debug($"[AlbumCardSlot] Showing preview for {targetCardDefinition.Name}");
}
/// <summary>
/// Hide preview and return to normal
/// </summary>
private void HidePreview()
{
if (!_isPreviewShowing || previewCardDisplay == null)
return;
_isPreviewShowing = false;
// Disable preview mode on CardDisplay
previewCardDisplay.SetPreviewMode(false, null);
// Get AlbumViewPage to hide backdrop
AlbumViewPage albumPage = FindFirstObjectByType<AlbumViewPage>();
if (albumPage != null)
{
albumPage.HideSlotPreview(this, previewCardDisplay.transform, () =>
{
// After shrink completes, reparent back to slot
previewCardDisplay.transform.SetParent(transform, false);
// Reset RectTransform properties
RectTransform previewRect = previewCardDisplay.transform as RectTransform;
if (previewRect != null)
{
// Set anchors to stretch in all directions (matching original setup)
previewRect.anchorMin = Vector2.zero; // (0, 0)
previewRect.anchorMax = Vector2.one; // (1, 1)
// Reset offsets to zero (left, right, top, bottom all = 0)
previewRect.offsetMin = Vector2.zero; // Sets left and bottom to 0
previewRect.offsetMax = Vector2.zero; // Sets right and top to 0 (note: these are negative values internally)
previewRect.pivot = new Vector2(0.5f, 0.5f);
}
previewCardDisplay.transform.localPosition = Vector3.zero;
previewCardDisplay.transform.localRotation = Quaternion.identity;
previewCardDisplay.transform.localScale = _previewOriginalScale;
// Hide the preview card after returning to slot
previewCardDisplay.gameObject.SetActive(false);
Logging.Debug($"[AlbumCardSlot] Preview hidden and reset for {targetCardDefinition.Name}");
});
}
Logging.Debug($"[AlbumCardSlot] Hiding preview for {targetCardDefinition.Name}");
}
/// <summary>
/// Public method to dismiss preview - can be called by CardDisplay when clicked
/// </summary>
public void DismissPreview()
{
Logging.Debug($"[CLICK-TRACE-SLOT] DismissPreview called on {name}");
HidePreview();
}
/// <summary>
/// Get the target card definition for this slot
/// </summary>
public CardDefinition TargetCardDefinition => targetCardDefinition;
}
}

View File

@@ -307,7 +307,7 @@ namespace UI.CardSystem.DragDrop
}
#endregion
protected override void OnDestroy()
{
base.OnDestroy();

View File

@@ -1,62 +0,0 @@
using AppleHills.Data.CardSystem;
using UI.DragAndDrop.Core;
using UnityEngine;
namespace UI.CardSystem.DragDrop
{
/// <summary>
/// Card-specific implementation of DraggableObject.
/// Manages card data and card-specific drag behavior.
/// </summary>
public class CardDraggable : DraggableObject
{
[Header("Card Data")]
[SerializeField] private CardData cardData;
// Events
public event System.Action<CardDraggable, CardData> OnCardDataChanged;
public CardData CardData => cardData;
/// <summary>
/// Set the card data for this draggable card
/// </summary>
public void SetCardData(CardData data)
{
cardData = data;
OnCardDataChanged?.Invoke(this, cardData);
// Update visual if it exists
if (_visualInstance != null && _visualInstance is CardDraggableVisual cardVisual)
{
cardVisual.RefreshCardDisplay();
}
}
protected override void OnDragStartedHook()
{
base.OnDragStartedHook();
// Card-specific drag started behavior
}
protected override void OnDragEndedHook()
{
base.OnDragEndedHook();
// Card-specific drag ended behavior
}
protected override void OnSelectionChangedHook(bool selected)
{
base.OnSelectionChangedHook(selected);
// Card-specific selection behavior
}
protected override void OnSlotChangedHook(DraggableSlot previousSlot, DraggableSlot newSlot)
{
base.OnSlotChangedHook(previousSlot, newSlot);
// Card-specific slot changed behavior
// Could trigger events for card collection reordering, etc.
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 5a2741bb7299441b9f9bd44d746ebb4b
timeCreated: 1762420654

View File

@@ -1,121 +0,0 @@
using AppleHills.Data.CardSystem;
using UI.DragAndDrop.Core;
using UnityEngine;
namespace UI.CardSystem.DragDrop
{
/// <summary>
/// Visual representation for CardDraggable.
/// Uses the existing CardDisplay component to render the card.
/// </summary>
public class CardDraggableVisual : DraggableVisual
{
[Header("Card Visual Components")]
[SerializeField] private CardDisplay cardDisplay;
[SerializeField] private Transform shadowTransform;
[SerializeField] private float shadowOffset = 20f;
private Vector3 _shadowInitialPosition;
private CardDraggable _cardDraggable;
public CardDisplay CardDisplay => cardDisplay;
public override void Initialize(DraggableObject parent)
{
base.Initialize(parent);
_cardDraggable = parent as CardDraggable;
// Get CardDisplay component if not assigned
if (cardDisplay == null)
{
cardDisplay = GetComponentInChildren<CardDisplay>();
}
// Initialize shadow
if (shadowTransform != null)
{
_shadowInitialPosition = shadowTransform.localPosition;
}
// Subscribe to card data changes
if (_cardDraggable != null)
{
_cardDraggable.OnCardDataChanged += HandleCardDataChanged;
// Initial card setup
if (_cardDraggable.CardData != null && cardDisplay != null)
{
cardDisplay.SetupCard(_cardDraggable.CardData);
}
}
}
protected override void UpdateVisualContent()
{
// CardDisplay handles its own rendering, no need to update every frame
// This is called every frame but we only update when card data changes
}
/// <summary>
/// Refresh the card display with current data
/// </summary>
public void RefreshCardDisplay()
{
if (cardDisplay != null && _cardDraggable != null && _cardDraggable.CardData != null)
{
cardDisplay.SetupCard(_cardDraggable.CardData);
}
}
private void HandleCardDataChanged(CardDraggable draggable, CardData data)
{
RefreshCardDisplay();
}
protected override void OnPointerDownVisual()
{
base.OnPointerDownVisual();
// Move shadow down when pressed
if (shadowTransform != null)
{
shadowTransform.localPosition = _shadowInitialPosition + (-Vector3.up * shadowOffset);
}
}
protected override void OnPointerUpVisual(bool longPress)
{
base.OnPointerUpVisual(longPress);
// Restore shadow position
if (shadowTransform != null)
{
shadowTransform.localPosition = _shadowInitialPosition;
}
}
protected override void OnDragStartedVisual()
{
base.OnDragStartedVisual();
// Card-specific visual effects when dragging starts
}
protected override void OnDragEndedVisual()
{
base.OnDragEndedVisual();
// Card-specific visual effects when dragging ends
}
protected override void OnDestroy()
{
base.OnDestroy();
if (_cardDraggable != null)
{
_cardDraggable.OnCardDataChanged -= HandleCardDataChanged;
}
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: 2a4c3884410d44f98182cd8119a972a4
timeCreated: 1762420668

View File

@@ -1,673 +0,0 @@
using System;
using AppleHills.Data.CardSystem;
using Core;
using Pixelplacement;
using Pixelplacement.TweenSystem;
using UnityEngine;
using UnityEngine.EventSystems;
namespace UI.CardSystem
{
/// <summary>
/// Flippable card wrapper that shows a card back, then flips to reveal the CardDisplay front.
/// This component nests an existing CardDisplay prefab to reuse card visuals everywhere.
/// </summary>
public class FlippableCard : MonoBehaviour, IPointerEnterHandler, IPointerExitHandler, IPointerClickHandler
{
[Header("Card References")]
[SerializeField] private GameObject cardBackObject; // The card back visual
[SerializeField] private GameObject cardFrontObject; // Your CardDisplay prefab instance
[SerializeField] private CardDisplay cardDisplay; // Reference to CardDisplay component
[SerializeField] private AlbumCard albumCard; // Reference to nested AlbumCard (for album placement flow)
[Header("Idle Hover Animation")]
[SerializeField] private bool enableIdleHover = true;
[SerializeField] private float idleHoverHeight = 10f;
[SerializeField] private float idleHoverDuration = 1.5f;
[SerializeField] private float hoverScaleMultiplier = 1.05f;
[Header("Flip Animation")]
[SerializeField] private float flipDuration = 0.6f;
[SerializeField] private float flipScalePunch = 1.1f;
[Header("New/Repeat Card Display")]
[SerializeField] private GameObject newCardText;
[SerializeField] private GameObject newCardIdleText;
[SerializeField] private GameObject repeatText;
[SerializeField] private GameObject progressBarContainer;
[SerializeField] private int cardsToUpgrade = 5;
[SerializeField] private float enlargedScale = 1.5f;
// State
private bool _isFlipped = false;
private bool _isFlipping = false;
private TweenBase _idleHoverTween;
private CardData _cardData;
private Vector2 _originalPosition; // Track original spawn position
private bool _isWaitingForTap = false; // Waiting for tap after reveal
private bool _isNew = false; // Is this a new card
private int _ownedCount = 0; // Owned count for repeat cards
private bool _isClickable = true; // Can this card be clicked
// Events
public event Action<FlippableCard, CardData> OnCardRevealed;
public event Action<FlippableCard> OnCardTappedAfterReveal;
public event Action<FlippableCard> OnClickedWhileInactive; // Fired when clicked but not clickable
public event Action<FlippableCard> OnFlipStarted; // Fired when flip animation begins
public bool IsFlipped => _isFlipped;
public CardData CardData => _cardData;
public int CardsToUpgrade => cardsToUpgrade; // Expose upgrade threshold
private void Awake()
{
// Auto-find CardDisplay if not assigned
if (cardDisplay == null && cardFrontObject != null)
{
cardDisplay = cardFrontObject.GetComponent<CardDisplay>();
}
// Auto-find AlbumCard if not assigned
if (albumCard == null)
{
albumCard = GetComponentInChildren<AlbumCard>();
}
// Card back: starts at 0° rotation (normal, facing camera, clickable)
// Card front: starts at 180° rotation (flipped away, will rotate to 0° when revealed)
if (cardBackObject != null)
{
cardBackObject.transform.localRotation = Quaternion.Euler(0, 0, 0);
cardBackObject.SetActive(true);
}
if (cardFrontObject != null)
{
cardFrontObject.transform.localRotation = Quaternion.Euler(0, 180, 0);
cardFrontObject.SetActive(false);
}
// Hide all new/repeat UI elements initially
if (newCardText != null)
newCardText.SetActive(false);
if (newCardIdleText != null)
newCardIdleText.SetActive(false);
if (repeatText != null)
repeatText.SetActive(false);
if (progressBarContainer != null)
progressBarContainer.SetActive(false);
}
private void Start()
{
// Save the original position so we can return to it after hover
RectTransform rectTransform = GetComponent<RectTransform>();
if (rectTransform != null)
{
_originalPosition = rectTransform.anchoredPosition;
}
// Start idle hover animation
if (enableIdleHover && !_isFlipped)
{
StartIdleHover();
}
}
/// <summary>
/// Setup the card data (stores it but doesn't reveal until flipped)
/// </summary>
public void SetupCard(CardData data)
{
_cardData = data;
// Setup the CardDisplay but keep it hidden
if (cardDisplay != null)
{
cardDisplay.SetupCard(data);
}
}
/// <summary>
/// Flip the card to reveal the front
/// </summary>
public void FlipToReveal()
{
if (_isFlipped || _isFlipping)
return;
_isFlipping = true;
// Fire flip started event IMMEDIATELY (before animations)
OnFlipStarted?.Invoke(this);
// Stop idle hover
StopIdleHover();
// Flip animation: Rotate the visual children (back from 0→90, front from 180→0)
// ...existing code...
// Card back: 0° → 90° (rotates away)
// Card front: 180° → 90° → 0° (rotates into view)
// Phase 1: Rotate both to 90 degrees (edge view)
if (cardBackObject != null)
{
Tween.LocalRotation(cardBackObject.transform, Quaternion.Euler(0, 90, 0), flipDuration * 0.5f, 0f, Tween.EaseInOut);
}
if (cardFrontObject != null)
{
Tween.LocalRotation(cardFrontObject.transform, Quaternion.Euler(0, 90, 0), flipDuration * 0.5f, 0f, Tween.EaseInOut,
completeCallback: () =>
{
// At edge (90°), switch visibility
if (cardBackObject != null)
cardBackObject.SetActive(false);
if (cardFrontObject != null)
cardFrontObject.SetActive(true);
// Phase 2: Rotate front from 90 to 0 (show at correct orientation)
Tween.LocalRotation(cardFrontObject.transform, Quaternion.Euler(0, 0, 0), flipDuration * 0.5f, 0f, Tween.EaseInOut,
completeCallback: () =>
{
_isFlipped = true;
_isFlipping = false;
// Fire revealed event
OnCardRevealed?.Invoke(this, _cardData);
});
});
}
// Scale punch during flip for extra juice
Vector3 originalScale = transform.localScale;
Tween.LocalScale(transform, originalScale * flipScalePunch, flipDuration * 0.5f, 0f, Tween.EaseOutBack,
completeCallback: () =>
{
Tween.LocalScale(transform, originalScale, flipDuration * 0.5f, 0f, Tween.EaseInBack);
});
}
/// <summary>
/// Start idle hover animation (gentle bobbing)
/// </summary>
private void StartIdleHover()
{
if (_idleHoverTween != null)
return;
RectTransform rectTransform = GetComponent<RectTransform>();
if (rectTransform == null)
return;
Vector2 originalPos = rectTransform.anchoredPosition;
Vector2 targetPos = originalPos + Vector2.up * idleHoverHeight;
_idleHoverTween = Tween.Value(0f, 1f,
(val) =>
{
if (rectTransform != null)
{
float t = Mathf.Sin(val * Mathf.PI * 2f) * 0.5f + 0.5f; // Smooth sine wave
rectTransform.anchoredPosition = Vector2.Lerp(originalPos, targetPos, t);
}
},
idleHoverDuration, 0f, Tween.EaseInOut, Tween.LoopType.Loop);
}
/// <summary>
/// Stop idle hover animation
/// </summary>
private void StopIdleHover()
{
if (_idleHoverTween != null)
{
_idleHoverTween.Stop();
_idleHoverTween = null;
// Reset to ORIGINAL position (not Vector2.zero!)
RectTransform rectTransform = GetComponent<RectTransform>();
if (rectTransform != null)
{
Tween.AnchoredPosition(rectTransform, _originalPosition, 0.3f, 0f, Tween.EaseOutBack);
}
}
}
#region Pointer Event Handlers
public void OnPointerEnter(PointerEventData eventData)
{
if (_isFlipped || _isFlipping)
return;
// Scale up slightly on hover
Tween.LocalScale(transform, Vector3.one * hoverScaleMultiplier, 0.2f, 0f, Tween.EaseOutBack);
}
public void OnPointerExit(PointerEventData eventData)
{
if (_isFlipped || _isFlipping)
return;
// Scale back to normal
Tween.LocalScale(transform, Vector3.one, 0.2f, 0f, Tween.EaseOutBack);
}
public void OnPointerClick(PointerEventData eventData)
{
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] OnPointerClick on {name}, _isClickable={_isClickable}, _isWaitingForTap={_isWaitingForTap}, _isFlipped={_isFlipped}, position={eventData.position}");
// If not clickable, notify and return
if (!_isClickable)
{
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Not clickable, firing OnClickedWhileInactive");
OnClickedWhileInactive?.Invoke(this);
return;
}
// If waiting for tap after reveal, handle that
if (_isWaitingForTap)
{
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Waiting for tap, dismissing enlarged state");
OnCardTappedAfterReveal?.Invoke(this);
_isWaitingForTap = false;
return;
}
if (_isFlipped || _isFlipping)
{
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Ignoring click (flipped={_isFlipped}, flipping={_isFlipping})");
return;
}
Logging.Debug($"[CLICK-TRACE-FLIPPABLE] {name} - Processing click, starting flip");
// Flip on click
FlipToReveal();
}
#endregion
#region New/Repeat Card Display
/// <summary>
/// Show this card as a new card (enlarge, show "NEW CARD" text, wait for tap)
/// </summary>
public void ShowAsNew()
{
_isNew = true;
_isWaitingForTap = true;
// Show new card text
if (newCardText != null)
newCardText.SetActive(true);
// Enlarge the card
EnlargeCard();
}
/// <summary>
/// Show this card as a repeat that will trigger an upgrade (enlarge, show progress, auto-transition to upgrade)
/// </summary>
/// <param name="ownedCount">Number of copies owned BEFORE this one</param>
/// <param name="lowerRarityCard">The existing card data at lower rarity (for upgrade reference)</param>
public void ShowAsRepeatWithUpgrade(int ownedCount, AppleHills.Data.CardSystem.CardData lowerRarityCard)
{
_isNew = false;
_ownedCount = ownedCount;
_isWaitingForTap = false; // Don't wait yet - upgrade will happen automatically
// Show repeat text
if (repeatText != null)
repeatText.SetActive(true);
// Enlarge the card
EnlargeCard();
// Show progress bar with owned count, then auto-trigger upgrade
ShowProgressBar(ownedCount, () =>
{
// Progress animation complete - trigger upgrade!
TriggerUpgradeTransition(lowerRarityCard);
});
}
/// <summary>
/// Trigger the upgrade transition (called after progress bar fills)
/// </summary>
private void TriggerUpgradeTransition(AppleHills.Data.CardSystem.CardData lowerRarityCard)
{
Logging.Debug($"[FlippableCard] Triggering upgrade transition from {lowerRarityCard.Rarity}!");
AppleHills.Data.CardSystem.CardRarity oldRarity = lowerRarityCard.Rarity;
AppleHills.Data.CardSystem.CardRarity newRarity = oldRarity + 1;
// Reset the lower rarity count to 0
lowerRarityCard.CopiesOwned = 0;
// Create upgraded card data
AppleHills.Data.CardSystem.CardData upgradedCardData = new AppleHills.Data.CardSystem.CardData(_cardData);
upgradedCardData.Rarity = newRarity;
upgradedCardData.CopiesOwned = 1;
// Check if we already have this card at the higher rarity
bool isNewAtHigherRarity = Data.CardSystem.CardSystemManager.Instance.IsCardNew(upgradedCardData, out AppleHills.Data.CardSystem.CardData existingHigherRarity);
// Add the higher rarity card to inventory
Data.CardSystem.CardSystemManager.Instance.GetCardInventory().AddCard(upgradedCardData);
// Update our displayed card data
_cardData.Rarity = newRarity;
// Transition to appropriate display
if (isNewAtHigherRarity || newRarity == AppleHills.Data.CardSystem.CardRarity.Legendary)
{
// Show as NEW at higher rarity
TransitionToNewCardView(newRarity);
}
else
{
// Show progress for higher rarity, then transition to NEW
int ownedAtHigherRarity = existingHigherRarity.CopiesOwned;
ShowProgressBar(ownedAtHigherRarity, () =>
{
TransitionToNewCardView(newRarity);
});
}
}
/// <summary>
/// Show this card as a repeat (enlarge, show progress bar, wait for tap)
/// </summary>
/// <param name="ownedCount">Number of copies owned BEFORE this one</param>
public void ShowAsRepeat(int ownedCount)
{
_isNew = false;
_ownedCount = ownedCount;
_isWaitingForTap = true;
// Show repeat text
if (repeatText != null)
repeatText.SetActive(true);
// Enlarge the card
EnlargeCard();
// Show progress bar with owned count, then blink new element
ShowProgressBar(ownedCount, () =>
{
// Progress animation complete
});
}
/// <summary>
/// Show this card as upgraded (hide progress bar, show as new with upgraded rarity)
/// </summary>
public void ShowAsUpgraded(AppleHills.Data.CardSystem.CardRarity oldRarity, AppleHills.Data.CardSystem.CardRarity newRarity)
{
_isNew = true;
_isWaitingForTap = true;
// Update the CardDisplay to show new rarity
if (cardDisplay != null && _cardData != null)
{
_cardData.Rarity = newRarity;
cardDisplay.SetupCard(_cardData);
}
// Hide progress bar and repeat text
if (progressBarContainer != null)
progressBarContainer.SetActive(false);
if (repeatText != null)
repeatText.SetActive(false);
// Show new card text (it's now a "new" card at the higher rarity)
if (newCardText != null)
newCardText.SetActive(true);
Logging.Debug($"[FlippableCard] Card upgraded from {oldRarity} to {newRarity}! Showing as NEW.");
// Card is already enlarged from the repeat display, so no need to enlarge again
}
/// <summary>
/// Show this card as upgraded with progress bar (already have copies at higher rarity)
/// </summary>
public void ShowAsUpgradedWithProgress(AppleHills.Data.CardSystem.CardRarity oldRarity, AppleHills.Data.CardSystem.CardRarity newRarity, int ownedAtNewRarity)
{
_isNew = false;
_isWaitingForTap = false; // Don't wait for tap yet, progress bar will complete first
// Hide new card text
if (newCardText != null)
newCardText.SetActive(false);
// Show repeat text (it's a repeat at the new rarity)
if (repeatText != null)
repeatText.SetActive(true);
// Show progress bar for the new rarity
ShowProgressBar(ownedAtNewRarity, () =>
{
// Progress animation complete - now transition to "NEW CARD" view
TransitionToNewCardView(newRarity);
});
Logging.Debug($"[FlippableCard] Card upgraded from {oldRarity} to {newRarity}! Showing progress {ownedAtNewRarity}/5");
}
/// <summary>
/// Transition to "NEW CARD" view after upgrade progress completes
/// </summary>
private void TransitionToNewCardView(AppleHills.Data.CardSystem.CardRarity newRarity)
{
Logging.Debug($"[FlippableCard] Transitioning to NEW CARD view at {newRarity} rarity");
// Update the CardDisplay to show new rarity
if (cardDisplay != null && _cardData != null)
{
_cardData.Rarity = newRarity;
cardDisplay.SetupCard(_cardData);
}
// Hide progress bar and repeat text
if (progressBarContainer != null)
progressBarContainer.SetActive(false);
if (repeatText != null)
repeatText.SetActive(false);
// Show "NEW CARD" text
if (newCardText != null)
newCardText.SetActive(true);
// Now wait for tap
_isNew = true;
_isWaitingForTap = true;
Logging.Debug($"[FlippableCard] Now showing as NEW CARD at {newRarity}, waiting for tap");
}
/// <summary>
/// Enlarge the card
/// </summary>
private void EnlargeCard()
{
Tween.LocalScale(transform, Vector3.one * enlargedScale, 0.3f, 0f, Tween.EaseOutBack);
}
/// <summary>
/// Return card to normal size
/// </summary>
public void ReturnToNormalSize()
{
Tween.LocalScale(transform, Vector3.one, 0.3f, 0f, Tween.EaseOutBack, completeCallback: () =>
{
// After returning to normal, hide new card text, show idle text
if (_isNew)
{
if (newCardText != null)
newCardText.SetActive(false);
if (newCardIdleText != null)
newCardIdleText.SetActive(true);
}
// Keep repeat text visible
});
}
/// <summary>
/// Show progress bar with owned count, then blink the new element
/// </summary>
private void ShowProgressBar(int ownedCount, System.Action onComplete)
{
if (progressBarContainer == null)
{
onComplete?.Invoke();
return;
}
progressBarContainer.SetActive(true);
// Get all child Image components
UnityEngine.UI.Image[] progressElements = progressBarContainer.GetComponentsInChildren<UnityEngine.UI.Image>(true);
// Check if we have the required number of elements (should match cardsToUpgrade)
if (progressElements.Length < cardsToUpgrade)
{
Logging.Warning($"[FlippableCard] Not enough Image components in progress bar! Expected {cardsToUpgrade}, found {progressElements.Length}");
onComplete?.Invoke();
return;
}
// Disable all elements first
foreach (var img in progressElements)
{
img.enabled = false;
}
// Show owned count (from the END, going backwards)
// E.g., if owned 3 cards, enable elements at index [4], [3], [2] (last 3 elements)
int startIndex = Mathf.Max(0, cardsToUpgrade - ownedCount);
for (int i = startIndex; i < cardsToUpgrade && i < progressElements.Length; i++)
{
progressElements[i].enabled = true;
}
// Wait a moment, then blink the new element
// New element is at index (cardsToUpgrade - ownedCount - 1)
int newElementIndex = Mathf.Max(0, cardsToUpgrade - ownedCount - 1);
if (newElementIndex >= 0 && newElementIndex < progressElements.Length)
{
Tween.Value(0f, 1f, (val) => { }, 0.3f, 0f, completeCallback: () =>
{
BlinkProgressElement(newElementIndex, progressElements, onComplete);
});
}
else
{
onComplete?.Invoke();
}
}
/// <summary>
/// Blink a progress element (enable/disable rapidly)
/// </summary>
private void BlinkProgressElement(int index, UnityEngine.UI.Image[] elements, System.Action onComplete)
{
if (index < 0 || index >= elements.Length)
{
onComplete?.Invoke();
return;
}
UnityEngine.UI.Image element = elements[index];
int blinkCount = 0;
const int maxBlinks = 3;
void Blink()
{
element.enabled = !element.enabled;
blinkCount++;
if (blinkCount >= maxBlinks * 2)
{
element.enabled = true; // End on enabled
onComplete?.Invoke();
}
else
{
Tween.Value(0f, 1f, (val) => { }, 0.15f, 0f, completeCallback: Blink);
}
}
Blink();
}
/// <summary>
/// Enable or disable clickability of this card
/// </summary>
public void SetClickable(bool clickable)
{
_isClickable = clickable;
}
/// <summary>
/// Jiggle the card (shake animation)
/// </summary>
public void Jiggle()
{
// Quick shake animation - rotate left, then right, then center
Transform cardTransform = transform;
Quaternion originalRotation = cardTransform.localRotation;
// Shake sequence: 0 -> -5 -> +5 -> 0
Tween.LocalRotation(cardTransform, Quaternion.Euler(0, 0, -5), 0.05f, 0f, Tween.EaseInOut,
completeCallback: () =>
{
Tween.LocalRotation(cardTransform, Quaternion.Euler(0, 0, 5), 0.1f, 0f, Tween.EaseInOut,
completeCallback: () =>
{
Tween.LocalRotation(cardTransform, originalRotation, 0.05f, 0f, Tween.EaseInOut);
});
});
}
/// <summary>
/// Extract the nested AlbumCard and reparent it to a new parent
/// Used when placing card in album slot - extracts the AlbumCard from this wrapper
/// The caller is responsible for tweening it to the final position
/// </summary>
/// <param name="newParent">The transform to reparent the AlbumCard to (typically the AlbumCardSlot)</param>
/// <returns>The extracted AlbumCard component, or null if not found</returns>
public AlbumCard ExtractAlbumCard(Transform newParent)
{
if (albumCard == null)
{
Logging.Warning("[FlippableCard] Cannot extract AlbumCard - none found!");
return null;
}
// Reparent AlbumCard to new parent (maintain world position temporarily)
// The caller will tween it to the final position
albumCard.transform.SetParent(newParent, true);
// Setup the card data on the AlbumCard
if (_cardData != null)
{
albumCard.SetupCard(_cardData);
}
Logging.Debug($"[FlippableCard] Extracted AlbumCard '{_cardData?.Name}' to {newParent.name} - ready for tween");
return albumCard;
}
#endregion
private void OnDestroy()
{
StopIdleHover();
}
}
}

View File

@@ -1,3 +0,0 @@
fileFormatVersion: 2
guid: ffa05ec4ecbd4cc485e2127683c29f09
timeCreated: 1762454507

View File

@@ -0,0 +1,205 @@
using System.Collections;
using Core;
using UnityEngine;
using UnityEngine.UI;
using AppleHills.Core.Settings;
namespace UI.CardSystem
{
/// <summary>
/// Controls a vertical progress bar made of individual Image elements.
/// Fills from bottom to top and animates the newest element with a blink effect.
///
/// Setup: Place on GameObject with VerticalLayoutGroup (Reverse Arrangement enabled).
/// First child = first progress element (1/5), last child = last progress element (5/5).
/// </summary>
public class ProgressBarController : MonoBehaviour
{
[Header("Progress Elements")]
[Tooltip("The individual Image components representing progress segments (auto-detected from children)")]
private Image[] _progressElements;
private ICardSystemSettings _settings;
private Coroutine _currentBlinkCoroutine;
private void Awake()
{
_settings = GameManager.GetSettingsObject<ICardSystemSettings>();
// Auto-detect all child Image components
_progressElements = GetComponentsInChildren<Image>(true);
if (_progressElements.Length == 0)
{
Logging.Warning("[ProgressBarController] No child Image components found! Add Image children to this GridLayout.");
}
}
/// <summary>
/// Show progress and animate the newest element with a blink effect.
/// </summary>
/// <param name="currentCount">Current progress (1 to maxCount)</param>
/// <param name="maxCount">Maximum progress value (typically 5)</param>
/// <param name="onComplete">Callback invoked after blink animation completes</param>
public void ShowProgress(int currentCount, int maxCount, System.Action onComplete)
{
// Validate input
if (currentCount < 0 || currentCount > maxCount)
{
Logging.Warning($"[ProgressBarController] Invalid progress: {currentCount}/{maxCount}");
onComplete?.Invoke();
return;
}
// Validate element count
if (_progressElements.Length < maxCount)
{
Logging.Warning($"[ProgressBarController] Not enough progress elements! Expected {maxCount}, found {_progressElements.Length}");
onComplete?.Invoke();
return;
}
// Stop any existing blink animation
if (_currentBlinkCoroutine != null)
{
StopCoroutine(_currentBlinkCoroutine);
_currentBlinkCoroutine = null;
}
// Disable all elements first
foreach (var element in _progressElements)
{
element.enabled = false;
}
// Enable first N elements (since first child = 1/5, last child = 5/5)
// If currentCount = 3, enable elements [0], [1], [2] (first 3 elements)
for (int i = 0; i < currentCount && i < _progressElements.Length; i++)
{
_progressElements[i].enabled = true;
}
Logging.Debug($"[ProgressBarController] Showing progress {currentCount}/{maxCount}");
// Blink the NEWEST element (the last one we just enabled)
// Newest element is at index (currentCount - 1)
int newestIndex = currentCount - 1;
if (newestIndex >= 0 && newestIndex < _progressElements.Length && currentCount > 0)
{
_currentBlinkCoroutine = StartCoroutine(BlinkElement(newestIndex, onComplete));
}
else
{
// No element to blink (e.g., currentCount = 0)
onComplete?.Invoke();
}
}
/// <summary>
/// Show progress without blink animation (instant display).
/// </summary>
/// <param name="currentCount">Current progress (1 to maxCount)</param>
/// <param name="maxCount">Maximum progress value</param>
public void ShowProgressInstant(int currentCount, int maxCount)
{
// Validate
if (currentCount < 0 || currentCount > maxCount || _progressElements.Length < maxCount)
{
return;
}
// Disable all
foreach (var element in _progressElements)
{
element.enabled = false;
}
// Enable first N elements
for (int i = 0; i < currentCount && i < _progressElements.Length; i++)
{
_progressElements[i].enabled = true;
}
}
/// <summary>
/// Hide all progress elements.
/// </summary>
public void HideProgress()
{
foreach (var element in _progressElements)
{
element.enabled = false;
}
}
/// <summary>
/// Blink a specific element by toggling enabled/disabled.
/// </summary>
private IEnumerator BlinkElement(int index, System.Action onComplete)
{
if (index < 0 || index >= _progressElements.Length)
{
onComplete?.Invoke();
yield break;
}
Image element = _progressElements[index];
// Get blink settings (or use defaults if not available)
float blinkDuration = 0.15f; // Duration for each on/off toggle
int blinkCount = 3; // Number of full blinks (on->off->on = 1 blink)
// Try to get settings if available
if (_settings != null)
{
// Settings could expose these if needed:
// blinkDuration = _settings.ProgressBlinkDuration;
// blinkCount = _settings.ProgressBlinkCount;
}
Logging.Debug($"[ProgressBarController] Blinking element {index} ({blinkCount} times)");
// Wait a brief moment before starting blink
yield return new WaitForSeconds(0.3f);
// Perform blinks (on->off->on = 1 full blink)
for (int i = 0; i < blinkCount; i++)
{
// Off
element.enabled = false;
yield return new WaitForSeconds(blinkDuration);
// On
element.enabled = true;
yield return new WaitForSeconds(blinkDuration);
}
// Ensure element is enabled at the end
element.enabled = true;
Logging.Debug($"[ProgressBarController] Blink complete for element {index}");
_currentBlinkCoroutine = null;
onComplete?.Invoke();
}
/// <summary>
/// Get the total number of progress elements available.
/// </summary>
public int GetElementCount()
{
return _progressElements?.Length ?? 0;
}
private void OnDestroy()
{
// Clean up any running coroutines
if (_currentBlinkCoroutine != null)
{
StopCoroutine(_currentBlinkCoroutine);
_currentBlinkCoroutine = null;
}
}
}
}

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: e91de41001c14101b8fa4216d6c7888b
timeCreated: 1762939781

View File

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 80f8dd01edcd4742b3edbb5c7fcecd12
timeCreated: 1762884650

View File

@@ -0,0 +1,227 @@
using AppleHills.Data.CardSystem;
using Core;
using Core.SaveLoad;
using UI.DragAndDrop.Core;
using UnityEngine;
namespace UI.CardSystem.StateMachine
{
/// <summary>
/// Main Card controller component.
/// Orchestrates the card state machine, context, and animator.
/// Inherits from DraggableObject to provide drag/drop capabilities for album placement.
/// This is the single entry point for working with cards.
/// </summary>
public class Card : DraggableObject
{
[Header("Components")]
[SerializeField] private CardContext context;
[SerializeField] private CardAnimator animator;
[SerializeField] private AppleMachine stateMachine;
[Header("Configuration")]
[SerializeField] private string initialState = "IdleState";
// Public accessors
public CardContext Context => context;
public CardAnimator Animator => animator;
public AppleMachine StateMachine => stateMachine;
public CardData CardData => context?.CardData;
// State inspection properties for booster flow
public bool IsIdle => GetCurrentStateName() == "IdleState";
public bool IsRevealing => !IsIdle && !IsComplete;
public bool IsComplete => context?.HasCompletedReveal ?? false;
// Event fired when this card is successfully placed into an AlbumCardSlot
public event System.Action<Card, AlbumCardSlot> OnPlacedInAlbumSlot;
protected override void Initialize()
{
base.Initialize(); // Call DraggableObject initialization
// Auto-find components if not assigned
if (context == null)
context = GetComponent<CardContext>();
if (animator == null)
animator = GetComponent<CardAnimator>();
if (stateMachine == null)
stateMachine = GetComponentInChildren<AppleMachine>();
}
#region DraggableObject Hooks - Trigger State Transitions
protected override void OnDragStartedHook()
{
base.OnDragStartedHook();
string current = GetCurrentStateName();
if (current == "PendingFaceDownState")
{
// Notify AlbumViewPage to assign data & flip
var albumPage = FindObjectOfType<AlbumViewPage>();
if (albumPage != null)
{
albumPage.HandlePendingCardDragStart(this);
}
// State change will be triggered by album page after data assignment
}
else
{
Logging.Debug($"[Card] Drag started on {CardData?.Name}, transitioning to DraggingState");
ChangeState("DraggingState");
}
}
protected override void OnDragEndedHook()
{
base.OnDragEndedHook();
string current = GetCurrentStateName();
if (current == "DraggingState")
{
// Existing logic
if (CurrentSlot is AlbumCardSlot albumSlot)
{
Logging.Debug($"[Card] Dropped in album slot, transitioning to PlacedInSlotState");
var placedState = GetStateComponent<States.CardPlacedInSlotState>("PlacedInSlotState");
if (placedState != null)
{
placedState.SetParentSlot(albumSlot);
}
ChangeState("PlacedInSlotState");
OnPlacedInAlbumSlot?.Invoke(this, albumSlot);
}
else
{
Logging.Debug("[Card] Dropped outside valid slot, returning to RevealedState");
ChangeState("RevealedState");
}
}
else if (current == "DraggingRevealedState")
{
// Pending revealed drag state end
if (CurrentSlot is AlbumCardSlot albumSlot)
{
var placedState = GetStateComponent<States.CardPlacedInSlotState>("PlacedInSlotState");
if (placedState != null) placedState.SetParentSlot(albumSlot);
ChangeState("PlacedInSlotState");
OnPlacedInAlbumSlot?.Invoke(this, albumSlot);
}
else
{
// Return to corner face-down
ChangeState("PendingFaceDownState");
}
}
}
#endregion
/// <summary>
/// Setup the card with data and optional initial state
/// </summary>
public void SetupCard(CardData data, string startState = null)
{
if (context != null)
{
context.SetupCard(data);
}
// Start the state machine with specified or default state
string targetState = startState ?? initialState;
if (stateMachine != null && !string.IsNullOrEmpty(targetState))
{
stateMachine.ChangeState(targetState);
}
}
/// <summary>
/// Setup for booster reveal flow (starts at IdleState, will flip on click)
/// Dragging is DISABLED for booster cards
/// States will query CardSystemManager for collection state as needed
/// </summary>
public void SetupForBoosterReveal(CardData data, bool isNew)
{
SetupCard(data, "IdleState");
SetDraggingEnabled(false); // Booster cards cannot be dragged
}
/// <summary>
/// Setup for album placement flow (starts at RevealedState, can be dragged)
/// Dragging is ENABLED for album placement cards
/// </summary>
public void SetupForAlbumPlacement(CardData data)
{
SetupCard(data, "RevealedState");
SetDraggingEnabled(true); // Album placement cards can be dragged
}
/// <summary>
/// Setup for album placement (starts at PlacedInSlotState)
/// Dragging is DISABLED once placed in slot
/// </summary>
public void SetupForAlbumSlot(CardData data, AlbumCardSlot slot)
{
SetupCard(data, "PlacedInSlotState");
SetDraggingEnabled(false); // Cards in slots cannot be dragged out
// Set the parent slot on the PlacedInSlotState
var placedState = GetStateComponent<States.CardPlacedInSlotState>("PlacedInSlotState");
if (placedState != null)
{
placedState.SetParentSlot(slot);
}
}
/// <summary>
/// Setup for album pending state (starts at PendingFaceDownState)
/// Dragging is ENABLED; state will assign data when dragged
/// </summary>
public void SetupForAlbumPending()
{
// Start with no data; state will assign when dragged
SetupCard(null, "PendingFaceDownState");
SetDraggingEnabled(true);
}
/// <summary>
/// Transition to a specific state
/// </summary>
public void ChangeState(string stateName)
{
if (stateMachine != null)
{
stateMachine.ChangeState(stateName);
}
}
/// <summary>
/// Get a specific state component by name
/// </summary>
public T GetStateComponent<T>(string stateName) where T : AppleState
{
if (stateMachine == null) return null;
Transform stateTransform = stateMachine.transform.Find(stateName);
if (stateTransform != null)
{
return stateTransform.GetComponent<T>();
}
return null;
}
/// <summary>
/// Get the current active state name
/// </summary>
public string GetCurrentStateName()
{
if (stateMachine?.currentState != null)
{
return stateMachine.currentState.name;
}
return "None";
}
}
}

Some files were not shown because too many files have changed in this diff Show More