Second commit
This commit is contained in:
commit
36840f3ad4
999 files changed
+61364
No files matched your search
@@ -0,0 +1,37 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TinyGoose.Tremble.Editor
|
||||
{
|
||||
internal static class AssetDatabaseUtil
|
||||
{
|
||||
internal static List<string> GetAllTrembleMapPaths()
|
||||
{
|
||||
List<string> allMaps = new();
|
||||
|
||||
string[] assetPaths = AssetDatabase.GetAllAssetPaths();
|
||||
foreach (string assetPath in assetPaths)
|
||||
{
|
||||
if (!IsTrembleMapFile(assetPath))
|
||||
continue;
|
||||
|
||||
if (assetPath.Contains("autosave/"))
|
||||
continue;
|
||||
|
||||
allMaps.Add(assetPath);
|
||||
}
|
||||
|
||||
return allMaps;
|
||||
}
|
||||
|
||||
internal static bool IsTrembleMapFile(string assetPath)
|
||||
=> Path.GetExtension(assetPath).EqualsInvariant(".map");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ee00bb59f3db43ceb0674202088a8b91
|
||||
timeCreated: 1707729646
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Editor/Utils/AssetDatabaseUtil.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,113 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text.RegularExpressions;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble.Editor
|
||||
{
|
||||
public static class EditorCompileUtil
|
||||
{
|
||||
private static readonly EditorPrefsBackedString s_CompileList = new("Tremble_PostCompileActions");
|
||||
|
||||
/// <summary>
|
||||
/// Compile scripts, then call a static method.
|
||||
/// Method MUST be static.
|
||||
/// Method can be private or public.
|
||||
/// Method must take 0 args, or any number of STRING args only.
|
||||
/// </summary>
|
||||
/// <param name="type">Type containing method</param>
|
||||
/// <param name="staticFunctionName">Method name (use nameof)</param>
|
||||
/// <param name="stringArgs">Optional list of STRING only args to pass (must not contain ',')</param>
|
||||
public static void CompileThen(Type type, string staticFunctionName, params string[] stringArgs)
|
||||
{
|
||||
foreach (string stringArg in stringArgs)
|
||||
{
|
||||
if (stringArg.Contains(','))
|
||||
{
|
||||
Debug.LogError($"Cannot schedule call to {type.Name}.{staticFunctionName} - arg contains ',' :(");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add to compile list, backed by editor prefs
|
||||
string[] existing = s_CompileList.Values;
|
||||
string[] newList = new string[existing.Length + 1];
|
||||
|
||||
if (existing.Length > 0)
|
||||
{
|
||||
Array.Copy(existing, newList, existing.Length);
|
||||
}
|
||||
|
||||
newList[^1] = $"{type.FullName}.{staticFunctionName}({String.Join(',', stringArgs)})";
|
||||
s_CompileList.Values = newList;
|
||||
|
||||
// Now recompile
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceSynchronousImport | ImportAssetOptions.ForceUpdate);
|
||||
}
|
||||
|
||||
[UnityEditor.Callbacks.DidReloadScripts]
|
||||
private static void PostCompile()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get list of calls and call each one
|
||||
string[] calls = s_CompileList.Values;
|
||||
foreach (string call in calls)
|
||||
{
|
||||
RunCall(call);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Finally clear!
|
||||
s_CompileList.Values = null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void RunCall(string call)
|
||||
{
|
||||
Match match = Regex.Match(call, @"(.+)\.(.+?)\((.+?)?\)");
|
||||
if (match.Groups.Count < 4)
|
||||
{
|
||||
Debug.LogError($"Call '{call}' was not in the correct format :(");
|
||||
return;
|
||||
}
|
||||
|
||||
string className = match.Groups[1].Captures[0].Value;
|
||||
string methodName = match.Groups[2].Captures[0].Value;
|
||||
|
||||
string argString = match.Groups[3].Captures.Count > 0 ? match.Groups[3].Captures[0].Value : null;
|
||||
string[] args = argString.IsNullOrEmpty() ? Array.Empty<string>() : argString.Split(',');
|
||||
|
||||
Type finalType = Unsupported.GetTypeFromFullName(className);
|
||||
if (finalType == null)
|
||||
{
|
||||
Debug.LogError($"Couldn't find type {className}!");
|
||||
return;
|
||||
}
|
||||
|
||||
MethodInfo method = finalType.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
||||
if (method == null)
|
||||
{
|
||||
Debug.LogError($"Couldn't find static method {finalType.Name}.{methodName}!");
|
||||
return;
|
||||
}
|
||||
|
||||
int numDeclaringParams = method.GetParameters().Length;
|
||||
if (numDeclaringParams != args.Length)
|
||||
{
|
||||
Debug.LogError($"Couldn't call static method {finalType.Name}.{methodName} with {args.Length} args (expected: {numDeclaringParams}!");
|
||||
return;
|
||||
}
|
||||
|
||||
method.Invoke(null, args.Select(s => (object)s).ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 024f8fc5df2a44c288a85b38e4688027
|
||||
timeCreated: 1725008201
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Editor/Utils/EditorCompileUtil.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
|
||||
namespace TinyGoose.Tremble.Editor
|
||||
{
|
||||
public class EditorPrefsBackedString
|
||||
{
|
||||
private readonly string m_Key;
|
||||
private string m_Value;
|
||||
|
||||
public EditorPrefsBackedString(string key)
|
||||
{
|
||||
m_Key = key;
|
||||
}
|
||||
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Value == null)
|
||||
{
|
||||
if (!EditorPrefs.HasKey(m_Key))
|
||||
return null;
|
||||
|
||||
m_Value = EditorPrefs.GetString(m_Key);
|
||||
}
|
||||
|
||||
return m_Value;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
m_Value = value;
|
||||
|
||||
if (value == null)
|
||||
{
|
||||
EditorPrefs.DeleteKey(m_Key);
|
||||
return;
|
||||
}
|
||||
|
||||
EditorPrefs.SetString(m_Key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public string[] Values
|
||||
{
|
||||
get
|
||||
{
|
||||
if (m_Value == null)
|
||||
{
|
||||
if (!EditorPrefs.HasKey(m_Key))
|
||||
return Array.Empty<string>();
|
||||
|
||||
m_Value = EditorPrefs.GetString(m_Key);
|
||||
}
|
||||
|
||||
return m_Value.IsNullOrEmpty() ? Array.Empty<string>() : m_Value.Split(';');
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
m_Value = null;
|
||||
EditorPrefs.DeleteKey(m_Key);
|
||||
return;
|
||||
}
|
||||
|
||||
string joinedValue = String.Join(';', value);
|
||||
m_Value = joinedValue;
|
||||
|
||||
EditorPrefs.SetString(m_Key, joinedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c91b5487d0aa4bd1ab8350151bb0e544
|
||||
timeCreated: 1724773115
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Editor/Utils/EditorPrefsBackedString.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,158 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace TinyGoose.Tremble.Editor
|
||||
{
|
||||
public class ModTimeDB
|
||||
{
|
||||
private readonly string m_DbFile;
|
||||
private readonly Dictionary<string, ulong> m_Data = new();
|
||||
|
||||
public ModTimeDB(string dbFile)
|
||||
{
|
||||
m_DbFile = dbFile;
|
||||
ReadFromFile();
|
||||
}
|
||||
|
||||
public ulong GetFileModifiedTime(Object asset)
|
||||
{
|
||||
string assetDatabasePath = AssetDatabase.GetAssetPath(asset);
|
||||
if (assetDatabasePath.IsNullOrEmpty() || !m_Data.TryGetValue(assetDatabasePath, out ulong time))
|
||||
return 0ul;
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
public void SetFileModifiedTime(Object asset, ulong time)
|
||||
{
|
||||
string assetDatabasePath = AssetDatabase.GetAssetPath(asset);
|
||||
if (assetDatabasePath.IsNullOrEmpty())
|
||||
return;
|
||||
|
||||
m_Data[assetDatabasePath] = time;
|
||||
}
|
||||
|
||||
public static ulong CalcModelModifiedTime(GameObject gameObject)
|
||||
{
|
||||
ulong time = 0ul;
|
||||
|
||||
// Prefab time
|
||||
AppendObjectModifiedTime(gameObject, ref time);
|
||||
|
||||
// Materials
|
||||
foreach (Renderer renderer in gameObject.GetComponentsInChildren<Renderer>())
|
||||
{
|
||||
foreach (Material material in renderer.sharedMaterials)
|
||||
{
|
||||
if (!material)
|
||||
continue;
|
||||
|
||||
ulong matTime = CalcMaterialModifiedTime(material);
|
||||
if (matTime > time)
|
||||
{
|
||||
time = matTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Meshes
|
||||
foreach (MeshFilter filter in gameObject.GetComponentsInChildren<MeshFilter>())
|
||||
{
|
||||
if (!filter.sharedMesh)
|
||||
continue;
|
||||
|
||||
AppendObjectModifiedTime(filter.sharedMesh, ref time);
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
public static ulong CalcMaterialModifiedTime(Material material)
|
||||
{
|
||||
ulong time = 0ul;
|
||||
|
||||
// Material time
|
||||
AppendObjectModifiedTime(material, ref time);
|
||||
|
||||
if (material.shader)
|
||||
{
|
||||
// Shader time
|
||||
AppendObjectModifiedTime(material.shader, ref time);
|
||||
|
||||
foreach (string texName in material.GetTexturePropertyNames())
|
||||
{
|
||||
// Texture times
|
||||
Texture texture = material.GetTexture(texName);
|
||||
if (!texture)
|
||||
continue;
|
||||
|
||||
AppendObjectModifiedTime(texture, ref time);
|
||||
}
|
||||
}
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
|
||||
private void ReadFromFile()
|
||||
{
|
||||
if (!File.Exists(m_DbFile))
|
||||
return;
|
||||
|
||||
string data = File.ReadAllText(m_DbFile);
|
||||
|
||||
TokenParser tp = new(data);
|
||||
while (!tp.IsAtEnd)
|
||||
{
|
||||
ReadOnlySpan<char> file = tp.ReadToken(supportCommentsAndQuotes: true);
|
||||
ulong time = tp.ReadUlong();
|
||||
|
||||
m_Data[file.ToString()] = time;
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteToFile()
|
||||
{
|
||||
using FileStream stream = new(m_DbFile, FileMode.Create, FileAccess.Write);
|
||||
using StreamWriter writer = new(stream);
|
||||
|
||||
foreach ((string file, ulong time) in m_Data)
|
||||
{
|
||||
writer.WriteLine($"\"{file}\" {time}");
|
||||
}
|
||||
}
|
||||
|
||||
public static ulong GetObjectModifiedTime(Object unityObject)
|
||||
{
|
||||
string objectPath = AssetDatabase.GetAssetPath(unityObject);
|
||||
|
||||
if (objectPath.IsNullOrEmpty())
|
||||
return 0ul;
|
||||
|
||||
AssetImporter importer = AssetImporter.GetAtPath(objectPath);
|
||||
if (!importer)
|
||||
return 0ul;
|
||||
|
||||
return importer.assetTimeStamp;
|
||||
}
|
||||
|
||||
private static void AppendObjectModifiedTime(Object unityObject, ref ulong time)
|
||||
{
|
||||
ulong thisTime = GetObjectModifiedTime(unityObject);
|
||||
|
||||
if (thisTime > time)
|
||||
{
|
||||
time = thisTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9ad6c3317444439e821b6999629b97e0
|
||||
timeCreated: 1711965846
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Editor/Utils/ModTimeDB.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,169 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
namespace TinyGoose.Tremble.Editor
|
||||
{
|
||||
internal static class SerializedObjectUtil
|
||||
{
|
||||
internal static void Modify(this Component component, Action<SerializedObject> actions) => Modify(new SerializedObject(component), actions);
|
||||
|
||||
internal static void Modify(this Object obj, Action<SerializedObject> actions) => Modify(new SerializedObject(obj), actions);
|
||||
|
||||
|
||||
private static void Modify(SerializedObject so, Action<SerializedObject> actions)
|
||||
{
|
||||
actions?.Invoke(so);
|
||||
so.ApplyModifiedPropertiesWithoutUndo();
|
||||
}
|
||||
|
||||
internal static SerializedProperty FindBackedProperty(this SerializedObject obj, string name) => obj.FindProperty("m_" + name);
|
||||
internal static SerializedProperty FindBackedRelativeProperty(this SerializedProperty obj, string name) => obj.FindPropertyRelative("m_" + name);
|
||||
|
||||
internal static SerializedProperty AppendArrayElement(this SerializedProperty prop)
|
||||
{
|
||||
int elemIdx = prop.arraySize;
|
||||
prop.InsertArrayElementAtIndex(elemIdx);
|
||||
return prop.GetArrayElementAtIndex(elemIdx);
|
||||
}
|
||||
|
||||
internal static uint GetHashOfContent(this SerializedProperty prop)
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
if (prop.propertyType == SerializedPropertyType.Generic && !prop.isArray)
|
||||
return (uint)prop.boxedValue.GetHashCode();
|
||||
|
||||
return prop.contentHash;
|
||||
#else
|
||||
switch (prop.propertyType)
|
||||
{
|
||||
case SerializedPropertyType.Integer:
|
||||
return (uint)prop.intValue.GetHashCode();
|
||||
case SerializedPropertyType.Boolean:
|
||||
return (uint)prop.boolValue.GetHashCode();
|
||||
case SerializedPropertyType.Float:
|
||||
return (uint)prop.floatValue.GetHashCode();
|
||||
case SerializedPropertyType.String:
|
||||
return (uint)prop.stringValue.GetHashCode();
|
||||
case SerializedPropertyType.Color:
|
||||
return (uint)prop.colorValue.GetHashCode();
|
||||
case SerializedPropertyType.ObjectReference:
|
||||
return (uint)(prop.objectReferenceValue ? prop.objectReferenceValue.GetHashCode() : 0);
|
||||
case SerializedPropertyType.LayerMask:
|
||||
return (uint)prop.intValue.GetHashCode();
|
||||
case SerializedPropertyType.Enum:
|
||||
return (uint)prop.enumValueIndex.GetHashCode();
|
||||
case SerializedPropertyType.Vector2:
|
||||
return (uint)prop.vector2Value.GetHashCode();
|
||||
case SerializedPropertyType.Vector3:
|
||||
return (uint)prop.vector3Value.GetHashCode();
|
||||
case SerializedPropertyType.Vector4:
|
||||
return (uint)prop.vector4Value.GetHashCode();
|
||||
case SerializedPropertyType.Rect:
|
||||
return (uint)prop.rectValue.GetHashCode();
|
||||
case SerializedPropertyType.Character:
|
||||
return (uint)prop.intValue.GetHashCode();
|
||||
case SerializedPropertyType.AnimationCurve:
|
||||
return (uint)prop.animationCurveValue.GetHashCode();
|
||||
case SerializedPropertyType.Bounds:
|
||||
return (uint)prop.boundsValue.GetHashCode();
|
||||
|
||||
case SerializedPropertyType.Generic:
|
||||
return (uint)(prop.isArray ? prop.arraySize : 0);
|
||||
|
||||
default:
|
||||
Debug.LogWarning("Unsupported property type: " + prop.propertyType + $" '{prop.name}'");
|
||||
return 0u;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
internal static void SetTo(this SerializedProperty prop, SerializedProperty other)
|
||||
{
|
||||
switch (other.propertyType)
|
||||
{
|
||||
case SerializedPropertyType.Integer:
|
||||
prop.intValue = other.intValue;
|
||||
break;
|
||||
case SerializedPropertyType.Boolean:
|
||||
prop.boolValue = other.boolValue;
|
||||
break;
|
||||
case SerializedPropertyType.Float:
|
||||
prop.floatValue = other.floatValue;
|
||||
break;
|
||||
case SerializedPropertyType.String:
|
||||
prop.stringValue = other.stringValue;
|
||||
break;
|
||||
case SerializedPropertyType.Color:
|
||||
prop.colorValue = other.colorValue;
|
||||
break;
|
||||
case SerializedPropertyType.ObjectReference:
|
||||
prop.objectReferenceValue = other.objectReferenceValue;
|
||||
break;
|
||||
case SerializedPropertyType.LayerMask:
|
||||
prop.intValue = other.intValue;
|
||||
break;
|
||||
case SerializedPropertyType.Enum:
|
||||
prop.enumValueIndex = other.enumValueIndex;
|
||||
break;
|
||||
case SerializedPropertyType.Vector2:
|
||||
prop.vector2Value = other.vector2Value;
|
||||
break;
|
||||
case SerializedPropertyType.Vector3:
|
||||
prop.vector3Value = other.vector3Value;
|
||||
break;
|
||||
case SerializedPropertyType.Vector4:
|
||||
prop.vector4Value = other.vector4Value;
|
||||
break;
|
||||
case SerializedPropertyType.Rect:
|
||||
prop.rectValue = other.rectValue;
|
||||
break;
|
||||
case SerializedPropertyType.Character:
|
||||
prop.intValue = other.intValue;
|
||||
break;
|
||||
case SerializedPropertyType.AnimationCurve:
|
||||
prop.animationCurveValue = other.animationCurveValue;
|
||||
break;
|
||||
case SerializedPropertyType.Bounds:
|
||||
prop.boundsValue = other.boundsValue;
|
||||
break;
|
||||
case SerializedPropertyType.Generic:
|
||||
if (prop.isArray)
|
||||
{
|
||||
prop.ClearArray();
|
||||
for (int i = 0; i < other.arraySize; i++)
|
||||
{
|
||||
prop.AppendArrayElement().SetTo(prop.GetArrayElementAtIndex(i));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
prop.boxedValue = other.boxedValue;
|
||||
#endif
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
#if UNITY_2022_1_OR_NEWER
|
||||
case SerializedPropertyType.Gradient:
|
||||
prop.gradientValue = other.gradientValue;
|
||||
break;
|
||||
#endif
|
||||
|
||||
default:
|
||||
Debug.LogWarning("Unsupported property type: " + prop.propertyType + $" '{prop.name}'");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
internal static bool EqualByValue(this SerializedProperty prop, SerializedProperty other)
|
||||
=> prop.GetHashOfContent() == other.GetHashOfContent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3865af53ccaf4f119a7f26638a8a9234
|
||||
timeCreated: 1707730421
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Editor/Utils/SerializedObjectUtil.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,152 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Networking;
|
||||
using UnityEngine.Serialization;
|
||||
|
||||
namespace TinyGoose.Tremble.Editor
|
||||
{
|
||||
[Serializable]
|
||||
public record Changeset
|
||||
{
|
||||
public string Version;
|
||||
public string[] Changes;
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public record VersionsFile
|
||||
{
|
||||
public Changeset[] Changes;
|
||||
}
|
||||
|
||||
public static class VersionCheck
|
||||
{
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Consts
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
private const string VERSION_CHECK_URL = "https://tinygoose.com/data/tremble_version.json";
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// State
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
private static VersionsFile s_Versions;
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Public API
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
public static bool HasData => s_Versions?.Changes is { Length: > 0 };
|
||||
private static Changeset LatestChange => s_Versions.Changes[0];
|
||||
|
||||
public static Changeset CurrentInstalledVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
int currentVersion = GetVersion(TrembleConsts.VERSION_STRING);
|
||||
if (HasData)
|
||||
{
|
||||
Changeset versionInfo = s_Versions.Changes.FirstOrDefault(c => GetVersion(c.Version) == currentVersion);
|
||||
if (versionInfo != null)
|
||||
return versionInfo;
|
||||
}
|
||||
|
||||
// Make an empty version info
|
||||
return new()
|
||||
{
|
||||
Changes = new[] { "Development Version"},
|
||||
Version = TrembleConsts.VERSION_STRING,
|
||||
};
|
||||
}
|
||||
}
|
||||
public static Changeset NewestAvailableVersion => HasData ? LatestChange : default;
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Checking and prompting
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
public static void FetchLatestVersionsInBackground(Action thenMainThread = null)
|
||||
{
|
||||
// Start web request on main thread
|
||||
UnityWebRequest request = UnityWebRequest.Get(VERSION_CHECK_URL);
|
||||
UnityWebRequestAsyncOperation async = request.SendWebRequest();
|
||||
async.completed += operation =>
|
||||
{
|
||||
if (request.responseCode != 200)
|
||||
return;
|
||||
|
||||
s_Versions = JsonUtility.FromJson<VersionsFile>(request.downloadHandler.text);
|
||||
|
||||
thenMainThread?.Invoke();
|
||||
};
|
||||
}
|
||||
|
||||
public static bool IsNewerVersionAvailable
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!HasData)
|
||||
return false;
|
||||
|
||||
int latestVersion = GetVersion(s_Versions.Changes[0].Version);
|
||||
int currentVersion = GetVersion(TrembleConsts.VERSION_STRING);
|
||||
|
||||
return latestVersion > currentVersion;
|
||||
}
|
||||
}
|
||||
|
||||
public static void PromptToUpgradeIfAvailable(bool showEvenIfDeclined = false)
|
||||
{
|
||||
// First prompt to upgrade Tremble itself
|
||||
bool showMainVersionUpgrade = IsNewerVersionAvailable && (showEvenIfDeclined || !HasPromptedForVersion(LatestChange.Version));
|
||||
if (showMainVersionUpgrade)
|
||||
{
|
||||
SetHasPromptedForVersion(LatestChange.Version);
|
||||
EditorUtility.DisplayDialog(
|
||||
title: "New Tremble Version",
|
||||
message: $"A newer version of Tremble (v{LatestChange.Version}) is available! "
|
||||
+ "Open Window > Package Manager to update. You won't be reminded about this version again.",
|
||||
ok: "Cool!");
|
||||
}
|
||||
}
|
||||
|
||||
public static string[] ChangesSinceCurrentVersion => HasData
|
||||
? s_Versions.Changes
|
||||
.Where(c => GetVersion(c.Version) > GetVersion(TrembleConsts.VERSION_STRING))
|
||||
.SelectMany(c => c.Changes)
|
||||
.ToArray()
|
||||
: Array.Empty<string>();
|
||||
|
||||
public static int NumVersionsBehind => HasData
|
||||
? s_Versions.Changes.Count(c => GetVersion(c.Version) > GetVersion(TrembleConsts.VERSION_STRING))
|
||||
: 0;
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Editor prefs
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
private static string GetPromptKey(string version) => $"Tremble_{Application.productName}_PromptedFor_{version}";
|
||||
private static bool HasPromptedForVersion(string version) => EditorPrefs.HasKey(GetPromptKey(version));
|
||||
private static void SetHasPromptedForVersion(string version) => EditorPrefs.SetBool(GetPromptKey(version), true);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Utils
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
private static int GetVersion(string versionString)
|
||||
{
|
||||
if (versionString.IsNullOrEmpty())
|
||||
return 0;
|
||||
|
||||
string[] parts = versionString.Split(".");
|
||||
if (parts.Length != 3)
|
||||
return 0;
|
||||
|
||||
int[] intParts = parts.Select(p => int.TryParse(p, out int intPart) ? intPart : 0).ToArray();
|
||||
|
||||
return intParts[0] * 1000000 + intParts[1] * 1000 + intParts[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ff8e7fdbe35c46b1a9b0d0dc4b4757ac
|
||||
timeCreated: 1720202784
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/Editor/Utils/VersionCheck.cs
|
||||
uploadId: 939664
|
||||
Reference in new issue
Block a user