OctoCore 0.0.1
This commit is contained in:
@@ -0,0 +1,699 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using OctoCore.Inputs;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
using UnityEngine.InputSystem;
|
||||
#endif
|
||||
|
||||
namespace OctoCore
|
||||
{
|
||||
/// <summary>
|
||||
/// Global settings for the OctoCore framework.
|
||||
/// Configure save system, input mappings, localization, and UI settings.
|
||||
/// </summary>
|
||||
[CreateAssetMenu(fileName = "OctoSettings", menuName = "Octo/Settings Global", order = 0)]
|
||||
public class OctoSettings : ScriptableObject
|
||||
{
|
||||
/// <summary>
|
||||
/// Save system configuration.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class SaveSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// All boolean save data keys in the project.
|
||||
/// </summary>
|
||||
public global::OctoCore.Save.Data.OctoDataBool[] Booleans;
|
||||
|
||||
/// <summary>
|
||||
/// All integer save data keys in the project.
|
||||
/// </summary>
|
||||
public global::OctoCore.Save.Data.OctoDataInt[] Integers;
|
||||
|
||||
/// <summary>
|
||||
/// All float save data keys in the project.
|
||||
/// </summary>
|
||||
public global::OctoCore.Save.Data.OctoDataFloat[] Floats;
|
||||
|
||||
/// <summary>
|
||||
/// All string save data keys in the project.
|
||||
/// </summary>
|
||||
public global::OctoCore.Save.Data.OctoDataString[] Strings;
|
||||
|
||||
/// <summary>
|
||||
/// All vector save data keys in the project.
|
||||
/// </summary>
|
||||
public global::OctoCore.Save.Data.OctoDataVector[] Vectors;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Input mapping configuration.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class MappingSettings
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Icon
|
||||
{
|
||||
public bool UseName = true;
|
||||
public Sprite Sprite;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
public class ActionData
|
||||
{
|
||||
[HideInInspector]
|
||||
public string Name;
|
||||
|
||||
[HideInInspector]
|
||||
public string MapName;
|
||||
|
||||
public OctoActions Action;
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
[Tooltip("Reference to the InputAction from the asset")]
|
||||
public InputActionReference Reference;
|
||||
#endif
|
||||
|
||||
public Icon Icon;
|
||||
|
||||
public ActionData(OctoActions action, string name, string mapName)
|
||||
{
|
||||
Action = action;
|
||||
Name = name;
|
||||
MapName = mapName;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference Input Action Asset.
|
||||
/// </summary>
|
||||
#if ENABLE_INPUT_SYSTEM
|
||||
[Tooltip("Assign your Input Action Asset here")]
|
||||
public InputActionAsset InputActionAsset;
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Generated Actions.
|
||||
/// </summary>
|
||||
[Tooltip("Actions (generated automatically)")]
|
||||
public List<ActionData> Actions = new List<ActionData>();
|
||||
|
||||
/// <summary>
|
||||
/// Get action map name for a specific action.
|
||||
/// </summary>
|
||||
public string GetActionMapName(OctoActions action)
|
||||
{
|
||||
foreach (var actionData in Actions)
|
||||
{
|
||||
if (actionData.Action == action)
|
||||
return actionData.MapName;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM && UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// Get InputActionReference for a specific action.
|
||||
/// </summary>
|
||||
public InputActionReference GetReference(OctoActions action)
|
||||
{
|
||||
foreach (var actionData in Actions)
|
||||
{
|
||||
if (actionData.Action == action)
|
||||
return actionData.Reference;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Language configuration.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class LanguagesSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Font override settings for specific languages.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class Override
|
||||
{
|
||||
[HideInInspector] public string Name;
|
||||
|
||||
/// <summary>
|
||||
/// The language this override applies to.
|
||||
/// </summary>
|
||||
public Localization.OctoLanguages Language;
|
||||
|
||||
/// <summary>
|
||||
/// Custom font for this language.
|
||||
/// </summary>
|
||||
public TMP_FontAsset Font;
|
||||
|
||||
/// <summary>
|
||||
/// Size multiplier for this language's text.
|
||||
/// </summary>
|
||||
public float SizeMultiplier = 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default language to use when no preference is set.
|
||||
/// </summary>
|
||||
public Localization.OctoLanguages Default;
|
||||
|
||||
/// <summary>
|
||||
/// Save data key for written language preference.
|
||||
/// </summary>
|
||||
public global::OctoCore.Save.Data.OctoDataString SaveWritten;
|
||||
|
||||
/// <summary>
|
||||
/// Save data key for audio language preference.
|
||||
/// </summary>
|
||||
public global::OctoCore.Save.Data.OctoDataString SaveAudio;
|
||||
|
||||
/// <summary>
|
||||
/// Font overrides for specific languages.
|
||||
/// </summary>
|
||||
public Override[] Overrides;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Configuration for UI scaling.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class UiSettings
|
||||
{
|
||||
[System.Serializable]
|
||||
public class Sprites
|
||||
{
|
||||
public Sprite DefaultButton;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reference screen size for UI scaling calculations.
|
||||
/// </summary>
|
||||
public Vector2Int ReferenceSize = new Vector2Int(1920, 1080);
|
||||
|
||||
/// <summary>
|
||||
/// Reference screen size for UI scaling calculations.
|
||||
/// </summary>
|
||||
public Sprites IconsBackground;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scene management configuration.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class ScenesSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Fade transition settings.
|
||||
/// </summary>
|
||||
[System.Serializable]
|
||||
public class FadeTransitionSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Fade in duration in seconds.
|
||||
/// </summary>
|
||||
[Tooltip("Fade in duration")]
|
||||
public float FadeInDuration = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Fade out duration in seconds.
|
||||
/// </summary>
|
||||
[Tooltip("Fade out duration")]
|
||||
public float FadeOutDuration = 0.5f;
|
||||
|
||||
/// <summary>
|
||||
/// Fade color.
|
||||
/// </summary>
|
||||
[Tooltip("Fade color")]
|
||||
public Color FadeColor = Color.black;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// All scene data in the project.
|
||||
/// </summary>
|
||||
[Tooltip("All scene data in the project")]
|
||||
public Navigation.Data.OctoSceneData[] SceneDatas;
|
||||
|
||||
/// <summary>
|
||||
/// Use Addressables for scene loading.
|
||||
/// Requires OCTO_ADDRESSABLES scripting define symbol.
|
||||
/// </summary>
|
||||
[Tooltip("Use Addressables for scene loading (requires OCTO_ADDRESSABLES define)")]
|
||||
public bool UseAddressables = false;
|
||||
|
||||
/// <summary>
|
||||
/// Global fade transition settings.
|
||||
/// </summary>
|
||||
[Tooltip("Global fade transition settings")]
|
||||
public FadeTransitionSettings FadeSettings = new FadeTransitionSettings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save system settings.
|
||||
/// </summary>
|
||||
[OctoReadOnly] public SaveSettings Save;
|
||||
|
||||
/// <summary>
|
||||
/// Input mapping settings.
|
||||
/// </summary>
|
||||
public MappingSettings Mapping;
|
||||
|
||||
/// <summary>
|
||||
/// Language system settings.
|
||||
/// </summary>
|
||||
public LanguagesSettings Languages;
|
||||
|
||||
/// <summary>
|
||||
/// Scene management settings.
|
||||
/// </summary>
|
||||
public ScenesSettings Scenes;
|
||||
|
||||
/// <summary>
|
||||
/// UI settings.
|
||||
/// </summary>
|
||||
public UiSettings Ui;
|
||||
|
||||
|
||||
#region DATAS SET
|
||||
|
||||
#if UNITY_EDITOR
|
||||
void OnValidate()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes and validates settings in the Unity Editor.
|
||||
/// </summary>
|
||||
public void Init()
|
||||
{
|
||||
// Update language override names
|
||||
foreach (LanguagesSettings.Override langOverride in Languages.Overrides)
|
||||
{
|
||||
langOverride.Name = langOverride.Language.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans the project for all OctoData assets and populates the Save settings.
|
||||
/// </summary>
|
||||
public void GetAllDatas()
|
||||
{
|
||||
List<global::OctoCore.Save.Data.OctoDataBool> booleans = new();
|
||||
List<global::OctoCore.Save.Data.OctoDataInt> integers = new();
|
||||
List<global::OctoCore.Save.Data.OctoDataFloat> floats = new();
|
||||
List<global::OctoCore.Save.Data.OctoDataString> strings = new();
|
||||
List<global::OctoCore.Save.Data.OctoDataVector> vectors = new();
|
||||
|
||||
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:" + typeof(global::OctoCore.Save.Data.OctoData).Name);
|
||||
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
{
|
||||
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
global::OctoCore.Save.Data.OctoData data = (global::OctoCore.Save.Data.OctoData)UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath, typeof(global::OctoCore.Save.Data.OctoData));
|
||||
|
||||
if (data)
|
||||
{
|
||||
data.Id = data.name;
|
||||
UnityEditor.EditorUtility.SetDirty(data);
|
||||
|
||||
if (data is global::OctoCore.Save.Data.OctoDataBool)
|
||||
booleans.Add((global::OctoCore.Save.Data.OctoDataBool)data);
|
||||
|
||||
if (data is global::OctoCore.Save.Data.OctoDataInt)
|
||||
integers.Add((global::OctoCore.Save.Data.OctoDataInt)data);
|
||||
|
||||
if (data is global::OctoCore.Save.Data.OctoDataFloat)
|
||||
floats.Add((global::OctoCore.Save.Data.OctoDataFloat)data);
|
||||
|
||||
if (data is global::OctoCore.Save.Data.OctoDataString)
|
||||
strings.Add((global::OctoCore.Save.Data.OctoDataString)data);
|
||||
|
||||
if (data is global::OctoCore.Save.Data.OctoDataVector)
|
||||
vectors.Add((global::OctoCore.Save.Data.OctoDataVector)data);
|
||||
}
|
||||
}
|
||||
|
||||
Save.Booleans = booleans.ToArray();
|
||||
Save.Integers = integers.ToArray();
|
||||
Save.Floats = floats.ToArray();
|
||||
Save.Strings = strings.ToArray();
|
||||
Save.Vectors = vectors.ToArray();
|
||||
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
UnityEditor.AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Scans the project for all OctoSceneData assets and populates the Scenes settings.
|
||||
/// </summary>
|
||||
public void GetAllSceneDatas()
|
||||
{
|
||||
List<Navigation.Data.OctoSceneData> sceneDatas = new();
|
||||
|
||||
string[] guids = UnityEditor.AssetDatabase.FindAssets("t:" + typeof(Navigation.Data.OctoSceneData).Name);
|
||||
|
||||
for (int i = 0; i < guids.Length; i++)
|
||||
{
|
||||
string assetPath = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
|
||||
Navigation.Data.OctoSceneData sceneData = (Navigation.Data.OctoSceneData)UnityEditor.AssetDatabase.LoadAssetAtPath(assetPath, typeof(Navigation.Data.OctoSceneData));
|
||||
|
||||
if (sceneData)
|
||||
{
|
||||
sceneData.Id = sceneData.name;
|
||||
UnityEditor.EditorUtility.SetDirty(sceneData);
|
||||
|
||||
sceneDatas.Add(sceneData);
|
||||
}
|
||||
}
|
||||
|
||||
Scenes.SceneDatas = sceneDatas.ToArray();
|
||||
|
||||
UnityEditor.EditorUtility.SetDirty(this);
|
||||
UnityEditor.AssetDatabase.SaveAssets();
|
||||
|
||||
Debug.Log("[OctoSettings] Found " + sceneDatas.Count + " Scene Datas");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if ENABLE_INPUT_SYSTEM && UNITY_EDITOR
|
||||
private static string GetActionsFilePath()
|
||||
{
|
||||
// Find OctoInputs.cs to locate the package
|
||||
string[] guids = AssetDatabase.FindAssets("OctoInputs t:script");
|
||||
foreach (string guid in guids)
|
||||
{
|
||||
string path = AssetDatabase.GUIDToAssetPath(guid);
|
||||
if (path.Contains("/Inputs/OctoInputs.cs"))
|
||||
{
|
||||
// Found it! Same directory
|
||||
string directory = Path.GetDirectoryName(path);
|
||||
return Path.Combine(directory, "OctoActions.cs").Replace("\\", "/");
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback
|
||||
return "Assets/OctoCore/Generated/OctoActions.cs";
|
||||
}
|
||||
|
||||
private const string ActionsBackupFile = "Assets/OctoCore/Editor/OctoActions.json";
|
||||
|
||||
public void GenerateInputs()
|
||||
{
|
||||
Debug.Log("[OctoCore] GenerateInputs() called");
|
||||
|
||||
if (Mapping.InputActionAsset == null)
|
||||
{
|
||||
EditorUtility.DisplayDialog("Error", "Please assign an Input Actions asset first!", "OK");
|
||||
return;
|
||||
}
|
||||
|
||||
string actionsFile = GetActionsFilePath();
|
||||
|
||||
Debug.Log($"[OctoCore] Input Action Asset: {Mapping.InputActionAsset.name}");
|
||||
Debug.Log($"[OctoCore] Target file: {actionsFile}");
|
||||
|
||||
// Ensure directory exists
|
||||
string directory = Path.GetDirectoryName(actionsFile);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Debug.Log($"[OctoCore] Creating directory: {directory}");
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
Debug.Log("[OctoCore] Calling GenerateActionsEnum...");
|
||||
|
||||
// Generate enum file
|
||||
GenerateActionsEnum(Mapping.InputActionAsset, actionsFile);
|
||||
|
||||
Debug.Log("[OctoCore] GenerateActionsEnum completed");
|
||||
|
||||
// Refresh to compile new enums
|
||||
AssetDatabase.Refresh();
|
||||
|
||||
EditorUtility.DisplayProgressBar("Generating Inputs", "Waiting for compilation...", 0.5f);
|
||||
|
||||
// Wait a bit longer for compilation with multiple delays
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
EditorApplication.delayCall += () =>
|
||||
{
|
||||
EditorUtility.ClearProgressBar();
|
||||
|
||||
// Populate mappings after compilation
|
||||
PopulateMappings();
|
||||
|
||||
// Mark data as dirty to save changes
|
||||
EditorUtility.SetDirty(this);
|
||||
|
||||
EditorUtility.DisplayDialog(
|
||||
"Success",
|
||||
$"Input enums generated successfully!\n\n" +
|
||||
$"Generated in: {actionsFile}\n" +
|
||||
$"Backup saved in: {ActionsBackupFile}\n" +
|
||||
$"Total Actions: {CountTotalActions(Mapping.InputActionAsset)}\n\n" +
|
||||
$"Note: Backup is automatically restored after package updates!",
|
||||
"OK"
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
public void PopulateMappings()
|
||||
{
|
||||
Mapping.Actions.Clear();
|
||||
|
||||
foreach (var map in Mapping.InputActionAsset.actionMaps)
|
||||
{
|
||||
string mapName = CleanName(map.name);
|
||||
|
||||
foreach (var action in map.actions)
|
||||
{
|
||||
string actionName = CleanName(action.name);
|
||||
string fullName = $"{mapName}_{actionName}";
|
||||
|
||||
if (!System.Enum.TryParse<OctoActions>(fullName, out var actionEnum))
|
||||
{
|
||||
Debug.LogWarning($"[OctoSettings] Could not parse action: {fullName}");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Create action data with map name
|
||||
var actionData = new MappingSettings.ActionData(actionEnum, action.name, map.name);
|
||||
|
||||
// Find InputActionReference in the asset's sub-assets
|
||||
actionData.Reference = FindInputActionReferenceInAsset(Mapping.InputActionAsset, action);
|
||||
|
||||
if (actionData.Reference == null)
|
||||
{
|
||||
Debug.LogWarning($"[OctoSettings] No InputActionReference found for {map.name}/{action.name}");
|
||||
}
|
||||
|
||||
Mapping.Actions.Add(actionData);
|
||||
}
|
||||
}
|
||||
|
||||
EditorUtility.SetDirty(this);
|
||||
AssetDatabase.SaveAssets();
|
||||
}
|
||||
|
||||
private InputActionReference FindInputActionReferenceInAsset(InputActionAsset asset, InputAction action)
|
||||
{
|
||||
// Get the asset path
|
||||
string assetPath = AssetDatabase.GetAssetPath(asset);
|
||||
|
||||
// Load all sub-assets (InputActionReference are stored as sub-assets)
|
||||
var allAssets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
|
||||
|
||||
foreach (var subAsset in allAssets)
|
||||
{
|
||||
if (subAsset is InputActionReference reference)
|
||||
{
|
||||
if (reference.action == action)
|
||||
{
|
||||
return reference;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int CountTotalActions(InputActionAsset asset)
|
||||
{
|
||||
int count = 0;
|
||||
foreach (var map in asset.actionMaps)
|
||||
{
|
||||
count += map.actions.Count;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private void GenerateActionsEnum(InputActionAsset inputActions, string outputFile)
|
||||
{
|
||||
Debug.Log($"[OctoCore] GenerateActionsEnum started for: {inputActions.name}");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List<ActionBackupData> backupData = new List<ActionBackupData>();
|
||||
|
||||
sb.AppendLine("// ═══════════════════════════════════════════════════════════════════════════");
|
||||
sb.AppendLine("// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY");
|
||||
sb.AppendLine("// ═══════════════════════════════════════════════════════════════════════════");
|
||||
sb.AppendLine("// Generated by OctoSettings");
|
||||
sb.AppendLine("// Backup saved in: Assets/OctoCore/Generated/OctoActions.json");
|
||||
sb.AppendLine("// To regenerate: OctoSettings > Mapping > Click 'Generate Inputs'");
|
||||
sb.AppendLine($"// Generated from: {inputActions.name}");
|
||||
sb.AppendLine($"// Generated on: {System.DateTime.Now:yyyy-MM-dd HH:mm:ss}");
|
||||
sb.AppendLine("// ═══════════════════════════════════════════════════════════════════════════");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine("namespace OctoCore.Inputs");
|
||||
sb.AppendLine("{");
|
||||
sb.AppendLine(" /// <summary>");
|
||||
sb.AppendLine(" /// Actions from Unity Input Actions.");
|
||||
sb.AppendLine($" /// Generated from: {inputActions.name}");
|
||||
sb.AppendLine(" /// Format: ActionMap_ActionName");
|
||||
sb.AppendLine(" /// Values are stable hashes to prevent serialization issues when regenerating.");
|
||||
sb.AppendLine(" /// </summary>");
|
||||
sb.AppendLine(" public enum OctoActions");
|
||||
sb.AppendLine(" {");
|
||||
|
||||
bool first = true;
|
||||
foreach (var map in inputActions.actionMaps)
|
||||
{
|
||||
string mapName = CleanName(map.name);
|
||||
|
||||
foreach (var action in map.actions)
|
||||
{
|
||||
string actionName = CleanName(action.name);
|
||||
string fullName = $"{mapName}_{actionName}";
|
||||
|
||||
// Generate stable hash from name
|
||||
int hash = GetStableHash(fullName);
|
||||
|
||||
// Save to backup data
|
||||
backupData.Add(new ActionBackupData
|
||||
{
|
||||
Name = fullName,
|
||||
Hash = hash,
|
||||
MapName = map.name,
|
||||
ActionName = action.name
|
||||
});
|
||||
|
||||
if (!first)
|
||||
sb.AppendLine(",");
|
||||
|
||||
sb.AppendLine($" /// <summary>{map.name} > {action.name}</summary>");
|
||||
sb.Append($" {fullName} = {hash}");
|
||||
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
sb.AppendLine();
|
||||
|
||||
sb.AppendLine(" }");
|
||||
sb.AppendLine("}");
|
||||
|
||||
// Write enum file
|
||||
File.WriteAllText(outputFile, sb.ToString());
|
||||
Debug.Log($"[OctoCore] OctoActions.cs written to: {outputFile}");
|
||||
Debug.Log($"[OctoCore] File contains {backupData.Count} actions");
|
||||
|
||||
// Force Unity to see the change
|
||||
AssetDatabase.ImportAsset(outputFile, ImportAssetOptions.ForceUpdate);
|
||||
|
||||
// Save backup JSON
|
||||
SaveActionsBackup(backupData);
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class ActionBackupData
|
||||
{
|
||||
public string Name;
|
||||
public int Hash;
|
||||
public string MapName;
|
||||
public string ActionName;
|
||||
}
|
||||
|
||||
[System.Serializable]
|
||||
private class ActionsBackup
|
||||
{
|
||||
public string GeneratedFrom;
|
||||
public string GeneratedOn;
|
||||
public List<ActionBackupData> Actions;
|
||||
}
|
||||
|
||||
private void SaveActionsBackup(List<ActionBackupData> actions)
|
||||
{
|
||||
// Ensure directory exists
|
||||
string directory = Path.GetDirectoryName(ActionsBackupFile);
|
||||
if (!Directory.Exists(directory))
|
||||
{
|
||||
Directory.CreateDirectory(directory);
|
||||
}
|
||||
|
||||
var backup = new ActionsBackup
|
||||
{
|
||||
GeneratedFrom = Mapping.InputActionAsset.name,
|
||||
GeneratedOn = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"),
|
||||
Actions = actions
|
||||
};
|
||||
|
||||
string json = JsonUtility.ToJson(backup, true);
|
||||
File.WriteAllText(ActionsBackupFile, json);
|
||||
|
||||
Debug.Log($"[OctoCore] Actions backup saved to: {ActionsBackupFile}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Generate a stable hash from a string (same string always gives same hash).
|
||||
/// </summary>
|
||||
private int GetStableHash(string str)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash1 = 5381;
|
||||
int hash2 = hash1;
|
||||
|
||||
for (int i = 0; i < str.Length && str[i] != '\0'; i += 2)
|
||||
{
|
||||
hash1 = ((hash1 << 5) + hash1) ^ str[i];
|
||||
if (i == str.Length - 1 || str[i + 1] == '\0')
|
||||
break;
|
||||
hash2 = ((hash2 << 5) + hash2) ^ str[i + 1];
|
||||
}
|
||||
|
||||
return hash1 + (hash2 * 1566083941);
|
||||
}
|
||||
}
|
||||
|
||||
private string CleanName(string name)
|
||||
{
|
||||
name = name.Replace(" ", "_").Replace("-", "_");
|
||||
name = new string(name.Where(c => char.IsLetterOrDigit(c) || c == '_').ToArray());
|
||||
if (char.IsDigit(name[0]))
|
||||
name = "_" + name;
|
||||
return name;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user