First commit for private source control. Older commits available on Github.
This commit is contained in:
BIN
Assets/Scripts/.DS_Store
vendored
Normal file
BIN
Assets/Scripts/.DS_Store
vendored
Normal file
Binary file not shown.
3
Assets/Scripts/Data.meta
Normal file
3
Assets/Scripts/Data.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 75e2bfdd1e61468781777eb41e041df7
|
||||
timeCreated: 1769700576
|
||||
BIN
Assets/Scripts/Data/.DS_Store
vendored
Normal file
BIN
Assets/Scripts/Data/.DS_Store
vendored
Normal file
Binary file not shown.
3
Assets/Scripts/Data/Assets.meta
Normal file
3
Assets/Scripts/Data/Assets.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 11e83d25ac154a7c9d8d905c6ba277a7
|
||||
timeCreated: 1769711173
|
||||
85
Assets/Scripts/Data/Assets/AssetEntry.cs
Normal file
85
Assets/Scripts/Data/Assets/AssetEntry.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using BriarQueen.Data.Identifiers;
|
||||
using NaughtyAttributes;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
|
||||
namespace BriarQueen.Data.Assets
|
||||
{
|
||||
[Serializable]
|
||||
[CreateAssetMenu(fileName = "New Asset Entry", menuName = "Briar Queen/Assets/New Asset Entry")]
|
||||
public class AssetEntry : ScriptableObject
|
||||
{
|
||||
public enum AssetEntryType
|
||||
{
|
||||
None = 0,
|
||||
UI = 1,
|
||||
Scene = 2,
|
||||
Level = 3,
|
||||
Item = 4
|
||||
}
|
||||
|
||||
[Header("Asset Type")]
|
||||
[SerializeField]
|
||||
private AssetEntryType _entryType;
|
||||
|
||||
[Header("Asset Key")]
|
||||
[SerializeField]
|
||||
[ShowIf(nameof(IsUI))]
|
||||
private UIKey _uiKey;
|
||||
|
||||
[SerializeField]
|
||||
[ShowIf(nameof(IsScene))]
|
||||
private SceneKey _sceneKey;
|
||||
|
||||
[SerializeField]
|
||||
[ShowIf(nameof(IsLevel))]
|
||||
private LevelKey _levelKey;
|
||||
|
||||
[SerializeField]
|
||||
[ShowIf(nameof(IsItem))]
|
||||
private AssetItemKey _itemKey;
|
||||
|
||||
[Header("Addressable Reference")]
|
||||
[Tooltip("Addressable asset reference to load.")]
|
||||
[SerializeField]
|
||||
private AssetReference _asset;
|
||||
|
||||
public bool IsUI => _entryType == AssetEntryType.UI;
|
||||
public bool IsScene => _entryType == AssetEntryType.Scene;
|
||||
public bool IsLevel => _entryType == AssetEntryType.Level;
|
||||
public bool IsItem => _entryType == AssetEntryType.Item;
|
||||
|
||||
public AssetEntryType EntryType => _entryType;
|
||||
|
||||
public UIKey UIKey => _uiKey;
|
||||
public SceneKey SceneKey => _sceneKey;
|
||||
public LevelKey LevelKey => _levelKey;
|
||||
public AssetItemKey ItemKey => _itemKey;
|
||||
|
||||
public AssetReference Asset => _asset;
|
||||
|
||||
public string AssetKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return _entryType switch
|
||||
{
|
||||
AssetEntryType.UI when _uiKey != UIKey.None =>
|
||||
AssetKeyIdentifiers.Get(_uiKey),
|
||||
|
||||
AssetEntryType.Scene when _sceneKey != SceneKey.None =>
|
||||
AssetKeyIdentifiers.Get(_sceneKey),
|
||||
|
||||
AssetEntryType.Level when _levelKey != LevelKey.None =>
|
||||
AssetKeyIdentifiers.Get(_levelKey),
|
||||
|
||||
AssetEntryType.Item when _itemKey != AssetItemKey.None =>
|
||||
AssetKeyIdentifiers.Get(_itemKey),
|
||||
|
||||
_ => string.Empty
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Assets/AssetEntry.cs.meta
Normal file
3
Assets/Scripts/Data/Assets/AssetEntry.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b492dfc759934d71b4f9cc4f8b41a155
|
||||
timeCreated: 1769711173
|
||||
17
Assets/Scripts/Data/BriarQueen.Data.asmdef
Normal file
17
Assets/Scripts/Data/BriarQueen.Data.asmdef
Normal file
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"name": "BriarQueen.Data",
|
||||
"rootNamespace": "BriarQueen",
|
||||
"references": [
|
||||
"GUID:776d03a35f1b52c4a9aed9f56d7b4229",
|
||||
"GUID:9e24947de15b9834991c9d8411ea37cf"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/Scripts/Data/BriarQueen.Data.asmdef.meta
Normal file
7
Assets/Scripts/Data/BriarQueen.Data.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bdf0eff65032c4178bf18aa9c96b1c70
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Scripts/Data/IO.meta
Normal file
3
Assets/Scripts/Data/IO.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 42bc99ebdabe4d1fb2065896a1f6e552
|
||||
timeCreated: 1769703501
|
||||
13
Assets/Scripts/Data/IO/FilePaths.cs
Normal file
13
Assets/Scripts/Data/IO/FilePaths.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Data.IO
|
||||
{
|
||||
public static class FilePaths
|
||||
{
|
||||
private static readonly string ApplicationData = Application.persistentDataPath;
|
||||
public static readonly string SaveDataFolder = Path.Combine(ApplicationData, "Saves");
|
||||
public static readonly string SaveBackupDataFolder = Path.Combine(Application.persistentDataPath, "Backups");
|
||||
public static readonly string ConfigFolder = Path.Combine(Application.persistentDataPath, "Configs");
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/IO/FilePaths.cs.meta
Normal file
3
Assets/Scripts/Data/IO/FilePaths.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 437ea8a487054abc95c09442f73f0374
|
||||
timeCreated: 1769703501
|
||||
3
Assets/Scripts/Data/IO/Saves.meta
Normal file
3
Assets/Scripts/Data/IO/Saves.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 377fc30dd8794b1a8fa98f9842272263
|
||||
timeCreated: 1769703058
|
||||
150
Assets/Scripts/Data/IO/Saves/SaveGame.cs
Normal file
150
Assets/Scripts/Data/IO/Saves/SaveGame.cs
Normal file
@@ -0,0 +1,150 @@
|
||||
// ==============================
|
||||
// SaveGame.cs (refactored)
|
||||
// ==============================
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BriarQueen.Data.Identifiers;
|
||||
using MemoryPack;
|
||||
|
||||
namespace BriarQueen.Data.IO.Saves
|
||||
{
|
||||
[Serializable]
|
||||
[MemoryPackable]
|
||||
public partial class SaveGame
|
||||
{
|
||||
public string SaveVersion = "0.0.2-alpha";
|
||||
public string SaveFileName;
|
||||
|
||||
// Inventory & item tracking
|
||||
public List<ItemSaveData> InventoryData = new();
|
||||
public List<ItemSaveData> CollectedItems = new();
|
||||
public List<ItemSaveData> RemovedItems = new();
|
||||
|
||||
public Dictionary<ToolID, bool> Tools = new();
|
||||
|
||||
// Codex
|
||||
public List<CodexSaveData> DiscoveredCodexEntries = new();
|
||||
|
||||
// Current location
|
||||
public string CurrentSceneID;
|
||||
public string CurrentLevelID;
|
||||
|
||||
// Per-puzzle persisted state (resume progress when revisiting)
|
||||
public List<PuzzleStateSaveData> PuzzleStates = new();
|
||||
|
||||
public bool OpeningCinematicPlayed;
|
||||
|
||||
// Centralized game variables
|
||||
public PersistentGameVariables PersistentVariables = new();
|
||||
|
||||
// Level-specific hints
|
||||
public Dictionary<string, int> LevelHintStages = new();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[MemoryPackable]
|
||||
public partial class ItemSaveData
|
||||
{
|
||||
public string UniqueIdentifier;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[MemoryPackable]
|
||||
public partial class CodexSaveData
|
||||
{
|
||||
public string UniqueIdentifier;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[MemoryPackable]
|
||||
public partial class PuzzleStateSaveData
|
||||
{
|
||||
public string PuzzleID;
|
||||
public byte[] State;
|
||||
public bool Completed;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[MemoryPackable]
|
||||
public partial class PersistentGameVariables
|
||||
{
|
||||
public GameVariables Game = new();
|
||||
public TutorialPopupVariables TutorialPopupVariables = new();
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[MemoryPackable]
|
||||
public partial class TutorialPopupVariables
|
||||
{
|
||||
// Tracks which popups have been shown
|
||||
public HashSet<TutorialPopupID> DisplayedPopups = new();
|
||||
|
||||
public bool HasBeenDisplayed(TutorialPopupID id)
|
||||
{
|
||||
return DisplayedPopups.Contains(id);
|
||||
}
|
||||
|
||||
public void MarkDisplayed(TutorialPopupID id)
|
||||
{
|
||||
DisplayedPopups.Add(id);
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public enum LevelFlag
|
||||
{
|
||||
None = 0,
|
||||
FountainVinesCut,
|
||||
PumpHouseOpened,
|
||||
PumpHousePipesFixed,
|
||||
PumpWaterRestored,
|
||||
WorkshopBagHoleDug,
|
||||
WorkshopSafeUnlocked,
|
||||
WorkshopDownstairsDoorOpen,
|
||||
WorkshopDownstairsLightOn,
|
||||
WorkshopGrindstoneRepaired,
|
||||
StreetGateOpen,
|
||||
StreetVinesCut,
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
[MemoryPackable]
|
||||
public partial class GameVariables
|
||||
{
|
||||
// Type-safe level flags using enum
|
||||
public Dictionary<LevelFlag, bool> LevelFlags = new();
|
||||
|
||||
// Tracks completed puzzles
|
||||
public Dictionary<string, bool> PuzzleCompleted = new();
|
||||
|
||||
// Candle slots
|
||||
public Dictionary<int, string> WorkshopCandleSlotsFilled = new()
|
||||
{
|
||||
{ 0, ItemIDs.Pickups[ItemKey.BlueCandle] },
|
||||
{ 3, ItemIDs.Pickups[ItemKey.OrangeCandle] },
|
||||
{ 5, ItemIDs.Pickups[ItemKey.RedCandle] }
|
||||
};
|
||||
|
||||
// -------- Helper Methods --------
|
||||
public bool IsPuzzleCompleted(PuzzleKey puzzle)
|
||||
{
|
||||
return PuzzleCompleted.TryGetValue(PuzzleIdentifiers.AllPuzzles[puzzle], out var completed) && completed;
|
||||
}
|
||||
|
||||
public void SetPuzzleCompleted(PuzzleKey puzzle, bool completed = true)
|
||||
{
|
||||
PuzzleCompleted[PuzzleIdentifiers.AllPuzzles[puzzle]] = completed;
|
||||
}
|
||||
|
||||
public bool GetLevelFlag(LevelFlag flag)
|
||||
{
|
||||
return LevelFlags.TryGetValue(flag, out var value) && value;
|
||||
}
|
||||
|
||||
public void SetLevelFlag(LevelFlag flag, bool value = true)
|
||||
{
|
||||
LevelFlags[flag] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/IO/Saves/SaveGame.cs.meta
Normal file
3
Assets/Scripts/Data/IO/Saves/SaveGame.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bc844b48999c44058fe4696c9841c339
|
||||
timeCreated: 1769703058
|
||||
3
Assets/Scripts/Data/Identifiers.meta
Normal file
3
Assets/Scripts/Data/Identifiers.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ec4654a3dc1a46858389e602b21615b5
|
||||
timeCreated: 1769700576
|
||||
9
Assets/Scripts/Data/Identifiers/AchievementIDs.cs
Normal file
9
Assets/Scripts/Data/Identifiers/AchievementIDs.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum AchievementID
|
||||
{
|
||||
WorkshopSafeUnlocked,
|
||||
WorkshopPuzzleBoxSolved,
|
||||
FountainGemPuzzleSolved,
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/AchievementIDs.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/AchievementIDs.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7157dac196b247998ae88da719c9aedc
|
||||
timeCreated: 1772721612
|
||||
8
Assets/Scripts/Data/Identifiers/ActionMaps.cs
Normal file
8
Assets/Scripts/Data/Identifiers/ActionMaps.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public static class ActionMaps
|
||||
{
|
||||
public const string GAMEPLAY_MAP = "Gameplay";
|
||||
public const string UI_MAP = "UI";
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/ActionMaps.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/ActionMaps.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 33b4f39a4dbe41acb0a53cdb18e8daaa
|
||||
timeCreated: 1769708292
|
||||
145
Assets/Scripts/Data/Identifiers/AssetKeyIdentifiers.cs
Normal file
145
Assets/Scripts/Data/Identifiers/AssetKeyIdentifiers.cs
Normal file
@@ -0,0 +1,145 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum UIKey
|
||||
{
|
||||
None = 0,
|
||||
InventorySlot,
|
||||
CodexLocationButton,
|
||||
CodexEntryButton
|
||||
}
|
||||
|
||||
public enum SceneKey
|
||||
{
|
||||
None = 0,
|
||||
MainMenuScene,
|
||||
UIScene,
|
||||
OpeningCinematicScene,
|
||||
GameScene
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public enum LevelKey
|
||||
{
|
||||
None = 0,
|
||||
ChapterOneVillageEdge,
|
||||
ChapterOneVillage,
|
||||
ChapterOneVillageFurther,
|
||||
ChapterOnePumphouse,
|
||||
ChapterOneFountain,
|
||||
ChapterOneWorkshop,
|
||||
ChapterOnePumphousePipes,
|
||||
ChapterOneWorkshopDrawer,
|
||||
ChapterOneWorkshopUpstairs,
|
||||
ChapterOneWorkshopCandlePuzzle,
|
||||
ChapterOneWorkshopJewelleryBox,
|
||||
ChapterOneWorkshopJewelleryBoxOpen,
|
||||
ChapterOneWorkshopSafe,
|
||||
ChapterOneWorkshopBag,
|
||||
ChapterOneWorkshopDownstairs,
|
||||
ChapterOnePumphouseTable,
|
||||
ChapterOneWorkshopBookcase,
|
||||
ChapterOneFountainPuzzle,
|
||||
ChapterOneStreetGateSign,
|
||||
ChapterOneStreetCart,
|
||||
}
|
||||
|
||||
public enum AssetItemKey
|
||||
{
|
||||
None = 0,
|
||||
ChapterOneBoxPuzzlePiece1,
|
||||
ChapterOneBoxPuzzlePiece2,
|
||||
ChapterOneBoxPuzzlePiece3,
|
||||
ChapterOneBoxPuzzlePiece4,
|
||||
ChapterOneBoxPuzzlePiece5,
|
||||
ChapterOneBoxPuzzlePiece6,
|
||||
ChapterOneBoxPuzzlePiece7,
|
||||
ChapterOneBoxPuzzlePiece8,
|
||||
ChapterOneWorkshopWornBook
|
||||
}
|
||||
|
||||
public static class AssetKeyIdentifiers
|
||||
{
|
||||
private const string UI_PREFIX = "UI:";
|
||||
private const string SCENE_PREFIX = "Scene:";
|
||||
private const string LEVEL_PREFIX = "Level:";
|
||||
private const string ITEM_PREFIX = "Item:";
|
||||
|
||||
public static string Get(UIKey key)
|
||||
{
|
||||
if (key == UIKey.None)
|
||||
return string.Empty;
|
||||
|
||||
return $"{UI_PREFIX}{key}";
|
||||
}
|
||||
|
||||
public static string Get(SceneKey key)
|
||||
{
|
||||
if (key == SceneKey.None)
|
||||
return string.Empty;
|
||||
|
||||
return $"{SCENE_PREFIX}{key}";
|
||||
}
|
||||
|
||||
public static string Get(LevelKey key)
|
||||
{
|
||||
if (key == LevelKey.None)
|
||||
return string.Empty;
|
||||
|
||||
return $"{LEVEL_PREFIX}{key}";
|
||||
}
|
||||
|
||||
public static string Get(AssetItemKey key)
|
||||
{
|
||||
if (key == AssetItemKey.None)
|
||||
return string.Empty;
|
||||
|
||||
return $"{ITEM_PREFIX}{key}";
|
||||
}
|
||||
|
||||
public static bool TryGet(UIKey key, out string value)
|
||||
{
|
||||
value = Get(key);
|
||||
return !string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
public static bool TryGet(SceneKey key, out string value)
|
||||
{
|
||||
value = Get(key);
|
||||
return !string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
public static bool TryGet(LevelKey key, out string value)
|
||||
{
|
||||
value = Get(key);
|
||||
return !string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
public static bool TryGet(AssetItemKey key, out string value)
|
||||
{
|
||||
value = Get(key);
|
||||
return !string.IsNullOrEmpty(value);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetAllKeys()
|
||||
{
|
||||
foreach (UIKey key in Enum.GetValues(typeof(UIKey)))
|
||||
if (key != UIKey.None)
|
||||
yield return Get(key);
|
||||
|
||||
foreach (SceneKey key in Enum.GetValues(typeof(SceneKey)))
|
||||
if (key != SceneKey.None)
|
||||
yield return Get(key);
|
||||
|
||||
foreach (LevelKey key in Enum.GetValues(typeof(LevelKey)))
|
||||
if (key != LevelKey.None)
|
||||
yield return Get(key);
|
||||
|
||||
foreach (AssetItemKey key in Enum.GetValues(typeof(AssetItemKey)))
|
||||
if (key != AssetItemKey.None)
|
||||
yield return Get(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70c2ada094a34e04b4f5d7d1cc2c5327
|
||||
timeCreated: 1769711192
|
||||
112
Assets/Scripts/Data/Identifiers/AudioNameIdentifiers.cs
Normal file
112
Assets/Scripts/Data/Identifiers/AudioNameIdentifiers.cs
Normal file
@@ -0,0 +1,112 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum MusicKey
|
||||
{
|
||||
None = 0,
|
||||
}
|
||||
|
||||
public enum SFXKey
|
||||
{
|
||||
None = 0,
|
||||
WorkshopSafeUnlocked,
|
||||
WorkshopPuzzleBoxUnlocked,
|
||||
DoorCreek,
|
||||
ItemCollected,
|
||||
GateOpening,
|
||||
PuzzleIncorrect,
|
||||
ResetPuzzle,
|
||||
SharpenKnife
|
||||
}
|
||||
|
||||
public enum UIFXKey
|
||||
{
|
||||
None = 0,
|
||||
AchievementUnlocked,
|
||||
CodexEntryUnlocked
|
||||
}
|
||||
|
||||
public enum AmbienceKey
|
||||
{
|
||||
None = 0,
|
||||
}
|
||||
|
||||
public enum VoiceKey
|
||||
{
|
||||
None = 0,
|
||||
}
|
||||
|
||||
public static class AudioNameIdentifiers
|
||||
{
|
||||
public static readonly IReadOnlyDictionary<MusicKey, string> Music =
|
||||
new ReadOnlyDictionary<MusicKey, string>(
|
||||
new Dictionary<MusicKey, string>
|
||||
{
|
||||
// Add when you have music
|
||||
// { MusicKey.SomeTrack, "MUSIC_SomeTrack" }
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<SFXKey, string> SFX =
|
||||
new ReadOnlyDictionary<SFXKey, string>(
|
||||
new Dictionary<SFXKey, string>
|
||||
{
|
||||
{ SFXKey.WorkshopSafeUnlocked, "SFX_WorkshopSafeUnlocked" },
|
||||
{ SFXKey.WorkshopPuzzleBoxUnlocked, "SFX_WorkshopPuzzleBoxUnlocked" },
|
||||
{ SFXKey.DoorCreek, "SFX_DoorCreek" },
|
||||
{ SFXKey.ItemCollected, "SFX_ItemCollected" },
|
||||
{ SFXKey.GateOpening, "SFX_GateOpening" },
|
||||
{ SFXKey.PuzzleIncorrect, "SFX_PuzzleIncorrect" },
|
||||
{ SFXKey.ResetPuzzle, "SFX_ResetPuzzle" },
|
||||
{ SFXKey.SharpenKnife, "SFX_SharpenKnife"}
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<UIFXKey, string> UIFX =
|
||||
new ReadOnlyDictionary<UIFXKey, string>(
|
||||
new Dictionary<UIFXKey, string>
|
||||
{
|
||||
{ UIFXKey.AchievementUnlocked, "UIFX_AchievementUnlocked" },
|
||||
{ UIFXKey.CodexEntryUnlocked, "UIFX_CodexEntryUnlocked" },
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<AmbienceKey, string> Ambience =
|
||||
new ReadOnlyDictionary<AmbienceKey, string>(
|
||||
new Dictionary<AmbienceKey, string>
|
||||
{
|
||||
// Add ambience mappings here
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<VoiceKey, string> Voice =
|
||||
new ReadOnlyDictionary<VoiceKey, string>(
|
||||
new Dictionary<VoiceKey, string>
|
||||
{
|
||||
// Add voice mappings here
|
||||
});
|
||||
|
||||
public static string Get(MusicKey key)
|
||||
{
|
||||
return Music.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(SFXKey key)
|
||||
{
|
||||
return SFX.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(UIFXKey key)
|
||||
{
|
||||
return UIFX.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(AmbienceKey key)
|
||||
{
|
||||
return Ambience.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(VoiceKey key)
|
||||
{
|
||||
return Voice.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07b91c112560408d842204fefd8f68db
|
||||
timeCreated: 1769802314
|
||||
22
Assets/Scripts/Data/Identifiers/AudioParameters.cs
Normal file
22
Assets/Scripts/Data/Identifiers/AudioParameters.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public static class AudioMixerParameters
|
||||
{
|
||||
public const string MASTER_VOLUME = "Master_Volume";
|
||||
public const string MUSIC_VOLUME = "Music_Volume";
|
||||
public const string SFX_VOLUME = "SFX_Volume";
|
||||
public const string AMBIENCE_VOLUME = "Ambience_Volume";
|
||||
public const string VOICE_VOLUME = "Voice_Volume";
|
||||
public const string UI_VOLUME = "UI_Volume";
|
||||
}
|
||||
|
||||
public static class AudioMixerGroups
|
||||
{
|
||||
public const string MASTER_GROUP = "Master";
|
||||
public const string MUSIC_GROUP = "Music";
|
||||
public const string SFX_GROUP = "SFX";
|
||||
public const string AMBIENCE_GROUP = "Ambience";
|
||||
public const string VOICE_GROUP = "Voice";
|
||||
public const string UI_GROUP = "UI";
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/AudioParameters.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/AudioParameters.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ad39fe6d08874fe69d0acf0a6e8a195e
|
||||
timeCreated: 1769802894
|
||||
72
Assets/Scripts/Data/Identifiers/CodexEntryIDs.cs
Normal file
72
Assets/Scripts/Data/Identifiers/CodexEntryIDs.cs
Normal file
@@ -0,0 +1,72 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum BookEntryID
|
||||
{
|
||||
None = 0,
|
||||
WorkshopDiary = 1
|
||||
}
|
||||
|
||||
public enum ClueEntryID
|
||||
{
|
||||
None = 0,
|
||||
WorkshopBookshelfClue = 1,
|
||||
WorkshopRainbowClue = 2,
|
||||
PumphouseScratchedTable = 3
|
||||
}
|
||||
|
||||
public enum PhotoEntryID
|
||||
{
|
||||
None = 0,
|
||||
WorkshopFadedPhoto = 1
|
||||
}
|
||||
|
||||
public enum LocationEntryID
|
||||
{
|
||||
None = 0,
|
||||
Village = 1,
|
||||
Workshop = 2
|
||||
}
|
||||
|
||||
public static class CodexEntryIDs
|
||||
{
|
||||
public static readonly IReadOnlyDictionary<BookEntryID, string> Books =
|
||||
new ReadOnlyDictionary<BookEntryID, string>(
|
||||
new Dictionary<BookEntryID, string>
|
||||
{
|
||||
{ BookEntryID.WorkshopDiary, "BOOK_WorkshopDiary" }
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<ClueEntryID, string> Clues =
|
||||
new ReadOnlyDictionary<ClueEntryID, string>(
|
||||
new Dictionary<ClueEntryID, string>
|
||||
{
|
||||
{ ClueEntryID.WorkshopBookshelfClue, "CLUE_WorkshopBookshelf" },
|
||||
{ ClueEntryID.WorkshopRainbowClue , "CLUE_WorkshopRainbow" }
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<PhotoEntryID, string> Photos =
|
||||
new ReadOnlyDictionary<PhotoEntryID, string>(
|
||||
new Dictionary<PhotoEntryID, string>
|
||||
{
|
||||
{ PhotoEntryID.WorkshopFadedPhoto, "PHOTO_WorkshopFadedPhoto" }
|
||||
});
|
||||
|
||||
public static string Get(BookEntryID id)
|
||||
{
|
||||
return Books.TryGetValue(id, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(ClueEntryID id)
|
||||
{
|
||||
return Clues.TryGetValue(id, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(PhotoEntryID id)
|
||||
{
|
||||
return Photos.TryGetValue(id, out var value) ? value : string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/CodexEntryIDs.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/CodexEntryIDs.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0acfa8405a384e76926ac6fd1cdf3542
|
||||
timeCreated: 1773682133
|
||||
10
Assets/Scripts/Data/Identifiers/CodexType.cs
Normal file
10
Assets/Scripts/Data/Identifiers/CodexType.cs
Normal file
@@ -0,0 +1,10 @@
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum CodexType
|
||||
{
|
||||
None = 0,
|
||||
BookEntry = 1,
|
||||
PuzzleClue = 2,
|
||||
Photo = 3
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/CodexType.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/CodexType.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1f418d7b7d864488b8fde53b789dc51c
|
||||
timeCreated: 1773834385
|
||||
136
Assets/Scripts/Data/Identifiers/InteractEventIDs.cs
Normal file
136
Assets/Scripts/Data/Identifiers/InteractEventIDs.cs
Normal file
@@ -0,0 +1,136 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum ItemInteractKey
|
||||
{
|
||||
None = 0,
|
||||
EmptyHands = 1,
|
||||
CantUseItem = 2,
|
||||
RustyKnife = 3,
|
||||
SomethingMissing = 4,
|
||||
PliersSnapped = 5,
|
||||
CarefulInteract = 6,
|
||||
RagFallsApart = 7,
|
||||
LooksImportant = 8,
|
||||
WrongTool = 9,
|
||||
}
|
||||
|
||||
public enum LevelInteractKey
|
||||
{
|
||||
None = 0,
|
||||
WaterValve = 1,
|
||||
ClearVinesOutside = 2,
|
||||
PumphouseChain = 3,
|
||||
CutVines = 4,
|
||||
WorkshopLockedSafe = 5,
|
||||
UnlockedPumphouse = 6,
|
||||
}
|
||||
|
||||
public enum EnvironmentInteractKey
|
||||
{
|
||||
None = 0,
|
||||
BrokenLantern = 1,
|
||||
WorkshopWriting = 2,
|
||||
UseGrindstone = 3,
|
||||
WorkshopBookDisintegrating = 4,
|
||||
UsingKnife = 5,
|
||||
AlreadySharpened = 6,
|
||||
Locked = 7,
|
||||
CantGoThere = 8,
|
||||
DirtyWindow = 9,
|
||||
WorkshopBagNoItems = 10,
|
||||
FindCandle = 11,
|
||||
DoesntBelong = 12,
|
||||
SharpGlass = 13,
|
||||
FreshAndCoolWater = 14,
|
||||
WorkshopBooks = 15,
|
||||
PumpTurnOn = 16,
|
||||
}
|
||||
|
||||
public enum UIInteractKey
|
||||
{
|
||||
None = 0,
|
||||
EmptySlot = 1,
|
||||
}
|
||||
|
||||
public static class InteractEventIDs
|
||||
{
|
||||
public static readonly IReadOnlyDictionary<ItemInteractKey, string> ItemInteractions =
|
||||
new ReadOnlyDictionary<ItemInteractKey, string>(
|
||||
new Dictionary<ItemInteractKey, string>
|
||||
{
|
||||
{ ItemInteractKey.EmptyHands, "I need to put my tools away." },
|
||||
{ ItemInteractKey.CantUseItem, "That won't work here." },
|
||||
{ ItemInteractKey.RustyKnife, "It's too blunt to be useful." },
|
||||
{ ItemInteractKey.SomethingMissing, "Something's missing." },
|
||||
{ ItemInteractKey.PliersSnapped, "The pliers snapped. They're no use now." },
|
||||
{ ItemInteractKey.CarefulInteract, "I need to be careful with this." },
|
||||
{ ItemInteractKey.RagFallsApart, "The rag fell apart." },
|
||||
{ ItemInteractKey.LooksImportant, "That looks important." },
|
||||
{ ItemInteractKey.WrongTool, "I need the proper tool for this."}
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<LevelInteractKey, string> LevelInteractions =
|
||||
new ReadOnlyDictionary<LevelInteractKey, string>(
|
||||
new Dictionary<LevelInteractKey, string>
|
||||
{
|
||||
{ LevelInteractKey.WaterValve, "I've already turned the water on." },
|
||||
{ LevelInteractKey.ClearVinesOutside, "I need to clear the vines outside first." },
|
||||
{ LevelInteractKey.PumphouseChain, "There must be a key around here somewhere." },
|
||||
{ LevelInteractKey.CutVines, "I need something to cut through these." },
|
||||
{ LevelInteractKey.WorkshopLockedSafe, "It's locked tight." },
|
||||
{ LevelInteractKey.UnlockedPumphouse, "You used the Pumphouse Key."},
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<EnvironmentInteractKey, string> EnvironmentInteractions =
|
||||
new ReadOnlyDictionary<EnvironmentInteractKey, string>(
|
||||
new Dictionary<EnvironmentInteractKey, string>
|
||||
{
|
||||
{ EnvironmentInteractKey.BrokenLantern, "It's too broken to use." },
|
||||
{ EnvironmentInteractKey.WorkshopWriting, "It could be worse... it could be blood." },
|
||||
{ EnvironmentInteractKey.UseGrindstone, "I could sharpen something on this." },
|
||||
{ EnvironmentInteractKey.WorkshopBookDisintegrating, "It fell apart in my hands." },
|
||||
{ EnvironmentInteractKey.UsingKnife, "I should be careful cutting these." },
|
||||
{ EnvironmentInteractKey.AlreadySharpened, "That should be sharp enough now." },
|
||||
{ EnvironmentInteractKey.Locked, "It's locked." },
|
||||
{ EnvironmentInteractKey.CantGoThere, "I can't go that way." },
|
||||
{ EnvironmentInteractKey.DirtyWindow, "I can't see through all this grime." },
|
||||
{ EnvironmentInteractKey.WorkshopBagNoItems, "There's nothing left inside." },
|
||||
{ EnvironmentInteractKey.FindCandle, "I should look for the candle." },
|
||||
{ EnvironmentInteractKey.DoesntBelong, "That doesn't belong here." },
|
||||
{ EnvironmentInteractKey.SharpGlass, "Ow... that's sharp." },
|
||||
{ EnvironmentInteractKey.FreshAndCoolWater, "The water feels cool and refreshing." },
|
||||
{ EnvironmentInteractKey.WorkshopBooks, "The books are ancient and crumbling." },
|
||||
{ EnvironmentInteractKey.PumpTurnOn, "The water pumps splutter into life."}
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<UIInteractKey, string> UIInteractions =
|
||||
new ReadOnlyDictionary<UIInteractKey, string>(
|
||||
new Dictionary<UIInteractKey, string>
|
||||
{
|
||||
{ UIInteractKey.EmptySlot, "Empty slot." },
|
||||
});
|
||||
|
||||
public static string Get(ItemInteractKey key)
|
||||
{
|
||||
return ItemInteractions.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(LevelInteractKey key)
|
||||
{
|
||||
return LevelInteractions.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(EnvironmentInteractKey key)
|
||||
{
|
||||
return EnvironmentInteractions.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(UIInteractKey key)
|
||||
{
|
||||
return UIInteractions.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/InteractEventIDs.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/InteractEventIDs.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 50e79aae8ef3433e835ccf3cdb6cf186
|
||||
timeCreated: 1773862120
|
||||
158
Assets/Scripts/Data/Identifiers/ItemIDs.cs
Normal file
158
Assets/Scripts/Data/Identifiers/ItemIDs.cs
Normal file
@@ -0,0 +1,158 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum ItemKey
|
||||
{
|
||||
None = 0,
|
||||
RustedKnife = 1,
|
||||
SharpenedKnife = 2,
|
||||
EmeraldAmulet = 3,
|
||||
DustyMirror = 4,
|
||||
SmallRag = 5,
|
||||
GreenCandle = 6,
|
||||
IndigoCandle = 7,
|
||||
DirtyMagnifyingGlass = 8,
|
||||
PumphouseKey = 9,
|
||||
RedCandle = 10,
|
||||
OrangeCandle = 11,
|
||||
YellowCandle = 12,
|
||||
BlueCandle = 13,
|
||||
VioletCandle = 14,
|
||||
Pliers = 15,
|
||||
Emerald = 16,
|
||||
Sapphire = 17,
|
||||
Ruby = 18,
|
||||
RubyRing = 19,
|
||||
SilverCoin = 20,
|
||||
GoldCoin = 21,
|
||||
GrindstoneAxlePin = 22,
|
||||
Diamond = 23,
|
||||
DiamondTiara = 24,
|
||||
DustySapphire = 25,
|
||||
}
|
||||
|
||||
public enum EnvironmentKey
|
||||
{
|
||||
None = 0,
|
||||
ChainLock = 1,
|
||||
FountainVines = 2,
|
||||
GrindingStone = 3,
|
||||
WorkshopWindow = 4,
|
||||
WorkshopDamagedBook = 5,
|
||||
WorkshopBookSlot = 6,
|
||||
WorkshopDiary = 7,
|
||||
PumphouseWaterValve = 8,
|
||||
WorkshopFadedPhoto = 9,
|
||||
WorkshopDownstairsLight = 10,
|
||||
WorkshopBrokenLantern = 11,
|
||||
WorkshopWriting = 12,
|
||||
StreetVines = 13,
|
||||
}
|
||||
|
||||
public enum PuzzleSlotKey
|
||||
{
|
||||
None = 0,
|
||||
WorkshopCandleSlot = 1,
|
||||
WorkshopPuzzleBoxSlot = 2,
|
||||
FountainGemSlot = 3,
|
||||
|
||||
}
|
||||
|
||||
public static class ItemIDs
|
||||
{
|
||||
public static readonly IReadOnlyDictionary<PuzzleSlotKey, string> PuzzleSlots =
|
||||
new ReadOnlyDictionary<PuzzleSlotKey, string>(
|
||||
new Dictionary<PuzzleSlotKey, string>
|
||||
{
|
||||
{ PuzzleSlotKey.WorkshopCandleSlot, "PUZ_WorkshopCandleSlot" },
|
||||
{ PuzzleSlotKey.WorkshopPuzzleBoxSlot, "PUZ_WorkshopPuzzleBoxSlot" }
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<EnvironmentKey, string> Environment =
|
||||
new ReadOnlyDictionary<EnvironmentKey, string>(
|
||||
new Dictionary<EnvironmentKey, string>
|
||||
{
|
||||
{ EnvironmentKey.ChainLock, "ENV_ChainLock" },
|
||||
{ EnvironmentKey.FountainVines, "ENV_FountainVines" },
|
||||
{ EnvironmentKey.GrindingStone, "ENV_GrindingStone" },
|
||||
{ EnvironmentKey.WorkshopWindow, "ENV_WorkshopWindow" },
|
||||
{ EnvironmentKey.WorkshopDamagedBook, "ENV_WorkshopDamagedBook" },
|
||||
{ EnvironmentKey.WorkshopBookSlot, "ENV_WorkshopBookSlot" },
|
||||
{ EnvironmentKey.WorkshopDiary, "ENV_WorkshopDiary" },
|
||||
{ EnvironmentKey.PumphouseWaterValve, "ENV_PumphouseWaterValve" },
|
||||
{ EnvironmentKey.WorkshopFadedPhoto, "ENV_WorkshopFadedPhoto" },
|
||||
{ EnvironmentKey.WorkshopDownstairsLight, "ENV_WorkshopDownstairsLight" },
|
||||
{ EnvironmentKey.WorkshopBrokenLantern, "ENV_WorkshopBrokenLantern" },
|
||||
{ EnvironmentKey.WorkshopWriting, "ENV_WorkshopWriting" },
|
||||
{ EnvironmentKey.StreetVines, "ENV_StreetVines" },
|
||||
});
|
||||
|
||||
public static readonly IReadOnlyDictionary<ItemKey, string> Pickups =
|
||||
new ReadOnlyDictionary<ItemKey, string>(
|
||||
new Dictionary<ItemKey, string>
|
||||
{
|
||||
{ ItemKey.RustedKnife, "00_RustedKnife" },
|
||||
{ ItemKey.SharpenedKnife, "01_SharpenedKnife" },
|
||||
{ ItemKey.EmeraldAmulet, "02_EmeraldAmulet" },
|
||||
{ ItemKey.DustyMirror, "03_DustyMirror" },
|
||||
{ ItemKey.SmallRag, "04_SmallRag" },
|
||||
{ ItemKey.GreenCandle, "05_GreenCandle" },
|
||||
{ ItemKey.IndigoCandle, "06_IndigoCandle" },
|
||||
{ ItemKey.DirtyMagnifyingGlass, "07_DirtyMagnifyingGlass" },
|
||||
{ ItemKey.PumphouseKey, "08_PumphouseKey" },
|
||||
{ ItemKey.RedCandle, "09_RedCandle" },
|
||||
{ ItemKey.OrangeCandle, "10_OrangeCandle" },
|
||||
{ ItemKey.YellowCandle, "11_YellowCandle" },
|
||||
{ ItemKey.BlueCandle, "12_BlueCandle" },
|
||||
{ ItemKey.VioletCandle, "13_VioletCandle" },
|
||||
{ ItemKey.Pliers, "14_Pliers" },
|
||||
{ ItemKey.Emerald, "15_Emerald" },
|
||||
{ ItemKey.Sapphire, "16_Sapphire" },
|
||||
{ ItemKey.Ruby, "17_Ruby" },
|
||||
{ ItemKey.RubyRing, "18_RubyRing" },
|
||||
{ ItemKey.SilverCoin, "19_SilverCoin" },
|
||||
{ ItemKey.GoldCoin, "20_GoldCoin" },
|
||||
{ ItemKey.GrindstoneAxlePin, "21_GrindstoneAxlePin" },
|
||||
{ ItemKey.Diamond, "22_Diamond" },
|
||||
{ ItemKey.DiamondTiara, "23_DiamondTiara" },
|
||||
{ ItemKey.DustySapphire, "24_DustySapphire" },
|
||||
});
|
||||
|
||||
public static string Get(ItemKey key)
|
||||
{
|
||||
return Pickups.TryGetValue(key, out var id) ? id : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(EnvironmentKey key)
|
||||
{
|
||||
return Environment.TryGetValue(key, out var id) ? id : string.Empty;
|
||||
}
|
||||
|
||||
public static string Get(PuzzleSlotKey key)
|
||||
{
|
||||
return PuzzleSlots.TryGetValue(key, out var id) ? id : string.Empty;
|
||||
}
|
||||
|
||||
public static bool TryGet(ItemKey key, out string id)
|
||||
{
|
||||
return Pickups.TryGetValue(key, out id);
|
||||
}
|
||||
|
||||
public static bool TryGet(EnvironmentKey key, out string id)
|
||||
{
|
||||
return Environment.TryGetValue(key, out id);
|
||||
}
|
||||
|
||||
public static bool TryGet(PuzzleSlotKey key, out string id)
|
||||
{
|
||||
return PuzzleSlots.TryGetValue(key, out id);
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetAllItemIDs()
|
||||
{
|
||||
return Pickups.Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/ItemIDs.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/ItemIDs.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c40ae7704af14f6e99941aba25344bb6
|
||||
timeCreated: 1769700576
|
||||
9
Assets/Scripts/Data/Identifiers/Location.cs
Normal file
9
Assets/Scripts/Data/Identifiers/Location.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum Location
|
||||
{
|
||||
None = 0,
|
||||
Village = 1,
|
||||
Workshop = 2
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/Location.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/Location.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1954efce3788423dbb70477d39ae226c
|
||||
timeCreated: 1773685340
|
||||
27
Assets/Scripts/Data/Identifiers/PuzzleIdentifiers.cs
Normal file
27
Assets/Scripts/Data/Identifiers/PuzzleIdentifiers.cs
Normal file
@@ -0,0 +1,27 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum PuzzleKey
|
||||
{
|
||||
WorkshopCandlePuzzle,
|
||||
WorkshopPuzzleBox,
|
||||
FountainGemPuzzle,
|
||||
}
|
||||
|
||||
public static class PuzzleIdentifiers
|
||||
{
|
||||
public static readonly Dictionary<PuzzleKey, string> AllPuzzles = new()
|
||||
{
|
||||
{ PuzzleKey.WorkshopCandlePuzzle, "CH1:Puzzle:WorkshopCandles" },
|
||||
{ PuzzleKey.WorkshopPuzzleBox, "CH1:Puzzle:WorkshopBox" },
|
||||
{ PuzzleKey.FountainGemPuzzle , "CH1:Puzzle:FountainGems" },
|
||||
};
|
||||
|
||||
// Optional helper to get all puzzle IDs
|
||||
public static IEnumerable<string> GetAllPuzzleIDs()
|
||||
{
|
||||
return AllPuzzles.Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 06b4a47cafea4e5ea0f02896de78ac30
|
||||
timeCreated: 1769876815
|
||||
34
Assets/Scripts/Data/Identifiers/SubtitleIdentifiers.cs
Normal file
34
Assets/Scripts/Data/Identifiers/SubtitleIdentifiers.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum SubtitleKey
|
||||
{
|
||||
None = 0,
|
||||
// Example:
|
||||
// IntroLine = 1,
|
||||
// TutorialTip = 2
|
||||
}
|
||||
|
||||
public static class SubtitleIdentifiers
|
||||
{
|
||||
public static readonly IReadOnlyDictionary<SubtitleKey, string> Subtitles =
|
||||
new ReadOnlyDictionary<SubtitleKey, string>(
|
||||
new Dictionary<SubtitleKey, string>
|
||||
{
|
||||
// { SubtitleKey.IntroLine, "SUB_IntroLine" },
|
||||
// { SubtitleKey.TutorialTip, "SUB_TutorialTip" }
|
||||
});
|
||||
|
||||
public static string Get(SubtitleKey key)
|
||||
{
|
||||
return Subtitles.TryGetValue(key, out var value) ? value : string.Empty;
|
||||
}
|
||||
|
||||
public static IEnumerable<string> GetAll()
|
||||
{
|
||||
return Subtitles.Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edc4b3fdb3c844a280d7ffeb90c8395f
|
||||
timeCreated: 1769802348
|
||||
8
Assets/Scripts/Data/Identifiers/ToolID.cs
Normal file
8
Assets/Scripts/Data/Identifiers/ToolID.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum ToolID
|
||||
{
|
||||
None = 0,
|
||||
Knife = 1
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/ToolID.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/ToolID.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c555346b81049da9f0203c0143823c7
|
||||
timeCreated: 1773955001
|
||||
11
Assets/Scripts/Data/Identifiers/TrackType.cs
Normal file
11
Assets/Scripts/Data/Identifiers/TrackType.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum TrackType
|
||||
{
|
||||
Music = 0,
|
||||
Ambience = 1,
|
||||
Sfx = 2,
|
||||
Voice = 3,
|
||||
UIFX = 4
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/TrackType.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/TrackType.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4eebcb38d8494fd3874dff753a742b82
|
||||
timeCreated: 1773850029
|
||||
85
Assets/Scripts/Data/Identifiers/TutorialPopupID.cs
Normal file
85
Assets/Scripts/Data/Identifiers/TutorialPopupID.cs
Normal file
@@ -0,0 +1,85 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BriarQueen.Data.Identifiers
|
||||
{
|
||||
public enum TutorialPopupID
|
||||
{
|
||||
ReturnToPreviousLevel,
|
||||
UsingItemsTogether,
|
||||
HideHUD,
|
||||
ExitItems,
|
||||
MultipleUseItems,
|
||||
DarkRooms,
|
||||
Codex,
|
||||
HiddenItems,
|
||||
ResetPuzzles,
|
||||
Tools,
|
||||
ItemsAway,
|
||||
ItemCycling,
|
||||
ToolCycling,
|
||||
}
|
||||
|
||||
public static class TutorialPopupTexts
|
||||
{
|
||||
public static readonly Dictionary<TutorialPopupID, string> AllPopups = new()
|
||||
{
|
||||
{
|
||||
TutorialPopupID.ReturnToPreviousLevel,
|
||||
"Click the bottom corners to go back the way you came."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.UsingItemsTogether,
|
||||
"Select an item, then click another to use it on that object."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.HideHUD,
|
||||
"Press 'H' to hide the HUD and see the world more clearly."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.ExitItems,
|
||||
"Right-click to exit the current interaction."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.MultipleUseItems,
|
||||
"Some items can be used more than once, but will eventually wear out."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.DarkRooms,
|
||||
"Dark rooms hide what matters. Look carefully—light reveals what they conceal."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.Codex,
|
||||
"New discoveries are added to your codex. Press 'C' to review what you've gathered."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.HiddenItems,
|
||||
"Some things are hidden on purpose. Search carefully to uncover them."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.ResetPuzzles,
|
||||
"Some puzzles can be reset if you make a mistake."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.Tools,
|
||||
"You'll find tools as you explore. Each has its own purpose—try them on different objects. Press 'Y' to view your tools."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.ItemsAway,
|
||||
"Right-click to put away any items."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.ItemCycling,
|
||||
"Press '[' or ']' to cycle through your backpack."
|
||||
},
|
||||
{
|
||||
TutorialPopupID.ToolCycling,
|
||||
"Press 'Q' or 'E' to cycle through your tools."
|
||||
}
|
||||
};
|
||||
|
||||
public static IEnumerable<string> GetAllTexts()
|
||||
{
|
||||
return AllPopups.Values;
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Data/Identifiers/TutorialPopupID.cs.meta
Normal file
3
Assets/Scripts/Data/Identifiers/TutorialPopupID.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96daeae63db0442bb8449e31e5867713
|
||||
timeCreated: 1772823170
|
||||
3
Assets/Scripts/Editor.meta
Normal file
3
Assets/Scripts/Editor.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 618d29950c9c4d518c6b56949f287669
|
||||
timeCreated: 1771172163
|
||||
19
Assets/Scripts/Editor/BriarQueen.Editor.asmdef
Normal file
19
Assets/Scripts/Editor/BriarQueen.Editor.asmdef
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"name": "BriarQueen.Editor",
|
||||
"rootNamespace": "BriarQueen",
|
||||
"references": [
|
||||
"GUID:bdf0eff65032c4178bf18aa9c96b1c70",
|
||||
"GUID:ac1be664c635c449eb9f3f52cf5c97f5"
|
||||
],
|
||||
"includePlatforms": [
|
||||
"Editor"
|
||||
],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
7
Assets/Scripts/Editor/BriarQueen.Editor.asmdef.meta
Normal file
7
Assets/Scripts/Editor/BriarQueen.Editor.asmdef.meta
Normal file
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d63909dd781c643ecbc1295f0dc761a3
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Scripts/Editor/Drawers.meta
Normal file
3
Assets/Scripts/Editor/Drawers.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1954361a8cce45498b2c8b2888144b5e
|
||||
timeCreated: 1771172177
|
||||
79
Assets/Scripts/Editor/Drawers/BaseInteractionDrawer.cs
Normal file
79
Assets/Scripts/Editor/Drawers/BaseInteractionDrawer.cs
Normal file
@@ -0,0 +1,79 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using BriarQueen.Framework.Managers.Interaction.Data;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Editor.Drawers
|
||||
{
|
||||
[CustomPropertyDrawer(typeof(BaseInteraction), true)]
|
||||
public class BaseItemInteractionDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
EditorGUI.BeginProperty(position, label, property);
|
||||
|
||||
if (property.managedReferenceValue == null)
|
||||
{
|
||||
if (GUI.Button(position, "Select Interaction Type"))
|
||||
{
|
||||
ShowTypeMenu(property);
|
||||
}
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
return;
|
||||
}
|
||||
|
||||
var type = property.managedReferenceValue.GetType();
|
||||
var headerRect = new Rect(position.x, position.y, position.width, EditorGUIUtility.singleLineHeight);
|
||||
|
||||
if (GUI.Button(headerRect, type.Name, EditorStyles.popup))
|
||||
{
|
||||
ShowTypeMenu(property);
|
||||
}
|
||||
|
||||
var bodyRect = new Rect(
|
||||
position.x,
|
||||
position.y + EditorGUIUtility.singleLineHeight + 2,
|
||||
position.width,
|
||||
position.height - EditorGUIUtility.singleLineHeight - 2);
|
||||
|
||||
EditorGUI.indentLevel++;
|
||||
EditorGUI.PropertyField(bodyRect, property, GUIContent.none, true);
|
||||
EditorGUI.indentLevel--;
|
||||
|
||||
EditorGUI.EndProperty();
|
||||
}
|
||||
|
||||
private void ShowTypeMenu(SerializedProperty property)
|
||||
{
|
||||
var menu = new GenericMenu();
|
||||
|
||||
var types = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.SelectMany(a => a.GetTypes())
|
||||
.Where(t =>
|
||||
!t.IsAbstract &&
|
||||
typeof(BaseInteraction).IsAssignableFrom(t));
|
||||
|
||||
foreach (var type in types)
|
||||
{
|
||||
menu.AddItem(new GUIContent(type.Name), false, () =>
|
||||
{
|
||||
property.serializedObject.Update();
|
||||
property.managedReferenceValue = Activator.CreateInstance(type);
|
||||
property.serializedObject.ApplyModifiedProperties();
|
||||
});
|
||||
}
|
||||
|
||||
menu.ShowAsContext();
|
||||
}
|
||||
|
||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.managedReferenceValue == null)
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
|
||||
return EditorGUI.GetPropertyHeight(property, true) + EditorGUIUtility.singleLineHeight + 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 627cc55408bb4796839600a1516a5eba
|
||||
timeCreated: 1771172177
|
||||
3
Assets/Scripts/Editor/Drawers/Registries.meta
Normal file
3
Assets/Scripts/Editor/Drawers/Registries.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5c40c1262cbd4128a9b3c3446304a845
|
||||
timeCreated: 1773921681
|
||||
@@ -0,0 +1,74 @@
|
||||
using System.Collections.Generic;
|
||||
using BriarQueen.Data.Assets;
|
||||
using BriarQueen.Framework.Registries;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Editor.Drawers.Registries
|
||||
{
|
||||
[CustomEditor(typeof(AssetRegistry))]
|
||||
public class AssetRegistryFill : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("Discover AssetEntry Assets"))
|
||||
{
|
||||
Populate((AssetRegistry)target);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Populate(AssetRegistry registry)
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:AssetEntry");
|
||||
|
||||
var scenes = new List<AssetEntry>();
|
||||
var levels = new List<AssetEntry>();
|
||||
var items = new List<AssetEntry>();
|
||||
var ui = new List<AssetEntry>();
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var entry = AssetDatabase.LoadAssetAtPath<AssetEntry>(path);
|
||||
|
||||
if (entry == null)
|
||||
continue;
|
||||
|
||||
switch (entry.EntryType)
|
||||
{
|
||||
case AssetEntry.AssetEntryType.Scene:
|
||||
scenes.Add(entry);
|
||||
break;
|
||||
|
||||
case AssetEntry.AssetEntryType.Level:
|
||||
levels.Add(entry);
|
||||
break;
|
||||
|
||||
case AssetEntry.AssetEntryType.Item:
|
||||
items.Add(entry);
|
||||
break;
|
||||
|
||||
case AssetEntry.AssetEntryType.UI:
|
||||
ui.Add(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
scenes.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
levels.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
items.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
ui.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
|
||||
Undo.RecordObject(registry, "Discover AssetEntry Assets");
|
||||
registry.SetDiscoveredEntries(scenes, levels, items, ui);
|
||||
EditorUtility.SetDirty(registry);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Debug.Log($"[AssetRegistry] Discovery complete. Scenes: {scenes.Count}, Levels: {levels.Count}, Items: {items.Count}, UI: {ui.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f49114100e741bb849cbdfb5fc457cc
|
||||
timeCreated: 1773602794
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Collections.Generic;
|
||||
using BriarQueen.Data.Identifiers;
|
||||
using BriarQueen.Framework.Managers.Player.Data;
|
||||
using BriarQueen.Framework.Registries;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Editor.Drawers.Registries
|
||||
{
|
||||
[CustomEditor(typeof(CodexRegistry))]
|
||||
public class CodexRegistryFill : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("Discover Codex Entry Assets"))
|
||||
{
|
||||
Populate((CodexRegistry)target);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Populate(CodexRegistry registry)
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:CodexEntrySo");
|
||||
|
||||
var books = new List<CodexEntrySo>();
|
||||
var clues = new List<CodexEntrySo>();
|
||||
var photos = new List<CodexEntrySo>();
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var entry = AssetDatabase.LoadAssetAtPath<CodexEntrySo>(path);
|
||||
|
||||
if (entry == null)
|
||||
continue;
|
||||
|
||||
switch (entry.EntryType)
|
||||
{
|
||||
case CodexType.BookEntry:
|
||||
books.Add(entry);
|
||||
break;
|
||||
|
||||
case CodexType.PuzzleClue:
|
||||
clues.Add(entry);
|
||||
break;
|
||||
|
||||
case CodexType.Photo:
|
||||
photos.Add(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
books.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
clues.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
photos.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
|
||||
Undo.RecordObject(registry, "Discover Codex Assets");
|
||||
registry.SetDiscoveredEntries(books, clues, photos);
|
||||
EditorUtility.SetDirty(registry);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Debug.Log($"[AssetRegistry] Discovery complete. Books: {books.Count}, Clues: {clues.Count}, Photos: {photos.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 04adf387d1e94429a6c320005150cb90
|
||||
timeCreated: 1773921705
|
||||
69
Assets/Scripts/Editor/Drawers/Registries/ItemRegistryFill.cs
Normal file
69
Assets/Scripts/Editor/Drawers/Registries/ItemRegistryFill.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System.Collections.Generic;
|
||||
using BriarQueen.Framework.Managers.Player.Data;
|
||||
using BriarQueen.Framework.Registries;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Editor.Drawers.Registries
|
||||
{
|
||||
[CustomEditor(typeof(ItemRegistry))]
|
||||
public class ItemRegistryFill : UnityEditor.Editor
|
||||
{
|
||||
public override void OnInspectorGUI()
|
||||
{
|
||||
DrawDefaultInspector();
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
if (GUILayout.Button("Discover Item Assets"))
|
||||
{
|
||||
Populate((ItemRegistry)target);
|
||||
}
|
||||
}
|
||||
|
||||
private static void Populate(ItemRegistry registry)
|
||||
{
|
||||
string[] guids = AssetDatabase.FindAssets("t:ItemDataSo");
|
||||
|
||||
var puzzleSlots = new List<ItemDataSo>();
|
||||
var pickupItems = new List<ItemDataSo>();
|
||||
var environmentInteractables = new List<ItemDataSo>();
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var entry = AssetDatabase.LoadAssetAtPath<ItemDataSo>(path);
|
||||
|
||||
if (entry == null)
|
||||
continue;
|
||||
|
||||
switch (entry.IdType)
|
||||
{
|
||||
case ItemDataSo.ItemIdType.PuzzleSlot:
|
||||
puzzleSlots.Add(entry);
|
||||
break;
|
||||
|
||||
case ItemDataSo.ItemIdType.Pickup:
|
||||
pickupItems.Add(entry);
|
||||
break;
|
||||
|
||||
case ItemDataSo.ItemIdType.Environment:
|
||||
environmentInteractables.Add(entry);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
puzzleSlots.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
pickupItems.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
environmentInteractables.Sort((a, b) => string.CompareOrdinal(a.name, b.name));
|
||||
|
||||
Undo.RecordObject(registry, "Discover Item Assets");
|
||||
registry.SetDiscoveredEntries(puzzleSlots, pickupItems, environmentInteractables);
|
||||
EditorUtility.SetDirty(registry);
|
||||
AssetDatabase.SaveAssets();
|
||||
|
||||
Debug.Log(
|
||||
$"[ItemRegistry] Discovery complete. Puzzle Slots: {puzzleSlots.Count}, Pickup Items: {pickupItems.Count}, Environment Interactables: {environmentInteractables.Count}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a9e6445d7af341b6995266514b666497
|
||||
timeCreated: 1773921699
|
||||
3
Assets/Scripts/Editor/Windows.meta
Normal file
3
Assets/Scripts/Editor/Windows.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 62c44b8b6745497c8ec129a63cbabd07
|
||||
timeCreated: 1773597607
|
||||
93
Assets/Scripts/Editor/Windows/FilePathsWindow.cs
Normal file
93
Assets/Scripts/Editor/Windows/FilePathsWindow.cs
Normal file
@@ -0,0 +1,93 @@
|
||||
using System.IO;
|
||||
using BriarQueen.Data.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Editor.Windows
|
||||
{
|
||||
public class FilePathsWindow : EditorWindow
|
||||
{
|
||||
[MenuItem("Briar Queen/IO/Open Persistent Data/Save Data")]
|
||||
private static void OpenSaveDataFolder()
|
||||
{
|
||||
OpenFolder(FilePaths.SaveDataFolder);
|
||||
}
|
||||
|
||||
[MenuItem("Briar Queen/IO/Open Persistent Data/Save Backups")]
|
||||
private static void OpenSaveBackupFolder()
|
||||
{
|
||||
OpenFolder(FilePaths.SaveBackupDataFolder);
|
||||
}
|
||||
|
||||
[MenuItem("Briar Queen/IO/Open Persistent Data/Configs")]
|
||||
private static void OpenConfigFolder()
|
||||
{
|
||||
OpenFolder(FilePaths.ConfigFolder);
|
||||
}
|
||||
|
||||
[MenuItem("Briar Queen/IO/Open Persistent Data/All Paths Window")]
|
||||
private static void ShowWindow()
|
||||
{
|
||||
var window = GetWindow<FilePathsWindow>("Persistent Data Paths");
|
||||
window.minSize = new Vector2(520f, 180f);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
GUILayout.Space(10f);
|
||||
EditorGUILayout.LabelField("BriarQueen Persistent Data Paths", EditorStyles.boldLabel);
|
||||
GUILayout.Space(8f);
|
||||
|
||||
DrawPathRow("Save Data", FilePaths.SaveDataFolder);
|
||||
DrawPathRow("Save Backups", FilePaths.SaveBackupDataFolder);
|
||||
DrawPathRow("Configs", FilePaths.ConfigFolder);
|
||||
|
||||
GUILayout.Space(12f);
|
||||
|
||||
if (GUILayout.Button("Open Application Persistent Data Root", GUILayout.Height(28f)))
|
||||
{
|
||||
OpenFolder(Application.persistentDataPath);
|
||||
}
|
||||
}
|
||||
|
||||
private static void DrawPathRow(string label, string path)
|
||||
{
|
||||
using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox))
|
||||
{
|
||||
EditorGUILayout.LabelField(label, EditorStyles.boldLabel);
|
||||
EditorGUILayout.SelectableLabel(path, EditorStyles.textField, GUILayout.Height(18f));
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Open", GUILayout.Height(24f)))
|
||||
{
|
||||
OpenFolder(path);
|
||||
}
|
||||
|
||||
if (GUILayout.Button("Copy Path", GUILayout.Height(24f)))
|
||||
{
|
||||
EditorGUIUtility.systemCopyBuffer = path;
|
||||
Debug.Log($"Copied path: {path}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void OpenFolder(string folderPath)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(folderPath))
|
||||
{
|
||||
Debug.LogError("Cannot open folder: path is null or empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(folderPath))
|
||||
{
|
||||
Directory.CreateDirectory(folderPath);
|
||||
Debug.Log($"Created folder: {folderPath}");
|
||||
}
|
||||
|
||||
EditorUtility.RevealInFinder(folderPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Editor/Windows/FilePathsWindow.cs.meta
Normal file
3
Assets/Scripts/Editor/Windows/FilePathsWindow.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 09ff6a774c3b4bb18d1fc39ac9d70284
|
||||
timeCreated: 1773668525
|
||||
655
Assets/Scripts/Editor/Windows/ScriptableObjectGenerator.cs
Normal file
655
Assets/Scripts/Editor/Windows/ScriptableObjectGenerator.cs
Normal file
@@ -0,0 +1,655 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using BriarQueen.Data.Assets;
|
||||
using BriarQueen.Data.Identifiers;
|
||||
using BriarQueen.Framework.Managers.Player.Data;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BriarQueen.Editor.Windows
|
||||
{
|
||||
public class ScriptableObjectGenerator : EditorWindow
|
||||
{
|
||||
private const string DEFAULT_ITEM_ROOT_FOLDER = "Assets/Data/Information/Items";
|
||||
private const string DEFAULT_ICON_FOLDER = "Assets/Data/Artwork/Icons";
|
||||
private const string DEFAULT_ASSET_ENTRY_ROOT_FOLDER = "Assets/Data/Information/Asset Keys";
|
||||
private const string DEFAULT_CODEX_ROOT_FOLDER = "Assets/Data/Information/Codex";
|
||||
|
||||
private string _itemRootFolder = DEFAULT_ITEM_ROOT_FOLDER;
|
||||
private string _iconFolder = DEFAULT_ICON_FOLDER;
|
||||
private string _assetEntryRootFolder = DEFAULT_ASSET_ENTRY_ROOT_FOLDER;
|
||||
private string _codexRootFolder = DEFAULT_CODEX_ROOT_FOLDER;
|
||||
|
||||
private bool _overwriteExisting;
|
||||
private bool _assignIconsDuringCreate = true;
|
||||
private bool _overwriteExistingIcons;
|
||||
|
||||
private bool _createPickups = true;
|
||||
private bool _createEnvironment = true;
|
||||
private bool _createPuzzleSlots = true;
|
||||
|
||||
private bool _createUIAssetEntries = true;
|
||||
private bool _createSceneAssetEntries = true;
|
||||
private bool _createLevelAssetEntries = true;
|
||||
private bool _createItemAssetEntries = true;
|
||||
|
||||
private bool _createBookEntries = true;
|
||||
private bool _createPuzzleClues = true;
|
||||
private bool _createPhotos = true;
|
||||
|
||||
[MenuItem("Briar Queen/Tools/Assets/Scriptable Object Generator")]
|
||||
public static void Open()
|
||||
{
|
||||
var window = GetWindow<ScriptableObjectGenerator>("ItemDataSO Generator");
|
||||
window.minSize = new Vector2(700f, 600f);
|
||||
}
|
||||
|
||||
private void OnGUI()
|
||||
{
|
||||
EditorGUILayout.Space();
|
||||
EditorGUILayout.LabelField("Content Generator", EditorStyles.boldLabel);
|
||||
EditorGUILayout.HelpBox(
|
||||
"Create or update ItemDataSo assets from enums, assign icons to existing ItemDataSo assets, create/update AssetEntry assets from asset enums, and create/update CodexEntrySO assets from codex enums.",
|
||||
MessageType.Info);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
DrawItemDataSection();
|
||||
EditorGUILayout.Space(10f);
|
||||
DrawAssetEntrySection();
|
||||
EditorGUILayout.Space(10f);
|
||||
DrawCodexSection();
|
||||
}
|
||||
|
||||
private void DrawItemDataSection()
|
||||
{
|
||||
EditorGUILayout.LabelField("ItemDataSo", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Folders", EditorStyles.miniBoldLabel);
|
||||
_itemRootFolder = EditorGUILayout.TextField("Items Root Folder", _itemRootFolder);
|
||||
_iconFolder = EditorGUILayout.TextField("Icons Folder", _iconFolder);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Create / Update Options", EditorStyles.miniBoldLabel);
|
||||
_overwriteExisting = EditorGUILayout.Toggle("Overwrite Existing Assets", _overwriteExisting);
|
||||
_assignIconsDuringCreate = EditorGUILayout.Toggle("Assign Icons During Create", _assignIconsDuringCreate);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Generate Groups", EditorStyles.miniBoldLabel);
|
||||
_createPickups = EditorGUILayout.Toggle("Pickups", _createPickups);
|
||||
_createEnvironment = EditorGUILayout.Toggle("Environment", _createEnvironment);
|
||||
_createPuzzleSlots = EditorGUILayout.Toggle("Puzzle Slots", _createPuzzleSlots);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Icon Assignment Options", EditorStyles.miniBoldLabel);
|
||||
_overwriteExistingIcons = EditorGUILayout.Toggle("Overwrite Existing Icons", _overwriteExistingIcons);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Create / Update ItemDataSO Assets", GUILayout.Height(32f)))
|
||||
CreateOrUpdateItemAssets();
|
||||
|
||||
if (GUILayout.Button("Assign Icons To Existing ItemDataSOs", GUILayout.Height(32f)))
|
||||
AssignIconsToExistingItemAssets();
|
||||
}
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Reveal Items Folder", GUILayout.Height(28f)))
|
||||
RevealFolder(_itemRootFolder);
|
||||
|
||||
if (GUILayout.Button("Reveal Icons Folder", GUILayout.Height(28f)))
|
||||
RevealFolder(_iconFolder);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawAssetEntrySection()
|
||||
{
|
||||
EditorGUILayout.LabelField("AssetEntry", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Folders", EditorStyles.miniBoldLabel);
|
||||
_assetEntryRootFolder = EditorGUILayout.TextField("AssetEntry Root Folder", _assetEntryRootFolder);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Generate AssetEntry Groups", EditorStyles.miniBoldLabel);
|
||||
_createUIAssetEntries = EditorGUILayout.Toggle("UI Entries", _createUIAssetEntries);
|
||||
_createSceneAssetEntries = EditorGUILayout.Toggle("Scene Entries", _createSceneAssetEntries);
|
||||
_createLevelAssetEntries = EditorGUILayout.Toggle("Level Entries", _createLevelAssetEntries);
|
||||
_createItemAssetEntries = EditorGUILayout.Toggle("Item Entries", _createItemAssetEntries);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Create / Update AssetEntry Assets", GUILayout.Height(32f)))
|
||||
CreateOrUpdateAssetEntries();
|
||||
|
||||
if (GUILayout.Button("Reveal AssetEntry Folder", GUILayout.Height(32f)))
|
||||
RevealFolder(_assetEntryRootFolder);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawCodexSection()
|
||||
{
|
||||
EditorGUILayout.LabelField("CodexEntrySO", EditorStyles.boldLabel);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Folders", EditorStyles.miniBoldLabel);
|
||||
_codexRootFolder = EditorGUILayout.TextField("Codex Root Folder", _codexRootFolder);
|
||||
|
||||
EditorGUILayout.Space(4f);
|
||||
EditorGUILayout.LabelField("Generate Codex Groups", EditorStyles.miniBoldLabel);
|
||||
_createBookEntries = EditorGUILayout.Toggle("Book Entries", _createBookEntries);
|
||||
_createPuzzleClues = EditorGUILayout.Toggle("Puzzle Clues", _createPuzzleClues);
|
||||
_createPhotos = EditorGUILayout.Toggle("Photos", _createPhotos);
|
||||
|
||||
EditorGUILayout.Space();
|
||||
|
||||
using (new EditorGUILayout.HorizontalScope())
|
||||
{
|
||||
if (GUILayout.Button("Create / Update CodexEntrySO Assets", GUILayout.Height(32f)))
|
||||
CreateOrUpdateCodexEntries();
|
||||
|
||||
if (GUILayout.Button("Reveal Codex Folder", GUILayout.Height(32f)))
|
||||
RevealFolder(_codexRootFolder);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateOrUpdateItemAssets()
|
||||
{
|
||||
if (!IsValidAssetsPath(_itemRootFolder))
|
||||
{
|
||||
Debug.LogError("[Content Generator] Items Root Folder must start with 'Assets'.");
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureFolderExists(_itemRootFolder);
|
||||
|
||||
int created = 0;
|
||||
int updated = 0;
|
||||
int skipped = 0;
|
||||
|
||||
if (_createPickups)
|
||||
{
|
||||
ProcessEnum<ItemKey, ItemDataSo>(
|
||||
rootFolder: _itemRootFolder,
|
||||
folderName: "Pickups",
|
||||
noneValue: ItemKey.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<ItemDataSo>(path),
|
||||
createAsset: () => CreateInstance<ItemDataSo>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_idType", (int)ItemDataSo.ItemIdType.Pickup);
|
||||
SetEnumField(so, "_itemKey", (int)key);
|
||||
SetEnumField(so, "_environmentKey", (int)EnvironmentKey.None);
|
||||
SetEnumField(so, "_puzzleSlotKey", (int)PuzzleSlotKey.None);
|
||||
SetStringFieldIfEmpty(so, "_itemName", ObjectNames.NicifyVariableName(key.ToString()));
|
||||
|
||||
if (_assignIconsDuringCreate)
|
||||
AssignIcon(so, key.ToString(), _overwriteExistingIcons);
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
if (_createEnvironment)
|
||||
{
|
||||
ProcessEnum<EnvironmentKey, ItemDataSo>(
|
||||
rootFolder: _itemRootFolder,
|
||||
folderName: "Environment",
|
||||
noneValue: EnvironmentKey.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<ItemDataSo>(path),
|
||||
createAsset: () => CreateInstance<ItemDataSo>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_idType", (int)ItemDataSo.ItemIdType.Environment);
|
||||
SetEnumField(so, "_itemKey", (int)ItemKey.None);
|
||||
SetEnumField(so, "_environmentKey", (int)key);
|
||||
SetEnumField(so, "_puzzleSlotKey", (int)PuzzleSlotKey.None);
|
||||
SetStringFieldIfEmpty(so, "_itemName", ObjectNames.NicifyVariableName(key.ToString()));
|
||||
|
||||
if (_assignIconsDuringCreate)
|
||||
AssignIcon(so, key.ToString(), _overwriteExistingIcons);
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
if (_createPuzzleSlots)
|
||||
{
|
||||
ProcessEnum<PuzzleSlotKey, ItemDataSo>(
|
||||
rootFolder: _itemRootFolder,
|
||||
folderName: "PuzzleSlots",
|
||||
noneValue: PuzzleSlotKey.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<ItemDataSo>(path),
|
||||
createAsset: () => CreateInstance<ItemDataSo>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_idType", (int)ItemDataSo.ItemIdType.PuzzleSlot);
|
||||
SetEnumField(so, "_itemKey", (int)ItemKey.None);
|
||||
SetEnumField(so, "_environmentKey", (int)EnvironmentKey.None);
|
||||
SetEnumField(so, "_puzzleSlotKey", (int)key);
|
||||
SetStringFieldIfEmpty(so, "_itemName", ObjectNames.NicifyVariableName(key.ToString()));
|
||||
|
||||
if (_assignIconsDuringCreate)
|
||||
AssignIcon(so, key.ToString(), _overwriteExistingIcons);
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"[Content Generator] ItemDataSO generation complete. Created: {created}, Updated: {updated}, Skipped: {skipped}");
|
||||
}
|
||||
|
||||
private void AssignIconsToExistingItemAssets()
|
||||
{
|
||||
if (!IsValidAssetsPath(_iconFolder))
|
||||
{
|
||||
Debug.LogError("[Content Generator] Icons Folder must start with 'Assets'.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!AssetDatabase.IsValidFolder(_iconFolder))
|
||||
{
|
||||
Debug.LogError($"[Content Generator] Icons folder not found: {_iconFolder}");
|
||||
return;
|
||||
}
|
||||
|
||||
string[] guids = AssetDatabase.FindAssets("t:ItemDataSo", new[] { _itemRootFolder });
|
||||
|
||||
int assigned = 0;
|
||||
int skipped = 0;
|
||||
int missing = 0;
|
||||
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string assetPath = AssetDatabase.GUIDToAssetPath(guid);
|
||||
var asset = AssetDatabase.LoadAssetAtPath<ItemDataSo>(assetPath);
|
||||
|
||||
if (asset == null)
|
||||
continue;
|
||||
|
||||
var so = new SerializedObject(asset);
|
||||
so.Update();
|
||||
|
||||
bool changed = AssignIcon(so, asset.name, _overwriteExistingIcons);
|
||||
|
||||
if (changed)
|
||||
{
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
EditorUtility.SetDirty(asset);
|
||||
assigned++;
|
||||
}
|
||||
else
|
||||
{
|
||||
var iconProp = so.FindProperty("_icon");
|
||||
if (iconProp != null && iconProp.objectReferenceValue != null && !_overwriteExistingIcons)
|
||||
skipped++;
|
||||
else
|
||||
missing++;
|
||||
}
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"[Content Generator] Icon assignment complete. Assigned: {assigned}, Skipped: {skipped}, Missing Icons: {missing}");
|
||||
}
|
||||
|
||||
private void CreateOrUpdateAssetEntries()
|
||||
{
|
||||
if (!IsValidAssetsPath(_assetEntryRootFolder))
|
||||
{
|
||||
Debug.LogError("[Content Generator] AssetEntry Root Folder must start with 'Assets'.");
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureFolderExists(_assetEntryRootFolder);
|
||||
|
||||
int created = 0;
|
||||
int updated = 0;
|
||||
int skipped = 0;
|
||||
|
||||
if (_createUIAssetEntries)
|
||||
{
|
||||
ProcessEnum<UIKey, AssetEntry>(
|
||||
rootFolder: _assetEntryRootFolder,
|
||||
folderName: "UI",
|
||||
noneValue: UIKey.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
||||
createAsset: () => CreateInstance<AssetEntry>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.UI);
|
||||
SetEnumField(so, "_uiKey", (int)key);
|
||||
SetEnumField(so, "_sceneKey", (int)SceneKey.None);
|
||||
SetEnumField(so, "_levelKey", (int)LevelKey.None);
|
||||
SetEnumField(so, "_itemKey", (int)AssetItemKey.None);
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
if (_createSceneAssetEntries)
|
||||
{
|
||||
ProcessEnum<SceneKey, AssetEntry>(
|
||||
rootFolder: _assetEntryRootFolder,
|
||||
folderName: "Scenes",
|
||||
noneValue: SceneKey.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
||||
createAsset: () => CreateInstance<AssetEntry>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.Scene);
|
||||
SetEnumField(so, "_uiKey", (int)UIKey.None);
|
||||
SetEnumField(so, "_sceneKey", (int)key);
|
||||
SetEnumField(so, "_levelKey", (int)LevelKey.None);
|
||||
SetEnumField(so, "_itemKey", (int)AssetItemKey.None);
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
if (_createLevelAssetEntries)
|
||||
{
|
||||
ProcessEnum<LevelKey, AssetEntry>(
|
||||
rootFolder: _assetEntryRootFolder,
|
||||
folderName: "Levels",
|
||||
noneValue: LevelKey.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
||||
createAsset: () => CreateInstance<AssetEntry>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.Level);
|
||||
SetEnumField(so, "_uiKey", (int)UIKey.None);
|
||||
SetEnumField(so, "_sceneKey", (int)SceneKey.None);
|
||||
SetEnumField(so, "_levelKey", (int)key);
|
||||
SetEnumField(so, "_itemKey", (int)AssetItemKey.None);
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
if (_createItemAssetEntries)
|
||||
{
|
||||
ProcessEnum<AssetItemKey, AssetEntry>(
|
||||
rootFolder: _assetEntryRootFolder,
|
||||
folderName: "Items",
|
||||
noneValue: AssetItemKey.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<AssetEntry>(path),
|
||||
createAsset: () => CreateInstance<AssetEntry>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_entryType", (int)AssetEntry.AssetEntryType.Item);
|
||||
SetEnumField(so, "_uiKey", (int)UIKey.None);
|
||||
SetEnumField(so, "_sceneKey", (int)SceneKey.None);
|
||||
SetEnumField(so, "_levelKey", (int)LevelKey.None);
|
||||
SetEnumField(so, "_itemKey", (int)key);
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"[Content Generator] AssetEntry generation complete. Created: {created}, Updated: {updated}, Skipped: {skipped}");
|
||||
}
|
||||
|
||||
private void CreateOrUpdateCodexEntries()
|
||||
{
|
||||
if (!IsValidAssetsPath(_codexRootFolder))
|
||||
{
|
||||
Debug.LogError("[Content Generator] Codex Root Folder must start with 'Assets'.");
|
||||
return;
|
||||
}
|
||||
|
||||
EnsureFolderExists(_codexRootFolder);
|
||||
|
||||
int created = 0;
|
||||
int updated = 0;
|
||||
int skipped = 0;
|
||||
|
||||
if (_createBookEntries)
|
||||
{
|
||||
ProcessEnum<BookEntryID, CodexEntrySo>(
|
||||
rootFolder: _codexRootFolder,
|
||||
folderName: "Books",
|
||||
noneValue: BookEntryID.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<CodexEntrySo>(path),
|
||||
createAsset: () => CreateInstance<CodexEntrySo>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_codexType", (int)CodexType.BookEntry);
|
||||
SetEnumField(so, "_bookEntryID", (int)key);
|
||||
SetEnumField(so, "_clueEntryID", (int)ClueEntryID.None);
|
||||
SetEnumField(so, "_photoEntryID", (int)PhotoEntryID.None);
|
||||
SetStringFieldIfEmpty(so, "_title", ObjectNames.NicifyVariableName(key.ToString()));
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
if (_createPuzzleClues)
|
||||
{
|
||||
ProcessEnum<ClueEntryID, CodexEntrySo>(
|
||||
rootFolder: _codexRootFolder,
|
||||
folderName: "Clues",
|
||||
noneValue: ClueEntryID.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<CodexEntrySo>(path),
|
||||
createAsset: () => CreateInstance<CodexEntrySo>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_codexType", (int)CodexType.PuzzleClue);
|
||||
SetEnumField(so, "_bookEntryID", (int)BookEntryID.None);
|
||||
SetEnumField(so, "_clueEntryID", (int)key);
|
||||
SetEnumField(so, "_photoEntryID", (int)PhotoEntryID.None);
|
||||
SetStringFieldIfEmpty(so, "_title", ObjectNames.NicifyVariableName(key.ToString()));
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
if (_createPhotos)
|
||||
{
|
||||
ProcessEnum<PhotoEntryID, CodexEntrySo>(
|
||||
rootFolder: _codexRootFolder,
|
||||
folderName: "Photos",
|
||||
noneValue: PhotoEntryID.None,
|
||||
assetExtensionName: key => key.ToString(),
|
||||
loadExistingAsset: path => AssetDatabase.LoadAssetAtPath<CodexEntrySo>(path),
|
||||
createAsset: () => CreateInstance<CodexEntrySo>(),
|
||||
applyValues: (so, key) =>
|
||||
{
|
||||
SetEnumField(so, "_codexType", (int)CodexType.Photo);
|
||||
SetEnumField(so, "_bookEntryID", (int)BookEntryID.None);
|
||||
SetEnumField(so, "_clueEntryID", (int)ClueEntryID.None);
|
||||
SetEnumField(so, "_photoEntryID", (int)key);
|
||||
SetStringFieldIfEmpty(so, "_title", ObjectNames.NicifyVariableName(key.ToString()));
|
||||
},
|
||||
ref created,
|
||||
ref updated,
|
||||
ref skipped);
|
||||
}
|
||||
|
||||
AssetDatabase.SaveAssets();
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
Debug.Log($"[Content Generator] CodexEntrySO generation complete. Created: {created}, Updated: {updated}, Skipped: {skipped}");
|
||||
}
|
||||
|
||||
private void ProcessEnum<TEnum, TAsset>(
|
||||
string rootFolder,
|
||||
string folderName,
|
||||
TEnum noneValue,
|
||||
Func<TEnum, string> assetExtensionName,
|
||||
Func<string, TAsset> loadExistingAsset,
|
||||
Func<TAsset> createAsset,
|
||||
Action<SerializedObject, TEnum> applyValues,
|
||||
ref int created,
|
||||
ref int updated,
|
||||
ref int skipped)
|
||||
where TEnum : struct, Enum
|
||||
where TAsset : UnityEngine.Object
|
||||
{
|
||||
string folderPath = $"{rootFolder}/{folderName}";
|
||||
EnsureFolderExists(folderPath);
|
||||
|
||||
foreach (TEnum key in Enum.GetValues(typeof(TEnum)))
|
||||
{
|
||||
if (EqualityComparer<TEnum>.Default.Equals(key, noneValue))
|
||||
continue;
|
||||
|
||||
string assetName = assetExtensionName(key);
|
||||
string assetPath = $"{folderPath}/{assetName}.asset";
|
||||
|
||||
var existing = loadExistingAsset(assetPath);
|
||||
|
||||
if (existing != null && !_overwriteExisting)
|
||||
{
|
||||
skipped++;
|
||||
continue;
|
||||
}
|
||||
|
||||
TAsset asset;
|
||||
bool isNew = false;
|
||||
|
||||
if (existing == null)
|
||||
{
|
||||
asset = createAsset();
|
||||
AssetDatabase.CreateAsset(asset, assetPath);
|
||||
isNew = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
asset = existing;
|
||||
}
|
||||
|
||||
var so = new SerializedObject(asset);
|
||||
so.Update();
|
||||
|
||||
applyValues(so, key);
|
||||
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
EditorUtility.SetDirty(asset);
|
||||
|
||||
if (isNew)
|
||||
created++;
|
||||
else
|
||||
updated++;
|
||||
}
|
||||
}
|
||||
|
||||
private bool AssignIcon(SerializedObject so, string assetOrEnumName, bool overwriteExisting)
|
||||
{
|
||||
var iconProp = so.FindProperty("_icon");
|
||||
if (iconProp == null)
|
||||
return false;
|
||||
|
||||
if (!overwriteExisting && iconProp.objectReferenceValue != null)
|
||||
return false;
|
||||
|
||||
Sprite sprite = FindIconByName(assetOrEnumName);
|
||||
if (sprite == null)
|
||||
return false;
|
||||
|
||||
iconProp.objectReferenceValue = sprite;
|
||||
return true;
|
||||
}
|
||||
|
||||
private Sprite FindIconByName(string iconName)
|
||||
{
|
||||
if (!AssetDatabase.IsValidFolder(_iconFolder))
|
||||
return null;
|
||||
|
||||
string[] guids = AssetDatabase.FindAssets($"{iconName} t:Sprite", new[] { _iconFolder });
|
||||
if (guids == null || guids.Length == 0)
|
||||
return null;
|
||||
|
||||
string path = AssetDatabase.GUIDToAssetPath(guids[0]);
|
||||
return AssetDatabase.LoadAssetAtPath<Sprite>(path);
|
||||
}
|
||||
|
||||
private static void SetEnumField(SerializedObject so, string propertyName, int enumValue)
|
||||
{
|
||||
var prop = so.FindProperty(propertyName);
|
||||
if (prop != null)
|
||||
prop.enumValueIndex = enumValue;
|
||||
}
|
||||
|
||||
private static void SetStringFieldIfEmpty(SerializedObject so, string propertyName, string value)
|
||||
{
|
||||
var prop = so.FindProperty(propertyName);
|
||||
if (prop == null)
|
||||
return;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(prop.stringValue))
|
||||
prop.stringValue = value;
|
||||
}
|
||||
|
||||
private static bool IsValidAssetsPath(string path)
|
||||
{
|
||||
return !string.IsNullOrWhiteSpace(path) && path.StartsWith("Assets", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
private static void EnsureFolderExists(string fullPath)
|
||||
{
|
||||
string[] parts = fullPath.Split('/');
|
||||
if (parts.Length == 0 || parts[0] != "Assets")
|
||||
throw new InvalidOperationException($"Invalid Unity folder path: {fullPath}");
|
||||
|
||||
string current = "Assets";
|
||||
|
||||
for (int i = 1; i < parts.Length; i++)
|
||||
{
|
||||
string next = $"{current}/{parts[i]}";
|
||||
if (!AssetDatabase.IsValidFolder(next))
|
||||
AssetDatabase.CreateFolder(current, parts[i]);
|
||||
|
||||
current = next;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RevealFolder(string folderPath)
|
||||
{
|
||||
if (!IsValidAssetsPath(folderPath))
|
||||
return;
|
||||
|
||||
EnsureFolderExists(folderPath);
|
||||
|
||||
UnityEngine.Object folder = AssetDatabase.LoadAssetAtPath<UnityEngine.Object>(folderPath);
|
||||
if (folder != null)
|
||||
{
|
||||
Selection.activeObject = folder;
|
||||
EditorGUIUtility.PingObject(folder);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b81754fd377748c6a539d9077fa199b5
|
||||
timeCreated: 1773597607
|
||||
8
Assets/Scripts/Framework.meta
Normal file
8
Assets/Scripts/Framework.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6af79de96118949af9eacd7d09a95428
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scripts/Framework/.DS_Store
vendored
Normal file
BIN
Assets/Scripts/Framework/.DS_Store
vendored
Normal file
Binary file not shown.
3
Assets/Scripts/Framework/Assets.meta
Normal file
3
Assets/Scripts/Framework/Assets.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff2ed8f2f4124c45aad87cacd37abf0d
|
||||
timeCreated: 1769705501
|
||||
204
Assets/Scripts/Framework/Assets/AddressableManager.cs
Normal file
204
Assets/Scripts/Framework/Assets/AddressableManager.cs
Normal file
@@ -0,0 +1,204 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using BriarQueen.Framework.Assets.Components;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using UnityEngine.AddressableAssets;
|
||||
using UnityEngine.ResourceManagement.AsyncOperations;
|
||||
using UnityEngine.ResourceManagement.ResourceProviders;
|
||||
using UnityEngine.SceneManagement;
|
||||
using VContainer;
|
||||
using VContainer.Unity;
|
||||
|
||||
namespace BriarQueen.Framework.Assets
|
||||
{
|
||||
public class AddressableManager : IDisposable
|
||||
{
|
||||
private readonly Dictionary<object, AsyncOperationHandle> _assetHandles = new();
|
||||
private readonly Dictionary<GameObject, AsyncOperationHandle> _instanceHandles = new();
|
||||
private readonly IObjectResolver _lifetimeContainer;
|
||||
private readonly object _lock = new();
|
||||
|
||||
[Inject]
|
||||
public AddressableManager(IObjectResolver lifetimeContainer)
|
||||
{
|
||||
_lifetimeContainer = lifetimeContainer;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
foreach (var handle in _instanceHandles.Values)
|
||||
if (handle.IsValid())
|
||||
Addressables.ReleaseInstance(handle);
|
||||
|
||||
_instanceHandles.Clear();
|
||||
|
||||
foreach (var handle in _assetHandles.Values)
|
||||
if (handle.IsValid())
|
||||
Addressables.Release(handle);
|
||||
|
||||
_assetHandles.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask<T> LoadAssetAsync<T>(AssetReference reference) where T : class
|
||||
{
|
||||
var handle = Addressables.LoadAssetAsync<T>(reference);
|
||||
|
||||
try
|
||||
{
|
||||
await handle;
|
||||
|
||||
if (handle.Status == AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
lock (_lock)
|
||||
{
|
||||
_assetHandles[handle.Result] = handle;
|
||||
}
|
||||
|
||||
return handle.Result;
|
||||
}
|
||||
|
||||
Debug.LogError($"[AddressableManager] Failed to load asset: {reference.RuntimeKey}");
|
||||
return null;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
if (handle.IsValid()) Addressables.Release(handle);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public void ReleaseAsset<T>(T asset) where T : class
|
||||
{
|
||||
if (asset == null) return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_assetHandles.TryGetValue(asset, out var handle))
|
||||
{
|
||||
if (handle.IsValid()) Addressables.Release(handle);
|
||||
|
||||
_assetHandles.Remove(asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async UniTask<AsyncOperationHandle<SceneInstance>> LoadSceneAsync(
|
||||
AssetReference assetReference,
|
||||
LoadSceneMode loadSceneMode = LoadSceneMode.Additive,
|
||||
CancellationToken cancellationToken = default,
|
||||
IProgress<float> progress = null,
|
||||
bool autoLoad = true
|
||||
)
|
||||
{
|
||||
var handle = Addressables.LoadSceneAsync(assetReference, loadSceneMode, autoLoad);
|
||||
await handle.ToUniTask(progress, cancellationToken: cancellationToken);
|
||||
return handle;
|
||||
}
|
||||
|
||||
public async UniTask UnloadSceneAsync(AsyncOperationHandle<SceneInstance> sceneHandle)
|
||||
{
|
||||
if (sceneHandle.IsValid()) await Addressables.UnloadSceneAsync(sceneHandle);
|
||||
}
|
||||
|
||||
public async UniTask<GameObject> InstantiateAsync(
|
||||
AssetReference reference,
|
||||
Vector3 position = default,
|
||||
Quaternion rotation = default,
|
||||
Transform parent = null,
|
||||
IObjectResolver scope = null,
|
||||
CancellationToken cancellationToken = default
|
||||
)
|
||||
{
|
||||
var handle = Addressables.InstantiateAsync(reference, position, rotation, parent);
|
||||
|
||||
try
|
||||
{
|
||||
await handle.WithCancellation(cancellationToken);
|
||||
|
||||
if (handle.Status != AsyncOperationStatus.Succeeded)
|
||||
{
|
||||
Debug.LogError($"[AddressableManager] Failed to instantiate asset: {reference.RuntimeKey}");
|
||||
return null;
|
||||
}
|
||||
|
||||
var go = handle.Result;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
_instanceHandles[go] = handle;
|
||||
}
|
||||
|
||||
var prefabScope = go.GetComponent<LifetimeScope>();
|
||||
var injectionScope = scope ?? prefabScope?.Container ?? _lifetimeContainer;
|
||||
|
||||
injectionScope.InjectGameObject(go);
|
||||
|
||||
var notify = go.GetComponent<NotifyOnDestruction>();
|
||||
|
||||
if (!notify)
|
||||
{
|
||||
notify = go.AddComponent<NotifyOnDestruction>();
|
||||
injectionScope.Inject(notify);
|
||||
}
|
||||
|
||||
void OnInstanceDestroyed()
|
||||
{
|
||||
TryReleaseInstance(go);
|
||||
notify.OnDestroyedCalled -= OnInstanceDestroyed;
|
||||
}
|
||||
|
||||
notify.OnDestroyedCalled += OnInstanceDestroyed;
|
||||
|
||||
return go;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
if (handle.IsValid()) Addressables.ReleaseInstance(handle);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TryReleaseInstance(GameObject instance)
|
||||
{
|
||||
if (instance == null)
|
||||
return false;
|
||||
|
||||
Debug.Log($"[AddressableManager] Trying to release instance: {instance}");
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instanceHandles.TryGetValue(instance, out var handle))
|
||||
{
|
||||
if (handle.IsValid()) Addressables.ReleaseInstance(handle);
|
||||
|
||||
_instanceHandles.Remove(instance);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ReleaseInstance(GameObject instance)
|
||||
{
|
||||
if (instance == null) return;
|
||||
|
||||
lock (_lock)
|
||||
{
|
||||
if (_instanceHandles.TryGetValue(instance, out var handle))
|
||||
{
|
||||
if (handle.IsValid()) Addressables.ReleaseInstance(handle);
|
||||
|
||||
_instanceHandles.Remove(instance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e1db17fcf6194082baad6949fa448ca0
|
||||
timeCreated: 1769705501
|
||||
3
Assets/Scripts/Framework/Assets/Components.meta
Normal file
3
Assets/Scripts/Framework/Assets/Components.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff405febbf4c423ea26f3a0313bef4d5
|
||||
timeCreated: 1773836297
|
||||
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using BriarQueen.Framework.Services.Destruction;
|
||||
using Cysharp.Threading.Tasks;
|
||||
using UnityEngine;
|
||||
using VContainer;
|
||||
|
||||
namespace BriarQueen.Framework.Assets.Components
|
||||
{
|
||||
public class NotifyOnDestruction : MonoBehaviour, IDestructible
|
||||
{
|
||||
private DestructionService _destructionService;
|
||||
|
||||
public UniTask OnPreDestroy()
|
||||
{
|
||||
OnPreDestroyCalled?.Invoke();
|
||||
return UniTask.CompletedTask; // No async operation needed, just a notification
|
||||
}
|
||||
|
||||
public UniTask OnDestroyed()
|
||||
{
|
||||
OnDestroyedCalled?.Invoke();
|
||||
return UniTask.CompletedTask; // No async operation needed, just a notification
|
||||
}
|
||||
|
||||
[Inject]
|
||||
public void Construct(DestructionService destructionService)
|
||||
{
|
||||
_destructionService = destructionService;
|
||||
}
|
||||
|
||||
public event Action OnPreDestroyCalled;
|
||||
public event Action OnDestroyedCalled;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e2aae9ec81f949ffbc5de664b65b46b3
|
||||
timeCreated: 1769705628
|
||||
6
Assets/Scripts/Framework/Assets/IAssetProvider.cs
Normal file
6
Assets/Scripts/Framework/Assets/IAssetProvider.cs
Normal file
@@ -0,0 +1,6 @@
|
||||
namespace BriarQueen.Framework.Assets
|
||||
{
|
||||
public interface IAssetProvider
|
||||
{
|
||||
}
|
||||
}
|
||||
3
Assets/Scripts/Framework/Assets/IAssetProvider.cs.meta
Normal file
3
Assets/Scripts/Framework/Assets/IAssetProvider.cs.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 84550fd141464293b5d6680bdb50bf93
|
||||
timeCreated: 1769705539
|
||||
24
Assets/Scripts/Framework/BriarQueen.Framework.asmdef
Normal file
24
Assets/Scripts/Framework/BriarQueen.Framework.asmdef
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "BriarQueen.Framework",
|
||||
"rootNamespace": "BriarQueen",
|
||||
"references": [
|
||||
"GUID:b0214a6008ed146ff8f122a6a9c2f6cc",
|
||||
"GUID:f51ebe6a0ceec4240a699833d6309b23",
|
||||
"GUID:80ecb87cae9c44d19824e70ea7229748",
|
||||
"GUID:bdf0eff65032c4178bf18aa9c96b1c70",
|
||||
"GUID:9e24947de15b9834991c9d8411ea37cf",
|
||||
"GUID:593a5b492d29ac6448b1ebf7f035ef33",
|
||||
"GUID:84651a3751eca9349aac36a66bba901b",
|
||||
"GUID:75469ad4d38634e559750d17036d5f7c",
|
||||
"GUID:776d03a35f1b52c4a9aed9f56d7b4229"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ac1be664c635c449eb9f3f52cf5c97f5
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
3
Assets/Scripts/Framework/Coordinators.meta
Normal file
3
Assets/Scripts/Framework/Coordinators.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 842950604aa54cb8a98ece9875c94bfe
|
||||
timeCreated: 1773843729
|
||||
3
Assets/Scripts/Framework/Coordinators/Events.meta
Normal file
3
Assets/Scripts/Framework/Coordinators/Events.meta
Normal file
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d6d5109c39334a33a1ec140fed9aa971
|
||||
timeCreated: 1769705112
|
||||
BIN
Assets/Scripts/Framework/Coordinators/Events/.DS_Store
vendored
Normal file
BIN
Assets/Scripts/Framework/Coordinators/Events/.DS_Store
vendored
Normal file
Binary file not shown.
185
Assets/Scripts/Framework/Coordinators/Events/EventCoordinator.cs
Normal file
185
Assets/Scripts/Framework/Coordinators/Events/EventCoordinator.cs
Normal file
@@ -0,0 +1,185 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using BriarQueen.Framework.Events.System;
|
||||
using UnityEngine;
|
||||
using VContainer.Unity;
|
||||
|
||||
namespace BriarQueen.Framework.Coordinators.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// A type-safe, queued event bus for managing gameplay events.
|
||||
/// </summary>
|
||||
public class EventCoordinator : IDisposable, ITickable, IInitializable
|
||||
{
|
||||
private const int MAX_EVENTS_PER_FRAME = 500;
|
||||
|
||||
public static bool EnableDebugLogs = false;
|
||||
|
||||
private readonly Queue<(Type type, IEvent data)> _eventQueue = new();
|
||||
private readonly object _queueLock = new();
|
||||
private readonly Dictionary<Type, Dictionary<object, Action<IEvent>>> _typedEventListeners = new();
|
||||
|
||||
private bool _isProcessingQueue;
|
||||
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
Initialized = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
lock (_queueLock)
|
||||
{
|
||||
_typedEventListeners.Clear();
|
||||
_eventQueue.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void Tick()
|
||||
{
|
||||
ProcessQueue();
|
||||
}
|
||||
|
||||
public void Subscribe<T>(Action<T> listener) where T : IEvent
|
||||
{
|
||||
if (listener == null) return;
|
||||
|
||||
var eventType = typeof(T);
|
||||
|
||||
if (!_typedEventListeners.TryGetValue(eventType, out var listeners))
|
||||
{
|
||||
listeners = new Dictionary<object, Action<IEvent>>();
|
||||
_typedEventListeners[eventType] = listeners;
|
||||
}
|
||||
|
||||
if (listeners.ContainsKey(listener)) return;
|
||||
|
||||
Action<IEvent> wrapper = e => listener((T)e);
|
||||
listeners[listener] = wrapper;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
Debug.Log(
|
||||
$"[EventManager] Subscribed '{eventType.Name}' to '{listener.Method.Name}' from '{listener.Target}'");
|
||||
#endif
|
||||
}
|
||||
|
||||
public void Unsubscribe<T>(Action<T> listener) where T : IEvent
|
||||
{
|
||||
if (listener == null) return;
|
||||
|
||||
var eventType = typeof(T);
|
||||
|
||||
if (_typedEventListeners.TryGetValue(eventType, out var listeners))
|
||||
{
|
||||
listeners.Remove(listener);
|
||||
if (listeners.Count == 0)
|
||||
_typedEventListeners.Remove(eventType);
|
||||
}
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void Publish<T>(T eventData) where T : IEvent
|
||||
{
|
||||
if (eventData == null) return;
|
||||
|
||||
lock (_queueLock)
|
||||
{
|
||||
_eventQueue.Enqueue((typeof(T), eventData));
|
||||
}
|
||||
|
||||
if (EnableDebugLogs)
|
||||
Debug.Log($"[EventManager] Enqueued '{typeof(T).Name}'");
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void PublishImmediate<T>(T eventData) where T : IEvent
|
||||
{
|
||||
if (eventData == null) return;
|
||||
|
||||
var type = typeof(T);
|
||||
|
||||
if (_typedEventListeners.TryGetValue(type, out var listeners) && listeners.Count > 0)
|
||||
{
|
||||
var snapshot = new Action<IEvent>[listeners.Count];
|
||||
listeners.Values.CopyTo(snapshot, 0);
|
||||
|
||||
for (var i = 0; i < snapshot.Length; i++)
|
||||
{
|
||||
var listener = snapshot[i];
|
||||
try
|
||||
{
|
||||
listener?.Invoke(eventData);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"[EventManager] Exception in '{type.Name}' listener: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EnableDebugLogs)
|
||||
Debug.Log($"[EventManager] Fired '{type.Name}' (Immediate)");
|
||||
}
|
||||
|
||||
private void ProcessQueue()
|
||||
{
|
||||
if (_isProcessingQueue) return;
|
||||
|
||||
_isProcessingQueue = true;
|
||||
|
||||
try
|
||||
{
|
||||
var processed = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
(Type type, IEvent data) evt;
|
||||
|
||||
lock (_queueLock)
|
||||
{
|
||||
if (_eventQueue.Count == 0) break;
|
||||
evt = _eventQueue.Dequeue();
|
||||
}
|
||||
|
||||
processed++;
|
||||
if (processed > MAX_EVENTS_PER_FRAME)
|
||||
{
|
||||
Debug.LogWarning(
|
||||
"[EventManager] Max event processing limit reached. Possible infinite publish loop.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (_typedEventListeners.TryGetValue(evt.type, out var listeners) && listeners.Count > 0)
|
||||
{
|
||||
var snapshot = new Action<IEvent>[listeners.Count];
|
||||
listeners.Values.CopyTo(snapshot, 0);
|
||||
|
||||
for (var i = 0; i < snapshot.Length; i++)
|
||||
{
|
||||
var listener = snapshot[i];
|
||||
try
|
||||
{
|
||||
listener?.Invoke(evt.data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError(
|
||||
$"[EventManager] Exception in '{evt.type.Name}' listener during queue processing: {ex}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (EnableDebugLogs)
|
||||
Debug.Log($"[EventManager] Fired '{evt.type.Name}' (Queued)");
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
_isProcessingQueue = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2f0594880d694d8e9297c88bbffbce8f
|
||||
timeCreated: 1769705112
|
||||
8
Assets/Scripts/Framework/Events.meta
Normal file
8
Assets/Scripts/Framework/Events.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c6a5d896b814949f891721df67bc4d13
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
BIN
Assets/Scripts/Framework/Events/.DS_Store
vendored
Normal file
BIN
Assets/Scripts/Framework/Events/.DS_Store
vendored
Normal file
Binary file not shown.
8
Assets/Scripts/Framework/Events/Audio.meta
Normal file
8
Assets/Scripts/Framework/Events/Audio.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 83fb6ea2b08724af2bfa88da928ff310
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,7 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
using BriarQueen.Framework.Managers.Audio.Data;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Audio
|
||||
{
|
||||
public record MusicTrackChangedEvent(AudioFileSo Track) : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f3b589adbdecc410faad1a94d0e92943
|
||||
@@ -0,0 +1,6 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Audio
|
||||
{
|
||||
public record VoiceLineFinishedEvent(string VoiceLineID) : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86ad67d94ae87497a867a22b24fcab54
|
||||
@@ -0,0 +1,6 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Audio
|
||||
{
|
||||
public record VoiceLineStartedEvent(string VoiceLineID) : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8f19b51fb48104a5eae452ff3261ce05
|
||||
8
Assets/Scripts/Framework/Events/Gameplay.meta
Normal file
8
Assets/Scripts/Framework/Events/Gameplay.meta
Normal file
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3eca027f79f05492da343f57bf23ec94
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,6 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Gameplay
|
||||
{
|
||||
public record InventoryChangedEvent : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cdfd706f6f29d43ab80578bd9c9906b8
|
||||
@@ -0,0 +1,7 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
using BriarQueen.Framework.Managers.Levels.Data;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Gameplay
|
||||
{
|
||||
public record LevelChangedEvent(BaseLevel Level) : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54697a2ce8b80480cb269432c0402bc8
|
||||
@@ -0,0 +1,7 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
using BriarQueen.Framework.Managers.Player.Data;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Gameplay
|
||||
{
|
||||
public record OnNextItemClickedEvent() : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b741224892c24b6f899614e541f0bebd
|
||||
timeCreated: 1774433570
|
||||
@@ -0,0 +1,6 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Gameplay
|
||||
{
|
||||
public record OnNextToolChangedEvent() : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 720ded31a3f945e1b5a11c64099e370a
|
||||
timeCreated: 1774128263
|
||||
@@ -0,0 +1,7 @@
|
||||
using BriarQueen.Framework.Events.System;
|
||||
using BriarQueen.Framework.Managers.Player.Data;
|
||||
|
||||
namespace BriarQueen.Framework.Events.Gameplay
|
||||
{
|
||||
public record OnPreviousItemClickedEvent() : IEvent;
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9270b837f3004e398c669ccfefa92a19
|
||||
timeCreated: 1774433570
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user