Compare commits
13 Commits
main
...
achivments
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62a4290e76 | ||
|
|
1c5f93d8b1 | ||
|
|
e71f0ec8da | ||
|
|
1e6204e57e | ||
|
|
0270c50090 | ||
|
|
d0b4734572 | ||
|
|
36840271af | ||
|
|
bf79b07ea4 | ||
|
|
d731193948 | ||
|
|
af47348919 | ||
|
|
1bd77d9628 | ||
|
|
9dfb118f88 | ||
|
|
991c9ccdcc |
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 5a807a09d7c00be478bf44636c2cc89f
|
guid: ff9bb206aea50d14997771b9a0cc2b04
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
190
Achievments/Achievment.cs
Normal file
190
Achievments/Achievment.cs
Normal file
@ -0,0 +1,190 @@
|
|||||||
|
using NEG.Utils.Achievments.AchievmentTypes;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Static utility for achievment managment
|
||||||
|
/// </summary>
|
||||||
|
public static class Achievment
|
||||||
|
{
|
||||||
|
public static AchievmentManager Instance
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
if (instance == null)
|
||||||
|
{
|
||||||
|
instance = AchievmentManager.Builder.FromLabeledConfig(ConfigLabel)
|
||||||
|
.WithLabeledBackend(BackendLabel)
|
||||||
|
.Build();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string BackendLabel
|
||||||
|
{
|
||||||
|
get => backendLabel;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if(instance != null)
|
||||||
|
{
|
||||||
|
//Log + Quit helps debug builds
|
||||||
|
Debug.LogError("Achievments - Cannot set backend label, Managed already created");
|
||||||
|
Application.Quit(1);
|
||||||
|
}
|
||||||
|
if (backendLabel != null)
|
||||||
|
{
|
||||||
|
//Log + Quit helps debug builds
|
||||||
|
Debug.LogError("Multiple AchievmentBackends enabled, this is not allowed");
|
||||||
|
Application.Quit(1);
|
||||||
|
}
|
||||||
|
backendLabel = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private static string backendLabel;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// You shouldn't have any reason to change this
|
||||||
|
/// Used for tests.
|
||||||
|
/// </summary>
|
||||||
|
public static string ConfigLabel
|
||||||
|
{
|
||||||
|
private get => configLabel;
|
||||||
|
set => configLabel = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// You shouldn't have any reason to change this
|
||||||
|
/// Used for tests.
|
||||||
|
/// </summary>
|
||||||
|
private static string configLabel = "Achivments";
|
||||||
|
|
||||||
|
private static AchievmentManager instance;
|
||||||
|
|
||||||
|
#region Achievment Manipulation (Sets, Gets)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns if an achivment at a given id is completed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <seealso cref="AchievmentManager.IsCompleted(string)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id</remarks>
|
||||||
|
public static bool IsCompleted(string id)
|
||||||
|
{
|
||||||
|
return Instance.IsCompleted(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Toggle
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a <see cref="ToggleAchievmentData"/> as completed. <br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||||
|
/// <seealso cref="AchievmentManager.SetToggleAchivment(string)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static bool SetToggleAchivment(string id)
|
||||||
|
{
|
||||||
|
return Instance.SetToggleAchivment(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a completion state from a <see cref="ToggleAchievmentData"/>.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||||
|
/// <seealso cref="AchievmentManager.GetToggleState(string)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static bool GetToggleState(string id)
|
||||||
|
{
|
||||||
|
return Instance.GetToggleState(id);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Int
|
||||||
|
/// <summary>
|
||||||
|
/// Sets progress of a given <see cref="IntAchievmentData"/> to <paramref name="progress"/> <br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IntAchievmentDefinition"/>
|
||||||
|
/// <seealso cref="AchievmentManager.SetIntProgress(string, int)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static bool SetIntProgress(string id, int progress)
|
||||||
|
{
|
||||||
|
return Instance.SetIntProgress(id, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes progress of a given <see cref="IntAchievmentData"/> by <paramref name="delta"/><br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IntAchievmentDefinition"/>\
|
||||||
|
/// <seealso cref="AchievmentManager.ChangeIntProgress(string, int)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static bool ChangeIntProgress(string id, int delta)
|
||||||
|
{
|
||||||
|
return Instance.ChangeIntProgress(id, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets current progress from a <see cref="IntAchievmentData"/>.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||||
|
/// <seealso cref="AchievmentManager.GetIntProgress(string)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static int GetIntProgress(string id)
|
||||||
|
{
|
||||||
|
return Instance.GetIntProgress(id);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Float
|
||||||
|
/// <summary>
|
||||||
|
/// Sets progress of a given <see cref="FloatAchievmentData"/> to <paramref name="progress"/><br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||||
|
/// <seealso cref="AchievmentManager.SetFloatProgress(string, float)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static bool SetFloatProgress(string id, float progress)
|
||||||
|
{
|
||||||
|
return Instance.SetFloatProgress(id, progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes progress of a given <see cref="FloatAchievmentData"/> by <paramref name="delta"/><br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||||
|
/// <seealso cref="AchievmentManager.ChangeFloatProgress(string, float)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static bool ChangeFloatProgress(string id, float delta)
|
||||||
|
{
|
||||||
|
return Instance.ChangeFloatProgress(id, delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets current progress from a <see cref="FloatAchievmentData"/>.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||||
|
/// <seealso cref="AchievmentManager.GetFloatProgress(string)"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public static float GetFloatProgress(string id)
|
||||||
|
{
|
||||||
|
return Instance.GetFloatProgress(id);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Test Api
|
||||||
|
/// <summary>
|
||||||
|
/// You shouldn't have any reason to use this <br/>
|
||||||
|
/// Use at your own risk, may cause unexpected behaviour <br/>
|
||||||
|
/// Used for tests
|
||||||
|
/// </summary>
|
||||||
|
public static void NullifyInstance()
|
||||||
|
{
|
||||||
|
instance = null;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b3f8438db4084014bab0a063e4675d3f
|
guid: 696bafd4c06b0a8458f008103441ea7f
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
44
Achievments/AchievmentException.cs
Normal file
44
Achievments/AchievmentException.cs
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
using JetBrains.Annotations;
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
public class AchievmentException : ApplicationException
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id of related achievment
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="AchievmentTypes.AchievmentData"/>
|
||||||
|
/// <seealso cref="AchievmentTypes.AchievmentDefinition"/>
|
||||||
|
public string Id { get; private set; }
|
||||||
|
|
||||||
|
public AchievmentException(string message, string achievmentId) : base(message)
|
||||||
|
{
|
||||||
|
Id = achievmentId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AchievmentTypeException : AchievmentException
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Expected achievment type under <see cref="AchievmentException.Id"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="AchievmentTypes.AchievmentData"/>
|
||||||
|
/// <seealso cref="AchievmentTypes.AchievmentDefinition"/>
|
||||||
|
public Type Expected { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Actual achievment type under <see cref="AchievmentException.Id"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="AchievmentTypes.AchievmentData"/>
|
||||||
|
/// <seealso cref="AchievmentTypes.AchievmentDefinition"/>
|
||||||
|
public Type Actual { get; private set; }
|
||||||
|
|
||||||
|
public AchievmentTypeException(string message, string achievmentId, Type expectedType, Type actualType) : base(message, achievmentId)
|
||||||
|
{
|
||||||
|
Expected = expectedType;
|
||||||
|
Actual = actualType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 4b09e744f7ec6704c95ec273584a964f
|
guid: 241344322b9771049b6962e48ac98085
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
366
Achievments/AchievmentManager.cs
Normal file
366
Achievments/AchievmentManager.cs
Normal file
@ -0,0 +1,366 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.AddressableAssets;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using UnityEditor;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
using AchievmentTypes;
|
||||||
|
|
||||||
|
public class AchievmentManager
|
||||||
|
{
|
||||||
|
public class Builder
|
||||||
|
{
|
||||||
|
public const string DefaultAchivmentsConfigLabel = "Achivments";
|
||||||
|
|
||||||
|
private AchievmentManager manager = new AchievmentManager();
|
||||||
|
private IAchievmentBackend backend;
|
||||||
|
|
||||||
|
public static Builder FromDefaultConfig()
|
||||||
|
{
|
||||||
|
return FromLabeledConfig(DefaultAchivmentsConfigLabel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Builder FromLabeledConfig(string label)
|
||||||
|
{
|
||||||
|
var builder = new Builder();
|
||||||
|
|
||||||
|
var handle = Addressables.LoadAssetsAsync<IAchivmentManagerConfig>((IEnumerable)new string[] { label }, delegate { }, Addressables.MergeMode.Union, false);
|
||||||
|
|
||||||
|
var configs = handle.WaitForCompletion();
|
||||||
|
|
||||||
|
foreach (var config in configs)
|
||||||
|
{
|
||||||
|
config.Apply(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var config in configs)
|
||||||
|
{
|
||||||
|
config.ApplyLast(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
Addressables.Release(handle);
|
||||||
|
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder WithDefinitionsFrom(AchievmentManagerConfig collection)
|
||||||
|
{
|
||||||
|
foreach (var def in collection.Achivments)
|
||||||
|
{
|
||||||
|
manager.RegisterAchivment(def);
|
||||||
|
}
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder WithLabeledBackend(string label)
|
||||||
|
{
|
||||||
|
var backendConfigHandle = Addressables.LoadAssetAsync<IAchievmentBackendConfig>(label);
|
||||||
|
|
||||||
|
var backendConfig = backendConfigHandle.WaitForCompletion();
|
||||||
|
|
||||||
|
WithBackend(backendConfig.ConstructBackend());
|
||||||
|
|
||||||
|
Addressables.Release(backendConfigHandle);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder WithBackend(IAchievmentBackend backendIn)
|
||||||
|
{
|
||||||
|
if (backend != null)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("There can only be one Achievment Backend at a time");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.backend = backendIn;
|
||||||
|
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder WithCallbackReciever(IAchievmentCallbackReciever callbackReciever)
|
||||||
|
{
|
||||||
|
manager.AddCallbackReciever(callbackReciever);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AchievmentManager Build()
|
||||||
|
{
|
||||||
|
if (backend != null)
|
||||||
|
{
|
||||||
|
manager.InitBackend(backend);
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
Debug.LogWarning("No AchievmentBackend selected. Is this intended?");
|
||||||
|
}
|
||||||
|
return manager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public delegate void AchievmentCompletedCallback(AchievmentData achivment);
|
||||||
|
public delegate void AchievmentStateChangedCallback(AchievmentData achivment);
|
||||||
|
|
||||||
|
public event AchievmentCompletedCallback AchievmentCompleted;
|
||||||
|
public event AchievmentStateChangedCallback AchievmentStateChanged;
|
||||||
|
|
||||||
|
private Dictionary<string, AchievmentDefinition> definitionCache;
|
||||||
|
private Dictionary<AchievmentDefinition, AchievmentData> dataCache;
|
||||||
|
|
||||||
|
private IAchievmentBackend activeBackend;
|
||||||
|
|
||||||
|
private AchievmentManager()
|
||||||
|
{
|
||||||
|
definitionCache = new Dictionary<string, AchievmentDefinition>();
|
||||||
|
dataCache = new Dictionary<AchievmentDefinition, AchievmentData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterAchivment(AchievmentDefinition definition)
|
||||||
|
{
|
||||||
|
if (!definitionCache.ContainsKey(definition.Id))
|
||||||
|
{
|
||||||
|
definitionCache.Add(definition.Id, definition);
|
||||||
|
dataCache.Add(definition, definition.Construct());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Duplicate Achivment with ID: {definition.Id}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a backend syncing achievments data with it and redistering it as a callback reciever
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>Resets all achievments data</remarks>
|
||||||
|
private void InitBackend(IAchievmentBackend achievmentBackend)
|
||||||
|
{
|
||||||
|
activeBackend = achievmentBackend;
|
||||||
|
foreach (var definition in definitionCache.Values)
|
||||||
|
{
|
||||||
|
var storedProgress = achievmentBackend.GetStoredAchivment(definition);
|
||||||
|
|
||||||
|
if (storedProgress != null)
|
||||||
|
{
|
||||||
|
dataCache[definition] = storedProgress;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
dataCache[definition] = definition.Construct();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
AddCallbackReciever(achievmentBackend);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCallbackRecievers(IEnumerable<IAchievmentCallbackReciever> initialCallbacks)
|
||||||
|
{
|
||||||
|
foreach (var callback in initialCallbacks)
|
||||||
|
{
|
||||||
|
AddCallbackReciever(callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AddCallbackReciever(IAchievmentCallbackReciever callback)
|
||||||
|
{
|
||||||
|
AchievmentCompleted += callback.AchievmentCompleted;
|
||||||
|
AchievmentStateChanged += callback.AchievmentStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveCallbackReciever(IAchievmentCallbackReciever callback)
|
||||||
|
{
|
||||||
|
AchievmentCompleted -= callback.AchievmentCompleted;
|
||||||
|
AchievmentStateChanged -= callback.AchievmentStateChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Achievment Manipulation (Sets, Gets)
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns if an achivment at a given id is completed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id</remarks>
|
||||||
|
public bool IsCompleted(string id)
|
||||||
|
{
|
||||||
|
return GetAchievmentForId(id).IsCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Toggle
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a <see cref="ToggleAchievmentData"/> as completed, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public bool SetToggleAchivment(string id)
|
||||||
|
{
|
||||||
|
return ManipulateAchievment<ToggleAchievmentData>(id, (achievment) => achievment.CompletionState = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a completion state from a <see cref="ToggleAchievmentData"/>.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public bool GetToggleState(string id)
|
||||||
|
{
|
||||||
|
return GetAchievmentForId<ToggleAchievmentData>(id).CompletionState;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Int
|
||||||
|
/// <summary>
|
||||||
|
/// Sets progress of a given <see cref="IntAchievmentData"/> to <paramref name="progress"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IntAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public bool SetIntProgress(string id, int progress)
|
||||||
|
{
|
||||||
|
return ManipulateAchievment<IntAchievmentData>(id, (achievment) => achievment.CurrentProgress = progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes progress of a given <see cref="IntAchievmentData"/> by <paramref name="delta"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IntAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public bool ChangeIntProgress(string id, int delta)
|
||||||
|
{
|
||||||
|
return ManipulateAchievment<IntAchievmentData>(id, (achievment) => achievment.CurrentProgress += delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets current progress from a <see cref="IntAchievmentData"/>.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="ToggleAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public int GetIntProgress(string id)
|
||||||
|
{
|
||||||
|
return GetAchievmentForId<IntAchievmentData>(id).CurrentProgress;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Float
|
||||||
|
/// <summary>
|
||||||
|
/// Sets progress of a given <see cref="FloatAchievmentData"/> to <paramref name="progress"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public bool SetFloatProgress(string id, float progress)
|
||||||
|
{
|
||||||
|
return ManipulateAchievment<FloatAchievmentData>(id, (achievment) => achievment.CurrentProgress = progress);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Changes progress of a given <see cref="FloatAchievmentData"/> by <paramref name="delta"/>, after which sends <see cref="AchievmentStateChanged"/>, also if the achievment is completed sends a <see cref="AchievmentCompleted"/>. <br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public bool ChangeFloatProgress(string id, float delta)
|
||||||
|
{
|
||||||
|
return ManipulateAchievment<FloatAchievmentData>(id, (achievment) => achievment.CurrentProgress += delta);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets current progress from a <see cref="FloatAchievmentData"/>.<br/>
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="FloatAchievmentDefinition"/>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public float GetFloatProgress(string id)
|
||||||
|
{
|
||||||
|
return GetAchievmentForId<FloatAchievmentData>(id).CurrentProgress;
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an achievment of type <typeparamref name="T"/> under <paramref name="id"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">Type of the achievment</typeparam>
|
||||||
|
/// <param name="id">Id of requested achievment</param>
|
||||||
|
/// <remarks>throws an <see cref="AchievmentException"/> if there is no achievment under id or an <see cref="AchievmentTypeException"/> if achievment under id is of a different type</remarks>
|
||||||
|
public T GetAchievmentForId<T>(string id) where T : AchievmentData
|
||||||
|
{
|
||||||
|
return ValidateAchievmentType<T>(GetAchievmentForId(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns an achievment under <paramref name="id"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Id of requested achievment</param>
|
||||||
|
/// <remarks>throws an <see cref="ApplicationException"/> if there is no achievment under id</remarks>
|
||||||
|
public AchievmentData GetAchievmentForId(string id)
|
||||||
|
{
|
||||||
|
var def = definitionCache.GetValueOrDefault(id);
|
||||||
|
if (def != null)
|
||||||
|
{
|
||||||
|
return dataCache[def];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throw new AchievmentException($"Invalid achivment id {id}", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void UpdateBackend()
|
||||||
|
{
|
||||||
|
activeBackend?.Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
private T ValidateAchievmentType<T>(AchievmentData data) where T : AchievmentData
|
||||||
|
{
|
||||||
|
if (data is not T convetred)
|
||||||
|
{
|
||||||
|
throw new AchievmentTypeException($"Attempting to perform an operation on an invalid achievment type. Expected {typeof(T)} got {data.GetType()}", data.Achievment.Id, typeof(T), data.GetType());
|
||||||
|
}
|
||||||
|
return convetred;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T"></typeparam>
|
||||||
|
/// <param name="id"></param>
|
||||||
|
/// <param name="manipulation">Action to perform on the achievment</param>
|
||||||
|
private bool ManipulateAchievment<T>(string id, Action<T> manipulation) where T : AchievmentData
|
||||||
|
{
|
||||||
|
var data = GetAchievmentForId<T>(id);
|
||||||
|
|
||||||
|
if (CheckNotCompleted(data))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
manipulation(data);
|
||||||
|
|
||||||
|
SendUpdateCallbacks(data);
|
||||||
|
|
||||||
|
return data.IsCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Helper method to print a warning if an achievment is already completed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="data"></param>
|
||||||
|
/// <returns>Completion state</returns>
|
||||||
|
private bool CheckNotCompleted(AchievmentData data)
|
||||||
|
{
|
||||||
|
if (data.IsCompleted)
|
||||||
|
{
|
||||||
|
Debug.LogWarning($"Achievment already completed: {data.Achievment.Id}");
|
||||||
|
}
|
||||||
|
return data.IsCompleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendUpdateCallbacks(AchievmentData data)
|
||||||
|
{
|
||||||
|
AchievmentStateChanged?.Invoke(data);
|
||||||
|
|
||||||
|
if (data.IsCompleted)
|
||||||
|
{
|
||||||
|
AchievmentCompleted?.Invoke(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 1906fa5e31f79fe48a6edda94b9c1b4d
|
guid: 7339f725e382e4b4bab7db6d7cc14b30
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
24
Achievments/AchievmentManagerConfig.cs
Normal file
24
Achievments/AchievmentManagerConfig.cs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
using NEG.Utils.Achievments.AchievmentTypes;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(menuName = "Achievments/Config/BaseConfig")]
|
||||||
|
public class AchievmentManagerConfig : ScriptableObject, IAchivmentManagerConfig
|
||||||
|
{
|
||||||
|
[field: SerializeField]
|
||||||
|
public List<AchievmentDefinition> Achivments { get; private set; } = new List<AchievmentDefinition>();
|
||||||
|
|
||||||
|
public void Apply(AchievmentManager.Builder builder)
|
||||||
|
{
|
||||||
|
builder.WithDefinitionsFrom(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void ApplyLast(AchievmentManager.Builder builder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: f032e3d346d243d458c929d4046f0a1e
|
guid: 88120b6e616164f489387a6a32a25dee
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
8
Achievments/AchievmentTypes.meta
Normal file
8
Achievments/AchievmentTypes.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 79e626bf8b94e5f4d813912f9b1d304e
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
21
Achievments/AchievmentTypes/AchievmentData.cs
Normal file
21
Achievments/AchievmentTypes/AchievmentData.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
public abstract class AchievmentData
|
||||||
|
{
|
||||||
|
public AchievmentDefinition Achievment { get; private set; }
|
||||||
|
|
||||||
|
public abstract bool IsCompleted { get; }
|
||||||
|
|
||||||
|
public AchievmentData(AchievmentDefinition achivment)
|
||||||
|
{
|
||||||
|
Achievment = achivment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/AchievmentTypes/AchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/AchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1f39500a9deabad43b87bc76122646fc
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
15
Achievments/AchievmentTypes/AchievmentDefinition.cs
Normal file
15
Achievments/AchievmentTypes/AchievmentDefinition.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
public abstract class AchievmentDefinition : ScriptableObject
|
||||||
|
{
|
||||||
|
[field: SerializeField]
|
||||||
|
public string Id { get; private set; }
|
||||||
|
|
||||||
|
public abstract AchievmentData Construct();
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/AchievmentTypes/AchievmentDefinition.cs.meta
Normal file
11
Achievments/AchievmentTypes/AchievmentDefinition.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 4aef60a6b4e41e243845a476862049e1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
40
Achievments/AchievmentTypes/FloatAchievmentData.cs
Normal file
40
Achievments/AchievmentTypes/FloatAchievmentData.cs
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
public class FloatAchievmentData : AchievmentData
|
||||||
|
{
|
||||||
|
public override bool IsCompleted => CurrentProgress >= Def.ProgressRequired;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use to GET current progress
|
||||||
|
/// Do not SET the value directly use <see cref="AchievmentManager"/> or <see cref="Achievment"/> Instead <br/>
|
||||||
|
/// Unless you are in <see cref="IAchievmentBackend.GetStoredAchivment(AchievmentDefinition)">
|
||||||
|
/// </summary>
|
||||||
|
public float CurrentProgress
|
||||||
|
{
|
||||||
|
get => currentProgress;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Def.Clamped)
|
||||||
|
{
|
||||||
|
value = Mathf.Max(value, Def.LowerBound);
|
||||||
|
}
|
||||||
|
currentProgress = Mathf.Min(value, Def.ProgressRequired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float ProgressLeft => Def.ProgressRequired - CurrentProgress;
|
||||||
|
|
||||||
|
private FloatAchievmentDefinition Def => (FloatAchievmentDefinition)Achievment;
|
||||||
|
|
||||||
|
private float currentProgress;
|
||||||
|
|
||||||
|
public FloatAchievmentData(FloatAchievmentDefinition def) : base(def)
|
||||||
|
{
|
||||||
|
currentProgress = def.InitialProgress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/AchievmentTypes/FloatAchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/FloatAchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 32572809c0644434d8e64878a3c22f0e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
29
Achievments/AchievmentTypes/FloatAchievmentDefinition.cs
Normal file
29
Achievments/AchievmentTypes/FloatAchievmentDefinition.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(menuName = "Achievments/Float Achievment")]
|
||||||
|
public class FloatAchievmentDefinition : AchievmentDefinition
|
||||||
|
{
|
||||||
|
[field: Tooltip("Amount of progress required for completion, required to be at leas 1, otherwise would be considered completed from the beginning")]
|
||||||
|
[field: Min(0)]
|
||||||
|
[field: SerializeField]
|
||||||
|
public float ProgressRequired { get; private set; } = 1;
|
||||||
|
|
||||||
|
[field: SerializeField]
|
||||||
|
public float InitialProgress { get; private set; } = 0;
|
||||||
|
|
||||||
|
[field: SerializeField]
|
||||||
|
public bool Clamped { get; private set; } = false;
|
||||||
|
|
||||||
|
public float LowerBound { get; private set; } = 0;
|
||||||
|
|
||||||
|
|
||||||
|
public override AchievmentData Construct()
|
||||||
|
{
|
||||||
|
return new FloatAchievmentData(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2d7270d5452c9b04ca07ef43a491a18d
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
41
Achievments/AchievmentTypes/IntAchievmentData.cs
Normal file
41
Achievments/AchievmentTypes/IntAchievmentData.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.Serialization.Formatters;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
public class IntAchievmentData : AchievmentData
|
||||||
|
{
|
||||||
|
public override bool IsCompleted => CurrentProgress >= Def.ProgressRequired;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use to GET current progress
|
||||||
|
/// Do not SET the value directly use <see cref="AchievmentManager"/> or <see cref="Achievment"/> Instead <br/>
|
||||||
|
/// Unless you are in <see cref="IAchievmentBackend.GetStoredAchivment(AchievmentDefinition)">
|
||||||
|
/// </summary>
|
||||||
|
public int CurrentProgress
|
||||||
|
{
|
||||||
|
get => currentProgress;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (Def.Clamped)
|
||||||
|
{
|
||||||
|
value = Mathf.Max(value, Def.LowerBound);
|
||||||
|
}
|
||||||
|
currentProgress = Mathf.Min(value, Def.ProgressRequired);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public int ProgressLeft => Def.ProgressRequired - CurrentProgress;
|
||||||
|
|
||||||
|
private IntAchievmentDefinition Def => (IntAchievmentDefinition)Achievment;
|
||||||
|
|
||||||
|
private int currentProgress;
|
||||||
|
|
||||||
|
public IntAchievmentData(IntAchievmentDefinition def) : base(def)
|
||||||
|
{
|
||||||
|
currentProgress = def.InitialProgress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/AchievmentTypes/IntAchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/IntAchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 0a121b6e6fa8ecc45ab4506c15e5f46e
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
27
Achievments/AchievmentTypes/IntAchievmentDefinition.cs
Normal file
27
Achievments/AchievmentTypes/IntAchievmentDefinition.cs
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(menuName = "Achievments/Int Achievment")]
|
||||||
|
public class IntAchievmentDefinition : AchievmentDefinition
|
||||||
|
{
|
||||||
|
[field: Tooltip("Amount of progress required for completion, required to be at leas 1, otherwise would be considered completed from the beginning")]
|
||||||
|
[field: SerializeField]
|
||||||
|
public int ProgressRequired { get; private set; } = 1;
|
||||||
|
|
||||||
|
[field: SerializeField]
|
||||||
|
public int InitialProgress { get; private set; } = 0;
|
||||||
|
|
||||||
|
[field: SerializeField]
|
||||||
|
public bool Clamped { get; private set; } = false;
|
||||||
|
|
||||||
|
public int LowerBound { get; private set; } = 0;
|
||||||
|
|
||||||
|
public override AchievmentData Construct()
|
||||||
|
{
|
||||||
|
return new IntAchievmentData(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta
Normal file
11
Achievments/AchievmentTypes/IntAchievmentDefinition.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 5318fea685aa56646a3310c38a9a9bac
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
23
Achievments/AchievmentTypes/ToggleAchievmentData.cs
Normal file
23
Achievments/AchievmentTypes/ToggleAchievmentData.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
public class ToggleAchievmentData : AchievmentData
|
||||||
|
{
|
||||||
|
public override bool IsCompleted => CompletionState;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use to GET current progress
|
||||||
|
/// Do not SET the value directly use <see cref="AchievmentManager"/> or <see cref="Achievment"/> Instead <br/>
|
||||||
|
/// Unless you are in <see cref="IAchievmentBackend.GetStoredAchivment(AchievmentDefinition)">
|
||||||
|
/// </summary>
|
||||||
|
public bool CompletionState { get; set; } = false;
|
||||||
|
|
||||||
|
public ToggleAchievmentData(ToggleAchievmentDefinition def) : base(def)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta
Normal file
11
Achievments/AchievmentTypes/ToggleAchievmentData.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1e0806da00902994f9aeb26d295956f0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
15
Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs
Normal file
15
Achievments/AchievmentTypes/ToggleAchievmentDefinition.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.AchievmentTypes
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(menuName = "Achievments/Toggle Achievment")]
|
||||||
|
public class ToggleAchievmentDefinition : AchievmentDefinition
|
||||||
|
{
|
||||||
|
public override AchievmentData Construct()
|
||||||
|
{
|
||||||
|
return new ToggleAchievmentData(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 608c7e921b8b16b42919fc6f55b67fcb
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
15
Achievments/AchievmentsUpdater.cs
Normal file
15
Achievments/AchievmentsUpdater.cs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
public class AchievmentsUpdater : MonoBehaviour
|
||||||
|
{
|
||||||
|
void Update()
|
||||||
|
{
|
||||||
|
Achievment.Instance.UpdateBackend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/AchievmentsUpdater.cs.meta
Normal file
11
Achievments/AchievmentsUpdater.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: b5a8c2721326a014bb32737116e4d74b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Achievments/Backend.meta
Normal file
8
Achievments/Backend.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3541d03056defb3468d957da0b69a7b9
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Achievments/Backend/LoacalBaackend.meta
Normal file
8
Achievments/Backend/LoacalBaackend.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: e0226747b74e86c4b8e89d01e9eeeb3f
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
145
Achievments/Backend/LoacalBaackend/LocalBackendConfig.cs
Normal file
145
Achievments/Backend/LoacalBaackend/LocalBackendConfig.cs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
using NEG.Utils.Achievments.AchievmentTypes;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(menuName = "Achievments/Config/Backend/Local")]
|
||||||
|
public class LocalBackendConfig : ScriptableObject, IAchievmentBackendConfig
|
||||||
|
{
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
#if LOCAL_ACHIEVMENT_BACKEND
|
||||||
|
Achievment.BackendLabel = "LocalAchievments";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
[SerializeField]
|
||||||
|
private string saveLocation;
|
||||||
|
|
||||||
|
public IAchievmentBackend ConstructBackend()
|
||||||
|
{
|
||||||
|
return new LocalBackend(saveLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This backend is not optimised at all, do not use in public builds
|
||||||
|
/// </summary>
|
||||||
|
public class LocalBackend : IAchievmentBackend
|
||||||
|
{
|
||||||
|
private string saveLocation;
|
||||||
|
|
||||||
|
public LocalBackend(string saveLocation)
|
||||||
|
{
|
||||||
|
this.saveLocation = saveLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AchievmentCompleted(AchievmentData achievment)
|
||||||
|
{
|
||||||
|
string id = achievment.Achievment.Id;
|
||||||
|
JObject jobj = LoadJson();
|
||||||
|
|
||||||
|
JToken token = jobj[id];
|
||||||
|
|
||||||
|
if (token is not JObject achievmentObj)
|
||||||
|
{
|
||||||
|
achievmentObj = new JObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
achievmentObj["completed"] = true;
|
||||||
|
|
||||||
|
jobj[id] = achievmentObj;
|
||||||
|
|
||||||
|
SaveJson(jobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AchievmentStateChanged(AchievmentData achievment)
|
||||||
|
{
|
||||||
|
string id = achievment.Achievment.Id;
|
||||||
|
JObject jobj = LoadJson();
|
||||||
|
|
||||||
|
JToken token = jobj[id];
|
||||||
|
|
||||||
|
if (token is not JObject achievmentObj)
|
||||||
|
{
|
||||||
|
achievmentObj = new JObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (achievment)
|
||||||
|
{
|
||||||
|
case IntAchievmentData intAchievment:
|
||||||
|
achievmentObj["data"] = intAchievment.CurrentProgress;
|
||||||
|
break;
|
||||||
|
case FloatAchievmentData floatAchievment:
|
||||||
|
achievmentObj["data"] = floatAchievment.CurrentProgress;
|
||||||
|
break;
|
||||||
|
case ToggleAchievmentData toggleAchievment:
|
||||||
|
achievmentObj["data"] = toggleAchievment.IsCompleted;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
jobj[id] = achievmentObj;
|
||||||
|
|
||||||
|
SaveJson(jobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public AchievmentData GetStoredAchivment(AchievmentDefinition definition)
|
||||||
|
{
|
||||||
|
JObject jobj = LoadJson();
|
||||||
|
|
||||||
|
JToken token = jobj[definition.Id];
|
||||||
|
|
||||||
|
if (token is not JObject)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
AchievmentData achievment = definition.Construct();
|
||||||
|
|
||||||
|
switch (achievment)
|
||||||
|
{
|
||||||
|
case IntAchievmentData intAchievment:
|
||||||
|
intAchievment.CurrentProgress = (int)token["data"];
|
||||||
|
break;
|
||||||
|
case FloatAchievmentData floatAchievment:
|
||||||
|
floatAchievment.CurrentProgress = (float)token["data"];
|
||||||
|
break;
|
||||||
|
case ToggleAchievmentData toggleAchievment:
|
||||||
|
toggleAchievment.CompletionState = (bool)token["data"];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return achievment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
//Nothing here
|
||||||
|
}
|
||||||
|
|
||||||
|
private JObject LoadJson()
|
||||||
|
{
|
||||||
|
if (Directory.Exists(Path.GetDirectoryName(saveLocation)) && File.Exists(saveLocation))
|
||||||
|
{
|
||||||
|
return JObject.Parse(File.ReadAllText(saveLocation));
|
||||||
|
}
|
||||||
|
return new JObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SaveJson(JObject obj)
|
||||||
|
{
|
||||||
|
if (!Directory.Exists(Path.GetDirectoryName(saveLocation)))
|
||||||
|
{
|
||||||
|
Directory.CreateDirectory(Path.GetDirectoryName(saveLocation));
|
||||||
|
}
|
||||||
|
|
||||||
|
File.WriteAllText(saveLocation, obj.ToString(Formatting.Indented));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 6a1257a87feec064697193df412554d4
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Achievments/Backend/SteamBackend.meta
Normal file
8
Achievments/Backend/SteamBackend.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: db06184b29a56ba44aa446107ada7f66
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"name": "NEG.Utils.Achivmnets.Backend.SteamBackend",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:380ad496eab7ace4b98ceede94941223",
|
||||||
|
"GUID:68bd7fdb68ef2684e982e8a9825b18a5"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [
|
||||||
|
"STEAM_ACHIEVMENT_BACKEND"
|
||||||
|
],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: f8cf2e6d12f27fb47a577cb5a7537ccf
|
guid: 243913f72edbe1c4294164fe2ed9dc0c
|
||||||
AssemblyDefinitionImporter:
|
AssemblyDefinitionImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
115
Achievments/Backend/SteamBackend/SteamBackendConfig.cs
Normal file
115
Achievments/Backend/SteamBackend/SteamBackendConfig.cs
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
using NEG.Utils.Achievments.AchievmentTypes;
|
||||||
|
#if STEAM_ACHIEVMENT_BACKEND
|
||||||
|
using Steamworks;
|
||||||
|
#endif
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
[CreateAssetMenu(menuName = "Achievments/Config/Backend/Local")]
|
||||||
|
public class SteamBackendConfig : ScriptableObject, IAchievmentBackendConfig
|
||||||
|
{
|
||||||
|
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)]
|
||||||
|
private static void Init()
|
||||||
|
{
|
||||||
|
#if STEAM_ACHIEVMENT_BACKEND
|
||||||
|
Achievment.BackendLabel = "SteamAchievments";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAchievmentBackend ConstructBackend()
|
||||||
|
{
|
||||||
|
return new SteamBackend();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if STEAM_ACHIEVMENT_BACKEND
|
||||||
|
public class SteamBackend : IAchievmentBackend
|
||||||
|
{
|
||||||
|
private bool isDirty = false;
|
||||||
|
|
||||||
|
public SteamBackend()
|
||||||
|
{
|
||||||
|
//
|
||||||
|
SteamUserStats.RequestCurrentStats();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AchievmentCompleted(AchievmentData achievment)
|
||||||
|
{
|
||||||
|
SteamUserStats.SetAchievement(achievment.Achievment.Id);
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AchievmentStateChanged(AchievmentData achievment)
|
||||||
|
{
|
||||||
|
string id = achievment.Achievment.Id;
|
||||||
|
|
||||||
|
switch (achievment)
|
||||||
|
{
|
||||||
|
case IntAchievmentData intAchievment:
|
||||||
|
SteamUserStats.SetStat(id, intAchievment.CurrentProgress);
|
||||||
|
break;
|
||||||
|
case FloatAchievmentData floatAchievment:
|
||||||
|
SteamUserStats.SetStat(id, floatAchievment.CurrentProgress);
|
||||||
|
break;
|
||||||
|
case ToggleAchievmentData toggleAchievment:
|
||||||
|
//Do nothing, Achievment completed will also be called
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
isDirty = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AchievmentData GetStoredAchivment(AchievmentDefinition definition)
|
||||||
|
{
|
||||||
|
string id = definition.Id;
|
||||||
|
|
||||||
|
AchievmentData achievment = definition.Construct();
|
||||||
|
|
||||||
|
switch (achievment)
|
||||||
|
{
|
||||||
|
case IntAchievmentData intAchievment:
|
||||||
|
if (SteamUserStats.GetStat(id, out int statI))
|
||||||
|
{
|
||||||
|
intAchievment.CurrentProgress = statI;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("Cannot get user stat, is steam initialised correctly?");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case FloatAchievmentData floatAchievment:
|
||||||
|
if (SteamUserStats.GetStat(id, out float statF))
|
||||||
|
{
|
||||||
|
floatAchievment.CurrentProgress = statF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("Cannot get user stat, is steam initialised correctly?");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ToggleAchievmentData toggleAchievment:
|
||||||
|
if (SteamUserStats.GetAchievement(id, out bool ach))
|
||||||
|
{
|
||||||
|
toggleAchievment.CompletionState = ach;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.Log("Cannot get user stat, is steam initialised correctly?");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return achievment;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Update()
|
||||||
|
{
|
||||||
|
if (isDirty)
|
||||||
|
{
|
||||||
|
//Reiterate on failure?
|
||||||
|
isDirty = !SteamUserStats.StoreStats();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
11
Achievments/Backend/SteamBackend/SteamBackendConfig.cs.meta
Normal file
11
Achievments/Backend/SteamBackend/SteamBackendConfig.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ad7436a24c5bdb84fa2e60e027b7a734
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
31
Achievments/IAchievmentBackend.cs
Normal file
31
Achievments/IAchievmentBackend.cs
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
using NEG.Utils.Achievments.AchievmentTypes;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Used to construct <see cref="IAchievmentBackend"/> instance
|
||||||
|
/// </summary>
|
||||||
|
public interface IAchievmentBackendConfig
|
||||||
|
{
|
||||||
|
/// <returns>Constructed backend</returns>
|
||||||
|
public IAchievmentBackend ConstructBackend();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public interface IAchievmentBackend : IAchievmentCallbackReciever
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Constructs an AchievmentData for given <paramref name="definition"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>May return null if there is no stored data for this achievment</remarks>
|
||||||
|
AchievmentData GetStoredAchivment(AchievmentDefinition definition);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used for e.g. syncing with upstream
|
||||||
|
/// </summary>
|
||||||
|
void Update();
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/IAchievmentBackend.cs.meta
Normal file
11
Achievments/IAchievmentBackend.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: cfab45a1ce7cc0a4899f35a61b6a60f6
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
23
Achievments/IAchievmentCallbackReciever.cs
Normal file
23
Achievments/IAchievmentCallbackReciever.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
using AchievmentTypes;
|
||||||
|
|
||||||
|
public interface IAchievmentCallbackReciever
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Called when an achivment is completed
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="achievment"></param>
|
||||||
|
void AchievmentCompleted(AchievmentData achievment);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called when achivment progress changes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="achievment"></param>
|
||||||
|
void AchievmentStateChanged(AchievmentData achievment);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/IAchievmentCallbackReciever.cs.meta
Normal file
11
Achievments/IAchievmentCallbackReciever.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7218fed73c5be2c4ba31eca9fe44d37a
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
21
Achievments/IAchivmentManagerConfig.cs
Normal file
21
Achievments/IAchivmentManagerConfig.cs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments
|
||||||
|
{
|
||||||
|
public interface IAchivmentManagerConfig
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Used to Apply config data
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
void Apply(AchievmentManager.Builder builder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Called after <see cref="Apply(AchievmentManager.Builder)"/> was called on every other config
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder"></param>
|
||||||
|
void ApplyLast(AchievmentManager.Builder builder);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/IAchivmentManagerConfig.cs.meta
Normal file
11
Achievments/IAchivmentManagerConfig.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bd4b0d54603883447b6458263d6b3605
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
17
Achievments/NEG.Utils.Achievments.asmdef
Normal file
17
Achievments/NEG.Utils.Achievments.asmdef
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"name": "NEG.Utils.Achievments",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"GUID:9e24947de15b9834991c9d8411ea37cf",
|
||||||
|
"GUID:84651a3751eca9349aac36a66bba901b"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": false,
|
||||||
|
"precompiledReferences": [],
|
||||||
|
"autoReferenced": true,
|
||||||
|
"defineConstraints": [],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 7ff6afcd64a25ab4497e324400b59140
|
guid: 380ad496eab7ace4b98ceede94941223
|
||||||
AssemblyDefinitionImporter:
|
AssemblyDefinitionImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
userData:
|
userData:
|
||||||
8
Achievments/PlaymodeTests.meta
Normal file
8
Achievments/PlaymodeTests.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d7c140577a904c8419a760a8ac6133c7
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
65
Achievments/PlaymodeTests/BackendTests.cs
Normal file
65
Achievments/PlaymodeTests/BackendTests.cs
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.Tests
|
||||||
|
{
|
||||||
|
public class BackendTests
|
||||||
|
{
|
||||||
|
//If stests start to fail first make sure these are correct in relation to test config asset
|
||||||
|
public const string configLabel = "TestAchievments";
|
||||||
|
public const string backendLabel = "AchievmentsLocalTests";
|
||||||
|
public const string saveLocation = "./LocalAchievments/Tests.json";
|
||||||
|
|
||||||
|
public const string AchievmentIdToggle = "TOGGLE";
|
||||||
|
public const string AchievmentIdInt = "INT";
|
||||||
|
public const string AchievmentIdFloat = "FLOAT";
|
||||||
|
|
||||||
|
[OneTimeSetUp]
|
||||||
|
public void OneTtimeSetup()
|
||||||
|
{
|
||||||
|
Achievment.BackendLabel = backendLabel;
|
||||||
|
Achievment.ConfigLabel = configLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
[TearDown]
|
||||||
|
public void TearDown()
|
||||||
|
{
|
||||||
|
Achievment.NullifyInstance();
|
||||||
|
if (File.Exists(saveLocation))
|
||||||
|
{
|
||||||
|
File.Delete(saveLocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void ReadWrite()
|
||||||
|
{
|
||||||
|
#if ACHIEVMENT_BACKEND_TESTS
|
||||||
|
//We assume that the achievments are set correctly because otherwise other tests would fail
|
||||||
|
Achievment.SetToggleAchivment(AchievmentIdToggle);
|
||||||
|
Achievment.SetIntProgress(AchievmentIdInt, 20);
|
||||||
|
Achievment.SetFloatProgress(AchievmentIdFloat, 20);
|
||||||
|
|
||||||
|
//We need to assume NullifyInstance works correctly because we dont have access to an AchievmentManager which has not syncked yet
|
||||||
|
Achievment.NullifyInstance();
|
||||||
|
|
||||||
|
Assert.IsTrue(Achievment.IsCompleted(AchievmentIdToggle));
|
||||||
|
Assert.AreEqual(Achievment.GetIntProgress(AchievmentIdInt), 20);
|
||||||
|
Assert.AreEqual(Achievment.GetFloatProgress(AchievmentIdFloat), 20, 0f);
|
||||||
|
|
||||||
|
Achievment.SetIntProgress(AchievmentIdInt, 30);
|
||||||
|
Achievment.SetFloatProgress(AchievmentIdFloat, 30);
|
||||||
|
|
||||||
|
Achievment.NullifyInstance();
|
||||||
|
|
||||||
|
Assert.AreEqual(Achievment.GetIntProgress(AchievmentIdInt), 30);
|
||||||
|
Assert.AreEqual(Achievment.GetFloatProgress(AchievmentIdFloat), 30, 0f);
|
||||||
|
#else
|
||||||
|
throw new System.Exception("Backend tests are not enabled. To enable Backend tests add define ACHIEVMENT_BACKEND_TESTS");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/PlaymodeTests/BackendTests.cs.meta
Normal file
11
Achievments/PlaymodeTests/BackendTests.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c09ce9536c2c5f541bb7d07d5eca1d69
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "NEG.Utils.Achievments.Tests.Playmode",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"UnityEngine.TestRunner",
|
||||||
|
"UnityEditor.TestRunner",
|
||||||
|
"NEG.Utils.Achievments"
|
||||||
|
],
|
||||||
|
"includePlatforms": [],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": true,
|
||||||
|
"precompiledReferences": [
|
||||||
|
"nunit.framework.dll"
|
||||||
|
],
|
||||||
|
"autoReferenced": false,
|
||||||
|
"defineConstraints": [
|
||||||
|
"UNITY_INCLUDE_TESTS"
|
||||||
|
],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 38e8b1e483202e14182d34baaea3958e
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Achievments/PlaymodeTests/TestAssets.meta
Normal file
8
Achievments/PlaymodeTests/TestAssets.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: fad16eb700fc70c408c359dca9a76fc9
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
15
Achievments/PlaymodeTests/TestAssets/TestLocalBackend.asset
Normal file
15
Achievments/PlaymodeTests/TestAssets/TestLocalBackend.asset
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 6a1257a87feec064697193df412554d4, type: 3}
|
||||||
|
m_Name: TestLocalBackend
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
saveLocation: ./LocalAchievments/Tests.json
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 47c9689c811dc9842a5a5e9ca19c6e3c
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
5
Achievments/TODO.txt
Normal file
5
Achievments/TODO.txt
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
Static Achievments class (done)
|
||||||
|
Implement Storage again API (done)
|
||||||
|
Fix typos
|
||||||
|
Merge AchievmentCollection with AchievmentManagerConfig (done)
|
||||||
|
Static backend constructors (done)
|
||||||
7
Achievments/TODO.txt.meta
Normal file
7
Achievments/TODO.txt.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 94e4aa3c6dc078c4db6a47949655f8a5
|
||||||
|
TextScriptImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Achievments/Tests.meta
Normal file
8
Achievments/Tests.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: bab659ddb2d136440a51c5c9b76fefcb
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
380
Achievments/Tests/ConfigTests.cs
Normal file
380
Achievments/Tests/ConfigTests.cs
Normal file
@ -0,0 +1,380 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using UnityEngine;
|
||||||
|
using UnityEngine.TestTools;
|
||||||
|
|
||||||
|
namespace NEG.Utils.Achievments.Tests
|
||||||
|
{
|
||||||
|
using AchievmentTypes;
|
||||||
|
using static Internal.Extensions;
|
||||||
|
|
||||||
|
public class ConfigTests
|
||||||
|
{
|
||||||
|
public const string AchievmentsLabel = "TestAchievments";
|
||||||
|
|
||||||
|
public const string AchievmentIdToggle = "TOGGLE";
|
||||||
|
public const string AchievmentIdInt = "INT";
|
||||||
|
public const string AchievmentIdFloat = "FLOAT";
|
||||||
|
public const string AchievmentIdInvalid = "huptyrz";
|
||||||
|
public const int RandomProgress = 15;
|
||||||
|
public const int ProgressChangeDelta = 15;
|
||||||
|
public const int CompletedProgress = 100;
|
||||||
|
public const int OvershootProgress = 150;
|
||||||
|
|
||||||
|
#region Id And Types
|
||||||
|
[Test]
|
||||||
|
public void AchivmentInvalidId()
|
||||||
|
{
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build();
|
||||||
|
|
||||||
|
TestInvalidId(AchievmentIdInvalid, (id) => manager.GetAchievmentForId(id), "Get");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentInvalidType()
|
||||||
|
{
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build();
|
||||||
|
|
||||||
|
manager.TestInvalidType<IntAchievmentData, ToggleAchievmentData>(AchievmentIdToggle, "Toggle");
|
||||||
|
manager.TestInvalidType<FloatAchievmentData, IntAchievmentData>(AchievmentIdInt, "Int");
|
||||||
|
manager.TestInvalidType<ToggleAchievmentData, FloatAchievmentData>(AchievmentIdFloat, "Float");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentCorrectIdAndType()
|
||||||
|
{
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel).Build();
|
||||||
|
|
||||||
|
manager.TestValidIdAndType<ToggleAchievmentData>(AchievmentIdToggle, "Toggle");
|
||||||
|
manager.TestValidIdAndType<IntAchievmentData>(AchievmentIdInt, "Int");
|
||||||
|
manager.TestValidIdAndType<FloatAchievmentData>(AchievmentIdFloat, "Float");
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Toggle
|
||||||
|
[Test]
|
||||||
|
public void AchivmentToggleSet()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
manager.SetToggleAchivment(AchievmentIdToggle);
|
||||||
|
callbackTester.TestCompleted<ToggleAchievmentData>(AchievmentIdToggle);
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
manager.SetToggleAchivment(AchievmentIdToggle);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Int
|
||||||
|
[Test]
|
||||||
|
public void AchivmentIntSetLess()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Set progress to some value progress
|
||||||
|
manager.SetIntProgress(AchievmentIdInt, RandomProgress);
|
||||||
|
var data = callbackTester.GetChanged<IntAchievmentData>();
|
||||||
|
|
||||||
|
Assert.AreEqual(RandomProgress, data.CurrentProgress);
|
||||||
|
Assert.IsFalse(data.IsCompleted);
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentIntSetEqual()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Set progress to some value equal to required value
|
||||||
|
manager.SetIntProgress(AchievmentIdInt, CompletedProgress);
|
||||||
|
var data = callbackTester.GetChanged<IntAchievmentData>();
|
||||||
|
Assert.AreEqual(CompletedProgress, data.CurrentProgress);
|
||||||
|
callbackTester.TestCompleted<IntAchievmentData>(AchievmentIdInt);
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, this time nothing sould change
|
||||||
|
manager.SetIntProgress(AchievmentIdInt, CompletedProgress);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentIntSetGreater()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Set progress to some value greater than required
|
||||||
|
manager.SetIntProgress(AchievmentIdInt, OvershootProgress);
|
||||||
|
var data = callbackTester.GetChanged<IntAchievmentData>();
|
||||||
|
//Testing against completed progress, should be clamped down
|
||||||
|
Assert.AreEqual(CompletedProgress, data.CurrentProgress);
|
||||||
|
callbackTester.TestCompleted<IntAchievmentData>(AchievmentIdInt);
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, this time nothing sould change
|
||||||
|
manager.SetIntProgress(AchievmentIdInt, OvershootProgress);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentIntChangeCompletion()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Add progresss one interval below completion
|
||||||
|
for (int i = 0; i < CompletedProgress / ProgressChangeDelta; i++)
|
||||||
|
{
|
||||||
|
manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta);
|
||||||
|
callbackTester.TestNotCompleted();
|
||||||
|
var changed = callbackTester.GetChanged<IntAchievmentData>();
|
||||||
|
|
||||||
|
Assert.AreEqual((i + 1) * ProgressChangeDelta, changed.CurrentProgress);
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add progress one more time, should now be completed
|
||||||
|
manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta);
|
||||||
|
var changed1 = callbackTester.GetChanged<IntAchievmentData>();
|
||||||
|
Assert.AreEqual(CompletedProgress, changed1.CurrentProgress);
|
||||||
|
callbackTester.TestCompleted<IntAchievmentData>(AchievmentIdInt);
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, this time nothing should change
|
||||||
|
manager.ChangeIntProgress(AchievmentIdInt, ProgressChangeDelta);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, but down this time also nothing should change
|
||||||
|
manager.ChangeIntProgress(AchievmentIdInt, -ProgressChangeDelta);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Float
|
||||||
|
[Test]
|
||||||
|
public void AchivmentFloatSetLess()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Set progress to some value progress
|
||||||
|
manager.SetFloatProgress(AchievmentIdFloat, RandomProgress);
|
||||||
|
var data = callbackTester.GetChanged<FloatAchievmentData>();
|
||||||
|
|
||||||
|
Assert.AreEqual((float)RandomProgress, data.CurrentProgress);
|
||||||
|
Assert.IsFalse(data.IsCompleted);
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentFloatSetEqual()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Set progress to some value equal to required value
|
||||||
|
manager.SetFloatProgress(AchievmentIdFloat, CompletedProgress);
|
||||||
|
var data = callbackTester.GetChanged<FloatAchievmentData>();
|
||||||
|
Assert.AreEqual((float)CompletedProgress, data.CurrentProgress);
|
||||||
|
callbackTester.TestCompleted<FloatAchievmentData>(AchievmentIdFloat);
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, this time nothing sould change
|
||||||
|
manager.SetFloatProgress(AchievmentIdFloat, CompletedProgress);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentFloatSetGreater()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Set progress to some value greater than required
|
||||||
|
manager.SetFloatProgress(AchievmentIdFloat, OvershootProgress);
|
||||||
|
var data = callbackTester.GetChanged<FloatAchievmentData>();
|
||||||
|
//Testing against completed progress, should be clamped down
|
||||||
|
Assert.AreEqual((float)CompletedProgress, data.CurrentProgress);
|
||||||
|
callbackTester.TestCompleted<FloatAchievmentData>(AchievmentIdFloat);
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, this time nothing sould change
|
||||||
|
manager.SetFloatProgress(AchievmentIdFloat, OvershootProgress);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void AchivmentFloatChangeCompletion()
|
||||||
|
{
|
||||||
|
var callbackTester = new TestCallbackRereiver();
|
||||||
|
|
||||||
|
AchievmentManager manager = AchievmentManager.Builder.FromLabeledConfig(AchievmentsLabel)
|
||||||
|
.WithCallbackReciever(callbackTester)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
//Add progresss one interval below completion
|
||||||
|
for (int i = 0; i < CompletedProgress / ProgressChangeDelta; i++)
|
||||||
|
{
|
||||||
|
manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta);
|
||||||
|
callbackTester.TestNotCompleted();
|
||||||
|
var changed = callbackTester.GetChanged<FloatAchievmentData>();
|
||||||
|
|
||||||
|
Assert.AreEqual((i + 1) * ProgressChangeDelta, changed.CurrentProgress, 0.0f);
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Add progress one more time, should now be completed
|
||||||
|
manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta);
|
||||||
|
var changed1 = callbackTester.GetChanged<FloatAchievmentData>();
|
||||||
|
Assert.AreEqual((float)CompletedProgress, changed1.CurrentProgress);
|
||||||
|
callbackTester.TestCompleted<FloatAchievmentData>(AchievmentIdFloat);
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, this time nothing should change
|
||||||
|
manager.ChangeFloatProgress(AchievmentIdFloat, ProgressChangeDelta);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
|
||||||
|
//Do that again, but down this time also nothing should change
|
||||||
|
manager.ChangeFloatProgress(AchievmentIdFloat, -ProgressChangeDelta);
|
||||||
|
callbackTester.TestNoChanges();
|
||||||
|
callbackTester.Reset();
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
private class TestCallbackRereiver : IAchievmentCallbackReciever
|
||||||
|
{
|
||||||
|
public AchievmentData LastDataUpdated { get; private set; } = null;
|
||||||
|
public Type LastTypeSet { get; private set; } = null;
|
||||||
|
public string LastIdSet { get; private set; } = null;
|
||||||
|
|
||||||
|
public void Reset()
|
||||||
|
{
|
||||||
|
LastDataUpdated = null;
|
||||||
|
LastTypeSet = null;
|
||||||
|
LastIdSet = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T GetChanged<T>() where T : AchievmentData
|
||||||
|
{
|
||||||
|
Assert.IsInstanceOf(typeof(T), LastDataUpdated);
|
||||||
|
|
||||||
|
return (T)LastDataUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestNoChanges()
|
||||||
|
{
|
||||||
|
Assert.IsNull(LastDataUpdated);
|
||||||
|
Assert.IsNull(LastTypeSet);
|
||||||
|
Assert.IsNull(LastIdSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestNotCompleted()
|
||||||
|
{
|
||||||
|
//No need to also check LastTypeSet, they are both set or bot null
|
||||||
|
Assert.IsNull(LastIdSet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestCompleted<Type>(string id)
|
||||||
|
{
|
||||||
|
Assert.AreEqual(typeof(Type), LastTypeSet);
|
||||||
|
Assert.AreEqual(id, LastIdSet);
|
||||||
|
//Shold not be null: if we axpect achievment to be completed it must have also been updated
|
||||||
|
Assert.IsTrue(LastDataUpdated.IsCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AchievmentCompleted(AchievmentData achievment)
|
||||||
|
{
|
||||||
|
LastTypeSet = achievment.GetType();
|
||||||
|
LastIdSet = achievment.Achievment.Id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void AchievmentStateChanged(AchievmentData achievment)
|
||||||
|
{
|
||||||
|
LastDataUpdated = achievment;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Internal
|
||||||
|
{
|
||||||
|
public static class Extensions
|
||||||
|
{
|
||||||
|
public static void TestValidIdAndType<Type>(this AchievmentManager manager, string id, string testName) where Type : AchievmentData
|
||||||
|
{
|
||||||
|
TestValidIdAndType(id, (id) => manager.GetAchievmentForId<Type>(id), testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TestValidIdAndType(string id, Action<string> manipulation, string testName)
|
||||||
|
{
|
||||||
|
Assert.DoesNotThrow(() => manipulation(id), $"{testName}: Invalid type or id");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TestInvalidId(this AchievmentManager manager, string id, string testName)
|
||||||
|
{
|
||||||
|
TestInvalidId(id, (id) => manager.GetAchievmentForId(id), testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TestInvalidId(string id, Action<string> manipulation, string testName)
|
||||||
|
{
|
||||||
|
var exception = Assert.Throws<AchievmentException>(() => manipulation(id), $"Expected to fail with {typeof(AchievmentTypeException)}");
|
||||||
|
|
||||||
|
Assert.AreEqual(exception.Id, id, $"{testName}: Achievment id does not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TestInvalidType<Expected, Actual>(this AchievmentManager manager, string id, string testName) where Expected : AchievmentData where Actual : AchievmentData
|
||||||
|
{
|
||||||
|
TestInvalidType<Expected, Actual>(id, (id) => manager.GetAchievmentForId<Expected>(id), testName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void TestInvalidType<Expected, Actual>(string id, Action<string> manipulation, string testName) where Expected : AchievmentData where Actual : AchievmentData
|
||||||
|
{
|
||||||
|
var exception = Assert.Throws<AchievmentTypeException>(() => manipulation(id), $"Expected to fail with {typeof(AchievmentTypeException)}");
|
||||||
|
|
||||||
|
Assert.AreEqual(id, exception.Id, $"{testName}: Achievment id does not match");
|
||||||
|
Assert.AreSame(typeof(Expected), exception.Expected, $"{testName}: Target achievment type does not match");
|
||||||
|
Assert.AreSame(typeof(Actual), exception.Actual, $"{testName}: Actual achievment type does not match");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Achievments/Tests/ConfigTests.cs.meta
Normal file
11
Achievments/Tests/ConfigTests.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c47a38eaf8bffa849b130320427701cc
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
26
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef
Normal file
26
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"name": "NEG.Utils.Achivments.Tests",
|
||||||
|
"rootNamespace": "",
|
||||||
|
"references": [
|
||||||
|
"UnityEngine.TestRunner",
|
||||||
|
"UnityEditor.TestRunner",
|
||||||
|
"Unity.Addressables",
|
||||||
|
"Unity.ResourceManager",
|
||||||
|
"NEG.Utils.Achievments"
|
||||||
|
],
|
||||||
|
"includePlatforms": [
|
||||||
|
"Editor"
|
||||||
|
],
|
||||||
|
"excludePlatforms": [],
|
||||||
|
"allowUnsafeCode": false,
|
||||||
|
"overrideReferences": true,
|
||||||
|
"precompiledReferences": [
|
||||||
|
"nunit.framework.dll"
|
||||||
|
],
|
||||||
|
"autoReferenced": false,
|
||||||
|
"defineConstraints": [
|
||||||
|
"UNITY_INCLUDE_TESTS"
|
||||||
|
],
|
||||||
|
"versionDefines": [],
|
||||||
|
"noEngineReferences": false
|
||||||
|
}
|
||||||
7
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef.meta
Normal file
7
Achievments/Tests/NEG.Utils.Achivments.Tests.asmdef.meta
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 18b8be0ae04b6ad45ba52b2ddeb8198d
|
||||||
|
AssemblyDefinitionImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Achievments/Tests/TestAssets.meta
Normal file
8
Achievments/Tests/TestAssets.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3f7445ed9dd5a4548b89d56c196cbec7
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
18
Achievments/Tests/TestAssets/BaseConfig.asset
Normal file
18
Achievments/Tests/TestAssets/BaseConfig.asset
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 88120b6e616164f489387a6a32a25dee, type: 3}
|
||||||
|
m_Name: BaseConfig
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
<Achivments>k__BackingField:
|
||||||
|
- {fileID: 11400000, guid: 7734df2e5d4033346aac56f0a2b2a836, type: 2}
|
||||||
|
- {fileID: 11400000, guid: c704b1ea2247ad540842a9caff628211, type: 2}
|
||||||
|
- {fileID: 11400000, guid: c71840de74e747e45afc82ecf8922dcd, type: 2}
|
||||||
8
Achievments/Tests/TestAssets/BaseConfig.asset.meta
Normal file
8
Achievments/Tests/TestAssets/BaseConfig.asset.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 15513fd07fae44548bac5d923171a2a3
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
18
Achievments/Tests/TestAssets/Float.asset
Normal file
18
Achievments/Tests/TestAssets/Float.asset
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 2d7270d5452c9b04ca07ef43a491a18d, type: 3}
|
||||||
|
m_Name: Float
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
<Id>k__BackingField: FLOAT
|
||||||
|
<ProgressRequired>k__BackingField: 100
|
||||||
|
<InitialProgress>k__BackingField: 0
|
||||||
|
<Clamped>k__BackingField: 0
|
||||||
8
Achievments/Tests/TestAssets/Float.asset.meta
Normal file
8
Achievments/Tests/TestAssets/Float.asset.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 7734df2e5d4033346aac56f0a2b2a836
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
18
Achievments/Tests/TestAssets/Int.asset
Normal file
18
Achievments/Tests/TestAssets/Int.asset
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 5318fea685aa56646a3310c38a9a9bac, type: 3}
|
||||||
|
m_Name: Int
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
<Id>k__BackingField: INT
|
||||||
|
<ProgressRequired>k__BackingField: 100
|
||||||
|
<InitialProgress>k__BackingField: 0
|
||||||
|
<Clamped>k__BackingField: 0
|
||||||
8
Achievments/Tests/TestAssets/Int.asset.meta
Normal file
8
Achievments/Tests/TestAssets/Int.asset.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c704b1ea2247ad540842a9caff628211
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
15
Achievments/Tests/TestAssets/Toggle.asset
Normal file
15
Achievments/Tests/TestAssets/Toggle.asset
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
%YAML 1.1
|
||||||
|
%TAG !u! tag:unity3d.com,2011:
|
||||||
|
--- !u!114 &11400000
|
||||||
|
MonoBehaviour:
|
||||||
|
m_ObjectHideFlags: 0
|
||||||
|
m_CorrespondingSourceObject: {fileID: 0}
|
||||||
|
m_PrefabInstance: {fileID: 0}
|
||||||
|
m_PrefabAsset: {fileID: 0}
|
||||||
|
m_GameObject: {fileID: 0}
|
||||||
|
m_Enabled: 1
|
||||||
|
m_EditorHideFlags: 0
|
||||||
|
m_Script: {fileID: 11500000, guid: 608c7e921b8b16b42919fc6f55b67fcb, type: 3}
|
||||||
|
m_Name: Toggle
|
||||||
|
m_EditorClassIdentifier:
|
||||||
|
<Id>k__BackingField: TOGGLE
|
||||||
8
Achievments/Tests/TestAssets/Toggle.asset.meta
Normal file
8
Achievments/Tests/TestAssets/Toggle.asset.meta
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c71840de74e747e45afc82ecf8922dcd
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 11400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@ -1,4 +1,5 @@
|
|||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEngine.SceneManagement;
|
||||||
|
|
||||||
namespace NEG.Utils
|
namespace NEG.Utils
|
||||||
{
|
{
|
||||||
@ -8,4 +9,5 @@ namespace NEG.Utils
|
|||||||
private void Start() => SceneManager.LoadScene(1);
|
private void Start() => SceneManager.LoadScene(1);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,7 @@ namespace NEG.Utils.Collections
|
|||||||
public static class DictionaryExtensions
|
public static class DictionaryExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds given value to a dictionary if there was no element at given <paramref name="key" />, replaces element with
|
/// Adds given value to a dictionary if there was no element at given <paramref name="key"/>, replaces element with <paramref name="value"> otherwise.
|
||||||
/// <paramref name="value"> otherwise.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>true if element was added, false if it was replaced</returns>
|
/// <returns>true if element was added, false if it was replaced</returns>
|
||||||
public static bool AddOrUpdate<K, V>(this Dictionary<K, V> dict, K key, V value)
|
public static bool AddOrUpdate<K, V>(this Dictionary<K, V> dict, K key, V value)
|
||||||
@ -16,23 +15,27 @@ namespace NEG.Utils.Collections
|
|||||||
dict[key] = value;
|
dict[key] = value;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
dict.Add(key, value);
|
{
|
||||||
return true;
|
dict.Add(key, value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a value from the dictionary under a specified key or adds it if did not exist and returns
|
/// Gets a value from the dictionary under a specified key or adds it if did not exist and returns <paramref name="defaultValue"/>.
|
||||||
/// <paramref name="defaultValue" />.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>value under a given <paramref name="key" /> if it exists, <paramref name="defaultValue" /> otherwise</returns>
|
/// <returns>value under a given <paramref name="key"/> if it exists, <paramref name="defaultValue"/> otherwise</returns>
|
||||||
public static V GetOrSetToDefault<K, V>(this Dictionary<K, V> dict, K key, V defaultValue)
|
public static V GetOrSetToDefault<K, V>(this Dictionary<K, V> dict, K key, V defaultValue)
|
||||||
{
|
{
|
||||||
if (dict.TryGetValue(key, out var value)) return value;
|
if (dict.TryGetValue(key, out V value))
|
||||||
|
{
|
||||||
|
return value;
|
||||||
|
}
|
||||||
dict.Add(key, defaultValue);
|
dict.Add(key, defaultValue);
|
||||||
|
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -6,42 +6,40 @@ namespace NEG.Utils
|
|||||||
{
|
{
|
||||||
public static class CoroutineUtils
|
public static class CoroutineUtils
|
||||||
{
|
{
|
||||||
private static readonly WaitForEndOfFrame WaitForEndOfFrame = new();
|
private static readonly WaitForEndOfFrame WaitForEndOfFrame = new WaitForEndOfFrame();
|
||||||
|
|
||||||
public static IEnumerator WaitForFrames(int count)
|
public static IEnumerator WaitForFrames(int count)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < count; i++) yield return null;
|
for (int i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
yield return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ActionAfterFrames(this MonoBehaviour mono, int count, Action action) =>
|
public static void ActionAfterFrames(this MonoBehaviour mono, int count, Action action)
|
||||||
|
{
|
||||||
mono.StartCoroutine(ActionAfterFrames(count, action));
|
mono.StartCoroutine(ActionAfterFrames(count, action));
|
||||||
|
}
|
||||||
|
|
||||||
public static IEnumerator ActionAfterFrames(int count, Action action)
|
public static IEnumerator ActionAfterFrames(int count, Action action)
|
||||||
{
|
{
|
||||||
yield return WaitForFrames(count);
|
yield return WaitForFrames(count);
|
||||||
action?.Invoke();
|
action?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ActionAfterEndOfFrame(this MonoBehaviour mono, Action action) =>
|
|
||||||
mono.StartCoroutine(ActionAtNextFrame(action));
|
|
||||||
|
|
||||||
public static IEnumerator ActionAfterEndOfFrame(Action action)
|
public static IEnumerator ActionAfterEndOfFrame(Action action)
|
||||||
{
|
{
|
||||||
yield return WaitForEndOfFrame;
|
yield return WaitForEndOfFrame;
|
||||||
action?.Invoke();
|
action?.Invoke();
|
||||||
}
|
}
|
||||||
|
public static void ActionAtNextFrame(this MonoBehaviour mono, Action action) => mono.StartCoroutine(ActionAtNextFrame(action));
|
||||||
public static void ActionAtNextFrame(this MonoBehaviour mono, Action action) =>
|
|
||||||
mono.StartCoroutine(ActionAtNextFrame(action));
|
|
||||||
|
|
||||||
public static IEnumerator ActionAtNextFrame(Action action)
|
public static IEnumerator ActionAtNextFrame(Action action)
|
||||||
{
|
{
|
||||||
yield return null;
|
yield return null;
|
||||||
action?.Invoke();
|
action?.Invoke();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void ActionAfterTime(this MonoBehaviour mono, float time, Action action) =>
|
public static void ActionAfterTime(this MonoBehaviour mono, float time, Action action) => mono.StartCoroutine(ActionAfterTime(time, action));
|
||||||
mono.StartCoroutine(ActionAfterTime(time, action));
|
|
||||||
|
|
||||||
public static IEnumerator ActionAfterTime(float time, Action action)
|
public static IEnumerator ActionAfterTime(float time, Action action)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,45 +1,13 @@
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.Build;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
using Debug = UnityEngine.Debug;
|
using Debug = UnityEngine.Debug;
|
||||||
|
|
||||||
public static class BuildingUtils
|
public static class BuildingUtils
|
||||||
{
|
{
|
||||||
private const string SteamBuildDefine = "STEAM_BUILD";
|
|
||||||
|
|
||||||
[MenuItem("Tools/PrepareForBuild", priority = -10)]
|
|
||||||
public static void PrepareForBuild()
|
|
||||||
{
|
|
||||||
var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(
|
|
||||||
BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget));
|
|
||||||
string[] args = PlayerSettings.GetAdditionalCompilerArguments(namedBuildTarget);
|
|
||||||
var argsList = args.ToList();
|
|
||||||
argsList.Remove(SteamBuildDefine);
|
|
||||||
PlayerSettings.SetScriptingDefineSymbols(namedBuildTarget, argsList.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/PlatformDefines/Steam", priority = -1)]
|
|
||||||
public static void SetDefinesForSteam()
|
|
||||||
{
|
|
||||||
PrepareForBuild();
|
|
||||||
|
|
||||||
var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(
|
|
||||||
BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget));
|
|
||||||
string[] args = PlayerSettings.GetAdditionalCompilerArguments(namedBuildTarget);
|
|
||||||
var argsList = args.ToList();
|
|
||||||
argsList.Add(SteamBuildDefine);
|
|
||||||
PlayerSettings.SetScriptingDefineSymbols(namedBuildTarget, argsList.ToArray());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MenuItem("Tools/Build/Steam/Release")]
|
[MenuItem("Tools/Build/Steam/Release")]
|
||||||
public static void SteamRelease()
|
public static void SteamRelease()
|
||||||
{
|
{
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
|
|
||||||
IncreaseBuildNumber();
|
IncreaseBuildNumber();
|
||||||
BuildRelease();
|
BuildRelease();
|
||||||
UploadSteam();
|
UploadSteam();
|
||||||
@ -48,102 +16,38 @@ public static class BuildingUtils
|
|||||||
[MenuItem("Tools/Build/Steam/Development")]
|
[MenuItem("Tools/Build/Steam/Development")]
|
||||||
public static void SteamDevelopment()
|
public static void SteamDevelopment()
|
||||||
{
|
{
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
|
|
||||||
IncreaseBuildNumber();
|
IncreaseBuildNumber();
|
||||||
BuildDevelopment();
|
BuildDevelopment();
|
||||||
UploadSteam();
|
UploadSteam();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[MenuItem("Tools/Build/Steam/Demo")]
|
|
||||||
public static void SteamDemo()
|
|
||||||
{
|
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
|
|
||||||
IncreaseBuildNumber();
|
|
||||||
BuildDemo();
|
|
||||||
UploadSteam(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Build/All Release")]
|
[MenuItem("Tools/Build/All Release")]
|
||||||
public static void BuildRelease()
|
public static void BuildRelease()
|
||||||
{
|
{
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
BuildWindowsRelease();
|
BuildWindowsRelease();
|
||||||
BuildLinuxRelease();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("Tools/Build/All Development")]
|
[MenuItem("Tools/Build/All Development")]
|
||||||
public static void BuildDevelopment()
|
public static void BuildDevelopment()
|
||||||
{
|
{
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
BuildWindowsDevelopment();
|
BuildWindowsDevelopment();
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("Tools/Build/All Demo")]
|
|
||||||
public static void BuildDemo()
|
|
||||||
{
|
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
BuildWindows(true, new[] { "DEMO" });
|
|
||||||
BuildLinux(true, new[] { "DEMO" });
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Build/Platform/Windows/x64-Development")]
|
[MenuItem("Tools/Build/Platform/Windows/x64-Development")]
|
||||||
public static void BuildWindowsDevelopment()
|
public static void BuildWindowsDevelopment() => BuildWindows(false);
|
||||||
{
|
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
BuildWindows(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Build/Platform/Windows/x64-Release")]
|
[MenuItem("Tools/Build/Platform/Windows/x64-Release")]
|
||||||
public static void BuildWindowsRelease()
|
public static void BuildWindowsRelease() => BuildWindows(true);
|
||||||
{
|
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
BuildWindows(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Build/Platform/Linux/x64-Release")]
|
|
||||||
public static void BuildLinuxRelease()
|
|
||||||
{
|
|
||||||
if (!CanBuild())
|
|
||||||
return;
|
|
||||||
BuildLinux(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
[MenuItem("Tools/Build/Platform/Android/GooglePlay")]
|
private static void BuildWindows(bool release)
|
||||||
public static void BuildGooglePlay()
|
|
||||||
{
|
|
||||||
IncreaseBuildNumber();
|
|
||||||
PlayerSettings.Android.bundleVersionCode++;
|
|
||||||
EditorUserBuildSettings.buildAppBundle = true;
|
|
||||||
|
|
||||||
var buildPlayerOptions = new BuildPlayerOptions { scenes = new string[EditorBuildSettings.scenes.Length] };
|
|
||||||
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
|
||||||
buildPlayerOptions.scenes[i] = EditorBuildSettings.scenes[i].path;
|
|
||||||
|
|
||||||
buildPlayerOptions.target = BuildTarget.Android;
|
|
||||||
buildPlayerOptions.options = BuildOptions.None;
|
|
||||||
buildPlayerOptions.locationPathName = Application.dataPath +
|
|
||||||
$"/../../{Application.productName}-GooglePlay/{Application.productName}.aab";
|
|
||||||
BuildPipeline.BuildPlayer(buildPlayerOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void BuildWindows(bool release, string[] additionalDefines = default)
|
|
||||||
{
|
{
|
||||||
var buildPlayerOptions = new BuildPlayerOptions { scenes = new string[EditorBuildSettings.scenes.Length] };
|
var buildPlayerOptions = new BuildPlayerOptions { scenes = new string[EditorBuildSettings.scenes.Length] };
|
||||||
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
||||||
|
{
|
||||||
buildPlayerOptions.scenes[i] = EditorBuildSettings.scenes[i].path;
|
buildPlayerOptions.scenes[i] = EditorBuildSettings.scenes[i].path;
|
||||||
|
}
|
||||||
buildPlayerOptions.extraScriptingDefines = additionalDefines;
|
|
||||||
|
|
||||||
buildPlayerOptions.target = BuildTarget.StandaloneWindows64;
|
buildPlayerOptions.target = BuildTarget.StandaloneWindows64;
|
||||||
buildPlayerOptions.options = release ? BuildOptions.None : BuildOptions.Development;
|
buildPlayerOptions.options = release ? BuildOptions.None : BuildOptions.Development;
|
||||||
@ -152,73 +56,29 @@ public static class BuildingUtils
|
|||||||
BuildPipeline.BuildPlayer(buildPlayerOptions);
|
BuildPipeline.BuildPlayer(buildPlayerOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void BuildLinux(bool release, string[] additionalDefines = default)
|
|
||||||
{
|
|
||||||
var buildPlayerOptions = new BuildPlayerOptions { scenes = new string[EditorBuildSettings.scenes.Length] };
|
|
||||||
for (int i = 0; i < EditorBuildSettings.scenes.Length; i++)
|
|
||||||
buildPlayerOptions.scenes[i] = EditorBuildSettings.scenes[i].path;
|
|
||||||
|
|
||||||
buildPlayerOptions.extraScriptingDefines = additionalDefines;
|
|
||||||
|
|
||||||
buildPlayerOptions.target = BuildTarget.StandaloneLinux64;
|
|
||||||
buildPlayerOptions.options = release ? BuildOptions.None : BuildOptions.Development;
|
|
||||||
buildPlayerOptions.locationPathName = Application.dataPath +
|
|
||||||
$"/../../{Application.productName}-Steam/ContentBuilder/content/linux/{Application.productName}.x86_64";
|
|
||||||
BuildPipeline.BuildPlayer(buildPlayerOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void IncreaseBuildNumber()
|
private static void IncreaseBuildNumber()
|
||||||
{
|
{
|
||||||
string[] versionParts = PlayerSettings.bundleVersion.Split('.');
|
string[] versionParts = PlayerSettings.bundleVersion.Split('.');
|
||||||
if (versionParts.Length != 3 || !int.TryParse(versionParts[2], out int version))
|
if (versionParts.Length != 3 || !int.TryParse(versionParts[2], out int version)) {
|
||||||
{
|
|
||||||
Debug.LogError("IncreaseBuildNumber failed to update version " + PlayerSettings.bundleVersion);
|
Debug.LogError("IncreaseBuildNumber failed to update version " + PlayerSettings.bundleVersion);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
versionParts[2] = (version + 1).ToString();
|
versionParts[2] = (version + 1).ToString();
|
||||||
PlayerSettings.bundleVersion = string.Join(".", versionParts);
|
PlayerSettings.bundleVersion = string.Join(".", versionParts);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void UploadSteam(bool demo = false)
|
private static void UploadSteam()
|
||||||
{
|
{
|
||||||
string command =
|
string command = $"cd {Application.dataPath}/../../{Application.productName}-Steam/ContentBuilder && run_build.bat";
|
||||||
$"cd {Application.dataPath}/../../{Application.productName}-Steam/ContentBuilder && push_build.bat";
|
|
||||||
if (demo)
|
|
||||||
{
|
|
||||||
command =
|
|
||||||
$"cd {Application.dataPath}/../../{Application.productName}-Steam/ContentBuilder && push_demo.bat";
|
|
||||||
}
|
|
||||||
|
|
||||||
var processInfo = new ProcessStartInfo("cmd.exe", $"/c {command}")
|
var processInfo = new ProcessStartInfo("cmd.exe", $"/c {command}")
|
||||||
{
|
{
|
||||||
CreateNoWindow = true, UseShellExecute = false
|
CreateNoWindow = true,
|
||||||
};
|
UseShellExecute = false
|
||||||
|
};
|
||||||
var process = Process.Start(processInfo);
|
var process = Process.Start(processInfo);
|
||||||
process.WaitForExit();
|
process.WaitForExit();
|
||||||
Debug.Log(process.ExitCode);
|
Debug.Log(process.ExitCode);
|
||||||
process.Close();
|
process.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool CanBuild()
|
|
||||||
{
|
|
||||||
if (CanBuildUtil())
|
|
||||||
return true;
|
|
||||||
Debug.LogError(
|
|
||||||
"Cannot build with defines set in project, please use PrepareForBuild and wait for scripts recompilation");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static bool CanBuildUtil()
|
|
||||||
{
|
|
||||||
var namedBuildTarget = NamedBuildTarget.FromBuildTargetGroup(
|
|
||||||
BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget));
|
|
||||||
string[] args = PlayerSettings.GetAdditionalCompilerArguments(namedBuildTarget);
|
|
||||||
var argsList = args.ToList();
|
|
||||||
|
|
||||||
if (argsList.Contains(SteamBuildDefine))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@ -8,19 +8,14 @@ namespace NEG.Utils.Editor.ComponentsAdditionalItems
|
|||||||
{
|
{
|
||||||
[MenuItem("CONTEXT/CanvasScaler/Full HD horizontal", false, 2000)]
|
[MenuItem("CONTEXT/CanvasScaler/Full HD horizontal", false, 2000)]
|
||||||
public static void SetFullHdHorizontal(MenuCommand command) => SetComponent(command, 1920, 1080);
|
public static void SetFullHdHorizontal(MenuCommand command) => SetComponent(command, 1920, 1080);
|
||||||
|
|
||||||
[MenuItem("CONTEXT/CanvasScaler/Full HD vertical", false, 2000)]
|
[MenuItem("CONTEXT/CanvasScaler/Full HD vertical", false, 2000)]
|
||||||
public static void SetFullHdVertical(MenuCommand command) => SetComponent(command, 1080, 1920);
|
public static void SetFullHdVertical(MenuCommand command) => SetComponent(command, 1080, 1920);
|
||||||
|
|
||||||
[MenuItem("CONTEXT/CanvasScaler/Full 2k horizontal", false, 2000)]
|
[MenuItem("CONTEXT/CanvasScaler/Full 2k horizontal", false, 2000)]
|
||||||
public static void Set2KHorizontal(MenuCommand command) => SetComponent(command, 2560, 1440);
|
public static void Set2KHorizontal(MenuCommand command) => SetComponent(command, 2560, 1440 );
|
||||||
|
|
||||||
[MenuItem("CONTEXT/CanvasScaler/Full 2k vertical", false, 2000)]
|
[MenuItem("CONTEXT/CanvasScaler/Full 2k vertical", false, 2000)]
|
||||||
public static void Set2KVertical(MenuCommand command) => SetComponent(command, 1440, 2560);
|
public static void Set2KVertical(MenuCommand command) => SetComponent(command, 1440, 2560);
|
||||||
|
|
||||||
[MenuItem("CONTEXT/CanvasScaler/Full 4k horizontal", false, 2000)]
|
[MenuItem("CONTEXT/CanvasScaler/Full 4k horizontal", false, 2000)]
|
||||||
public static void Set4KHorizontal(MenuCommand command) => SetComponent(command, 3840, 2160);
|
public static void Set4KHorizontal(MenuCommand command) => SetComponent(command, 3840, 2160);
|
||||||
|
|
||||||
[MenuItem("CONTEXT/CanvasScaler/Full 4k vertical", false, 2000)]
|
[MenuItem("CONTEXT/CanvasScaler/Full 4k vertical", false, 2000)]
|
||||||
public static void Set4KVertical(MenuCommand command) => SetComponent(command, 2160, 3840);
|
public static void Set4KVertical(MenuCommand command) => SetComponent(command, 2160, 3840);
|
||||||
|
|
||||||
|
|||||||
@ -11,57 +11,61 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
using Debug = UnityEngine.Debug;
|
using UnityEditor;
|
||||||
|
|
||||||
namespace TheGamedevGuru
|
namespace TheGamedevGuru
|
||||||
{
|
{
|
||||||
public class EditorInstanceCreator : EditorWindow
|
public class EditorInstanceCreator : EditorWindow
|
||||||
{
|
{
|
||||||
private string _extraSubdirectories;
|
string _projectInstanceName;
|
||||||
private bool _includeProjectSettings = true;
|
string _extraSubdirectories;
|
||||||
private string _projectInstanceName;
|
bool _includeProjectSettings = true;
|
||||||
|
|
||||||
private void OnGUI()
|
[MenuItem("Window/The Gamedev Guru/Editor Instance Creator")]
|
||||||
|
static void Init()
|
||||||
|
{
|
||||||
|
((EditorInstanceCreator)EditorWindow.GetWindow(typeof(EditorInstanceCreator))).Show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnGUI()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_projectInstanceName))
|
if (string.IsNullOrEmpty(_projectInstanceName))
|
||||||
|
{
|
||||||
_projectInstanceName = PlayerSettings.productName + "_Slave_1";
|
_projectInstanceName = PlayerSettings.productName + "_Slave_1";
|
||||||
|
}
|
||||||
|
|
||||||
EditorGUILayout.Separator();
|
EditorGUILayout.Separator();
|
||||||
EditorGUILayout.LabelField("The Gamedev Guru - Project Instance Creator");
|
EditorGUILayout.LabelField("The Gamedev Guru - Project Instance Creator");
|
||||||
EditorGUILayout.Separator();
|
EditorGUILayout.Separator();
|
||||||
EditorGUILayout.LabelField("Slave Project Name");
|
EditorGUILayout.LabelField("Slave Project Name");
|
||||||
_projectInstanceName = EditorGUILayout.TextField("", _projectInstanceName);
|
_projectInstanceName = EditorGUILayout.TextField("", _projectInstanceName);
|
||||||
EditorGUILayout.Separator();
|
EditorGUILayout.Separator();
|
||||||
|
|
||||||
EditorGUILayout.LabelField("Include Project Settings? (Recommended)");
|
EditorGUILayout.LabelField("Include Project Settings? (Recommended)");
|
||||||
_includeProjectSettings = EditorGUILayout.Toggle("", _includeProjectSettings);
|
_includeProjectSettings = EditorGUILayout.Toggle("", _includeProjectSettings);
|
||||||
EditorGUILayout.Separator();
|
EditorGUILayout.Separator();
|
||||||
|
|
||||||
EditorGUILayout.LabelField("Extra Subdirectories? (Separate by comma)");
|
EditorGUILayout.LabelField("Extra Subdirectories? (Separate by comma)");
|
||||||
_extraSubdirectories = EditorGUILayout.TextField("", _extraSubdirectories);
|
_extraSubdirectories = EditorGUILayout.TextField("", _extraSubdirectories);
|
||||||
EditorGUILayout.Separator();
|
EditorGUILayout.Separator();
|
||||||
|
|
||||||
if (GUILayout.Button("Create"))
|
if (GUILayout.Button("Create"))
|
||||||
|
{
|
||||||
CreateProjectInstance(_projectInstanceName, _includeProjectSettings, _extraSubdirectories);
|
CreateProjectInstance(_projectInstanceName, _includeProjectSettings, _extraSubdirectories);
|
||||||
|
}
|
||||||
|
|
||||||
if (GUILayout.Button("Help"))
|
if (GUILayout.Button("Help"))
|
||||||
|
{
|
||||||
Application.OpenURL("https://thegamedev.guru/multiple-unity-editor-instances-within-a-single-project/");
|
Application.OpenURL("https://thegamedev.guru/multiple-unity-editor-instances-within-a-single-project/");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[MenuItem("Window/The Gamedev Guru/Editor Instance Creator")]
|
static void CreateProjectInstance(string projectInstanceName, bool includeProjectSettings, string extraSubdirectories)
|
||||||
private static void Init() => ((EditorInstanceCreator)GetWindow(typeof(EditorInstanceCreator))).Show();
|
|
||||||
|
|
||||||
private static void CreateProjectInstance(string projectInstanceName, bool includeProjectSettings,
|
|
||||||
string extraSubdirectories)
|
|
||||||
{
|
{
|
||||||
string targetDirectory = Path.Combine(Directory.GetCurrentDirectory(), ".." + Path.DirectorySeparatorChar,
|
var targetDirectory = Path.Combine(Directory.GetCurrentDirectory(), ".." + Path.DirectorySeparatorChar, projectInstanceName);
|
||||||
projectInstanceName);
|
|
||||||
Debug.Log(targetDirectory);
|
Debug.Log(targetDirectory);
|
||||||
if (Directory.Exists(targetDirectory))
|
if (Directory.Exists(targetDirectory))
|
||||||
{
|
{
|
||||||
@ -71,21 +75,29 @@ namespace TheGamedevGuru
|
|||||||
|
|
||||||
Directory.CreateDirectory(targetDirectory);
|
Directory.CreateDirectory(targetDirectory);
|
||||||
|
|
||||||
var subdirectories = new List<string> { "Assets", "Packages" };
|
List<string> subdirectories = new List<string>{"Assets", "Packages"};
|
||||||
if (includeProjectSettings) subdirectories.Add("ProjectSettings");
|
if (includeProjectSettings)
|
||||||
|
{
|
||||||
|
subdirectories.Add("ProjectSettings");
|
||||||
|
}
|
||||||
|
|
||||||
foreach (string extraSubdirectory in extraSubdirectories.Split(','))
|
foreach (var extraSubdirectory in extraSubdirectories.Split(','))
|
||||||
|
{
|
||||||
subdirectories.Add(extraSubdirectory.Trim());
|
subdirectories.Add(extraSubdirectory.Trim());
|
||||||
|
}
|
||||||
|
|
||||||
foreach (string subdirectory in subdirectories)
|
foreach (var subdirectory in subdirectories)
|
||||||
Process.Start("CMD.exe", GetLinkCommand(subdirectory, targetDirectory));
|
{
|
||||||
|
System.Diagnostics.Process.Start("CMD.exe",GetLinkCommand(subdirectory, targetDirectory));
|
||||||
|
}
|
||||||
|
|
||||||
EditorUtility.RevealInFinder(targetDirectory + Path.DirectorySeparatorChar + "Assets");
|
EditorUtility.RevealInFinder(targetDirectory + Path.DirectorySeparatorChar + "Assets");
|
||||||
EditorUtility.DisplayDialog("Done!",
|
EditorUtility.DisplayDialog("Done!", $"Done! Feel free to add it as an existing project at: {targetDirectory}", "Ok :)");
|
||||||
$"Done! Feel free to add it as an existing project at: {targetDirectory}", "Ok :)");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string GetLinkCommand(string subdirectory, string targetDirectory) =>
|
static string GetLinkCommand(string subdirectory, string targetDirectory)
|
||||||
$"/c mklink /J \"{targetDirectory}{Path.DirectorySeparatorChar}{subdirectory}\" \"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}{subdirectory}\"";
|
{
|
||||||
|
return $"/c mklink /J \"{targetDirectory}{Path.DirectorySeparatorChar}{subdirectory}\" \"{Directory.GetCurrentDirectory()}{Path.DirectorySeparatorChar}{subdirectory}\"";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,42 +0,0 @@
|
|||||||
using System;
|
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
namespace NegUtils.Editor
|
|
||||||
{
|
|
||||||
public class EditorUtils
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AssetPath
|
|
||||||
{
|
|
||||||
private readonly string filter;
|
|
||||||
|
|
||||||
private string path;
|
|
||||||
|
|
||||||
|
|
||||||
public AssetPath(string filter)
|
|
||||||
{
|
|
||||||
this.filter = filter;
|
|
||||||
TryFindPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Path
|
|
||||||
{
|
|
||||||
get
|
|
||||||
{
|
|
||||||
if (path != null)
|
|
||||||
return path;
|
|
||||||
TryFindPath();
|
|
||||||
return path;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TryFindPath()
|
|
||||||
{
|
|
||||||
string[] candidates = AssetDatabase.FindAssets(filter);
|
|
||||||
if (candidates.Length == 0)
|
|
||||||
throw new Exception("Missing layout asset!");
|
|
||||||
path = AssetDatabase.GUIDToAssetPath(candidates[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: a4848b69c1024df8ad6f76cfd4415d01
|
|
||||||
timeCreated: 1698258811
|
|
||||||
@ -1,18 +1,23 @@
|
|||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
|
||||||
public class GUIDToAssetPath : EditorWindow
|
public class GUIDToAssetPath : EditorWindow
|
||||||
{
|
{
|
||||||
private string guid = "";
|
string guid = "";
|
||||||
private string path = "";
|
string path = "";
|
||||||
|
[MenuItem("Tools/GUIDToAssetPath")]
|
||||||
private void OnGUI()
|
static void CreateWindow()
|
||||||
|
{
|
||||||
|
GUIDToAssetPath window = (GUIDToAssetPath)EditorWindow.GetWindowWithRect(typeof(GUIDToAssetPath), new Rect(0, 0, 400, 120));
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnGUI()
|
||||||
{
|
{
|
||||||
GUILayout.Label("Enter guid");
|
GUILayout.Label("Enter guid");
|
||||||
guid = GUILayout.TextField(guid);
|
guid = GUILayout.TextField(guid);
|
||||||
GUILayout.BeginHorizontal();
|
GUILayout.BeginHorizontal();
|
||||||
GUILayout.FlexibleSpace();
|
GUILayout.FlexibleSpace();
|
||||||
if (GUILayout.Button("Get Asset Path", GUILayout.Width(120)))
|
if (GUILayout.Button("Get Asset Path",GUILayout.Width(120)))
|
||||||
path = GetAssetPath(guid);
|
path = GetAssetPath(guid);
|
||||||
GUILayout.FlexibleSpace();
|
GUILayout.FlexibleSpace();
|
||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
@ -24,17 +29,10 @@ public class GUIDToAssetPath : EditorWindow
|
|||||||
GUILayout.EndHorizontal();
|
GUILayout.EndHorizontal();
|
||||||
GUILayout.Label(path);
|
GUILayout.Label(path);
|
||||||
}
|
}
|
||||||
|
static string GetAssetPath(string guid)
|
||||||
[MenuItem("Tools/GUIDToAssetPath")]
|
|
||||||
private static void CreateWindow()
|
|
||||||
{
|
|
||||||
var window = (GUIDToAssetPath)GetWindowWithRect(typeof(GUIDToAssetPath), new Rect(0, 0, 400, 120));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetAssetPath(string guid)
|
|
||||||
{
|
{
|
||||||
guid = guid.Replace("-", "");
|
guid = guid.Replace("-", "");
|
||||||
|
|
||||||
string p = AssetDatabase.GUIDToAssetPath(guid);
|
string p = AssetDatabase.GUIDToAssetPath(guid);
|
||||||
Debug.Log(p);
|
Debug.Log(p);
|
||||||
if (p.Length == 0) p = "not found";
|
if (p.Length == 0) p = "not found";
|
||||||
|
|||||||
@ -1,46 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace NEG.Utils.Editor
|
|
||||||
{
|
|
||||||
public static class MonoBehaviourExtensions
|
|
||||||
{
|
|
||||||
[MenuItem("CONTEXT/MonoBehaviour/Change Script")]
|
|
||||||
public static void ChangeScript(MenuCommand command)
|
|
||||||
{
|
|
||||||
if (command.context == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
var monoBehaviour = command.context as MonoBehaviour;
|
|
||||||
var monoScript = MonoScript.FromMonoBehaviour(monoBehaviour);
|
|
||||||
|
|
||||||
string scriptPath = AssetDatabase.GetAssetPath(monoScript);
|
|
||||||
string directoryPath = new FileInfo(scriptPath).Directory?.FullName;
|
|
||||||
|
|
||||||
// Allow the user to select which script to replace with
|
|
||||||
string newScriptPath = EditorUtility.OpenFilePanel("Select replacement script", directoryPath, "cs");
|
|
||||||
|
|
||||||
// Don't log anything if they cancelled the window
|
|
||||||
if (string.IsNullOrEmpty(newScriptPath)) return;
|
|
||||||
|
|
||||||
// Load the selected asset
|
|
||||||
string relativePath = "Assets\\" + Path.GetRelativePath(Application.dataPath, newScriptPath);
|
|
||||||
var chosenTextAsset = AssetDatabase.LoadAssetAtPath<TextAsset>(relativePath);
|
|
||||||
|
|
||||||
if (chosenTextAsset == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning($"Selected script couldn't be loaded ({relativePath})");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Undo.RegisterCompleteObjectUndo(command.context, "Changing component script");
|
|
||||||
|
|
||||||
var so = new SerializedObject(monoBehaviour);
|
|
||||||
var scriptProperty = so.FindProperty("m_Script");
|
|
||||||
so.Update();
|
|
||||||
scriptProperty.objectReferenceValue = chosenTextAsset;
|
|
||||||
so.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 0501eedeaf1d4dcf8c4d0f1b7a0c1761
|
|
||||||
timeCreated: 1684519404
|
|
||||||
@ -1,18 +1,18 @@
|
|||||||
{
|
{
|
||||||
"name": "NEG.Utils.Editor",
|
"name": "NEG.Utils.Editor",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:3c4294719a93e3c4e831a9ff0c261e8a"
|
"GUID:3c4294719a93e3c4e831a9ff0c261e8a"
|
||||||
],
|
],
|
||||||
"includePlatforms": [
|
"includePlatforms": [
|
||||||
"Editor"
|
"Editor"
|
||||||
],
|
],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
"overrideReferences": false,
|
"overrideReferences": false,
|
||||||
"precompiledReferences": [],
|
"precompiledReferences": [],
|
||||||
"autoReferenced": true,
|
"autoReferenced": true,
|
||||||
"defineConstraints": [],
|
"defineConstraints": [],
|
||||||
"versionDefines": [],
|
"versionDefines": [],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
}
|
}
|
||||||
@ -1,19 +0,0 @@
|
|||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace NEG.Utils.Editor
|
|
||||||
{
|
|
||||||
[CustomPropertyDrawer(typeof(ReadOnlyAttribute))]
|
|
||||||
public class ReadOnlyPropertyDrawer : PropertyDrawer
|
|
||||||
{
|
|
||||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
GUI.enabled = false;
|
|
||||||
EditorGUI.PropertyField(position, property, label, true);
|
|
||||||
GUI.enabled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) =>
|
|
||||||
EditorGUI.GetPropertyHeight(property, label, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 1f837bac3a7b40528454a9fb9a46d0be
|
|
||||||
timeCreated: 1699371332
|
|
||||||
@ -1,6 +1,5 @@
|
|||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
|
using UnityEditor;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Drawer for the RequireInterface attribute.
|
/// Drawer for the RequireInterface attribute.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -11,7 +10,7 @@ namespace NEG.Utils
|
|||||||
public class RequireInterfaceDrawer : PropertyDrawer
|
public class RequireInterfaceDrawer : PropertyDrawer
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Overrides GUI drawing for the attribute.
|
/// Overrides GUI drawing for the attribute.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="position">Position.</param>
|
/// <param name="position">Position.</param>
|
||||||
/// <param name="property">Property.</param>
|
/// <param name="property">Property.</param>
|
||||||
@ -22,12 +21,11 @@ namespace NEG.Utils
|
|||||||
if (property.propertyType == SerializedPropertyType.ObjectReference)
|
if (property.propertyType == SerializedPropertyType.ObjectReference)
|
||||||
{
|
{
|
||||||
// Get attribute parameters.
|
// Get attribute parameters.
|
||||||
var requiredAttribute = attribute as RequireInterfaceAttribute;
|
var requiredAttribute = this.attribute as RequireInterfaceAttribute;
|
||||||
// Begin drawing property field.
|
// Begin drawing property field.
|
||||||
EditorGUI.BeginProperty(position, label, property);
|
EditorGUI.BeginProperty(position, label, property);
|
||||||
// Draw property field.
|
// Draw property field.
|
||||||
property.objectReferenceValue = EditorGUI.ObjectField(position, label, property.objectReferenceValue,
|
property.objectReferenceValue = EditorGUI.ObjectField(position, label, property.objectReferenceValue, requiredAttribute.requiredType, true);
|
||||||
requiredAttribute.requiredType, true);
|
|
||||||
// Finish drawing property field.
|
// Finish drawing property field.
|
||||||
EditorGUI.EndProperty();
|
EditorGUI.EndProperty();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +0,0 @@
|
|||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace NEG.Editor
|
|
||||||
{
|
|
||||||
public static class ScreenshotMaker
|
|
||||||
{
|
|
||||||
[MenuItem("CONTEXT/Camera/Save view")]
|
|
||||||
public static void Capture(MenuCommand command)
|
|
||||||
{
|
|
||||||
string path = EditorUtility.SaveFilePanel("Save screenshot", "", "screen.png", "png");
|
|
||||||
if (path.Length == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ScreenCapture.CaptureScreenshot(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 7dba407e8e8740a1bed3ee5fa833b13c
|
|
||||||
timeCreated: 1687881092
|
|
||||||
@ -1,16 +1,21 @@
|
|||||||
|
using System;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
|
|
||||||
namespace NEG.Utils.Serialization
|
namespace NEG.Utils.Serialization
|
||||||
{
|
{
|
||||||
public static class SerializationExtentions
|
public static class SerializationExtentions
|
||||||
{
|
{
|
||||||
public static SerializedProperty FindAutoProperty(this SerializedObject @this, string name) =>
|
public static SerializedProperty FindAutoProperty(this SerializedObject @this, string name)
|
||||||
@this.FindProperty(GetBackingFieldName(name));
|
{
|
||||||
|
return @this.FindProperty(GetBackingFieldName(name));
|
||||||
|
}
|
||||||
|
|
||||||
public static SerializedProperty FindAutoPropertyRelative(this SerializedProperty @this, string name) =>
|
public static SerializedProperty FindAutoPropertyRelative(this SerializedProperty @this, string name)
|
||||||
@this.FindPropertyRelative(GetBackingFieldName(name));
|
{
|
||||||
|
return @this.FindPropertyRelative(GetBackingFieldName(name));
|
||||||
|
}
|
||||||
|
|
||||||
public static string GetBackingFieldName(string name)
|
private static string GetBackingFieldName(string name)
|
||||||
{
|
{
|
||||||
#if NET_STANDARD || NET_STANDARD_2_1
|
#if NET_STANDARD || NET_STANDARD_2_1
|
||||||
return string.Create(1/*<*/ + name.Length + 16/*>k__BackingField*/, name, static (span, name) =>
|
return string.Create(1/*<*/ + name.Length + 16/*>k__BackingField*/, name, static (span, name) =>
|
||||||
@ -24,4 +29,4 @@ namespace NEG.Utils.Serialization
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using System.IO;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using UnityEditor;
|
using UnityEditor;
|
||||||
using UnityEditor.SceneManagement;
|
using UnityEditor.SceneManagement;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -9,34 +10,11 @@ namespace NegUtils.Editor
|
|||||||
[InitializeOnLoad]
|
[InitializeOnLoad]
|
||||||
public class ToolsWindowBase : EditorWindow
|
public class ToolsWindowBase : EditorWindow
|
||||||
{
|
{
|
||||||
private const int UnitySceneExtensionLength = 6;
|
|
||||||
|
|
||||||
static ToolsWindowBase()
|
static ToolsWindowBase()
|
||||||
{
|
{
|
||||||
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnGUI()
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Select Scene"))
|
|
||||||
ShowScenesList(GUILayoutUtility.GetLastRect());
|
|
||||||
|
|
||||||
bool startFromSceneIndex0 = EditorPrefs.GetBool("StartFromSceneIndex0");
|
|
||||||
bool newVal = GUILayout.Toggle(startFromSceneIndex0, "Start from scene with index 0 on start");
|
|
||||||
if (newVal != startFromSceneIndex0) EditorPrefs.SetBool("StartFromSceneIndex0", newVal);
|
|
||||||
|
|
||||||
if (!startFromSceneIndex0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
bool goToCurrentScene = EditorPrefs.GetBool("GoToCurrentSceneAfterPlay");
|
|
||||||
newVal = GUILayout.Toggle(goToCurrentScene, "Go to current scene after play");
|
|
||||||
if (newVal != goToCurrentScene) EditorPrefs.SetBool("GoToCurrentSceneAfterPlay", newVal);
|
|
||||||
|
|
||||||
bool goToFirstScene = EditorPrefs.GetBool("GoToFirstSceneAfterPlay");
|
|
||||||
newVal = GUILayout.Toggle(goToFirstScene, "Go to scene with index 1 after play");
|
|
||||||
if (newVal != goToFirstScene) EditorPrefs.SetBool("GoToFirstSceneAfterPlay", newVal);
|
|
||||||
}
|
|
||||||
|
|
||||||
[MenuItem("Tools/Show Tools Window")]
|
[MenuItem("Tools/Show Tools Window")]
|
||||||
private static void ShowWindow()
|
private static void ShowWindow()
|
||||||
{
|
{
|
||||||
@ -44,39 +22,47 @@ namespace NegUtils.Editor
|
|||||||
window.Show();
|
window.Show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected virtual void OnGUI()
|
||||||
|
{
|
||||||
|
if (GUILayout.Button("Select Scene"))
|
||||||
|
ShowScenesList(GUILayoutUtility.GetLastRect());
|
||||||
|
|
||||||
|
bool startFromSceneIndex0 = EditorPrefs.GetBool("StartFromSceneIndex0");
|
||||||
|
bool newVal = GUILayout.Toggle(startFromSceneIndex0, "Start from scene with index 0 on start");
|
||||||
|
if (newVal != startFromSceneIndex0)
|
||||||
|
{
|
||||||
|
EditorPrefs.SetBool("StartFromSceneIndex0", newVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (startFromSceneIndex0)
|
||||||
|
{
|
||||||
|
bool goToCurrentScene = EditorPrefs.GetBool("GoToCurrentSceneAfterPlay");
|
||||||
|
newVal = GUILayout.Toggle(goToCurrentScene, "Go to current scene after play");
|
||||||
|
if (newVal != goToCurrentScene)
|
||||||
|
{
|
||||||
|
EditorPrefs.SetBool("GoToCurrentSceneAfterPlay", newVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static void ShowScenesList(Rect position)
|
private static void ShowScenesList(Rect position)
|
||||||
{
|
{
|
||||||
var menu = new GenericMenu();
|
var menu = new GenericMenu();
|
||||||
|
|
||||||
string path = Application.dataPath + "/Scenes";
|
string path = Application.dataPath + "/Scenes/Production";
|
||||||
|
|
||||||
AddFiles(path, path, menu);
|
|
||||||
|
|
||||||
menu.DropDown(position);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AddFiles(string path, string basePath, GenericMenu menu)
|
|
||||||
{
|
|
||||||
string[] fileInfo = Directory.GetFiles(path, "*.unity");
|
string[] fileInfo = Directory.GetFiles(path, "*.unity");
|
||||||
for (int i = 0; i < fileInfo.Length; i++)
|
|
||||||
{
|
|
||||||
string s = fileInfo[i];
|
|
||||||
menu.AddItem(
|
|
||||||
new GUIContent(s.Remove(0, basePath.Length + 1)
|
|
||||||
.Remove(s.Length - basePath.Length - UnitySceneExtensionLength - 1, UnitySceneExtensionLength)
|
|
||||||
.Replace('\\', '/')), false, () =>
|
|
||||||
{
|
|
||||||
LoadScene(s);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (i == fileInfo.Length) continue;
|
foreach (string item in fileInfo)
|
||||||
|
{
|
||||||
|
string s = item;
|
||||||
|
menu.AddItem(new GUIContent(s.Remove(0, path.Length + 1).Remove(s.Length - path.Length - 7 ,6)), false, () => {
|
||||||
|
LoadScene(s);
|
||||||
|
});
|
||||||
menu.AddSeparator("");
|
menu.AddSeparator("");
|
||||||
}
|
}
|
||||||
|
menu.DropDown(position);
|
||||||
string[] dirInfo = Directory.GetDirectories(path);
|
|
||||||
foreach (string dir in dirInfo) AddFiles(dir, basePath, menu);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void LoadScene(string path)
|
private static void LoadScene(string path)
|
||||||
{
|
{
|
||||||
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
|
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
|
||||||
@ -85,11 +71,11 @@ namespace NegUtils.Editor
|
|||||||
|
|
||||||
private static void OnPlayModeStateChanged(PlayModeStateChange state)
|
private static void OnPlayModeStateChanged(PlayModeStateChange state)
|
||||||
{
|
{
|
||||||
switch (state)
|
switch(state)
|
||||||
{
|
{
|
||||||
case PlayModeStateChange.ExitingEditMode:
|
case PlayModeStateChange.ExitingEditMode:
|
||||||
{
|
{
|
||||||
if (!EditorPrefs.GetBool("StartFromSceneIndex0"))
|
if(!EditorPrefs.GetBool("StartFromSceneIndex0"))
|
||||||
return;
|
return;
|
||||||
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
|
EditorSceneManager.SaveCurrentModifiedScenesIfUserWantsTo();
|
||||||
EditorPrefs.SetString("LastOpenedScenePath", EditorSceneManager.GetSceneManagerSetup()[0].path);
|
EditorPrefs.SetString("LastOpenedScenePath", EditorSceneManager.GetSceneManagerSetup()[0].path);
|
||||||
@ -98,26 +84,25 @@ namespace NegUtils.Editor
|
|||||||
break;
|
break;
|
||||||
case PlayModeStateChange.EnteredPlayMode:
|
case PlayModeStateChange.EnteredPlayMode:
|
||||||
{
|
{
|
||||||
if (!EditorPrefs.GetBool("StartFromSceneIndex0"))
|
if(!EditorPrefs.GetBool("StartFromSceneIndex0"))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (EditorPrefs.GetBool("GoToCurrentSceneAfterPlay"))
|
if (EditorPrefs.GetBool("GoToCurrentSceneAfterPlay"))
|
||||||
{
|
|
||||||
EditorSceneManager.LoadSceneInPlayMode(EditorPrefs.GetString("LastOpenedScenePath"),
|
EditorSceneManager.LoadSceneInPlayMode(EditorPrefs.GetString("LastOpenedScenePath"),
|
||||||
new LoadSceneParameters(LoadSceneMode.Single));
|
new LoadSceneParameters(LoadSceneMode.Single));
|
||||||
}
|
else
|
||||||
else if (EditorPrefs.GetBool("GoToFirstSceneAfterPlay"))
|
|
||||||
SceneManager.LoadScene(1);
|
SceneManager.LoadScene(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PlayModeStateChange.EnteredEditMode:
|
case PlayModeStateChange.EnteredEditMode:
|
||||||
{
|
{
|
||||||
if (!EditorPrefs.GetBool("StartFromSceneIndex0"))
|
if(!EditorPrefs.GetBool("StartFromSceneIndex0"))
|
||||||
return;
|
return;
|
||||||
EditorSceneManager.OpenScene(EditorPrefs.GetString("LastOpenedScenePath"));
|
EditorSceneManager.OpenScene(EditorPrefs.GetString("LastOpenedScenePath"));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,14 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using UnityEditor.AssetImporters;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
[ScriptedImporter(1, "tsv")]
|
|
||||||
public class TsvImporter : ScriptedImporter
|
|
||||||
{
|
|
||||||
public override void OnImportAsset(AssetImportContext ctx)
|
|
||||||
{
|
|
||||||
var textAsset = new TextAsset(File.ReadAllText(ctx.assetPath));
|
|
||||||
ctx.AddObjectToAsset(Path.GetFileNameWithoutExtension(ctx.assetPath), textAsset);
|
|
||||||
ctx.SetMainObject(textAsset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
using JetBrains.Annotations;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Reflection;
|
|
||||||
|
|
||||||
namespace NEG.Utils
|
|
||||||
{
|
|
||||||
public class KeyBasedFactory<T1, T2>
|
|
||||||
{
|
|
||||||
[PublicAPI] protected Dictionary<T1, Type> data;
|
|
||||||
|
|
||||||
public KeyBasedFactory()
|
|
||||||
{
|
|
||||||
data = new Dictionary<T1, Type>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void FireRegistration()
|
|
||||||
{
|
|
||||||
ScanAssembly(typeof(T2).Assembly);
|
|
||||||
|
|
||||||
if (typeof(T2).Assembly.GetType().Assembly == typeof(T2).Assembly)
|
|
||||||
return;
|
|
||||||
|
|
||||||
ScanAssembly(typeof(T2).Assembly.GetType().Assembly);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void ScanAssembly(Assembly assembly)
|
|
||||||
{
|
|
||||||
foreach (var type in assembly.GetTypes())
|
|
||||||
{
|
|
||||||
var methodFields =
|
|
||||||
type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
|
|
||||||
for (int i = 0; i < methodFields.Length; i++)
|
|
||||||
{
|
|
||||||
if (Attribute.GetCustomAttribute(methodFields[i], typeof(FactoryRegistration)) != null)
|
|
||||||
methodFields[i].Invoke(null, Array.Empty<object>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Register(T1 key, Type type) => data.Add(key, type);
|
|
||||||
|
|
||||||
public T2 CreateInstance(T1 key, params object[] args) => (T2)Activator.CreateInstance(data[key], args);
|
|
||||||
}
|
|
||||||
|
|
||||||
[AttributeUsage(AttributeTargets.Method)]
|
|
||||||
public class FactoryRegistration : Attribute
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 2e0d3df1ddd34209bfb7262b4e51abfe
|
|
||||||
timeCreated: 1683917310
|
|
||||||
@ -1,16 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "NEG.Utils",
|
"name": "NEG.Utils",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [
|
||||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||||
],
|
],
|
||||||
"includePlatforms": [],
|
"includePlatforms": [],
|
||||||
"excludePlatforms": [],
|
"excludePlatforms": [],
|
||||||
"allowUnsafeCode": false,
|
"allowUnsafeCode": false,
|
||||||
"overrideReferences": false,
|
"overrideReferences": false,
|
||||||
"precompiledReferences": [],
|
"precompiledReferences": [],
|
||||||
"autoReferenced": true,
|
"autoReferenced": true,
|
||||||
"defineConstraints": [],
|
"defineConstraints": [],
|
||||||
"versionDefines": [],
|
"versionDefines": [],
|
||||||
"noEngineReferences": false
|
"noEngineReferences": false
|
||||||
}
|
}
|
||||||
@ -1,11 +1,9 @@
|
|||||||
using NEG.UI.WindowSlot;
|
using NEG.UI.WindowSlot;
|
||||||
using NegUtils.NEG.UI;
|
|
||||||
|
|
||||||
namespace NEG.UI.Area
|
namespace NEG.UI.Area
|
||||||
{
|
{
|
||||||
public interface IArea : ISlotsHolder, IControllable
|
public interface IArea : ISlotsHolder, IUiElement
|
||||||
{
|
{
|
||||||
void Open();
|
|
||||||
void Close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,18 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace NegUtils.NEG.UI
|
|
||||||
{
|
|
||||||
public interface IControllable
|
|
||||||
{
|
|
||||||
event Action<object> OnOpened;
|
|
||||||
event Action OnClosed;
|
|
||||||
event Action<BackUsed> OnBackUsed;
|
|
||||||
|
|
||||||
public void TryUseBack(ref BackUsed backUsed);
|
|
||||||
|
|
||||||
public class BackUsed
|
|
||||||
{
|
|
||||||
public bool Used { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 175798310e4048eda768cf40e6ee6de3
|
|
||||||
timeCreated: 1686596400
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
namespace NegUtils.NEG.UI
|
|
||||||
{
|
|
||||||
public interface IController
|
|
||||||
{
|
|
||||||
IControllable Controllable { get; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,3 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b88f4a93020a4bc6bde40e0438d296a9
|
|
||||||
timeCreated: 1686595825
|
|
||||||
11
NEG/UI/IUiElement.cs
Normal file
11
NEG/UI/IUiElement.cs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
namespace NEG.UI
|
||||||
|
{
|
||||||
|
public interface IUiElement
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Sets only visible state of element
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="setEnabled"></param>
|
||||||
|
void SetEnabled(bool setEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
3
NEG/UI/IUiElement.cs.meta
Normal file
3
NEG/UI/IUiElement.cs.meta
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 296bf6969a6347f8aea788a7bdd086af
|
||||||
|
timeCreated: 1670693177
|
||||||
@ -1,16 +1,14 @@
|
|||||||
{
|
{
|
||||||
"name": "NEG.UI",
|
"name": "NEG.UI",
|
||||||
"rootNamespace": "",
|
"rootNamespace": "",
|
||||||
"references": [
|
"references": [],
|
||||||
"GUID:3c4294719a93e3c4e831a9ff0c261e8a"
|
"includePlatforms": [],
|
||||||
],
|
"excludePlatforms": [],
|
||||||
"includePlatforms": [],
|
"allowUnsafeCode": false,
|
||||||
"excludePlatforms": [],
|
"overrideReferences": false,
|
||||||
"allowUnsafeCode": false,
|
"precompiledReferences": [],
|
||||||
"overrideReferences": false,
|
"autoReferenced": true,
|
||||||
"precompiledReferences": [],
|
"defineConstraints": [],
|
||||||
"autoReferenced": true,
|
"versionDefines": [],
|
||||||
"defineConstraints": [],
|
"noEngineReferences": false
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user