Merge branch 'main' into DamianCardStyles
This commit is contained in:
63
Assets/AppleHillsLightingSettings.lighting
Normal file
63
Assets/AppleHillsLightingSettings.lighting
Normal file
@@ -0,0 +1,63 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!850595691 &4890085278179872738
|
||||
LightingSettings:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_Name: AppleHillsLightingSettings
|
||||
serializedVersion: 9
|
||||
m_EnableBakedLightmaps: 0
|
||||
m_EnableRealtimeLightmaps: 0
|
||||
m_RealtimeEnvironmentLighting: 1
|
||||
m_BounceScale: 1
|
||||
m_AlbedoBoost: 1
|
||||
m_IndirectOutputScale: 1
|
||||
m_UsingShadowmask: 1
|
||||
m_BakeBackend: 1
|
||||
m_LightmapMaxSize: 1024
|
||||
m_LightmapSizeFixed: 0
|
||||
m_UseMipmapLimits: 1
|
||||
m_BakeResolution: 40
|
||||
m_Padding: 2
|
||||
m_LightmapCompression: 3
|
||||
m_AO: 0
|
||||
m_AOMaxDistance: 1
|
||||
m_CompAOExponent: 1
|
||||
m_CompAOExponentDirect: 0
|
||||
m_ExtractAO: 0
|
||||
m_MixedBakeMode: 2
|
||||
m_LightmapsBakeMode: 1
|
||||
m_FilterMode: 1
|
||||
m_LightmapParameters: {fileID: 15204, guid: 0000000000000000f000000000000000, type: 0}
|
||||
m_ExportTrainingData: 0
|
||||
m_EnableWorkerProcessBaking: 1
|
||||
m_TrainingDataDestination: TrainingData
|
||||
m_RealtimeResolution: 2
|
||||
m_ForceWhiteAlbedo: 0
|
||||
m_ForceUpdates: 0
|
||||
m_PVRCulling: 1
|
||||
m_PVRSampling: 1
|
||||
m_PVRDirectSampleCount: 32
|
||||
m_PVRSampleCount: 512
|
||||
m_PVREnvironmentSampleCount: 256
|
||||
m_PVREnvironmentReferencePointCount: 2048
|
||||
m_LightProbeSampleCountMultiplier: 4
|
||||
m_PVRBounces: 2
|
||||
m_PVRMinBounces: 2
|
||||
m_PVREnvironmentImportanceSampling: 1
|
||||
m_PVRFilteringMode: 1
|
||||
m_PVRDenoiserTypeDirect: 1
|
||||
m_PVRDenoiserTypeIndirect: 1
|
||||
m_PVRDenoiserTypeAO: 1
|
||||
m_PVRFilterTypeDirect: 0
|
||||
m_PVRFilterTypeIndirect: 0
|
||||
m_PVRFilterTypeAO: 0
|
||||
m_PVRFilteringGaussRadiusDirect: 1
|
||||
m_PVRFilteringGaussRadiusIndirect: 1
|
||||
m_PVRFilteringGaussRadiusAO: 1
|
||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
||||
m_RespectSceneVisibilityWhenBakingGI: 0
|
||||
8
Assets/AppleHillsLightingSettings.lighting.meta
Normal file
8
Assets/AppleHillsLightingSettings.lighting.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d13be91f5840cb447b407875cd9bbefc
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 4890085278179872738
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -22,7 +22,7 @@ MonoBehaviour:
|
||||
m_RequireDepthTexture: 0
|
||||
m_RequireOpaqueTexture: 0
|
||||
m_OpaqueDownsampling: 1
|
||||
m_SupportsTerrainHoles: 1
|
||||
m_SupportsTerrainHoles: 0
|
||||
m_SupportsHDR: 0
|
||||
m_HDRColorBufferPrecision: 0
|
||||
m_MSAA: 1
|
||||
@@ -44,7 +44,7 @@ MonoBehaviour:
|
||||
m_MainLightRenderingMode: 0
|
||||
m_MainLightShadowsSupported: 0
|
||||
m_MainLightShadowmapResolution: 2048
|
||||
m_AdditionalLightsRenderingMode: 1
|
||||
m_AdditionalLightsRenderingMode: 0
|
||||
m_AdditionalLightsPerObjectLimit: 4
|
||||
m_AdditionalLightShadowsSupported: 0
|
||||
m_AdditionalLightsShadowmapResolution: 2048
|
||||
@@ -71,8 +71,8 @@ MonoBehaviour:
|
||||
m_AdditionalLightsCookieFormat: 3
|
||||
m_UseSRPBatcher: 1
|
||||
m_SupportsDynamicBatching: 0
|
||||
m_MixedLightingSupported: 1
|
||||
m_SupportsLightCookies: 1
|
||||
m_MixedLightingSupported: 0
|
||||
m_SupportsLightCookies: 0
|
||||
m_SupportsLightLayers: 0
|
||||
m_DebugLevel: 0
|
||||
m_StoreActionsOptimization: 0
|
||||
@@ -91,7 +91,7 @@ MonoBehaviour:
|
||||
m_LocalShadowsAtlasResolution: 256
|
||||
m_MaxPixelLights: 0
|
||||
m_ShadowAtlasResolution: 256
|
||||
m_VolumeFrameworkUpdateMode: 0
|
||||
m_VolumeFrameworkUpdateMode: 1
|
||||
m_VolumeProfile: {fileID: 0}
|
||||
apvScenesData:
|
||||
obsoleteSceneBounds:
|
||||
|
||||
@@ -53,6 +53,6 @@ MonoBehaviour:
|
||||
m_CameraSortingLayerDownsamplingMethod: 0
|
||||
m_MaxLightRenderTextureCount: 16
|
||||
m_MaxShadowRenderTextureCount: 1
|
||||
m_PostProcessData: {fileID: 11400000, guid: 41439944d30ece34e96484bdb6645b55, type: 2}
|
||||
m_DefaultMaterialType: 0
|
||||
m_PostProcessData: {fileID: 0}
|
||||
m_DefaultMaterialType: 1
|
||||
m_DefaultCustomMaterial: {fileID: 2100000, guid: a97c105638bdf8b4a8650670310a4cd3, type: 2}
|
||||
|
||||
@@ -288,7 +288,7 @@ AnimationClip:
|
||||
m_AdditiveReferencePoseClip: {fileID: 0}
|
||||
m_AdditiveReferencePoseTime: 0
|
||||
m_StartTime: 0
|
||||
m_StopTime: 2.3999999
|
||||
m_StopTime: 2.4
|
||||
m_OrientationOffsetY: 0
|
||||
m_Level: 0
|
||||
m_CycleOffset: 0
|
||||
@@ -370,4 +370,11 @@ AnimationClip:
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
m_Events:
|
||||
- time: 2.4
|
||||
functionName: OnStationaryAnimationComplete
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
|
||||
@@ -336,4 +336,11 @@ AnimationClip:
|
||||
m_EulerEditorCurves: []
|
||||
m_HasGenericRootTransform: 0
|
||||
m_HasMotionFloatCurves: 0
|
||||
m_Events: []
|
||||
m_Events:
|
||||
- time: 1.6666666
|
||||
functionName: OnStationaryAnimationComplete
|
||||
data:
|
||||
objectReferenceParameter: {fileID: 0}
|
||||
floatParameter: 0
|
||||
intParameter: 0
|
||||
messageOptions: 0
|
||||
|
||||
@@ -26,3 +26,4 @@ MonoBehaviour:
|
||||
- {fileID: 3528960956969533010, guid: 53eea3840d3cde34a9768b8773a3a7e8, type: 3}
|
||||
- {fileID: 6895404274863911569, guid: 840f3d8a936b39a41b5896328a692005, type: 3}
|
||||
- {fileID: 3863019143023165617, guid: 774e30e3f0b1d0d49bad0c2abf11038a, type: 3}
|
||||
- {fileID: 5034240524438268576, guid: b15ba9d3d508ef244b0eeb76404dc9de, type: 3}
|
||||
|
||||
@@ -307,6 +307,7 @@ MonoBehaviour:
|
||||
- LoopThroughIncorrectItemLines
|
||||
- ForbiddenItemDialogueContent
|
||||
- LoopThroughForbiddenItemLines
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 4008004961314799713
|
||||
- rid: 4008004961314799714
|
||||
@@ -321,6 +322,7 @@ MonoBehaviour:
|
||||
- rid: 4008004961314799723
|
||||
- rid: 4008004961314799724
|
||||
- rid: 4008004961314799725
|
||||
- rid: 7545630068434796544
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -525,3 +527,7 @@ MonoBehaviour:
|
||||
- rid: 4008004961314799729
|
||||
type: {class: EndNode, ns: Editor.Dialogue, asm: AppleHillsEditor}
|
||||
data:
|
||||
- rid: 7545630068434796544
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 1
|
||||
|
||||
@@ -168,6 +168,7 @@ MonoBehaviour:
|
||||
- LoopThroughIncorrectItemLines
|
||||
- ForbiddenItemDialogueContent
|
||||
- LoopThroughForbiddenItemLines
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 4008004961314799803
|
||||
- rid: 4008004961314799804
|
||||
@@ -182,6 +183,7 @@ MonoBehaviour:
|
||||
- rid: 4008004961314799813
|
||||
- rid: 4008004961314799814
|
||||
- rid: 4008004961314799815
|
||||
- rid: 7545630068434796549
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -525,3 +527,7 @@ MonoBehaviour:
|
||||
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: AnneLise
|
||||
- rid: 7545630068434796549
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 0
|
||||
|
||||
@@ -168,6 +168,7 @@ MonoBehaviour:
|
||||
- LoopThroughIncorrectItemLines
|
||||
- ForbiddenItemDialogueContent
|
||||
- LoopThroughForbiddenItemLines
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 4008004961314799847
|
||||
- rid: 4008004961314799848
|
||||
@@ -182,6 +183,7 @@ MonoBehaviour:
|
||||
- rid: 4008004961314799857
|
||||
- rid: 4008004961314799858
|
||||
- rid: 4008004961314799859
|
||||
- rid: 7545630068434796550
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -525,3 +527,7 @@ MonoBehaviour:
|
||||
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: AnneLise
|
||||
- rid: 7545630068434796550
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 0
|
||||
|
||||
@@ -168,6 +168,7 @@ MonoBehaviour:
|
||||
- LoopThroughIncorrectItemLines
|
||||
- ForbiddenItemDialogueContent
|
||||
- LoopThroughForbiddenItemLines
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 4008004961314799891
|
||||
- rid: 4008004961314799892
|
||||
@@ -182,6 +183,7 @@ MonoBehaviour:
|
||||
- rid: 4008004961314799901
|
||||
- rid: 4008004961314799902
|
||||
- rid: 4008004961314799903
|
||||
- rid: 7545630068434796545
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -525,3 +527,7 @@ MonoBehaviour:
|
||||
type: {class: 'Constant`1[[System.String, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: AnneLise
|
||||
- rid: 7545630068434796545
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 0
|
||||
|
||||
@@ -42,12 +42,14 @@ MonoBehaviour:
|
||||
- RequiredPuzzleStep
|
||||
- DefaultDialogueContent
|
||||
- LoopThroughDefaultLines
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 4008004961314799759
|
||||
- rid: 4008004961314799760
|
||||
- rid: 4008004961314799761
|
||||
- rid: 4008004961314799762
|
||||
- rid: 4008004961314799763
|
||||
- rid: 7545630068434796551
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -169,6 +171,10 @@ MonoBehaviour:
|
||||
_text:
|
||||
_image: {fileID: 1487011052474782424, guid: f489e2c9ce64ff34aa3c7a91a4edbd77, type: 3}
|
||||
_audio: {fileID: 8300000, guid: b4ba973891dad4749b465e9a07987e1a, type: 3}
|
||||
- rid: 7545630068434796551
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 0
|
||||
- rid: 7772910664224079994
|
||||
type: {class: GraphModelImp, ns: Unity.GraphToolkit.Editor.Implementation, asm: Unity.GraphToolkit.Editor}
|
||||
data:
|
||||
|
||||
@@ -487,6 +487,7 @@ MonoBehaviour:
|
||||
- DefaultDialogueContent1
|
||||
- DefaultDialogueContent2
|
||||
- DefaultDialogueContent3
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 1226592702090707084
|
||||
- rid: 1226592702090707085
|
||||
@@ -495,6 +496,7 @@ MonoBehaviour:
|
||||
- rid: 7545629632211976304
|
||||
- rid: 7545629632211976305
|
||||
- rid: 7545629632211976306
|
||||
- rid: 7545630068434796546
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -689,12 +691,14 @@ MonoBehaviour:
|
||||
- RequiredResultItem
|
||||
- LoopThroughDefaultLines
|
||||
- DefaultDialogueContent
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 1226592736610877524
|
||||
- rid: 1226592736610877525
|
||||
- rid: 1226592736610877526
|
||||
- rid: 1226592736610877528
|
||||
- rid: 7545629632211976309
|
||||
- rid: 7545630068434796547
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -895,6 +899,7 @@ MonoBehaviour:
|
||||
- DefaultDialogueContent
|
||||
- IncorrectItemDialogueContent
|
||||
- ForbiddenItemDialogueContent
|
||||
- ShouldAutoPlay
|
||||
m_ValueList:
|
||||
- rid: 1226592736610877547
|
||||
- rid: 1226592736610877548
|
||||
@@ -909,6 +914,7 @@ MonoBehaviour:
|
||||
- rid: 7545629632211976311
|
||||
- rid: 7545629632211976312
|
||||
- rid: 7545629632211976313
|
||||
- rid: 7545630068434796548
|
||||
m_InputPortInfos:
|
||||
expandedPortsById:
|
||||
m_KeyList: []
|
||||
@@ -1212,3 +1218,15 @@ MonoBehaviour:
|
||||
_text: Yessssss, thanks!
|
||||
_image: {fileID: 0}
|
||||
_audio: {fileID: 0}
|
||||
- rid: 7545630068434796546
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 0
|
||||
- rid: 7545630068434796547
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 0
|
||||
- rid: 7545630068434796548
|
||||
type: {class: 'Constant`1[[System.Boolean, mscorlib]]', ns: Unity.GraphToolkit.Editor, asm: Unity.GraphToolkit.Internal.Editor}
|
||||
data:
|
||||
m_Value: 0
|
||||
|
||||
@@ -164,6 +164,8 @@ namespace Editor.Dialogue
|
||||
{
|
||||
runtimeNode.puzzleStepID = puzzleStep.stepId;
|
||||
}
|
||||
|
||||
runtimeNode.shouldAutoPlay = GetPortValue<bool>(node.GetInputPortByName("ShouldAutoPlay"));
|
||||
}
|
||||
|
||||
private void ProcessPickupNode(WaitOnPickup node, RuntimeDialogueNode runtimeNode)
|
||||
@@ -175,6 +177,8 @@ namespace Editor.Dialogue
|
||||
{
|
||||
runtimeNode.pickupItemID = pickup.itemId;
|
||||
}
|
||||
|
||||
runtimeNode.shouldAutoPlay = GetPortValue<bool>(node.GetInputPortByName("ShouldAutoPlay"));
|
||||
}
|
||||
|
||||
private void ProcessSlotNode(WaitOnSlot node, RuntimeDialogueNode runtimeNode)
|
||||
@@ -187,6 +191,8 @@ namespace Editor.Dialogue
|
||||
runtimeNode.slotItemID = slot.itemId;
|
||||
}
|
||||
|
||||
runtimeNode.shouldAutoPlay = GetPortValue<bool>(node.GetInputPortByName("ShouldAutoPlay"));
|
||||
|
||||
// Get line type and count options for incorrect items
|
||||
var incorrectItemLineTypeOption = node.GetNodeOptionByName("IncorrectItemDialogueLineType");
|
||||
incorrectItemLineTypeOption.TryGetValue<DialogueType>(out var incorrectItemLineType);
|
||||
@@ -296,6 +302,8 @@ namespace Editor.Dialogue
|
||||
{
|
||||
runtimeNode.combinationResultItemID = resultItem.itemId;
|
||||
}
|
||||
|
||||
runtimeNode.shouldAutoPlay = GetPortValue<bool>(node.GetInputPortByName("ShouldAutoPlay"));
|
||||
}
|
||||
|
||||
private T GetPortValue<T>(IPort port)
|
||||
|
||||
@@ -90,10 +90,12 @@ namespace Editor.Dialogue
|
||||
public class WaitOnPuzzleStep : DialogueNode
|
||||
{
|
||||
const string RequiredPuzzleStep = "RequiredPuzzleStep";
|
||||
const string ShouldAutoPlayOptionName = "ShouldAutoPlay";
|
||||
|
||||
protected override void OnDefinePorts(IPortDefinitionContext context)
|
||||
{
|
||||
context.AddInputPort<PuzzleStepSO>(RequiredPuzzleStep).WithDisplayName("Required Puzzle Step").Build();
|
||||
context.AddInputPort<bool>(ShouldAutoPlayOptionName).WithDisplayName("Should Auto-Play?").Build();
|
||||
|
||||
base.OnDefinePorts(context);
|
||||
}
|
||||
@@ -103,10 +105,12 @@ namespace Editor.Dialogue
|
||||
public class WaitOnPickup : DialogueNode
|
||||
{
|
||||
const string RequiredPickupsOptionName = "RequiredPickup";
|
||||
const string ShouldAutoPlayOptionName = "ShouldAutoPlay";
|
||||
|
||||
protected override void OnDefinePorts(IPortDefinitionContext context)
|
||||
{
|
||||
context.AddInputPort<PickupItemData>(RequiredPickupsOptionName).WithDisplayName("Required Pickup").Build();
|
||||
context.AddInputPort<bool>(ShouldAutoPlayOptionName).WithDisplayName("Should Auto-Play?").Build();
|
||||
|
||||
base.OnDefinePorts(context);
|
||||
}
|
||||
@@ -116,6 +120,7 @@ namespace Editor.Dialogue
|
||||
public class WaitOnSlot : DialogueNode
|
||||
{
|
||||
const string RequiredSlotOptionName = "RequiredSlot";
|
||||
const string ShouldAutoPlayOptionName = "ShouldAutoPlay";
|
||||
const string IncorrectItemLineTypeOptionName = "IncorrectItemDialogueLineType";
|
||||
const string IncorrectItemNoLinesOptionName = "IncorrectItemNoLines";
|
||||
const string LoopThroughIncorrectItemLinesOptionName = "LoopThroughIncorrectItemLines";
|
||||
@@ -156,6 +161,7 @@ namespace Editor.Dialogue
|
||||
protected override void OnDefinePorts(IPortDefinitionContext context)
|
||||
{
|
||||
context.AddInputPort<PickupItemData>(RequiredSlotOptionName).WithDisplayName("Required Slot").Build();
|
||||
context.AddInputPort<bool>(ShouldAutoPlayOptionName).WithDisplayName("Should Auto-Play?").Build();
|
||||
|
||||
base.OnDefinePorts(context);
|
||||
|
||||
@@ -219,10 +225,12 @@ namespace Editor.Dialogue
|
||||
public class WaitOnCombination : DialogueNode
|
||||
{
|
||||
const string RequiredResultItemOptionName = "RequiredResultItem";
|
||||
const string ShouldAutoPlayOptionName = "ShouldAutoPlay";
|
||||
|
||||
protected override void OnDefinePorts(IPortDefinitionContext context)
|
||||
{
|
||||
context.AddInputPort<PickupItemData>(RequiredResultItemOptionName).WithDisplayName("Required Result Item").Build();
|
||||
context.AddInputPort<bool>(ShouldAutoPlayOptionName).WithDisplayName("Should Auto-Play?").Build();
|
||||
|
||||
base.OnDefinePorts(context);
|
||||
}
|
||||
|
||||
63
Assets/Editor/Tools/ClearSavesMenuItem.cs
Normal file
63
Assets/Editor/Tools/ClearSavesMenuItem.cs
Normal file
@@ -0,0 +1,63 @@
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Editor.Tools
|
||||
{
|
||||
/// <summary>
|
||||
/// Editor utility to clear all save data from the SaveLoadManager's save folder
|
||||
/// </summary>
|
||||
public static class ClearSavesMenuItem
|
||||
{
|
||||
[MenuItem("AppleHills/Clear Saves")]
|
||||
private static void ClearSaves()
|
||||
{
|
||||
// Construct the save folder path (matches SaveLoadManager.DefaultSaveFolder)
|
||||
string saveFolder = Path.Combine(Application.persistentDataPath, "GameSaves");
|
||||
|
||||
if (!Directory.Exists(saveFolder))
|
||||
{
|
||||
Debug.Log($"[ClearSaves] Save folder does not exist: {saveFolder}");
|
||||
EditorUtility.DisplayDialog("Clear Saves", "No save data found to clear.", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
// Confirm with the user
|
||||
bool confirmed = EditorUtility.DisplayDialog(
|
||||
"Clear Saves",
|
||||
$"Are you sure you want to delete all save data?\n\nFolder: {saveFolder}",
|
||||
"Delete All",
|
||||
"Cancel"
|
||||
);
|
||||
|
||||
if (!confirmed)
|
||||
{
|
||||
Debug.Log("[ClearSaves] User cancelled save deletion");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Delete all files in the save folder
|
||||
string[] files = Directory.GetFiles(saveFolder);
|
||||
int deletedCount = 0;
|
||||
|
||||
foreach (string file in files)
|
||||
{
|
||||
File.Delete(file);
|
||||
deletedCount++;
|
||||
Debug.Log($"[ClearSaves] Deleted: {file}");
|
||||
}
|
||||
|
||||
Debug.Log($"[ClearSaves] Successfully deleted {deletedCount} save file(s)");
|
||||
EditorUtility.DisplayDialog("Clear Saves", $"Successfully deleted {deletedCount} save file(s).", "OK");
|
||||
}
|
||||
catch (System.Exception ex)
|
||||
{
|
||||
Debug.LogError($"[ClearSaves] Failed to clear saves: {ex}");
|
||||
EditorUtility.DisplayDialog("Clear Saves", $"Error clearing saves:\n{ex.Message}", "OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
3
Assets/Editor/Tools/ClearSavesMenuItem.cs.meta
Normal file
3
Assets/Editor/Tools/ClearSavesMenuItem.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 747ab9e66b014771bc1486f9ab073f90
|
||||
timeCreated: 1761569785
|
||||
@@ -62,19 +62,28 @@ public class SceneBrowserWindow : EditorWindow
|
||||
if (GUILayout.Button("Refresh"))
|
||||
RefreshScenes();
|
||||
_scroll = EditorGUILayout.BeginScrollView(_scroll);
|
||||
|
||||
// Create a safe copy to avoid collection modification during enumeration
|
||||
var foldersCopy = _scenesByFolder.Keys.ToList();
|
||||
|
||||
// Top-level scenes
|
||||
if (_scenesByFolder.ContainsKey(""))
|
||||
if (foldersCopy.Contains("") && _scenesByFolder.ContainsKey(""))
|
||||
{
|
||||
foreach (var scene in _scenesByFolder[""])
|
||||
var topLevelScenes = _scenesByFolder[""].ToList();
|
||||
foreach (var scene in topLevelScenes)
|
||||
DrawSceneRow(scene);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
// Subfolders
|
||||
foreach (var kvp in _scenesByFolder)
|
||||
foreach (var folderKey in foldersCopy)
|
||||
{
|
||||
if (string.IsNullOrEmpty(kvp.Key)) continue;
|
||||
EditorGUILayout.LabelField(kvp.Key, EditorStyles.boldLabel);
|
||||
foreach (var scene in kvp.Value)
|
||||
if (string.IsNullOrEmpty(folderKey)) continue;
|
||||
if (!_scenesByFolder.ContainsKey(folderKey)) continue;
|
||||
|
||||
EditorGUILayout.LabelField(folderKey, EditorStyles.boldLabel);
|
||||
var scenesInFolder = _scenesByFolder[folderKey].ToList();
|
||||
foreach (var scene in scenesInFolder)
|
||||
DrawSceneRow(scene);
|
||||
EditorGUILayout.Space();
|
||||
}
|
||||
|
||||
@@ -12,6 +12,22 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: fde0d25a170598d46a0b9dc16b4527a5, type: 3}
|
||||
m_Name: ActivationPlayableAsset
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.ActivationPlayableAsset
|
||||
--- !u!114 &-7800811525781169865
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 15c38f6fa1940124db1ab7f6fe7268d1, type: 3}
|
||||
m_Name: Signal Emitter
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalEmitter
|
||||
m_Time: 0
|
||||
m_Retroactive: 0
|
||||
m_EmitOnce: 0
|
||||
m_Asset: {fileID: 11400000, guid: 2a32e2abdb44cb1469e5c6b9a25f98bc, type: 2}
|
||||
--- !u!114 &-7584736085941489071
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
@@ -139,6 +155,22 @@ MonoBehaviour:
|
||||
m_bufferingTime: 0.1
|
||||
m_ClipProperties:
|
||||
volume: 0.683
|
||||
--- !u!114 &-5035745444053599677
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 15c38f6fa1940124db1ab7f6fe7268d1, type: 3}
|
||||
m_Name: Signal Emitter
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalEmitter
|
||||
m_Time: 1.65
|
||||
m_Retroactive: 0
|
||||
m_EmitOnce: 0
|
||||
m_Asset: {fileID: 11400000, guid: 2ec36cde76b6baf4299c0dd9ab54714e, type: 2}
|
||||
--- !u!114 &-4664548104421960294
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
@@ -491,12 +523,13 @@ MonoBehaviour:
|
||||
- {fileID: 5194333105783184030}
|
||||
- {fileID: 8484886637748558501}
|
||||
- {fileID: 8776627858148209300}
|
||||
- {fileID: 6964431640287062015}
|
||||
m_FixedDuration: 0
|
||||
m_EditorSettings:
|
||||
m_Framerate: 60
|
||||
m_ScenePreview: 1
|
||||
m_DurationMode: 0
|
||||
m_MarkerTrack: {fileID: 0}
|
||||
m_MarkerTrack: {fileID: 7948415667162652308}
|
||||
--- !u!114 &297111036028248502
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
@@ -746,6 +779,54 @@ MonoBehaviour:
|
||||
m_Script: {fileID: 11500000, guid: fde0d25a170598d46a0b9dc16b4527a5, type: 3}
|
||||
m_Name: ActivationPlayableAsset
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.ActivationPlayableAsset
|
||||
--- !u!114 &6964431640287062015
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: b46e36075dd1c124a8422c228e75e1fb, type: 3}
|
||||
m_Name: Signal Track
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalTrack
|
||||
m_Version: 3
|
||||
m_AnimClip: {fileID: 0}
|
||||
m_Locked: 0
|
||||
m_Muted: 0
|
||||
m_CustomPlayableFullTypename:
|
||||
m_Curves: {fileID: 0}
|
||||
m_Parent: {fileID: 11400000}
|
||||
m_Children: []
|
||||
m_Clips: []
|
||||
m_Markers:
|
||||
m_Objects:
|
||||
- {fileID: -7800811525781169865}
|
||||
- {fileID: -5035745444053599677}
|
||||
--- !u!114 &7948415667162652308
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 2a16748d9461eae46a725db9776d5390, type: 3}
|
||||
m_Name: Markers
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.MarkerTrack
|
||||
m_Version: 3
|
||||
m_AnimClip: {fileID: 0}
|
||||
m_Locked: 0
|
||||
m_Muted: 0
|
||||
m_CustomPlayableFullTypename:
|
||||
m_Curves: {fileID: 0}
|
||||
m_Parent: {fileID: 11400000}
|
||||
m_Children: []
|
||||
m_Clips: []
|
||||
m_Markers:
|
||||
m_Objects: []
|
||||
--- !u!114 &8484886637748558501
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 1
|
||||
|
||||
@@ -14,6 +14,7 @@ GameObject:
|
||||
- component: {fileID: 8947209170748834035}
|
||||
- component: {fileID: 7852204877518954380}
|
||||
- component: {fileID: 1621671461027776358}
|
||||
- component: {fileID: 7002695641417196458}
|
||||
m_Layer: 8
|
||||
m_Name: PulverCharacter
|
||||
m_TagString: Pulver
|
||||
@@ -184,6 +185,51 @@ MonoBehaviour:
|
||||
bezierTangentLength: 0.4
|
||||
offset: 0.2
|
||||
factor: 0.1
|
||||
--- !u!114 &7002695641417196458
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 1102400833121127473}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e52de21a22b6dd44c9cc19f810c65059, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalReceiver
|
||||
m_Events:
|
||||
m_Signals:
|
||||
- {fileID: 11400000, guid: 2a32e2abdb44cb1469e5c6b9a25f98bc, type: 2}
|
||||
- {fileID: 11400000, guid: 2ec36cde76b6baf4299c0dd9ab54714e, type: 2}
|
||||
m_Events:
|
||||
- m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 3435632802124758411}
|
||||
m_TargetAssemblyTypeName: FollowerController, AppleHillsScripts
|
||||
m_MethodName: PauseMovement
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||
m_IntArgument: 0
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
- m_PersistentCalls:
|
||||
m_Calls:
|
||||
- m_Target: {fileID: 3435632802124758411}
|
||||
m_TargetAssemblyTypeName: FollowerController, AppleHillsScripts
|
||||
m_MethodName: ResumeMovement
|
||||
m_Mode: 1
|
||||
m_Arguments:
|
||||
m_ObjectArgument: {fileID: 0}
|
||||
m_ObjectArgumentAssemblyTypeName: UnityEngine.Object, UnityEngine
|
||||
m_IntArgument: 0
|
||||
m_FloatArgument: 0
|
||||
m_StringArgument:
|
||||
m_BoolArgument: 0
|
||||
m_CallState: 2
|
||||
--- !u!1 &5934518940303293264
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -338,8 +384,29 @@ PrefabInstance:
|
||||
- {fileID: 2732140975288177209, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
|
||||
m_RemovedGameObjects: []
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_AddedComponents:
|
||||
- targetCorrespondingSourceObject: {fileID: 1102468210854536367, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
|
||||
insertIndex: -1
|
||||
addedObject: {fileID: 3454096590710680423}
|
||||
m_SourcePrefab: {fileID: 100100000, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
|
||||
--- !u!1 &780600094299918916 stripped
|
||||
GameObject:
|
||||
m_CorrespondingSourceObject: {fileID: 1102468210854536367, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
|
||||
m_PrefabInstance: {fileID: 403634400421951211}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
--- !u!114 &3454096590710680423
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 780600094299918916}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: 39f2e64420884f11a9022fea7b3be5d0, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::FollowerAnimationEventBridge
|
||||
followerController: {fileID: 3435632802124758411}
|
||||
--- !u!4 &6418503932309983819 stripped
|
||||
Transform:
|
||||
m_CorrespondingSourceObject: {fileID: 6668392923879433376, guid: e3b439d398cffdd4194cdb360a46c5a6, type: 3}
|
||||
|
||||
48
Assets/Prefabs/Managers/SaveLoadManager.prefab
Normal file
48
Assets/Prefabs/Managers/SaveLoadManager.prefab
Normal file
@@ -0,0 +1,48 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!1 &5034240524438268576
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
serializedVersion: 6
|
||||
m_Component:
|
||||
- component: {fileID: 536416456044738252}
|
||||
- component: {fileID: 6631817730171642502}
|
||||
m_Layer: 0
|
||||
m_Name: SaveLoadManager
|
||||
m_TagString: Untagged
|
||||
m_Icon: {fileID: 0}
|
||||
m_NavMeshLayer: 0
|
||||
m_StaticEditorFlags: 0
|
||||
m_IsActive: 1
|
||||
--- !u!4 &536416456044738252
|
||||
Transform:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5034240524438268576}
|
||||
serializedVersion: 2
|
||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
||||
m_LocalPosition: {x: 0, y: 0, z: 0}
|
||||
m_LocalScale: {x: 1, y: 1, z: 1}
|
||||
m_ConstrainProportionsScale: 0
|
||||
m_Children: []
|
||||
m_Father: {fileID: 0}
|
||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
||||
--- !u!114 &6631817730171642502
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 5034240524438268576}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: a1731f4790be4ec3bab71506427768d7, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: AppleHillsScripts::Core.SaveLoad.SaveLoadManager
|
||||
currentSaveData:
|
||||
playedDivingTutorial: 0
|
||||
7
Assets/Prefabs/Managers/SaveLoadManager.prefab.meta
Normal file
7
Assets/Prefabs/Managers/SaveLoadManager.prefab.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b15ba9d3d508ef244b0eeb76404dc9de
|
||||
PrefabImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -466228,6 +466228,17 @@ PrefabInstance:
|
||||
m_AddedGameObjects: []
|
||||
m_AddedComponents: []
|
||||
m_SourcePrefab: {fileID: 100100000, guid: 0bbded61e58193848ac59c8eea761bcc, type: 3}
|
||||
--- !u!114 &1760588396 stripped
|
||||
MonoBehaviour:
|
||||
m_CorrespondingSourceObject: {fileID: 7002695641417196458, guid: 8ac0210dbf9d7754e9526d6d5c214f49, type: 3}
|
||||
m_PrefabInstance: {fileID: 1363194738}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: e52de21a22b6dd44c9cc19f810c65059, type: 3}
|
||||
m_Name:
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalReceiver
|
||||
--- !u!1 &1761890788
|
||||
GameObject:
|
||||
m_ObjectHideFlags: 0
|
||||
@@ -477381,7 +477392,7 @@ PrefabInstance:
|
||||
objectReference: {fileID: 11400000, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2}
|
||||
- target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3}
|
||||
propertyPath: m_SceneBindings.Array.size
|
||||
value: 13
|
||||
value: 14
|
||||
objectReference: {fileID: 0}
|
||||
- target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3}
|
||||
propertyPath: m_SceneBindings.Array.data[3].key
|
||||
@@ -477423,6 +477434,10 @@ PrefabInstance:
|
||||
propertyPath: m_SceneBindings.Array.data[12].key
|
||||
value:
|
||||
objectReference: {fileID: 8776627858148209300, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2}
|
||||
- target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3}
|
||||
propertyPath: m_SceneBindings.Array.data[13].key
|
||||
value:
|
||||
objectReference: {fileID: 6964431640287062015, guid: 1791fd5a24a3142418ed441a2a25b374, type: 2}
|
||||
- target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3}
|
||||
propertyPath: m_SceneBindings.Array.data[0].value
|
||||
value:
|
||||
@@ -477467,6 +477482,10 @@ PrefabInstance:
|
||||
propertyPath: m_SceneBindings.Array.data[12].value
|
||||
value:
|
||||
objectReference: {fileID: 781815198}
|
||||
- target: {fileID: 1569498917964935965, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3}
|
||||
propertyPath: m_SceneBindings.Array.data[13].value
|
||||
value:
|
||||
objectReference: {fileID: 1760588396}
|
||||
- target: {fileID: 2084964592986606867, guid: c36b48a324dcaef4cb5ee0f8ca57f0d6, type: 3}
|
||||
propertyPath: m_LocalPosition.y
|
||||
value: 1.68
|
||||
|
||||
@@ -202,7 +202,7 @@ namespace AppleHillsCamera
|
||||
private void FindCameraAdapter()
|
||||
{
|
||||
// Try to find the camera adapter in the scene
|
||||
var adapters = FindObjectsOfType<CameraScreenAdapter>();
|
||||
var adapters = FindObjectsByType<CameraScreenAdapter>(FindObjectsSortMode.None);
|
||||
if (adapters != null && adapters.Length > 0)
|
||||
{
|
||||
// Prioritize any adapter that's on the same camera we're using
|
||||
|
||||
@@ -123,8 +123,12 @@ namespace Core
|
||||
/// <param name="shouldPause">True to pause; false to resume</param>
|
||||
private void ApplyPause(bool shouldPause)
|
||||
{
|
||||
// TODO: Do we want to stop time?
|
||||
// Time.timeScale = shouldPause ? 0f : 1f;
|
||||
// Only affect timescale if debug setting allows it
|
||||
var debugSettings = GetDeveloperSettings<DebugSettings>();
|
||||
if (debugSettings != null && debugSettings.PauseTimeOnPauseGame)
|
||||
{
|
||||
Time.timeScale = shouldPause ? 0f : 1f;
|
||||
}
|
||||
|
||||
// Notify registered components
|
||||
foreach (var component in _pausableComponents)
|
||||
@@ -213,8 +217,9 @@ namespace Core
|
||||
|
||||
// Load developer settings
|
||||
var divingDevSettings = DeveloperSettingsProvider.Instance.GetSettings<DivingDeveloperSettings>();
|
||||
var debugSettings = DeveloperSettingsProvider.Instance.GetSettings<DebugSettings>();
|
||||
|
||||
_developerSettingsLoaded = divingDevSettings != null;
|
||||
_developerSettingsLoaded = divingDevSettings != null && debugSettings != null;
|
||||
|
||||
if (_developerSettingsLoaded)
|
||||
{
|
||||
|
||||
3
Assets/Scripts/Core/SaveLoad.meta
Normal file
3
Assets/Scripts/Core/SaveLoad.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0541e0e1c3dd41f7a61773e4bc2c64ed
|
||||
timeCreated: 1761553949
|
||||
29
Assets/Scripts/Core/SaveLoad/SaveLoadData.cs
Normal file
29
Assets/Scripts/Core/SaveLoad/SaveLoadData.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Core.SaveLoad
|
||||
{
|
||||
[System.Serializable]
|
||||
public class SaveLoadData
|
||||
{
|
||||
public bool playedDivingTutorial = false;
|
||||
|
||||
// Snapshot of the player's card collection (MVP)
|
||||
public CardCollectionState cardCollection;
|
||||
}
|
||||
|
||||
// Minimal DTOs for card persistence
|
||||
[System.Serializable]
|
||||
public class CardCollectionState
|
||||
{
|
||||
public int boosterPackCount;
|
||||
public List<SavedCardEntry> cards = new List<SavedCardEntry>();
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class SavedCardEntry
|
||||
{
|
||||
public string definitionId;
|
||||
public AppleHills.Data.CardSystem.CardRarity rarity;
|
||||
public int copiesOwned;
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/SaveLoad/SaveLoadData.cs.meta
Normal file
3
Assets/Scripts/Core/SaveLoad/SaveLoadData.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1704f1fc7e6b4a398f39fb86cec265f8
|
||||
timeCreated: 1761553972
|
||||
238
Assets/Scripts/Core/SaveLoad/SaveLoadManager.cs
Normal file
238
Assets/Scripts/Core/SaveLoad/SaveLoadManager.cs
Normal file
@@ -0,0 +1,238 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
using Bootstrap;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Core.SaveLoad
|
||||
{
|
||||
/// <summary>
|
||||
/// Simple Save/Load manager that follows the project's bootstrap pattern.
|
||||
/// - Singleton instance
|
||||
/// - Registers a post-boot init action with BootCompletionService
|
||||
/// - Exposes simple async Save/Load methods (PlayerPrefs-backed placeholder)
|
||||
/// - Fires events on completion
|
||||
/// This is intended as boilerplate to be expanded with a real serialization backend.
|
||||
/// </summary>
|
||||
public class SaveLoadManager : MonoBehaviour
|
||||
{
|
||||
private static SaveLoadManager _instance;
|
||||
public static SaveLoadManager Instance => _instance;
|
||||
|
||||
// Path
|
||||
private static string DefaultSaveFolder => Path.Combine(Application.persistentDataPath, "GameSaves");
|
||||
public SaveLoadData currentSaveData;
|
||||
|
||||
// State
|
||||
public bool IsSaving { get; private set; }
|
||||
public bool IsLoading { get; private set; }
|
||||
public bool IsSaveDataLoaded { get; private set; }
|
||||
|
||||
// Events
|
||||
public event Action<string> OnSaveCompleted;
|
||||
public event Action<string> OnLoadCompleted;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
IsSaveDataLoaded = false;
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
Load();
|
||||
}
|
||||
|
||||
private void OnApplicationQuit()
|
||||
{
|
||||
Save();
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
Logging.Debug("[SaveLoadManager] Post-boot initialization complete");
|
||||
}
|
||||
|
||||
void OnDestroy()
|
||||
{
|
||||
if (_instance == this)
|
||||
_instance = null;
|
||||
}
|
||||
|
||||
private string GetFilePath(string slot)
|
||||
{
|
||||
return Path.Combine(DefaultSaveFolder, $"save_{slot}.json");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entry point to save to a named slot. Starts an async coroutine that writes to PlayerPrefs
|
||||
/// (placeholder behavior). Fires OnSaveCompleted when finished.
|
||||
/// </summary>
|
||||
public void Save(string slot = "default")
|
||||
{
|
||||
if (IsSaving)
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] Save called while another save is in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
StartCoroutine(SaveAsync(slot));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Entry point to load from a named slot. Starts an async coroutine that reads from PlayerPrefs
|
||||
/// (placeholder behavior). Fires OnLoadCompleted when finished.
|
||||
/// </summary>
|
||||
public void Load(string slot = "default")
|
||||
{
|
||||
if (IsLoading)
|
||||
{
|
||||
Logging.Warning("[SaveLoadManager] Load called while another load is in progress");
|
||||
return;
|
||||
}
|
||||
|
||||
StartCoroutine(LoadAsync(slot));
|
||||
}
|
||||
|
||||
// TODO: This is stupid overkill, but over verbose logging is king for now
|
||||
private IEnumerator SaveAsync(string slot)
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] Starting save for slot '{slot}'");
|
||||
IsSaving = true;
|
||||
|
||||
string path = GetFilePath(slot);
|
||||
string tempPath = path + ".tmp";
|
||||
string json = null;
|
||||
bool prepFailed = false;
|
||||
|
||||
// Prep phase: ensure folder exists and serialize (no yields allowed inside try/catch)
|
||||
try
|
||||
{
|
||||
Directory.CreateDirectory(DefaultSaveFolder);
|
||||
|
||||
if (currentSaveData == null)
|
||||
{
|
||||
Logging.Debug("[SaveLoadManager] currentSaveData is null, creating default instance before saving");
|
||||
currentSaveData = new SaveLoadData();
|
||||
}
|
||||
|
||||
// Pull latest card collection snapshot from CardSystem before serializing (don't overwrite with null)
|
||||
if (Data.CardSystem.CardSystemManager.Instance != null)
|
||||
{
|
||||
currentSaveData.cardCollection = Data.CardSystem.CardSystemManager.Instance.ExportCardCollectionState();
|
||||
}
|
||||
|
||||
json = JsonUtility.ToJson(currentSaveData, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Exception during save prep for slot '{slot}': {ex}");
|
||||
prepFailed = true;
|
||||
}
|
||||
|
||||
if (prepFailed || string.IsNullOrEmpty(json))
|
||||
{
|
||||
// Ensure we clean up state and notify listeners outside of the try/catch
|
||||
IsSaving = false;
|
||||
OnSaveCompleted?.Invoke(slot);
|
||||
Logging.Warning($"[SaveLoadManager] Aborting save for slot '{slot}' due to prep failure");
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Write phase: perform IO and atomic move with fallback
|
||||
try
|
||||
{
|
||||
File.WriteAllText(tempPath, json);
|
||||
|
||||
try
|
||||
{
|
||||
if (File.Exists(path))
|
||||
File.Delete(path);
|
||||
File.Move(tempPath, path);
|
||||
}
|
||||
catch (Exception moveEx)
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Atomic move failed for '{path}', attempting overwrite: {moveEx}");
|
||||
File.Copy(tempPath, path, true);
|
||||
File.Delete(tempPath);
|
||||
}
|
||||
|
||||
Logging.Debug($"[SaveLoadManager] Save data written to '{path}'");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Exception while saving slot '{slot}': {ex}");
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsSaving = false;
|
||||
OnSaveCompleted?.Invoke(slot);
|
||||
Debug.Log($"[SaveLoadManager] Save completed for slot '{slot}'");
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: This is stupid overkill, but over verbose logging is king for now
|
||||
private IEnumerator LoadAsync(string slot)
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] Starting load for slot '{slot}'");
|
||||
IsLoading = true;
|
||||
string path = GetFilePath(slot);
|
||||
|
||||
// Fast-path: no save file
|
||||
if (!File.Exists(path))
|
||||
{
|
||||
Logging.Debug($"[SaveLoadManager] No save found at '{path}', creating defaults");
|
||||
currentSaveData = new SaveLoadData();
|
||||
|
||||
// Simulate async operation and finish
|
||||
yield return null;
|
||||
|
||||
IsLoading = false;
|
||||
IsSaveDataLoaded = true;
|
||||
OnLoadCompleted?.Invoke(slot);
|
||||
yield break;
|
||||
}
|
||||
|
||||
// Simulate async operation (optional)
|
||||
yield return null;
|
||||
|
||||
try
|
||||
{
|
||||
string json = File.ReadAllText(path);
|
||||
|
||||
if (string.IsNullOrEmpty(json))
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Save file at '{path}' is empty. Creating defaults.");
|
||||
currentSaveData = new SaveLoadData();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Attempt to deserialize; if it fails or returns null, fall back to defaults
|
||||
var loaded = JsonUtility.FromJson<SaveLoadData>(json);
|
||||
if (loaded == null)
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Deserialized save data was null for slot '{slot}'. Creating defaults.");
|
||||
currentSaveData = new SaveLoadData();
|
||||
}
|
||||
else
|
||||
{
|
||||
currentSaveData = loaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Warning($"[SaveLoadManager] Exception while reading/deserializing save file at '{path}': {ex}");
|
||||
currentSaveData = new SaveLoadData();
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsLoading = false;
|
||||
IsSaveDataLoaded = true;
|
||||
OnLoadCompleted?.Invoke(slot);
|
||||
Logging.Debug($"[SaveLoadManager] Load completed for slot '{slot}'");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Core/SaveLoad/SaveLoadManager.cs.meta
Normal file
3
Assets/Scripts/Core/SaveLoad/SaveLoadManager.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a1731f4790be4ec3bab71506427768d7
|
||||
timeCreated: 1761553854
|
||||
@@ -25,8 +25,13 @@ namespace AppleHills.Core.Settings
|
||||
[Tooltip("Should debug messages be show on screen in Editor")]
|
||||
[SerializeField] private bool showDebugUiMessages = false;
|
||||
|
||||
[Header("Game Behavior Options")]
|
||||
[Tooltip("Should Time.timeScale be set to 0 when the game is paused")]
|
||||
[SerializeField] private bool pauseTimeOnPauseGame = true;
|
||||
|
||||
// Property getters
|
||||
public bool ShowDebugUiMessages => showDebugUiMessages;
|
||||
public bool PauseTimeOnPauseGame => pauseTimeOnPauseGame;
|
||||
|
||||
public override void OnValidate()
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Linq;
|
||||
using AppleHills.Data.CardSystem;
|
||||
using Bootstrap;
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
@@ -36,6 +37,9 @@ namespace Data.CardSystem
|
||||
public event Action<CardData> OnCardRarityUpgraded;
|
||||
public event Action<int> OnBoosterCountChanged;
|
||||
|
||||
// Keep a reference to unsubscribe safely
|
||||
private Action<string> _onSaveDataLoadedHandler;
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
_instance = this;
|
||||
@@ -49,9 +53,6 @@ namespace Data.CardSystem
|
||||
// Load card definitions from Addressables
|
||||
LoadCardDefinitionsFromAddressables();
|
||||
|
||||
// Build lookup dictionary
|
||||
BuildDefinitionLookup();
|
||||
|
||||
Logging.Debug("[CardSystemManager] Post-boot initialization complete");
|
||||
}
|
||||
|
||||
@@ -87,9 +88,54 @@ namespace Data.CardSystem
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build lookup now that cards are loaded
|
||||
BuildDefinitionLookup();
|
||||
|
||||
// Apply saved state when save data is available
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
if (SaveLoadManager.Instance.IsSaveDataLoaded)
|
||||
{
|
||||
ApplySavedCardStateIfAvailable();
|
||||
}
|
||||
else
|
||||
{
|
||||
SaveLoadManager.Instance.OnLoadCompleted += OnSaveDataLoadedHandler;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
// Apply saved state if present in the SaveLoadManager
|
||||
private void ApplySavedCardStateIfAvailable()
|
||||
{
|
||||
var data = SaveLoadManager.Instance?.currentSaveData;
|
||||
if (data?.cardCollection != null)
|
||||
{
|
||||
ApplyCardCollectionState(data.cardCollection);
|
||||
Logging.Debug("[CardSystemManager] Applied saved card collection state after loading definitions");
|
||||
}
|
||||
}
|
||||
|
||||
// Event handler for when save data load completes
|
||||
private void OnSaveDataLoadedHandler(string slot)
|
||||
{
|
||||
ApplySavedCardStateIfAvailable();
|
||||
if (SaveLoadManager.Instance != null)
|
||||
{
|
||||
SaveLoadManager.Instance.OnLoadCompleted -= OnSaveDataLoadedHandler;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Builds a lookup dictionary for quick access to card definitions by ID
|
||||
/// </summary>
|
||||
@@ -383,5 +429,58 @@ namespace Data.CardSystem
|
||||
|
||||
return (float)collectedOfRarity / totalOfRarity * 100f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Export current card collection to a serializable snapshot
|
||||
/// </summary>
|
||||
public CardCollectionState ExportCardCollectionState()
|
||||
{
|
||||
var state = new CardCollectionState
|
||||
{
|
||||
boosterPackCount = playerInventory.BoosterPackCount,
|
||||
cards = new List<SavedCardEntry>()
|
||||
};
|
||||
|
||||
foreach (var card in playerInventory.CollectedCards.Values)
|
||||
{
|
||||
if (string.IsNullOrEmpty(card.DefinitionId)) continue;
|
||||
state.cards.Add(new SavedCardEntry
|
||||
{
|
||||
definitionId = card.DefinitionId,
|
||||
rarity = card.Rarity,
|
||||
copiesOwned = card.CopiesOwned
|
||||
});
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Apply a previously saved snapshot to the runtime inventory
|
||||
/// </summary>
|
||||
public void ApplyCardCollectionState(CardCollectionState state)
|
||||
{
|
||||
if (state == null) return;
|
||||
|
||||
playerInventory.ClearAllCards();
|
||||
playerInventory.BoosterPackCount = state.boosterPackCount;
|
||||
OnBoosterCountChanged?.Invoke(playerInventory.BoosterPackCount);
|
||||
|
||||
foreach (var entry in state.cards)
|
||||
{
|
||||
if (string.IsNullOrEmpty(entry.definitionId)) continue;
|
||||
if (_definitionLookup.TryGetValue(entry.definitionId, out var def))
|
||||
{
|
||||
// Create from definition to ensure links, then overwrite runtime fields
|
||||
var cd = def.CreateCardData();
|
||||
cd.Rarity = entry.rarity;
|
||||
cd.CopiesOwned = entry.copiesOwned;
|
||||
playerInventory.AddCard(cd);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logging.Warning($"[CardSystemManager] Saved card definition not found: {entry.definitionId}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Bootstrap;
|
||||
using Core;
|
||||
using Interactions;
|
||||
using UnityEngine;
|
||||
@@ -46,23 +47,6 @@ namespace Dialogue
|
||||
Debug.LogError("SpeechBubble component is missing on Dialogue Component");
|
||||
}
|
||||
|
||||
// Register for global events
|
||||
if (PuzzleManager.Instance != null)
|
||||
PuzzleManager.Instance.OnStepCompleted += OnAnyPuzzleStepCompleted;
|
||||
|
||||
if (ItemManager.Instance != null)
|
||||
{
|
||||
ItemManager.Instance.OnItemPickedUp += OnAnyItemPickedUp;
|
||||
ItemManager.Instance.OnCorrectItemSlotted += OnAnyItemSlotted;
|
||||
ItemManager.Instance.OnIncorrectItemSlotted += OnAnyIncorrectItemSlotted;
|
||||
ItemManager.Instance.OnForbiddenItemSlotted += OnAnyForbiddenItemSlotted;
|
||||
ItemManager.Instance.OnItemSlotCleared += OnAnyItemSlotCleared;
|
||||
ItemManager.Instance.OnItemsCombined += OnAnyItemsCombined;
|
||||
}
|
||||
|
||||
// Auto-start the dialogue
|
||||
// StartDialogue();
|
||||
|
||||
var interactable = GetComponent<Interactable>();
|
||||
if (interactable != null)
|
||||
{
|
||||
@@ -74,6 +58,20 @@ namespace Dialogue
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
|
||||
BootCompletionService.RegisterInitAction(InitializePostBoot);
|
||||
}
|
||||
|
||||
private void InitializePostBoot()
|
||||
{
|
||||
// Register for global events
|
||||
PuzzleManager.Instance.OnStepCompleted += OnAnyPuzzleStepCompleted;
|
||||
ItemManager.Instance.OnItemPickedUp += OnAnyItemPickedUp;
|
||||
ItemManager.Instance.OnCorrectItemSlotted += OnAnyItemSlotted;
|
||||
ItemManager.Instance.OnIncorrectItemSlotted += OnAnyIncorrectItemSlotted;
|
||||
ItemManager.Instance.OnForbiddenItemSlotted += OnAnyForbiddenItemSlotted;
|
||||
ItemManager.Instance.OnItemSlotCleared += OnAnyItemSlotCleared;
|
||||
ItemManager.Instance.OnItemsCombined += OnAnyItemsCombined;
|
||||
}
|
||||
|
||||
private void OnCharacterArrived()
|
||||
@@ -457,6 +455,12 @@ namespace Dialogue
|
||||
// Global event handlers
|
||||
private void OnAnyPuzzleStepCompleted(PuzzleStepSO step)
|
||||
{
|
||||
// Initialize if needed
|
||||
if (!initialized)
|
||||
{
|
||||
StartDialogue();
|
||||
}
|
||||
|
||||
// Only react if we're active and waiting on a puzzle step
|
||||
if (!IsActive || IsCompleted || currentNode == null ||
|
||||
currentNode.nodeType != RuntimeDialogueNodeType.WaitOnPuzzleStep)
|
||||
@@ -465,19 +469,21 @@ namespace Dialogue
|
||||
// Check if this is the step we're waiting for
|
||||
if (step.stepId == currentNode.puzzleStepID)
|
||||
{
|
||||
// Instead of immediately moving to the next node, set the flag
|
||||
// Set the flag that condition is satisfied
|
||||
_conditionSatisfiedPendingAdvance = true;
|
||||
|
||||
// Update bubble visibility after state change to show interaction prompt
|
||||
if (speechBubble != null)
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
UpdateDialogueVisibilityOnItemEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAnyItemPickedUp(PickupItemData item)
|
||||
{
|
||||
// Initialize if needed
|
||||
if (!initialized)
|
||||
{
|
||||
StartDialogue();
|
||||
}
|
||||
|
||||
// Only react if we're active and waiting on an item pickup
|
||||
if (!IsActive || IsCompleted || currentNode == null ||
|
||||
currentNode.nodeType != RuntimeDialogueNodeType.WaitOnPickup)
|
||||
@@ -486,14 +492,10 @@ namespace Dialogue
|
||||
// Check if this is the item we're waiting for
|
||||
if (item.itemId == currentNode.pickupItemID)
|
||||
{
|
||||
// Instead of immediately moving to the next node, set the flag
|
||||
// Set the flag that condition is satisfied
|
||||
_conditionSatisfiedPendingAdvance = true;
|
||||
|
||||
// Update bubble visibility after state change to show interaction prompt
|
||||
if (speechBubble != null)
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
UpdateDialogueVisibilityOnItemEvent();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -501,6 +503,12 @@ namespace Dialogue
|
||||
{
|
||||
Logging.Debug("[DialogueComponent] OnAnyItemSlotted");
|
||||
|
||||
// Initialize if needed
|
||||
if (!initialized)
|
||||
{
|
||||
StartDialogue();
|
||||
}
|
||||
|
||||
// Only react if we're active and waiting on a slot
|
||||
if (!IsActive || IsCompleted || currentNode == null ||
|
||||
currentNode.nodeType != RuntimeDialogueNodeType.WaitOnSlot)
|
||||
@@ -509,19 +517,21 @@ namespace Dialogue
|
||||
// Check if this is the slot we're waiting for
|
||||
if (slotDefinition.itemId == currentNode.slotItemID)
|
||||
{
|
||||
// Instead of immediately moving to the next node, set the flag
|
||||
// Set the flag that condition is satisfied
|
||||
_conditionSatisfiedPendingAdvance = true;
|
||||
|
||||
// Update bubble visibility after state change to show interaction prompt
|
||||
if (speechBubble != null)
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
UpdateDialogueVisibilityOnItemEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAnyItemsCombined(PickupItemData itemA, PickupItemData itemB, PickupItemData resultItem)
|
||||
{
|
||||
// Initialize if needed
|
||||
if (!initialized)
|
||||
{
|
||||
StartDialogue();
|
||||
}
|
||||
|
||||
// Only react if we're active and waiting on a combination
|
||||
if (!IsActive || IsCompleted || currentNode == null ||
|
||||
currentNode.nodeType != RuntimeDialogueNodeType.WaitOnCombination)
|
||||
@@ -530,19 +540,21 @@ namespace Dialogue
|
||||
// Check if this is the result item we're waiting for
|
||||
if (resultItem.itemId == currentNode.combinationResultItemID)
|
||||
{
|
||||
// Instead of immediately moving to the next node, set the flag
|
||||
// Set the flag that condition is satisfied
|
||||
_conditionSatisfiedPendingAdvance = true;
|
||||
|
||||
// Update bubble visibility after state change to show interaction prompt
|
||||
if (speechBubble != null)
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
UpdateDialogueVisibilityOnItemEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAnyIncorrectItemSlotted(PickupItemData slotDefinition, PickupItemData slottedItem)
|
||||
{
|
||||
// Initialize if needed
|
||||
if (!initialized)
|
||||
{
|
||||
StartDialogue();
|
||||
}
|
||||
|
||||
// Update the slot state for displaying the correct dialogue lines
|
||||
if (!IsActive || IsCompleted || currentNode == null)
|
||||
return;
|
||||
@@ -554,16 +566,18 @@ namespace Dialogue
|
||||
_currentSlotState = ItemSlotState.Incorrect;
|
||||
_lastSlottedItem = slottedItem;
|
||||
|
||||
// Trigger dialogue update
|
||||
if (speechBubble != null)
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
UpdateDialogueVisibilityOnItemEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAnyForbiddenItemSlotted(PickupItemData slotDefinition, PickupItemData slottedItem)
|
||||
{
|
||||
// Initialize if needed
|
||||
if (!initialized)
|
||||
{
|
||||
StartDialogue();
|
||||
}
|
||||
|
||||
// Update the slot state for displaying the correct dialogue lines
|
||||
if (!IsActive || IsCompleted || currentNode == null)
|
||||
return;
|
||||
@@ -575,16 +589,18 @@ namespace Dialogue
|
||||
_currentSlotState = ItemSlotState.Forbidden;
|
||||
_lastSlottedItem = slottedItem;
|
||||
|
||||
// Trigger dialogue update
|
||||
if (speechBubble != null)
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
}
|
||||
UpdateDialogueVisibilityOnItemEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAnyItemSlotCleared(PickupItemData removedItem)
|
||||
{
|
||||
// Initialize if needed
|
||||
if (!initialized)
|
||||
{
|
||||
StartDialogue();
|
||||
}
|
||||
|
||||
// Update the slot state when an item is removed
|
||||
if (!IsActive || IsCompleted || currentNode == null)
|
||||
return;
|
||||
@@ -594,8 +610,21 @@ namespace Dialogue
|
||||
{
|
||||
_currentSlotState = ItemSlotState.None;
|
||||
_lastSlottedItem = null;
|
||||
|
||||
// Trigger dialogue update
|
||||
|
||||
UpdateDialogueVisibilityOnItemEvent();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateDialogueVisibilityOnItemEvent()
|
||||
{
|
||||
// If auto-play is enabled, immediately display dialogue
|
||||
if (currentNode.shouldAutoPlay)
|
||||
{
|
||||
OnCharacterArrived();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Manual mode: just update bubble visibility to show interaction prompt
|
||||
if (speechBubble != null)
|
||||
{
|
||||
speechBubble.UpdatePromptVisibility(HasAnyLines());
|
||||
|
||||
@@ -50,6 +50,9 @@ namespace Dialogue
|
||||
public string slotItemID; // For WaitOnSlot
|
||||
public string combinationResultItemID; // For WaitOnCombination
|
||||
|
||||
// Auto-play dialogue when condition is met (for item-related nodes)
|
||||
public bool shouldAutoPlay;
|
||||
|
||||
// For WaitOnSlot - different responses
|
||||
[HideInInspector]
|
||||
public List<string> incorrectItemLines = new List<string>();
|
||||
|
||||
@@ -109,6 +109,32 @@ namespace Interactions
|
||||
if ((heldItemData == null && _currentlySlottedItemObject != null)
|
||||
|| (heldItemData != null && _currentlySlottedItemObject != null))
|
||||
{
|
||||
// If both held and slotted items exist, attempt combination via follower (reuse existing logic from Pickup)
|
||||
if (heldItemData != null && _currentlySlottedItemData != null)
|
||||
{
|
||||
var slottedPickup = _currentlySlottedItemObject?.GetComponent<Pickup>();
|
||||
if (slottedPickup != null)
|
||||
{
|
||||
var comboResult = FollowerController.TryCombineItems(slottedPickup, out var combinationResultItem);
|
||||
if (combinationResultItem != null && comboResult == FollowerController.CombinationResult.Successful)
|
||||
{
|
||||
// Combination succeeded: fire slot-removed events and clear internals (don't call SlotItem to avoid duplicate events)
|
||||
onItemSlotRemoved?.Invoke();
|
||||
OnItemSlotRemoved?.Invoke(_currentlySlottedItemData);
|
||||
_currentState = ItemSlotState.None;
|
||||
|
||||
// Clear internal references and visuals
|
||||
_currentlySlottedItemObject = null;
|
||||
_currentlySlottedItemData = null;
|
||||
UpdateSlottedSprite();
|
||||
|
||||
Interactable.BroadcastInteractionComplete(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// No combination (or not applicable) -> perform normal swap/pickup behavior
|
||||
FollowerController.TryPickupItem(_currentlySlottedItemObject, _currentlySlottedItemData, false);
|
||||
onItemSlotRemoved?.Invoke();
|
||||
OnItemSlotRemoved?.Invoke(_currentlySlottedItemData);
|
||||
|
||||
40
Assets/Scripts/Movement/FollowerAnimationEventBridge.cs
Normal file
40
Assets/Scripts/Movement/FollowerAnimationEventBridge.cs
Normal file
@@ -0,0 +1,40 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Movement
|
||||
{
|
||||
/// <summary>
|
||||
/// Bridge script that forwards Animation Events from the character art child object
|
||||
/// to the FollowerController on the parent GameObject.
|
||||
/// Attach this to the same GameObject that has the Animator component.
|
||||
/// </summary>
|
||||
public class FollowerAnimationEventBridge : MonoBehaviour
|
||||
{
|
||||
[SerializeField] private FollowerController followerController;
|
||||
|
||||
void Awake()
|
||||
{
|
||||
// Find the FollowerController on the parent
|
||||
if (followerController == null)
|
||||
{
|
||||
followerController = GetComponentInParent<FollowerController>();
|
||||
}
|
||||
|
||||
if (followerController == null)
|
||||
{
|
||||
Debug.LogError("[FollowerAnimationEventBridge] Could not find FollowerController in parent. This script must be on a child of the FollowerController.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called by Animation Events. Forwards to the parent FollowerController.
|
||||
/// </summary>
|
||||
public void OnStationaryAnimationComplete()
|
||||
{
|
||||
if (followerController != null)
|
||||
{
|
||||
followerController.OnStationaryAnimationComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 39f2e64420884f11a9022fea7b3be5d0
|
||||
timeCreated: 1761571513
|
||||
@@ -11,6 +11,8 @@ using Core;
|
||||
/// </summary>
|
||||
public class FollowerController: MonoBehaviour
|
||||
{
|
||||
private static readonly int CombineTrigger = Animator.StringToHash("Combine");
|
||||
|
||||
[Header("Follower Settings")]
|
||||
public bool debugDrawTarget = true;
|
||||
/// <summary>
|
||||
@@ -52,6 +54,11 @@ public class FollowerController: MonoBehaviour
|
||||
/// </summary>
|
||||
public SpriteRenderer heldObjectRenderer;
|
||||
|
||||
// Stationary animation state
|
||||
private bool _isPlayingStationaryAnimation = false;
|
||||
private Coroutine _stationaryAnimationCoroutine;
|
||||
private System.Action _stationaryAnimationCallback;
|
||||
|
||||
private bool _isReturningToPlayer = false;
|
||||
private float _playerMaxSpeed = 5f;
|
||||
private float _followerMaxSpeed = 6f;
|
||||
@@ -117,6 +124,19 @@ public class FollowerController: MonoBehaviour
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip all movement logic when playing a stationary animation
|
||||
if (_isPlayingStationaryAnimation)
|
||||
{
|
||||
// Still update animator with zero speed to maintain idle state
|
||||
if (_animator != null)
|
||||
{
|
||||
_animator.SetFloat("Speed", 0f);
|
||||
_animator.SetFloat("DirX", _lastDirX);
|
||||
_animator.SetFloat("DirY", _lastDirY);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
_timer += Time.deltaTime;
|
||||
if (_timer >= _settings.FollowUpdateInterval)
|
||||
{
|
||||
@@ -420,6 +440,100 @@ public class FollowerController: MonoBehaviour
|
||||
}
|
||||
#endregion Movement
|
||||
|
||||
#region StationaryAnimations
|
||||
/// <summary>
|
||||
/// Pauses all movement. Can be called directly from Timeline, Animation Events, or code.
|
||||
/// Call ResumeMovement() to resume.
|
||||
/// </summary>
|
||||
public void PauseMovement()
|
||||
{
|
||||
_isPlayingStationaryAnimation = true;
|
||||
_currentSpeed = 0f;
|
||||
Logging.Debug("[FollowerController] Movement paused");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resumes movement after being paused. Can be called from Timeline, Animation Events, or code.
|
||||
/// </summary>
|
||||
public void ResumeMovement()
|
||||
{
|
||||
_isPlayingStationaryAnimation = false;
|
||||
Logging.Debug("[FollowerController] Movement resumed");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Plays an animation while pausing all movement. Resumes movement when animation completes.
|
||||
/// Uses a hybrid approach: Animation Events (if set up) OR timeout fallback (if not).
|
||||
/// To use Animation Events: Add an event at the end of your animation that calls OnStationaryAnimationComplete().
|
||||
/// </summary>
|
||||
/// <param name="triggerName">The animator trigger name to activate</param>
|
||||
/// <param name="maxDuration">Maximum time to wait before auto-resuming (fallback if no Animation Event)</param>
|
||||
/// <param name="onComplete">Optional callback to invoke when animation completes</param>
|
||||
public void PlayAnimationStationary(string triggerName, float maxDuration = 2f, System.Action onComplete = null)
|
||||
{
|
||||
if (_animator == null)
|
||||
{
|
||||
Logging.Warning("[FollowerController] Cannot play stationary animation - no Animator found");
|
||||
onComplete?.Invoke();
|
||||
return;
|
||||
}
|
||||
|
||||
// Stop any existing stationary animation
|
||||
if (_stationaryAnimationCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_stationaryAnimationCoroutine);
|
||||
}
|
||||
|
||||
_isPlayingStationaryAnimation = true;
|
||||
_stationaryAnimationCallback = onComplete;
|
||||
_currentSpeed = 0f; // Immediately stop movement
|
||||
|
||||
// Trigger the animation
|
||||
_animator.SetTrigger(triggerName);
|
||||
|
||||
// Start timeout coroutine (will be stopped early if Animation Event fires)
|
||||
_stationaryAnimationCoroutine = StartCoroutine(StationaryAnimationTimeoutCoroutine(maxDuration));
|
||||
}
|
||||
|
||||
private System.Collections.IEnumerator StationaryAnimationTimeoutCoroutine(float maxDuration)
|
||||
{
|
||||
yield return new WaitForSeconds(maxDuration);
|
||||
|
||||
// If we reach here, the Animation Event didn't fire - use fallback
|
||||
Logging.Debug($"[FollowerController] Stationary animation timeout reached ({maxDuration}s) - resuming movement");
|
||||
ResumeMovementAfterAnimation();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Public method to be called by Animation Events at the end of stationary animations.
|
||||
/// Add this as an Animation Event in your animation clip for frame-perfect timing.
|
||||
/// </summary>
|
||||
public void OnStationaryAnimationComplete()
|
||||
{
|
||||
Logging.Debug("[FollowerController] Stationary animation completed via Animation Event");
|
||||
ResumeMovementAfterAnimation();
|
||||
}
|
||||
|
||||
private void ResumeMovementAfterAnimation()
|
||||
{
|
||||
if (!_isPlayingStationaryAnimation) return; // Already resumed
|
||||
|
||||
// Stop the timeout coroutine if it's still running
|
||||
if (_stationaryAnimationCoroutine != null)
|
||||
{
|
||||
StopCoroutine(_stationaryAnimationCoroutine);
|
||||
_stationaryAnimationCoroutine = null;
|
||||
}
|
||||
|
||||
_isPlayingStationaryAnimation = false;
|
||||
|
||||
// Invoke callback if provided
|
||||
var callback = _stationaryAnimationCallback;
|
||||
_stationaryAnimationCallback = null;
|
||||
callback?.Invoke();
|
||||
}
|
||||
#endregion StationaryAnimations
|
||||
|
||||
#region ItemInteractions
|
||||
public void TryPickupItem(GameObject itemObject, PickupItemData itemData, bool dropItem = true)
|
||||
{
|
||||
@@ -445,7 +559,7 @@ public class FollowerController: MonoBehaviour
|
||||
|
||||
public CombinationResult TryCombineItems(Pickup pickupA, out GameObject newItem)
|
||||
{
|
||||
_animator.ResetTrigger("Combine");
|
||||
_animator.ResetTrigger(CombineTrigger);
|
||||
newItem = null;
|
||||
if (_cachedPickupObject == null)
|
||||
{
|
||||
@@ -468,7 +582,7 @@ public class FollowerController: MonoBehaviour
|
||||
Destroy(pickupA.gameObject);
|
||||
Destroy(pickupB.gameObject);
|
||||
TryPickupItem(newItem, itemData);
|
||||
_animator.SetTrigger("Combine");
|
||||
PlayAnimationStationary("Combine", 10.0f);
|
||||
return CombinationResult.Successful;
|
||||
}
|
||||
|
||||
|
||||
@@ -177,7 +177,7 @@ namespace AppleHills.Tests
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[CustomEditor(typeof(CardSystemTester))]
|
||||
public class CardSystemTesterEditor : Editor
|
||||
public class CardSystemTesterEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
@@ -274,7 +274,7 @@ namespace UI.CardSystem
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 0f;
|
||||
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
|
||||
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete, obeyTimescale: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -288,7 +288,7 @@ namespace UI.CardSystem
|
||||
// Simple fade out animation
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
|
||||
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete, obeyTimescale: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -177,7 +177,8 @@ namespace UI.CardSystem
|
||||
pulseDuration/2,
|
||||
0,
|
||||
Tween.EaseIn);
|
||||
});
|
||||
},
|
||||
obeyTimescale: false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace UI.CardSystem
|
||||
private void Awake()
|
||||
{
|
||||
_cardManager = CardSystemManager.Instance;
|
||||
_cardAlbumUI = FindObjectOfType<CardAlbumUI>();
|
||||
_cardAlbumUI = FindFirstObjectByType<CardAlbumUI>();
|
||||
|
||||
// Set up button listeners
|
||||
if (openBoosterButton != null)
|
||||
@@ -255,7 +255,7 @@ namespace UI.CardSystem
|
||||
// Animate the booster pack opening
|
||||
Tween.LocalScale(boosterPackObject.transform, Vector3.zero, 0.3f, 0f, Tween.EaseInBack, Tween.LoopType.None, null, () => {
|
||||
boosterPackObject.SetActive(false);
|
||||
});
|
||||
}, obeyTimescale: false);
|
||||
}
|
||||
|
||||
if (openBoosterButton != null)
|
||||
@@ -322,7 +322,7 @@ namespace UI.CardSystem
|
||||
Debug.Log($"[BoosterOpeningPage] Card back {i} activated");
|
||||
|
||||
// Play reveal animation using Pixelplacement.Tween
|
||||
Tween.LocalScale(cardBackObj.transform, Vector3.one, 0.5f, 0f, Tween.EaseOutBack);
|
||||
Tween.LocalScale(cardBackObj.transform, Vector3.one, 0.5f, 0f, Tween.EaseOutBack, obeyTimescale: false);
|
||||
|
||||
// Wait for animation delay
|
||||
yield return new WaitForSeconds(cardRevealDelay);
|
||||
@@ -374,7 +374,7 @@ namespace UI.CardSystem
|
||||
Transform cardBackTransform = cardBack.transform;
|
||||
|
||||
// Step 1: Flip the card 90 degrees (showing the edge)
|
||||
Tween.LocalRotation(cardBackTransform, new Vector3(0, 90, 0), flipAnimationDuration * 0.5f, 0);
|
||||
Tween.LocalRotation(cardBackTransform, new Vector3(0, 90, 0), flipAnimationDuration * 0.5f, 0, obeyTimescale: false);
|
||||
|
||||
// Wait for half the flip duration
|
||||
yield return new WaitForSeconds(flipAnimationDuration * 0.5f);
|
||||
@@ -405,7 +405,7 @@ namespace UI.CardSystem
|
||||
}
|
||||
|
||||
// Step 3: Finish the flip animation (from 90 degrees to 0)
|
||||
Tween.LocalRotation(cardObj.transform, Vector3.zero, flipAnimationDuration * 0.5f, 0);
|
||||
Tween.LocalRotation(cardObj.transform, Vector3.zero, flipAnimationDuration * 0.5f, 0, obeyTimescale: false);
|
||||
|
||||
// Increment counter of revealed cards
|
||||
_revealedCardCount++;
|
||||
@@ -441,8 +441,8 @@ namespace UI.CardSystem
|
||||
Vector3 originalScale = cardTransform.localScale;
|
||||
|
||||
// Sequence: Scale up slightly, then back to normal
|
||||
Tween.LocalScale(cardTransform, originalScale * 1.2f, 0.2f, 0.1f, Tween.EaseOutBack);
|
||||
Tween.LocalScale(cardTransform, originalScale, 0.15f, 0.3f, Tween.EaseIn);
|
||||
Tween.LocalScale(cardTransform, originalScale * 1.2f, 0.2f, 0.1f, Tween.EaseOutBack, obeyTimescale: false);
|
||||
Tween.LocalScale(cardTransform, originalScale, 0.15f, 0.3f, Tween.EaseIn, obeyTimescale: false);
|
||||
|
||||
// Play sound effect based on rarity (if available)
|
||||
// This would require audio source components to be set up
|
||||
@@ -463,7 +463,7 @@ namespace UI.CardSystem
|
||||
continueButton.gameObject.SetActive(true);
|
||||
continueButton.transform.localScale = Vector3.zero;
|
||||
|
||||
Tween.LocalScale(continueButton.transform, Vector3.one, 0.3f, 0f, Tween.EaseOutBack);
|
||||
Tween.LocalScale(continueButton.transform, Vector3.one, 0.3f, 0f, Tween.EaseOutBack, obeyTimescale: false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,8 +542,8 @@ namespace UI.CardSystem
|
||||
Vector3 targetPos = card.transform.parent.InverseTransformPoint(backpackWorldPos);
|
||||
|
||||
// Start the move animation - ensure no cancellation between animations
|
||||
Tween.LocalPosition(card.transform, targetPos, animationDuration, cardDelay * i, Tween.EaseInOut);
|
||||
Tween.LocalScale(card.transform, Vector3.zero, animationDuration, cardDelay * i, Tween.EaseIn);
|
||||
Tween.LocalPosition(card.transform, targetPos, animationDuration, cardDelay * i, Tween.EaseInOut, obeyTimescale: false);
|
||||
Tween.LocalScale(card.transform, Vector3.zero, animationDuration, cardDelay * i, Tween.EaseIn, obeyTimescale: false);
|
||||
|
||||
Debug.Log($"[BoosterOpeningPage] Starting animation for card {i}");
|
||||
}
|
||||
@@ -578,7 +578,7 @@ namespace UI.CardSystem
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 0f;
|
||||
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
|
||||
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete, obeyTimescale: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -595,7 +595,7 @@ namespace UI.CardSystem
|
||||
// Simple fade out animation
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
|
||||
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete, obeyTimescale: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace UI.CardSystem
|
||||
|
||||
// Animate the notification dot for feedback
|
||||
boosterNotificationDot.transform.localScale = Vector3.one * 1.2f;
|
||||
Tween.LocalScale(boosterNotificationDot.transform, Vector3.one, 0.3f, 0f);
|
||||
Tween.LocalScale(boosterNotificationDot.transform, Vector3.one, 0.3f, 0f, obeyTimescale: false);
|
||||
|
||||
// Update visibility based on count
|
||||
UpdateBoosterVisibility();
|
||||
|
||||
@@ -175,7 +175,7 @@ namespace UI.CardSystem
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
canvasGroup.alpha = 0f;
|
||||
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
|
||||
Tween.Value(0f, 1f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete, obeyTimescale: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -192,7 +192,7 @@ namespace UI.CardSystem
|
||||
// Simple fade out animation
|
||||
if (canvasGroup != null)
|
||||
{
|
||||
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete);
|
||||
Tween.Value(canvasGroup.alpha, 0f, (value) => canvasGroup.alpha = value, transitionDuration, 0f, Tween.EaseInOut, Tween.LoopType.None, null, onComplete, obeyTimescale: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace UI.CardSystem
|
||||
|
||||
#if UNITY_EDITOR
|
||||
[CustomEditor(typeof(CardUIElement))]
|
||||
public class CardUIElementEditor : Editor
|
||||
public class CardUIElementEditor : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections;
|
||||
using Bootstrap;
|
||||
using Core;
|
||||
using Core.SaveLoad;
|
||||
using Input;
|
||||
using Pixelplacement;
|
||||
using UI.Core;
|
||||
@@ -10,8 +11,15 @@ namespace UI.Tutorial
|
||||
{
|
||||
public class DivingTutorial : MonoBehaviour, ITouchInputConsumer
|
||||
{
|
||||
public enum ProgressType
|
||||
{
|
||||
Manual, // Wait for player tap after animation loop
|
||||
Auto // Automatically progress after animation loop
|
||||
}
|
||||
|
||||
private StateMachine _stateMachine;
|
||||
public bool playTutorial;
|
||||
[SerializeField] private ProgressType progressType = ProgressType.Auto;
|
||||
|
||||
// gating for input until current state's animation finishes first loop
|
||||
[SerializeField] private GameObject tapPrompt;
|
||||
@@ -31,8 +39,10 @@ namespace UI.Tutorial
|
||||
|
||||
void InitializeTutorial()
|
||||
{
|
||||
if (playTutorial)
|
||||
if (playTutorial && !SaveLoadManager.Instance.currentSaveData.playedDivingTutorial)
|
||||
{
|
||||
// TODO: Possibly do it better, but for now just mark tutorial as played immediately
|
||||
SaveLoadManager.Instance.currentSaveData.playedDivingTutorial = true;
|
||||
// pause the game, hide UI, and register for input overrides
|
||||
GameManager.Instance.RequestPause(this);
|
||||
UIPageController.Instance.HideAllUI();
|
||||
@@ -104,7 +114,8 @@ namespace UI.Tutorial
|
||||
_canAcceptInput = allow;
|
||||
if (tapPrompt != null)
|
||||
{
|
||||
tapPrompt.SetActive(allow);
|
||||
// Only show tap prompt in Manual mode
|
||||
tapPrompt.SetActive(allow && progressType == ProgressType.Manual);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +209,19 @@ namespace UI.Tutorial
|
||||
yield return null;
|
||||
}
|
||||
|
||||
SetInputEnabled(true);
|
||||
// After first loop completes, handle based on progress type
|
||||
if (progressType == ProgressType.Auto)
|
||||
{
|
||||
// Auto mode: immediately progress to next state
|
||||
_stateMachine.Next(true);
|
||||
SetupInputGateForCurrentState();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Manual mode: enable input and wait for player tap
|
||||
SetInputEnabled(true);
|
||||
}
|
||||
|
||||
_waitLoopCoroutine = null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,3 +13,4 @@ MonoBehaviour:
|
||||
m_Name: DebugSettings
|
||||
m_EditorClassIdentifier: AppleHillsScripts::AppleHills.Core.Settings.DebugSettings
|
||||
showDebugUiMessages: 1
|
||||
pauseTimeOnPauseGame: 1
|
||||
|
||||
8
Assets/Signals.meta
Normal file
8
Assets/Signals.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ba6a6b0f020a9741a46f32cdfe270f3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
14
Assets/Signals/PausePulverMovement.signal
Normal file
14
Assets/Signals/PausePulverMovement.signal
Normal file
@@ -0,0 +1,14 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d6fa2d92fc1b3f34da284357edf89c3b, type: 3}
|
||||
m_Name: PausePulverMovement
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalAsset
|
||||
8
Assets/Signals/PausePulverMovement.signal.meta
Normal file
8
Assets/Signals/PausePulverMovement.signal.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2a32e2abdb44cb1469e5c6b9a25f98bc
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
14
Assets/Signals/ResumePulverMovement.signal
Normal file
14
Assets/Signals/ResumePulverMovement.signal
Normal file
@@ -0,0 +1,14 @@
|
||||
%YAML 1.1
|
||||
%TAG !u! tag:unity3d.com,2011:
|
||||
--- !u!114 &11400000
|
||||
MonoBehaviour:
|
||||
m_ObjectHideFlags: 0
|
||||
m_CorrespondingSourceObject: {fileID: 0}
|
||||
m_PrefabInstance: {fileID: 0}
|
||||
m_PrefabAsset: {fileID: 0}
|
||||
m_GameObject: {fileID: 0}
|
||||
m_Enabled: 1
|
||||
m_EditorHideFlags: 0
|
||||
m_Script: {fileID: 11500000, guid: d6fa2d92fc1b3f34da284357edf89c3b, type: 3}
|
||||
m_Name: ResumePulverMovement
|
||||
m_EditorClassIdentifier: Unity.Timeline::UnityEngine.Timeline.SignalAsset
|
||||
8
Assets/Signals/ResumePulverMovement.signal.meta
Normal file
8
Assets/Signals/ResumePulverMovement.signal.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2ec36cde76b6baf4299c0dd9ab54714e
|
||||
NativeFormatImporter:
|
||||
externalObjects: {}
|
||||
mainObjectFileID: 11400000
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user