using UnityEngine; #if UNITY_EDITOR using UnityEditor; using System.IO; using System.Collections.Generic; using System.Text; using System.Linq; namespace OctoCore.Inputs { /// /// Automatically restores OctoActions.cs from backup JSON when package is updated. /// [InitializeOnLoad] public class OctoActionsPostImport { private const string BACKUP_FILE = "Assets/OctoCore/Editor/OctoActions.json"; 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"; } static OctoActionsPostImport() { // Restore from backup if needed EditorApplication.delayCall += RestoreFromBackup; } [MenuItem("OctoCore/Input Actions/Restore from Backup")] public static void ForceRestore() { RestoreFromBackup(); } [MenuItem("OctoCore/Input Actions/Reset to Template")] public static void ResetToTemplate() { if (!EditorUtility.DisplayDialog( "Reset OctoActions", "This will reset OctoActions.cs to the template (None = 0).\n\n" + "The backup JSON will be kept, so you can restore later.\n\n" + "Are you sure?", "Reset", "Cancel")) { return; } string actionsFile = GetActionsFilePath(); CreateTemplate(actionsFile); AssetDatabase.Refresh(); Debug.Log("[OctoCore] OctoActions.cs reset to template."); } [MenuItem("OctoCore/Input Actions/Delete Backup")] public static void DeleteBackup() { if (!File.Exists(BACKUP_FILE)) { EditorUtility.DisplayDialog("No Backup", "No backup file found.", "OK"); return; } if (!EditorUtility.DisplayDialog( "Delete Backup", "This will permanently delete the backup JSON.\n\n" + "You won't be able to restore your actions after a package update.\n\n" + "Are you sure?", "Delete", "Cancel")) { return; } File.Delete(BACKUP_FILE); // Delete meta file too string metaFile = BACKUP_FILE + ".meta"; if (File.Exists(metaFile)) { File.Delete(metaFile); } AssetDatabase.Refresh(); Debug.Log("[OctoCore] Backup file deleted."); } private static void RestoreFromBackup() { string actionsFile = GetActionsFilePath(); // Check if backup exists if (!File.Exists(BACKUP_FILE)) { Debug.Log("[OctoCore] No backup found. Generate your actions via OctoSettings."); return; } // Check if actions file needs restoration (is it the template?) if (File.Exists(actionsFile)) { string currentContent = File.ReadAllText(actionsFile); // If it contains real actions (not just None), skip restoration if (currentContent.Contains("_PLACEHOLDER_") || currentContent.Contains("None = 0")) { Debug.Log("[OctoCore] Restoring actions from backup..."); RestoreActionsFile(actionsFile); } else { // File already has real actions, don't overwrite return; } } else { // File doesn't exist, restore it RestoreActionsFile(actionsFile); } } private static void RestoreActionsFile(string actionsFile) { try { // Read backup JSON string json = File.ReadAllText(BACKUP_FILE); var backup = JsonUtility.FromJson(json); if (backup == null || backup.Actions == null || backup.Actions.Count == 0) { Debug.LogWarning("[OctoCore] Backup file is empty or invalid."); return; } // Generate enum file from backup StringBuilder sb = new StringBuilder(); sb.AppendLine("// ═══════════════════════════════════════════════════════════════════════════"); sb.AppendLine("// AUTO-GENERATED FILE - DO NOT EDIT MANUALLY"); sb.AppendLine("// ═══════════════════════════════════════════════════════════════════════════"); sb.AppendLine("// Restored from backup by OctoActionsPostImport"); sb.AppendLine($"// Original source: {backup.GeneratedFrom}"); sb.AppendLine($"// Originally generated on: {backup.GeneratedOn}"); sb.AppendLine($"// Restored on: {System.DateTime.Now:yyyy-MM-dd HH:mm:ss}"); sb.AppendLine("// ═══════════════════════════════════════════════════════════════════════════"); sb.AppendLine(); sb.AppendLine("namespace OctoCore.Inputs"); sb.AppendLine("{"); sb.AppendLine(" /// "); sb.AppendLine(" /// Actions from Unity Input Actions."); sb.AppendLine($" /// Generated from: {backup.GeneratedFrom}"); sb.AppendLine(" /// Format: ActionMap_ActionName"); sb.AppendLine(" /// Values are stable hashes to prevent serialization issues when regenerating."); sb.AppendLine(" /// "); sb.AppendLine(" public enum OctoActions"); sb.AppendLine(" {"); for (int i = 0; i < backup.Actions.Count; i++) { var action = backup.Actions[i]; if (i > 0) sb.AppendLine(","); sb.AppendLine($" /// {action.MapName} > {action.ActionName}"); sb.Append($" {action.Name} = {action.Hash}"); } sb.AppendLine(); sb.AppendLine(" }"); sb.AppendLine("}"); // Ensure directory exists string directory = Path.GetDirectoryName(actionsFile); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } // Write restored file File.WriteAllText(actionsFile, sb.ToString()); AssetDatabase.Refresh(); Debug.Log($"[OctoCore] Actions successfully restored from backup! ({backup.Actions.Count} actions)"); } catch (System.Exception ex) { Debug.LogError($"[OctoCore] Failed to restore actions from backup: {ex.Message}"); } } private static void CreateTemplate(string actionsFile) { string template = @"// ═══════════════════════════════════════════════════════════════════════════ // TEMPLATE FILE // ═══════════════════════════════════════════════════════════════════════════ // This is a template file for OctoActions. // // TO GENERATE YOUR REAL ACTIONS: // 1. Open OctoSettings in the Inspector // 2. Go to Mapping section // 3. Assign your Input Action Asset // 4. Click 'Generate Inputs' button // // This template allows the package to compile before actions are generated. // ═══════════════════════════════════════════════════════════════════════════ namespace OctoCore.Inputs { /// /// Template enum for input actions. /// Generate your real actions via OctoSettings > Mapping > Generate Inputs. /// public enum OctoActions { /// /// Placeholder value. /// This will be replaced when you generate your input actions. /// None = 0 } } "; // Ensure directory exists string directory = Path.GetDirectoryName(actionsFile); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } // Write template file File.WriteAllText(actionsFile, template); } [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 Actions; } } } #endif