699 lines
24 KiB
C#
699 lines
24 KiB
C#
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
|
|
|
|
}
|
|
} |