구글 시트 so 연동 시스템 수정

This commit is contained in:
NTG 2025-08-28 13:01:44 +09:00
parent ba5d3ffb59
commit 4a4c46f5a1
9 changed files with 1810 additions and 44 deletions

View File

@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 90984e9ede7c85d45b0883295d7cff8a
TextScriptImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -10,15 +10,15 @@
namespace DDD
{
public sealed class SoSynchronizer : ISoSynchronizer
public sealed class AssetSynchronizer : IAssetSynchronizer
{
private readonly IValueConverterRegistry _converter;
private readonly List<string> _updatedPaths = new();
public IReadOnlyList<string> UpdatedSoAssetPaths => _updatedPaths;
public IReadOnlyList<string> AssetUpdatedAssetPaths => _updatedPaths;
public SoSynchronizer(IValueConverterRegistry converter) => _converter = converter;
public AssetSynchronizer(IValueConverterRegistry converter) => _converter = converter;
public bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selectedSheets, string rootNamespace, string soFolderAssetPath)
public bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selectedSheets, string rootNamespace, string assetFolderAssetPath)
{
_updatedPaths.Clear();
if (string.IsNullOrEmpty(fullJson)) return false;
@ -27,8 +27,8 @@ public bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selected
bool allSuccess = true;
// 폴더 보장
if (!AssetDatabase.IsValidFolder(soFolderAssetPath))
CreateFolderRecursive(soFolderAssetPath);
if (!AssetDatabase.IsValidFolder(assetFolderAssetPath))
CreateFolderRecursive(assetFolderAssetPath);
// 타입 캐시
var types = AppDomain.CurrentDomain.GetAssemblies()
@ -40,38 +40,38 @@ public bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selected
.GroupBy(t => t.Name)
.ToDictionary(g => g.Key, g => g.First());
Debug.Log($"[SoSync] soFolder={soFolderAssetPath}");
Debug.Log($"[SoSync] selected: {string.Join(", ", selectedSheets)}");
Debug.Log($"[AssetSynchronizer] assetFolder={assetFolderAssetPath}");
Debug.Log($"[AssetSynchronizer] selected: {string.Join(", ", selectedSheets)}");
foreach (var pair in root)
{
string sheet = pair.Key;
if (!selectedSheets.Contains(sheet))
{
Debug.Log($"[SoSync] SKIP(not selected): {sheet}");
Debug.Log($"[AssetSynchronizer] SKIP(not selected): {sheet}");
continue;
}
types.TryGetValue(sheet, out var dataType);
types.TryGetValue($"{sheet}So", out var soType);
if (dataType == null || soType == null)
types.TryGetValue($"{sheet}Entry", out var dataType);
types.TryGetValue($"{sheet}Asset", out var assetType);
if (dataType == null || assetType == null)
{
Debug.LogWarning($"[SoSynchronizer] 타입 누락: {sheet} (data={dataType}, so={soType})");
Debug.LogWarning($"[AssetSynchronizer] 타입 누락: {sheet} (entry={dataType}, asset={assetType})");
allSuccess = false;
continue;
}
string soAssetPath = $"{soFolderAssetPath}/{sheet}So.asset";
var so = AssetDatabase.LoadAssetAtPath<ScriptableObject>(soAssetPath);
if (so == null)
string assetPath = $"{assetFolderAssetPath}/{sheet}Asset.asset";
var asset = AssetDatabase.LoadAssetAtPath<ScriptableObject>(assetPath);
if (asset == null)
{
Debug.Log($"[SoSync] CREATE SO: {soAssetPath}");
so = ScriptableObject.CreateInstance(soType);
AssetDatabase.CreateAsset(so, soAssetPath);
Debug.Log($"[AssetSynchronizer] CREATE SO: {assetPath}");
asset = ScriptableObject.CreateInstance(assetType);
AssetDatabase.CreateAsset(asset, assetPath);
}
else
{
Debug.Log($"[SoSync] FOUND SO: {soAssetPath}");
Debug.Log($"[AssetSynchronizer] FOUND SO: {assetPath}");
}
var list = (IList)Activator.CreateInstance(typeof(List<>).MakeGenericType(dataType));
@ -102,30 +102,30 @@ public bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selected
}
else
{
Debug.LogWarning($"[SoSynchronizer] 변환 실패: {sheet}.{field} -> {targetType?.Name} (원본:'{prop.Value}')");
Debug.LogWarning($"[AssetSynchronizer] 변환 실패: {sheet}.{field} -> {targetType?.Name} (원본:'{prop.Value}')");
}
}
catch (Exception e)
{
Debug.LogWarning($"[SoSynchronizer] 값 할당 예외: {sheet}.{field} -> {e.Message}");
Debug.LogWarning($"[AssetSynchronizer] 값 할당 예외: {sheet}.{field} -> {e.Message}");
}
}
list.Add(inst);
}
var setMethod = soType.GetMethod("SetDataList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
var setMethod = assetType.GetMethod("SetDataList", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
if (setMethod == null)
{
Debug.LogError($"{soType.Name}에 SetDataList 메서드가 없습니다.");
Debug.LogError($"{assetType.Name}에 SetDataList 메서드가 없습니다.");
allSuccess = false;
continue;
}
Debug.Log($"[SoSync] INVOKE SetDataList for {sheet} (rows={(pair.Value as JArray)?.Count ?? 0})");
Debug.Log($"[AssetSynchronizer] INVOKE SetDataList for {sheet} (rows={(pair.Value as JArray)?.Count ?? 0})");
setMethod.Invoke(so, new object[] { list });
EditorUtility.SetDirty(so);
_updatedPaths.Add(soAssetPath);
setMethod.Invoke(asset, new object[] { list });
EditorUtility.SetDirty(asset);
_updatedPaths.Add(assetPath);
}
AssetDatabase.SaveAssets();

View File

@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace DDD
{
public interface IAssetSynchronizer
{
IReadOnlyList<string> AssetUpdatedAssetPaths { get; }
bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selectedSheets, string rootNamespace, string assetFolderAssetPath);
}
}

View File

@ -1,10 +0,0 @@
using System.Collections.Generic;
namespace DDD
{
public interface ISoSynchronizer
{
IReadOnlyList<string> UpdatedSoAssetPaths { get; }
bool SynchronizeAll(string fullJson, IReadOnlyCollection<string> selectedSheets, string rootNamespace, string soFolderAssetPath);
}
}

View File

@ -31,7 +31,7 @@ public class GoogleSheetManager : ScriptableObject
private IJsonDiffer _differ;
private ICodeGenerator _codeGenerator;
private IValueConverterRegistry _converterRegistry;
private ISoSynchronizer _soSynchronizer;
private IAssetSynchronizer _assetSynchronizer;
private IAddressablesRegistrar _addressablesRegistrar;
private IVersionStore _versionStore;
private IReloadCoordinator _reloadCoordinator;
@ -49,7 +49,7 @@ private void BuildServices()
_differ = new NewtonsoftJsonDiffer();
_codeGenerator = new CSharpCodeGenerator(new DefaultTypeNameResolver());
_converterRegistry = new DefaultValueConverterRegistry();
_soSynchronizer = new SoSynchronizer(_converterRegistry);
_assetSynchronizer = new AssetSynchronizer(_converterRegistry);
_addressablesRegistrar = new AddressablesRegistrar();
_versionStore = new GoogleSheetChangeLogVersionStore(_settings.ChangeLogAssetPath);
_reloadCoordinator = new SessionStateReloadCoordinator();
@ -152,11 +152,11 @@ private async Task ContinueSoSync(string json, bool saveSnapshot)
if (_settings.AutoCreateSheets != null) foreach (var s in _settings.AutoCreateSheets) selected.Add(s);
if (_settings.SoSyncOnlySheets != null) foreach (var s in _settings.SoSyncOnlySheets) selected.Add(s);
bool ok = _soSynchronizer.SynchronizeAll(json, selected, _settings.RootNamespace, _settings.SoFolderAssetPath);
bool ok = _assetSynchronizer.SynchronizeAll(json, selected, _settings.RootNamespace, _settings.SoFolderAssetPath);
if (_settings.AutoRegisterToAddressables)
{
foreach (var soPath in _soSynchronizer.UpdatedSoAssetPaths)
foreach (var soPath in _assetSynchronizer.AssetUpdatedAssetPaths)
_addressablesRegistrar.RegisterOrMoveEntry(soPath, _settings.AddressablesGroupName, _settings.AddressablesLabel);
_addressablesRegistrar.SaveAll();
_addressablesRegistrar.BuildIfNeeded(_settings.AutoBuildAddressables);