[Add] FishNet
This commit is contained in:
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cd9a0ca39fab66c448fdc3e25da9d482
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e92e9b5fef66ccb4d991a260767c3be4
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,42 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Sirenix.OdinInspector
|
||||
{
|
||||
#if !ODIN_INSPECTOR
|
||||
|
||||
public class TabGroupAttribute : PropertyAttribute
|
||||
{
|
||||
public string name;
|
||||
public bool foldEverything;
|
||||
|
||||
public TabGroupAttribute(string name, bool foldEverything = false)
|
||||
{
|
||||
this.foldEverything = foldEverything;
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
public class ShowIfAttribute : PropertyAttribute
|
||||
{
|
||||
#region Fields
|
||||
public string comparedPropertyName { get; private set; }
|
||||
public object comparedValue { get; private set; }
|
||||
public DisablingType disablingType { get; private set; }
|
||||
|
||||
public enum DisablingType
|
||||
{
|
||||
ReadOnly = 2,
|
||||
DontDraw = 3
|
||||
}
|
||||
#endregion
|
||||
|
||||
public ShowIfAttribute(string comparedPropertyName, object comparedValue, DisablingType disablingType = DisablingType.DontDraw)
|
||||
{
|
||||
this.comparedPropertyName = comparedPropertyName;
|
||||
this.comparedValue = comparedValue;
|
||||
this.disablingType = disablingType;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8d18dbd89f49c7a4888bbc0e330675a9
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Editor/PlaceholderAttributes.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"name": "GameKit.Dependencies",
|
||||
"rootNamespace": "",
|
||||
"references": [
|
||||
"GUID:6055be8ebefd69e48b49212b09b47b2f"
|
||||
],
|
||||
"includePlatforms": [],
|
||||
"excludePlatforms": [],
|
||||
"allowUnsafeCode": false,
|
||||
"overrideReferences": false,
|
||||
"precompiledReferences": [],
|
||||
"autoReferenced": true,
|
||||
"defineConstraints": [],
|
||||
"versionDefines": [
|
||||
{
|
||||
"name": "com.unity.textmeshpro",
|
||||
"expression": "",
|
||||
"define": "TEXTMESHPRO"
|
||||
}
|
||||
],
|
||||
"noEngineReferences": false
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1d82bdf40e2465b44b34adf79595e74c
|
||||
AssemblyDefinitionImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/GameKit.Dependencies.asmdef
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 53002e457d153bf49aad4b2b28d4353c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,76 @@
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
[InitializeOnLoad]
|
||||
#endif
|
||||
public static class ApplicationState
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
/// <summary>
|
||||
/// True if application is quitting.
|
||||
/// </summary>
|
||||
private static bool _isQuitting;
|
||||
#endif
|
||||
static ApplicationState()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
_isQuitting = false;
|
||||
#endif
|
||||
Application.quitting -= Application_quitting;
|
||||
Application.quitting += Application_quitting;
|
||||
}
|
||||
|
||||
private static void Application_quitting()
|
||||
{
|
||||
#if !UNITY_EDITOR
|
||||
_isQuitting = true;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the application is quitting for editor or builds.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsQuitting()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
if ((!EditorApplication.isPlayingOrWillChangePlaymode && EditorApplication.isPlaying) || !EditorApplication.isPlaying)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
#else
|
||||
return _isQuitting;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the application is playing for editor or builds.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsPlaying()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
return EditorApplication.isPlaying;
|
||||
#else
|
||||
return Application.isPlaying;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Quits the application for editor or builds.
|
||||
/// </summary>
|
||||
public static void Quit()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
EditorApplication.isPlaying = false;
|
||||
#else
|
||||
Application.Quit();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 54eb82a57a65e8548b57f5ca2a62bb76
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/ApplicationState.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,135 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using GameKit.Dependencies.Utilities.Types;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Arrays
|
||||
{
|
||||
/// <summary>
|
||||
/// Randomizer used for shuffling.
|
||||
/// </summary>
|
||||
private static readonly System.Random _random = new();
|
||||
/// <summary>
|
||||
/// StringBuilder to save performance.
|
||||
/// </summary>
|
||||
private static readonly StringBuilder _stringBuilder = new();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Cast each item in the collection ToString and returns all values.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static string ToString<T>(this IEnumerable<T> collection, string delimeter = ", ")
|
||||
{
|
||||
if (collection == null)
|
||||
return string.Empty;
|
||||
|
||||
_stringBuilder.Clear();
|
||||
foreach (T item in collection)
|
||||
_stringBuilder.Append(item.ToString() + delimeter);
|
||||
|
||||
// Remove ending delimeter.
|
||||
if (_stringBuilder.Length > delimeter.Length)
|
||||
_stringBuilder.Length -= delimeter.Length;
|
||||
|
||||
return _stringBuilder.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an object from a list through re-ordering. This breaks the order of the list for a faster remove.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "list"></param>
|
||||
/// <param name = "value"></param>
|
||||
/// <returns></returns>
|
||||
public static bool FastReferenceRemove<T>(this List<T> list, object value)
|
||||
{
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
if (ReferenceEquals(list[i], value))
|
||||
{
|
||||
FastIndexRemove(list, i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an index from a list through re-ordering. This breaks the order of the list for a faster remove.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "list"></param>
|
||||
/// <param name = "index"></param>
|
||||
public static void FastIndexRemove<T>(this List<T> list, int index)
|
||||
{
|
||||
list[index] = list[^1];
|
||||
list.RemoveAt(list.Count - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles an array.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "array"></param>
|
||||
public static void Shuffle<T>(this T[] array)
|
||||
{
|
||||
int n = array.Length;
|
||||
for (int i = 0; i < n - 1; i++)
|
||||
{
|
||||
int r = i + _random.Next(n - i);
|
||||
T t = array[r];
|
||||
array[r] = array[i];
|
||||
array[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shuffles a list.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "lst"></param>
|
||||
public static void Shuffle<T>(this List<T> lst)
|
||||
{
|
||||
int n = lst.Count;
|
||||
for (int i = 0; i < n - 1; i++)
|
||||
{
|
||||
int r = i + _random.Next(n - i);
|
||||
T t = lst[r];
|
||||
lst[r] = lst[i];
|
||||
lst[i] = t;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an item to a collection, ordering it's position based on itemOrder. Lower values are inserted near the beginning of the collection.
|
||||
/// </summary>
|
||||
public static void AddOrdered<T>(this List<T> collection, T item) where T : IOrderable
|
||||
{
|
||||
int count = collection.Count;
|
||||
int itemOrder = item.Order;
|
||||
|
||||
/* If no entries or is equal or larger to last
|
||||
* entry then value can be added onto the end. */
|
||||
if (count == 0 || itemOrder >= collection[^1].Order)
|
||||
{
|
||||
collection.Add(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
/* If item being sorted is lower than the one in already added.
|
||||
* then insert it before the one already added. */
|
||||
if (itemOrder <= collection[i].Order)
|
||||
{
|
||||
collection.Insert(i, item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1b93eae9ff81b3e4b892128ca4b392ed
|
||||
timeCreated: 1530140103
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Arrays.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,13 @@
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Booleans
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a boolean to an integer, 1 for true 0 for false.
|
||||
/// </summary>
|
||||
public static int ToInt(this bool b)
|
||||
{
|
||||
return b ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 602eeac4b016b174f90ae5e85254ac86
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Bools.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,69 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Various utility classes relating to floats.
|
||||
/// </summary>
|
||||
public static class Bytes
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to encode and decode strings.
|
||||
/// </summary>
|
||||
private static readonly UTF8Encoding _encoding = new(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
|
||||
|
||||
/// <summary>
|
||||
/// Pads an index a specified value. Preferred over typical padding so that pad values used with skins can be easily found in the code.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static string Pad(this byte value, int padding) => Ints.PadInt(value, padding);
|
||||
|
||||
/// <summary>
|
||||
/// Provides a random inclusive int within a given range. Preferred over Unity's Random to eliminate confusion as Unity uses inclusive for floats max, and exclusive for int max.
|
||||
/// </summary>
|
||||
/// <param name = "minimum">Inclusive minimum value.</param>
|
||||
/// <param name = "maximum">Inclusive maximum value.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte RandomInclusiveRange(byte minimum, byte maximum) => (byte)Ints.RandomInclusiveRange(minimum, maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Provides a random exclusive int within a given range. Preferred over Unity's Random to eliminate confusion as Unity uses inclusive for floats max, and exclusive for int max.
|
||||
/// </summary>
|
||||
/// <param name = "minimum">Inclusive minimum value.</param>
|
||||
/// <param name = "maximum">Exclusive maximum value.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte RandomExclusiveRange(byte minimum, byte maximum) => (byte)Ints.RandomExclusiveRange(minimum, maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clamped int within a specified range.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to clamp.</param>
|
||||
/// <param name = "minimum">Minimum value.</param>
|
||||
/// <param name = "maximum">Maximum value.</param>
|
||||
/// <returns></returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte Clamp(byte value, byte minimum, byte maximum) => (byte)Ints.Clamp(value, minimum, maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Returns whichever value is lower.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static byte Min(byte a, byte b) => a < b ? a : b;
|
||||
|
||||
/// <summary>
|
||||
/// Determins if all values passed in are the same.
|
||||
/// </summary>
|
||||
/// <param name = "values">Values to check.</param>
|
||||
/// <returns>True if all values are the same.</returns>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static bool ValuesMatch(params byte[] values) => Ints.ValuesMatch((int[])(object)values);
|
||||
|
||||
/// <summary>
|
||||
/// Converts bytes to a string without error checking.
|
||||
/// </summary>
|
||||
public static string ToString(this byte[] bytes, int offset, int count) => _encoding.GetString(bytes, offset, count);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 26489022ceafbfe4d85bfd5cccf37303
|
||||
timeCreated: 1527268448
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Bytes.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,90 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Ways a CanvasGroup can have it's blocking properties modified.
|
||||
/// </summary>
|
||||
public enum CanvasGroupBlockingType
|
||||
{
|
||||
Unchanged = 0,
|
||||
DoNotBlock = 1,
|
||||
Block = 2
|
||||
}
|
||||
|
||||
public static class CanvaseGroups
|
||||
{
|
||||
public static void SetBlockingType(this CanvasGroup group, CanvasGroupBlockingType blockingType)
|
||||
{
|
||||
if (blockingType == CanvasGroupBlockingType.Unchanged)
|
||||
return;
|
||||
|
||||
bool block = blockingType == CanvasGroupBlockingType.Block;
|
||||
group.blocksRaycasts = block;
|
||||
group.interactable = block;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a CanvasGroup blocking type and alpha.
|
||||
/// </summary>
|
||||
/// <param name = "blockingType">How to handle interactions.</param>
|
||||
/// <param name = "alpha">Alpha for CanvasGroup.</param>
|
||||
public static void SetActive(this CanvasGroup group, CanvasGroupBlockingType blockingType, float alpha)
|
||||
{
|
||||
group.SetBlockingType(blockingType);
|
||||
group.alpha = alpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a canvasGroup active with specified alpha.
|
||||
/// </summary>
|
||||
public static void SetActive(this CanvasGroup group, float alpha)
|
||||
{
|
||||
group.SetActive(true, false);
|
||||
group.alpha = alpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a canvasGroup inactive with specified alpha.
|
||||
/// </summary>
|
||||
public static void SetInactive(this CanvasGroup group, float alpha)
|
||||
{
|
||||
group.SetActive(false, false);
|
||||
group.alpha = alpha;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a group active state by changing alpha and interaction toggles.
|
||||
/// </summary>
|
||||
public static void SetActive(this CanvasGroup group, bool active, bool setAlpha)
|
||||
{
|
||||
if (group == null)
|
||||
return;
|
||||
|
||||
if (setAlpha)
|
||||
{
|
||||
if (active)
|
||||
group.alpha = 1f;
|
||||
else
|
||||
group.alpha = 0f;
|
||||
}
|
||||
|
||||
group.interactable = active;
|
||||
group.blocksRaycasts = active;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a group active state by changing alpha and interaction toggles with a custom alpha.
|
||||
/// </summary>
|
||||
public static void SetActive(this CanvasGroup group, bool active, float alpha)
|
||||
{
|
||||
if (group == null)
|
||||
return;
|
||||
|
||||
group.alpha = alpha;
|
||||
|
||||
group.interactable = active;
|
||||
group.blocksRaycasts = active;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c0e7937b287d3d24d807a115c1a3a464
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/CanvasGroups.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,160 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class ColliderExtensions
|
||||
{
|
||||
public static void GetBoxOverlapParams(this BoxCollider boxCollider, out Vector3 center, out Vector3 halfExtents)
|
||||
{
|
||||
Transform cachedTransform = boxCollider.transform;
|
||||
|
||||
// DO NOT USE UNITY'S VECTOR OPERATIONS IN HOT PATHS, UNITY DOESN'T OPTIMISE THEM
|
||||
|
||||
center = cachedTransform.TransformPoint(boxCollider.center);
|
||||
|
||||
Vector3 lossyScale = cachedTransform.lossyScale;
|
||||
|
||||
Vector3 size = boxCollider.size;
|
||||
|
||||
float x = size.x * 0.5f * lossyScale.x;
|
||||
float y = size.y * 0.5f * lossyScale.y;
|
||||
float z = size.z * 0.5f * lossyScale.z;
|
||||
|
||||
halfExtents = new(x, y, z);
|
||||
}
|
||||
|
||||
public static void GetCapsuleCastParams(this CapsuleCollider capsuleCollider, out Vector3 point1, out Vector3 point2, out float radius)
|
||||
{
|
||||
Transform cachedTransform = capsuleCollider.transform;
|
||||
|
||||
Vector3 lossyScale = cachedTransform.lossyScale;
|
||||
|
||||
// Use System.Math instead of UnityEngine.Mathf because it's much faster.
|
||||
|
||||
float absX = Math.Abs(lossyScale.x);
|
||||
float absY = Math.Abs(lossyScale.y);
|
||||
float absZ = Math.Abs(lossyScale.z);
|
||||
|
||||
float height;
|
||||
|
||||
Vector3 direction;
|
||||
|
||||
switch (capsuleCollider.direction)
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
radius = capsuleCollider.radius * Math.Max(absX, absZ);
|
||||
|
||||
height = capsuleCollider.height * absY;
|
||||
|
||||
direction = Vector3.up;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case 2:
|
||||
{
|
||||
radius = capsuleCollider.radius * Math.Max(absX, absY);
|
||||
|
||||
height = capsuleCollider.height * absZ;
|
||||
|
||||
direction = Vector3.forward;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
// Falling back to X is Unity's default behaviour.
|
||||
|
||||
radius = capsuleCollider.radius * Math.Max(absY, absZ);
|
||||
|
||||
height = capsuleCollider.height * absX;
|
||||
|
||||
direction = Vector3.right;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Vector3 center = cachedTransform.TransformPoint(capsuleCollider.center);
|
||||
|
||||
Vector3 offset = height < radius * 2.0f ? Vector3.zero : cachedTransform.TransformDirection(direction * (height * 0.5f - radius));
|
||||
|
||||
// DO NOT USE UNITY'S VECTOR OPERATIONS IN HOT PATHS, UNITY DOESN'T OPTIMISE THEM
|
||||
|
||||
float x1 = center.x + offset.x;
|
||||
float y1 = center.y + offset.y;
|
||||
float z1 = center.z + offset.z;
|
||||
|
||||
float x2 = center.x - offset.x;
|
||||
float y2 = center.y - offset.y;
|
||||
float z2 = center.z - offset.z;
|
||||
|
||||
point1 = new(x1, y1, z1);
|
||||
|
||||
point2 = new(x2, y2, z2);
|
||||
}
|
||||
|
||||
public static void GetSphereOverlapParams(this SphereCollider sphereCollider, out Vector3 center, out float radius)
|
||||
{
|
||||
Transform cachedTransform = sphereCollider.transform;
|
||||
|
||||
center = cachedTransform.TransformPoint(sphereCollider.center);
|
||||
|
||||
Vector3 lossyScale = cachedTransform.lossyScale;
|
||||
|
||||
// Use System.Math instead of UnityEngine.Mathf because it's much faster.
|
||||
|
||||
float x = Math.Abs(lossyScale.x);
|
||||
float y = Math.Abs(lossyScale.y);
|
||||
float z = Math.Abs(lossyScale.z);
|
||||
|
||||
// Two calls of Math.Max are faster than a single Mathf.Max call because Math.Max doesn't allocate memory and doesn't use loops.
|
||||
|
||||
radius = sphereCollider.radius * Math.Max(Math.Max(x, y), z);
|
||||
}
|
||||
}
|
||||
|
||||
public static class Collider2DExtensions
|
||||
{
|
||||
public static void GetBox2DOverlapParams(this BoxCollider2D boxCollider, out Vector3 center, out Vector3 halfExtents)
|
||||
{
|
||||
Transform cachedTransform = boxCollider.transform;
|
||||
|
||||
// DO NOT USE UNITY'S VECTOR OPERATIONS IN HOT PATHS, UNITY DOESN'T OPTIMISE THEM
|
||||
|
||||
center = cachedTransform.TransformPoint(boxCollider.offset);
|
||||
|
||||
Vector3 lossyScale = cachedTransform.lossyScale;
|
||||
|
||||
Vector3 size = boxCollider.size;
|
||||
|
||||
float x = size.x * 0.5f * lossyScale.x;
|
||||
float y = size.y * 0.5f * lossyScale.y;
|
||||
float z = size.z * 0.5f * lossyScale.z;
|
||||
|
||||
halfExtents = new(x, y, z);
|
||||
}
|
||||
|
||||
public static void GetCircleOverlapParams(this CircleCollider2D circleCollider, out Vector3 center, out float radius)
|
||||
{
|
||||
Transform cachedTransform = circleCollider.transform;
|
||||
Vector3 offset = new(circleCollider.offset.x, circleCollider.offset.y, circleCollider.transform.position.z);
|
||||
center = cachedTransform.TransformPoint(offset);
|
||||
|
||||
Vector3 lossyScale = cachedTransform.lossyScale;
|
||||
|
||||
// Use System.Math instead of UnityEngine.Mathf because it's much faster.
|
||||
|
||||
float x = Math.Abs(lossyScale.x);
|
||||
float y = Math.Abs(lossyScale.y);
|
||||
float z = Math.Abs(lossyScale.z);
|
||||
|
||||
// Two calls of Math.Max are faster than a single Mathf.Max call because Math.Max doesn't allocate memory and doesn't use loops.
|
||||
|
||||
radius = circleCollider.radius * Math.Max(Math.Max(x, y), z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 29e69fa855dd3634d9e66313e7748db4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Colliders.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,79 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class DictionaryFN
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Uses a hacky way to TryGetValue on a dictionary when using IL2CPP and on mobile.
|
||||
/// This is to support older devices that don't properly handle IL2CPP builds.
|
||||
/// </summary>
|
||||
public static bool TryGetValueIL2CPP<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, TKey key, out TValue value)
|
||||
{
|
||||
#if ENABLE_IL2CPP && UNITY_IOS || UNITY_ANDROID
|
||||
if (dict.ContainsKey(key))
|
||||
{
|
||||
value = dict[key];
|
||||
return true;
|
||||
}
|
||||
|
||||
value = default;
|
||||
return false;
|
||||
#else
|
||||
return dict.TryGetValue(key, out value);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns values as a list.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<TValue> ValuesToList<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, bool useCache)
|
||||
{
|
||||
List<TValue> result = useCache ? CollectionCaches<TValue>.RetrieveList() : new(dict.Count);
|
||||
|
||||
//No need to clear the list since it's already clear.
|
||||
dict.ValuesToList(ref result, clearLst: false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds values to a list.
|
||||
/// </summary>
|
||||
public static void ValuesToList<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, ref List<TValue> result, bool clearLst)
|
||||
{
|
||||
if (clearLst)
|
||||
result.Clear();
|
||||
|
||||
foreach (TValue item in dict.Values)
|
||||
result.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns keys as a list.
|
||||
/// </summary>
|
||||
public static List<TKey> KeysToList<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, bool useCache)
|
||||
{
|
||||
List<TKey> result = useCache ? CollectionCaches<TKey>.RetrieveList() : new(dict.Count);
|
||||
|
||||
//No need to clear the list since it's already clear.
|
||||
dict.KeysToList(ref result, clearLst: false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds keys to a list.
|
||||
/// </summary>
|
||||
public static void KeysToList<TKey, TValue>(this IReadOnlyDictionary<TKey, TValue> dict, ref List<TKey> result, bool clearLst)
|
||||
{
|
||||
result.Clear();
|
||||
|
||||
foreach (TKey item in dict.Keys)
|
||||
result.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9d31d19bc39eb6041bad18d8eb68ed68
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Dictionaries.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,99 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Disks
|
||||
{
|
||||
/// <summary>
|
||||
/// Writes specified text to a file path.
|
||||
/// </summary>
|
||||
/// <param name = "text"></param>
|
||||
/// <param name = "path"></param>
|
||||
/// <param name = "formatPath">True to format the path to the current platform.</param>
|
||||
public static void WriteToFile(string text, string path, bool formatPath = true)
|
||||
{
|
||||
// If to format the path for the platform.
|
||||
if (formatPath)
|
||||
path = FormatPlatformPath(path);
|
||||
|
||||
// Path came back or was passed in as an empty string.
|
||||
if (path == string.Empty)
|
||||
{
|
||||
Debug.LogError("Path cannot be null.");
|
||||
return;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
// Get directory path.
|
||||
string directory = Path.GetDirectoryName(path);
|
||||
// If directory doesn't exist try to create it.
|
||||
if (!Directory.Exists(directory))
|
||||
Directory.CreateDirectory(directory);
|
||||
|
||||
//Try to write the file data.
|
||||
using (FileStream fs = new(path, FileMode.Create))
|
||||
{
|
||||
using (StreamWriter writer = new(fs))
|
||||
{
|
||||
writer.Write(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.LogError($"An error occured during a file write. Error: {ex.Message} {Environment.NewLine} File path: {path} {Environment.NewLine} Text: {text}");
|
||||
}
|
||||
|
||||
/* If within the editor then refresh the asset database so changes
|
||||
* reflect in the project folder. */
|
||||
#if UNITY_EDITOR
|
||||
UnityEditor.AssetDatabase.Refresh();
|
||||
#endif
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Formats a file path to the current platform.
|
||||
/// </summary>
|
||||
/// <param name = "path"></param>
|
||||
/// <returns></returns>
|
||||
public static string FormatPlatformPath(string path)
|
||||
{
|
||||
//No path specified.
|
||||
if (path == string.Empty)
|
||||
{
|
||||
Debug.LogError("Path cannot be empty.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string convertedPath = string.Empty;
|
||||
|
||||
//Get the directories as an array.
|
||||
string[] directories = path.Split(Path.DirectorySeparatorChar);
|
||||
|
||||
//Go through each directory.
|
||||
for (int i = 0; i < directories.Length; i++)
|
||||
{
|
||||
/* If only one entry in array then the path
|
||||
* is in the root of the Resources folder. */
|
||||
if (directories.Length == 1)
|
||||
{
|
||||
//Append to converted path and break from the loop.
|
||||
convertedPath = directories[i];
|
||||
break;
|
||||
}
|
||||
//More than one entry, meaning there are sub paths.
|
||||
else
|
||||
{
|
||||
/* Set converted path to the current
|
||||
* convertedPath combined with the next directory. */
|
||||
convertedPath = Path.Combine(convertedPath, directories[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return convertedPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a3a909760282d284591c20c873f20837
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Disks.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,13 @@
|
||||
// #if UNITY_EDITOR
|
||||
// using System;
|
||||
// using UnityEditor;
|
||||
// using UnityEngine;
|
||||
//
|
||||
// namespace GameKit.Dependencies.Utilities
|
||||
// {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// #endif
|
||||
// Remove in V5
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dd42f76391fc1254f82767dbf1a4bc8b
|
||||
timeCreated: 1525378031
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Editing.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,327 @@
|
||||
#if UNITY_EDITOR
|
||||
using System;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public enum EditorLayoutEnableType
|
||||
{
|
||||
Enabled = 0,
|
||||
Disabled = 1,
|
||||
DisabledWhilePlaying = 2
|
||||
}
|
||||
|
||||
public static class EditorGuiLayoutTools
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds a helpbox field.
|
||||
/// </summary>
|
||||
public static void AddHelpBox(string text, MessageType messageType = MessageType.Info)
|
||||
{
|
||||
EditorGUILayout.HelpBox(text, messageType);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a property field.
|
||||
/// </summary>
|
||||
public static void AddPropertyField(SerializedProperty sp, string fieldName, string tooltip = "")
|
||||
{
|
||||
if (tooltip == "")
|
||||
tooltip = sp.tooltip;
|
||||
|
||||
EditorGUILayout.PropertyField(sp, new GUIContent(fieldName, tooltip));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a property field.
|
||||
/// </summary>
|
||||
public static void AddPropertyField(SerializedProperty sp, GUIContent guiContent)
|
||||
{
|
||||
EditorGUILayout.PropertyField(sp, guiContent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a property field.
|
||||
/// </summary>
|
||||
public static void AddPropertyField(SerializedProperty sp, GUIContent guiContent = null, EditorLayoutEnableType enableType = EditorLayoutEnableType.Enabled, params GUILayoutOption[] options)
|
||||
{
|
||||
bool disable = IsDisableLayoutType(enableType);
|
||||
if (disable)
|
||||
GUI.enabled = false;
|
||||
|
||||
EditorGUILayout.PropertyField(sp, guiContent, options);
|
||||
|
||||
if (disable)
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a property field.
|
||||
/// </summary>
|
||||
/// <param name = "enabled">True to have property enabled.</param>
|
||||
[Obsolete("Use AddPropertyField(SerializedProperty, GUIContent, EditorLayoutEnableType, GUILayoutOption.")]
|
||||
public static void AddPropertyField(SerializedProperty sp, GUIContent guiContent = null, bool enabled = true, params GUILayoutOption[] options)
|
||||
{
|
||||
EditorLayoutEnableType enableType = enabled ? EditorLayoutEnableType.Enabled : EditorLayoutEnableType.Disabled;
|
||||
bool disable = IsDisableLayoutType(enableType);
|
||||
if (disable)
|
||||
GUI.enabled = false;
|
||||
|
||||
EditorGUILayout.PropertyField(sp, guiContent, options);
|
||||
|
||||
if (disable)
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds an object field.
|
||||
/// </summary>
|
||||
public static void AddObjectField(string label, MonoScript ms, Type type, bool allowSceneObjects, EditorLayoutEnableType enableType = EditorLayoutEnableType.Enabled, params GUILayoutOption[] options)
|
||||
{
|
||||
bool disable = IsDisableLayoutType(enableType);
|
||||
if (disable)
|
||||
GUI.enabled = false;
|
||||
|
||||
EditorGUILayout.ObjectField("Script:", ms, type, allowSceneObjects, options);
|
||||
|
||||
if (disable)
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disables GUI if playing.
|
||||
/// </summary>
|
||||
public static void DisableGUIIfPlaying()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
GUI.enabled = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Enables GUI if playing.
|
||||
/// </summary>
|
||||
public static void EnableGUIIfPlaying()
|
||||
{
|
||||
if (Application.isPlaying)
|
||||
GUI.enabled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a layout field should be disabled.
|
||||
/// </summary>
|
||||
/// <param name = "enableType"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsDisableLayoutType(EditorLayoutEnableType enableType)
|
||||
{
|
||||
return enableType == EditorLayoutEnableType.Disabled || (enableType == EditorLayoutEnableType.DisabledWhilePlaying && Application.isPlaying);
|
||||
}
|
||||
}
|
||||
|
||||
public static class PropertyDrawerToolExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns GetPropertyHeight value based on drawerTool properties.
|
||||
/// </summary>
|
||||
public static float GetPropertyHeight(this PropertyDrawerTool drawerTool)
|
||||
{
|
||||
if (drawerTool == null)
|
||||
return EditorGUIUtility.singleLineHeight;
|
||||
|
||||
return EditorGUIUtility.singleLineHeight * drawerTool.LineSpacingMultiplier * drawerTool.PropertiesDrawn;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Various utility classes relating to floats.
|
||||
/// </summary>
|
||||
public class PropertyDrawerTool
|
||||
{
|
||||
public PropertyDrawerTool()
|
||||
{
|
||||
Debug.LogError($"This initializer is not supported. Use the initializer with arguments.");
|
||||
}
|
||||
|
||||
public PropertyDrawerTool(Rect position, float lineSpacingMultiplier = 1f)
|
||||
{
|
||||
Position = position;
|
||||
LineSpacingMultiplier = lineSpacingMultiplier;
|
||||
Position = position;
|
||||
_startingIndent = EditorGUI.indentLevel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starting position as indicated by the OnGUI method.
|
||||
/// </summary>
|
||||
/// <remarks>This value may be modified by user code.</remarks>
|
||||
public Rect Position = default;
|
||||
/// <summary>
|
||||
/// Preferred spacing between each draw.
|
||||
/// </summary>
|
||||
public float LineSpacingMultiplier;
|
||||
/// <summary>
|
||||
/// Number of entries drawn by this object.
|
||||
/// </summary>
|
||||
public int PropertiesDrawn = 0;
|
||||
/// <summary>
|
||||
/// Additional position Y of next draw.
|
||||
/// </summary>
|
||||
private float _additionalPositionY = 0;
|
||||
/// <summary>
|
||||
/// Indent level during initialization.
|
||||
/// </summary>
|
||||
private readonly int _startingIndent;
|
||||
|
||||
/// <summary>
|
||||
/// Sets EditorGUI.Indent to the level it were when initializing this class.
|
||||
/// </summary>
|
||||
public void SetIndentToStarting() => EditorGUI.indentLevel = _startingIndent;
|
||||
|
||||
/// <summary>
|
||||
/// Draws a label.
|
||||
/// </summary>
|
||||
public void DrawLabel(GUIContent lLabel) => DrawLabel(lLabel, EditorStyles.label.fontStyle, indent: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a label.
|
||||
/// </summary>
|
||||
public void DrawLabel(GUIContent lLabel, FontStyle styleOverride) => DrawLabel(lLabel, styleOverride, indent: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a label.
|
||||
/// </summary>
|
||||
public void DrawLabel(GUIContent lLabel, FontStyle styleOverride, int indent)
|
||||
{
|
||||
PropertiesDrawn++;
|
||||
|
||||
if (indent != 0)
|
||||
EditorGUI.indentLevel += indent;
|
||||
|
||||
// Set style.
|
||||
FontStyle startingStyle = EditorStyles.label.fontStyle;
|
||||
EditorStyles.label.fontStyle = styleOverride;
|
||||
|
||||
EditorGUI.PrefixLabel(GetRect(), GUIUtility.GetControlID(FocusType.Passive), lLabel);
|
||||
|
||||
EditorStyles.label.fontStyle = startingStyle;
|
||||
|
||||
if (indent != 0)
|
||||
EditorGUI.indentLevel -= indent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop) => DrawProperty(prop, lLabel: "", indent: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, string label) => DrawProperty(prop, new GUIContent(label), EditorStyles.label.fontStyle, indent: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, GUIContent content) => DrawProperty(prop, content, EditorStyles.label.fontStyle, indent: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, int indent) => DrawProperty(prop, lLabel: "", indent);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, string lLabel, int indent) => DrawProperty(prop, lLabel, EditorStyles.label.fontStyle, indent);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, GUIContent content, int indent) => DrawProperty(prop, content, EditorStyles.label.fontStyle, indent);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, GUIContent content, FontStyle labelStyle) => DrawProperty(prop, content, labelStyle, indent: 0);
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, string lLabel, FontStyle labelStyle, int indent)
|
||||
{
|
||||
GUIContent content = lLabel == "" ? default : new GUIContent(lLabel);
|
||||
|
||||
DrawProperty(prop, content, labelStyle, indent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a property.
|
||||
/// </summary>
|
||||
public void DrawProperty(SerializedProperty prop, GUIContent content, FontStyle labelStyle, int indent)
|
||||
{
|
||||
PropertiesDrawn++;
|
||||
|
||||
EditorGUI.indentLevel += indent;
|
||||
|
||||
FontStyle startingStyle = EditorStyles.label.fontStyle;
|
||||
EditorStyles.label.fontStyle = labelStyle;
|
||||
|
||||
EditorGUI.PropertyField(GetRect(), prop, content);
|
||||
|
||||
EditorStyles.label.fontStyle = startingStyle;
|
||||
|
||||
EditorGUI.indentLevel -= indent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Draws a help box.
|
||||
/// </summary>
|
||||
public void DrawHelpBox(string message, MessageType type = MessageType.Info, int indent = 0)
|
||||
{
|
||||
PropertiesDrawn++;
|
||||
|
||||
if (indent != 0)
|
||||
EditorGUI.indentLevel += indent;
|
||||
|
||||
// Calculate how much height the help box needs based on the current width
|
||||
// We subtract the indent spacing from the width to ensure text wrapping is calculated correctly
|
||||
float indentSpacing = indent * 15f;
|
||||
float height = EditorStyles.helpBox.CalcHeight(new(message), Position.width - indentSpacing);
|
||||
|
||||
// Get the rect and draw
|
||||
EditorGUI.HelpBox(GetRectForHelpBox(height), message, type);
|
||||
|
||||
if (indent != 0)
|
||||
EditorGUI.indentLevel -= indent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specialized Rect getter for elements with variable heights like HelpBoxes.
|
||||
/// </summary>
|
||||
private Rect GetRectForHelpBox(float height)
|
||||
{
|
||||
Rect result = new(Position.x, Position.y + _additionalPositionY, Position.width, height);
|
||||
|
||||
// Advance the Y position by the specific height of the box + standard spacing
|
||||
_additionalPositionY += height + EditorGUIUtility.standardVerticalSpacing;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the next Rect to draw at.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Rect GetRect(float? lineSpacingMultiplierOverride = null)
|
||||
{
|
||||
float multiplier = lineSpacingMultiplierOverride ?? LineSpacingMultiplier;
|
||||
|
||||
Rect result = new(Position.x, Position.y + _additionalPositionY, Position.width, EditorGUIUtility.singleLineHeight * multiplier);
|
||||
|
||||
_additionalPositionY += EditorGUIUtility.singleLineHeight * multiplier;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dc822ae23a249704184fa571f551f9c8
|
||||
timeCreated: 1527268448
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/EditorTools.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,130 @@
|
||||
using System;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Enums
|
||||
{
|
||||
public const int SHIFT_EVERYTHING_INT = ~0;
|
||||
public const uint SHIFT_EVERYTHING_UINT = ~0u;
|
||||
|
||||
// 65535
|
||||
/// <summary>
|
||||
/// Determine an enum value from a given string. This can be an expensive function.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "text">Text of string.</param>
|
||||
/// <param name = "defaultValue">Default value if enum couldn't be found.</param>
|
||||
/// <returns>Enum found or default value if no enum is found.</returns>
|
||||
public static T FromString<T>(string text, T defaultValue)
|
||||
{
|
||||
// If string is empty or null return default value.
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return defaultValue;
|
||||
// If enum isn't defined return default value.
|
||||
if (!Enum.IsDefined(typeof(T), (string)text))
|
||||
return defaultValue;
|
||||
//Return parsed value.
|
||||
return (T)Enum.Parse(typeof(T), text, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if whole(extended enum) has any of the part values.
|
||||
/// </summary>
|
||||
/// <param name = "whole"></param>
|
||||
/// <param name = "part">Values to check for within whole.</param>
|
||||
/// <returns>Returns true part is within whole.</returns>
|
||||
public static bool ContainsAllocated(this Enum whole, Enum part)
|
||||
{
|
||||
//If not the same type of Enum return false.
|
||||
/* Commented out for performance. Designer
|
||||
* should know better than to compare two different
|
||||
* enums. */
|
||||
//if (!SameType(value, target))
|
||||
// return false;
|
||||
|
||||
/* Convert enum values to ulong. With so few
|
||||
* values a uint would be safe, but should
|
||||
* the options expand ulong is safer. */
|
||||
ulong wholeNum = Convert.ToUInt64(whole);
|
||||
ulong partNum = Convert.ToUInt64(part);
|
||||
|
||||
return (wholeNum & partNum) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if part values contains any of whole(extended enum).
|
||||
/// </summary>
|
||||
/// <param name = "whole"></param>
|
||||
/// <param name = "part"></param>
|
||||
/// <returns>Returns true whole is within part.</returns>
|
||||
public static bool ReverseContains(this Enum whole, Enum part)
|
||||
{
|
||||
//If not the same type of Enum return false.
|
||||
/* Commented out for performance. Designer
|
||||
* should know better than to compare two different
|
||||
* enums. */
|
||||
//if (!SameType(value, target))
|
||||
// return false;
|
||||
|
||||
/* Convert enum values to ulong. With so few
|
||||
* values a uint would be safe, but should
|
||||
* the options expand ulong is safer. */
|
||||
ulong wholeNum = Convert.ToUInt64(whole);
|
||||
ulong partNum = Convert.ToUInt64(part);
|
||||
|
||||
return (partNum & wholeNum) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if an enum equals a specified value.
|
||||
/// </summary>
|
||||
/// <param name = "value"></param>
|
||||
/// <param name = "target"></param>
|
||||
/// <returns></returns>
|
||||
public static bool Equals(this Enum value, Enum target)
|
||||
{
|
||||
//If not the same type of Enum return false.
|
||||
/* Commented out for performance. Designer
|
||||
* should know better than to compare two different
|
||||
* enums. */
|
||||
//if (!SameType(value, target))
|
||||
// return false;
|
||||
|
||||
ulong valueNum = Convert.ToUInt64(value);
|
||||
ulong wholeNum = Convert.ToUInt64(target);
|
||||
|
||||
return valueNum == wholeNum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a is the same Enum as b.
|
||||
/// </summary>
|
||||
/// <param name = "a"></param>
|
||||
/// <param name = "target"></param>
|
||||
/// <returns></returns>
|
||||
public static bool SameType(Enum a, Enum b)
|
||||
{
|
||||
return a.GetType() == b.GetType();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the highest numeric value for T.
|
||||
/// </summary>
|
||||
public static int GetHighestValue<T>()
|
||||
{
|
||||
Type enumType = typeof(T);
|
||||
/* Brute force enum values.
|
||||
* Linq Last/Max lookup throws for IL2CPP. */
|
||||
int highestValue = 0;
|
||||
Array pidValues = Enum.GetValues(enumType);
|
||||
foreach (T pid in pidValues)
|
||||
{
|
||||
object obj = Enum.Parse(enumType, pid.ToString());
|
||||
int value = Convert.ToInt32(obj);
|
||||
highestValue = Math.Max(highestValue, value);
|
||||
}
|
||||
|
||||
return highestValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e6c66aec505f9254491b2b126a2d4745
|
||||
timeCreated: 1522959833
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Enums.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,228 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Floats
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to randomize float values.
|
||||
/// </summary>
|
||||
private static System.Random _random = new();
|
||||
|
||||
/// <summary>
|
||||
/// Sets a source float to value if equal to or greater than tolerance.
|
||||
/// </summary>
|
||||
/// <param name = "source">Float to check against tolerance.</param>
|
||||
/// <param name = "tolerance">Tolerance float must be equal to or greater than to change to value.</param>
|
||||
/// <param name = "value">Value source is set to when breaking tolerance.</param>
|
||||
public static float SetIfOverTolerance(this float source, float tolerance, float value)
|
||||
{
|
||||
if (source >= tolerance)
|
||||
source = value;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a source float to value if equal to or less than tolerance.
|
||||
/// </summary>
|
||||
/// <param name = "source">Float to check against tolerance.</param>
|
||||
/// <param name = "tolerance">Tolerance float must be equal to or less than to change to value.</param>
|
||||
/// <param name = "value">Value source is set to when breaking tolerance.</param>
|
||||
public static float SetIfUnderTolerance(this float source, float tolerance, float value)
|
||||
{
|
||||
if (source <= tolerance)
|
||||
source = value;
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns how much time is left on an endTime. Returns -1 if no time is left.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static float TimeRemainingValue(this float endTime)
|
||||
{
|
||||
float remaining = endTime - Time.time;
|
||||
// None remaining.
|
||||
if (remaining < 0f)
|
||||
return -1f;
|
||||
|
||||
return endTime - Time.time;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns how much time is left on an endTime. Returns -1 if no time is left.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static int TimeRemainingValue(this float endTime, bool useFloor = true)
|
||||
{
|
||||
float remaining = endTime - Time.time;
|
||||
// None remaining.
|
||||
if (remaining < 0f)
|
||||
return -1;
|
||||
|
||||
float result = endTime - Time.time;
|
||||
return useFloor ? Mathf.FloorToInt(result) : Mathf.CeilToInt(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns time remaining as a string using hh:mm:ss.
|
||||
/// </summary>
|
||||
/// <param name = "value"></param>
|
||||
/// <param name = "segments">Number of places to return. 1 is seconds, 2 is minutes, 3 is hours. If a placement does not exist it is replaced with 00.</param>
|
||||
/// <param name = "emptyOnZero">True to return an empty string when value is 0 or less.</param>
|
||||
/// <returns></returns>
|
||||
public static string TimeRemainingText(this float value, byte segments, bool emptyOnZero = false)
|
||||
{
|
||||
if (emptyOnZero && value <= 0f)
|
||||
return string.Empty;
|
||||
|
||||
int timeRounded = Math.Max(Mathf.RoundToInt(value), 0);
|
||||
TimeSpan t = TimeSpan.FromSeconds(timeRounded);
|
||||
|
||||
int hours = Mathf.FloorToInt(t.Hours);
|
||||
int minutes = Mathf.FloorToInt(t.Minutes);
|
||||
int seconds = Mathf.FloorToInt(t.Seconds);
|
||||
|
||||
string timeText;
|
||||
if (segments == 1)
|
||||
{
|
||||
seconds += minutes * 60;
|
||||
seconds += hours * 3600;
|
||||
timeText = string.Format("{0:D2}", seconds);
|
||||
}
|
||||
else if (segments == 2)
|
||||
{
|
||||
minutes += hours * 60;
|
||||
timeText = string.Format("{0:D2}:{1:D2}", minutes, seconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
timeText = string.Format("{0:D2}:{1:D2}:{2:D2}", hours, minutes, seconds);
|
||||
}
|
||||
|
||||
return timeText;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a random inclusive int within a given range. Preferred over Unity's Random to eliminate confusion as Unity uses inclusive for floats max, and exclusive for int max.
|
||||
/// </summary>
|
||||
/// <param name = "minimum">Inclusive minimum value.</param>
|
||||
/// <param name = "maximum">Inclusive maximum value.</param>
|
||||
/// <returns></returns>
|
||||
public static float RandomInclusiveRange(float minimum, float maximum)
|
||||
{
|
||||
double min = Convert.ToDouble(minimum);
|
||||
double max = Convert.ToDouble(maximum);
|
||||
|
||||
double result = _random.NextDouble() * (max - min) + min;
|
||||
return Convert.ToSingle(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a random float between 0f and 1f.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static float Random01()
|
||||
{
|
||||
return RandomInclusiveRange(0f, 1f);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a target float is within variance of the source float.
|
||||
/// </summary>
|
||||
/// <param name = "a"></param>
|
||||
/// <param name = "b"></param>
|
||||
/// <param name = "tolerance"></param>
|
||||
public static bool Near(this float a, float b, float tolerance = 0.01f)
|
||||
{
|
||||
return Mathf.Abs(a - b) <= tolerance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clamps a float and returns if the float required clamping.
|
||||
/// </summary>
|
||||
/// <param name = "value"></param>
|
||||
/// <param name = "min"></param>
|
||||
/// <param name = "max"></param>
|
||||
/// <param name = "clamped"></param>
|
||||
/// <returns></returns>
|
||||
public static float Clamp(float value, float min, float max, ref bool clamped)
|
||||
{
|
||||
clamped = value < min;
|
||||
if (clamped)
|
||||
return min;
|
||||
|
||||
clamped = value > min;
|
||||
if (clamped)
|
||||
return max;
|
||||
|
||||
clamped = false;
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a float after being adjusted by the specified variance.
|
||||
/// </summary>
|
||||
/// <param name = "source"></param>
|
||||
/// <param name = "variance"></param>
|
||||
/// <returns></returns>
|
||||
public static float Variance(this float source, float variance)
|
||||
{
|
||||
float pickedVariance = RandomInclusiveRange(1f - variance, 1f + variance);
|
||||
return source * pickedVariance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a float value to result after being adjusted by the specified variance.
|
||||
/// </summary>
|
||||
/// <param name = "source"></param>
|
||||
/// <param name = "variance"></param>
|
||||
/// <returns></returns>
|
||||
public static void Variance(this float source, float variance, ref float result)
|
||||
{
|
||||
float pickedVariance = RandomInclusiveRange(1f - variance, 1f + variance);
|
||||
result = source * pickedVariance;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns negative-one, zero, or postive-one of a value instead of just negative-one or positive-one.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to sign.</param>
|
||||
/// <returns>Precise sign.</returns>
|
||||
public static float PreciseSign(float value)
|
||||
{
|
||||
if (value == 0f)
|
||||
return 0f;
|
||||
else
|
||||
return Mathf.Sign(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a float is within a range.
|
||||
/// </summary>
|
||||
/// <param name = "source">Value of float.</param>
|
||||
/// <param name = "rangeMin">Minimum of range.</param>
|
||||
/// <param name = "rangeMax">Maximum of range.</param>
|
||||
/// <returns></returns>
|
||||
public static bool InRange(this float source, float rangeMin, float rangeMax)
|
||||
{
|
||||
return source >= rangeMin && source <= rangeMax;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Randomly flips a float value.
|
||||
/// </summary>
|
||||
/// <param name = "value"></param>
|
||||
/// <returns></returns>
|
||||
public static float RandomlyFlip(this float value)
|
||||
{
|
||||
if (Ints.RandomInclusiveRange(0, 1) == 0)
|
||||
return value;
|
||||
else
|
||||
return value *= -1f;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4ab517aa5c3b6e34ca20461339adda04
|
||||
timeCreated: 1526172456
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Floats.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Guids
|
||||
{
|
||||
/// <summary>
|
||||
/// A buffer convert data and discard.
|
||||
/// </summary>
|
||||
public static byte[] Buffer = new byte[16];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 51b4d6f1925ec014d8e37fc1d8c89c71
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Guids.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,44 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class HashSetsFN
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Adds a collection of items.
|
||||
/// </summary>
|
||||
public static void AddRange<T>(this HashSet<T> hashSet, IEnumerable<T> items)
|
||||
{
|
||||
foreach (T item in items)
|
||||
hashSet.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns values as a list.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<T> ToList<T>(this HashSet<T> collection, bool useCache)
|
||||
{
|
||||
List<T> result = useCache ? CollectionCaches<T>.RetrieveList() : new(collection.Count);
|
||||
|
||||
//No need to clear the list since it's already clear.
|
||||
collection.ToList(ref result, clearLst: false);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds values to a list.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static void ToList<T>(this HashSet<T> collection, ref List<T> lst, bool clearLst)
|
||||
{
|
||||
if (clearLst)
|
||||
lst.Clear();
|
||||
|
||||
foreach (T item in collection)
|
||||
lst.Add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 552af765f3c527b4bb6d72c672044024
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/HashSets.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,74 @@
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Hashing
|
||||
{
|
||||
private const uint FNV_offset_basis32 = 2166136261;
|
||||
private const uint FNV_prime32 = 16777619;
|
||||
private const ulong FNV_offset_basis64 = 14695981039346656037;
|
||||
private const ulong FNV_prime64 = 1099511628211;
|
||||
|
||||
/// <summary>
|
||||
/// non cryptographic stable hash code,
|
||||
/// it will always return the same hash for the same
|
||||
/// string.
|
||||
/// This is simply an implementation of FNV-1 32 bit xor folded to 16 bit
|
||||
/// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
||||
/// </summary>
|
||||
/// <returns>The stable hash32.</returns>
|
||||
/// <param name = "txt">Text.</param>
|
||||
public static ushort GetStableHashU16(this string txt)
|
||||
{
|
||||
uint hash32 = txt.GetStableHashU32();
|
||||
|
||||
return (ushort)((hash32 >> 16) ^ hash32);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// non cryptographic stable hash code,
|
||||
/// it will always return the same hash for the same
|
||||
/// string.
|
||||
/// This is simply an implementation of FNV-1 32 bit
|
||||
/// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
||||
/// </summary>
|
||||
/// <returns>The stable hash32.</returns>
|
||||
/// <param name = "txt">Text.</param>
|
||||
public static uint GetStableHashU32(this string txt)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
uint hash = FNV_offset_basis32;
|
||||
for (int i = 0; i < txt.Length; i++)
|
||||
{
|
||||
uint ch = txt[i];
|
||||
hash = hash * FNV_prime32;
|
||||
hash = hash ^ ch;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// non cryptographic stable hash code,
|
||||
/// it will always return the same hash for the same
|
||||
/// string.
|
||||
/// This is simply an implementation of FNV-1 64 bit
|
||||
/// https://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
|
||||
/// </summary>
|
||||
/// <returns>The stable hash32.</returns>
|
||||
/// <param name = "txt">Text.</param>
|
||||
public static ulong GetStableHashU64(this string txt)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
ulong hash = FNV_offset_basis64;
|
||||
for (int i = 0; i < txt.Length; i++)
|
||||
{
|
||||
ulong ch = txt[i];
|
||||
hash = hash * FNV_prime64;
|
||||
hash = hash ^ ch;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7be723c9549bdd041ac1dc8e8c6d2d18
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Hashing.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,59 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class IOs
|
||||
{
|
||||
/// <summary>
|
||||
/// Finds all prefab files in a path.
|
||||
/// </summary>
|
||||
/// <param name = "startingPath">Path to begin searching in; this is typically "Assets".</param>
|
||||
/// <param name = "excludedPaths">Paths to exclude when searching.</param>
|
||||
/// <param name = "recursive">True to search subpaths.</param>
|
||||
/// <returns></returns>
|
||||
public static string[] GetDirectoryFiles(string startingPath, HashSet<string> excludedPaths, bool recursive, string extension)
|
||||
{
|
||||
// Opportunity to exit early if there are no excluded paths.
|
||||
if (excludedPaths.Count == 0)
|
||||
{
|
||||
string[] strResults = Directory.GetFiles(startingPath, extension, SearchOption.AllDirectories);
|
||||
return strResults;
|
||||
}
|
||||
// starting path is excluded.
|
||||
if (excludedPaths.Contains(startingPath))
|
||||
return new string[0];
|
||||
|
||||
// Folders remaining to be iterated.
|
||||
List<string> enumeratedCollection = new() { startingPath };
|
||||
// Only check other directories if recursive.
|
||||
if (recursive)
|
||||
{
|
||||
// Find all folders which aren't excluded.
|
||||
for (int i = 0; i < enumeratedCollection.Count; i++)
|
||||
{
|
||||
string[] allFolders = Directory.GetDirectories(enumeratedCollection[i], "*", SearchOption.TopDirectoryOnly);
|
||||
for (int z = 0; z < allFolders.Length; z++)
|
||||
{
|
||||
string current = allFolders[z];
|
||||
// Not excluded.
|
||||
if (!excludedPaths.Contains(current))
|
||||
enumeratedCollection.Add(current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Valid prefab files.
|
||||
List<string> results = new();
|
||||
// Build files from folders.
|
||||
int count = enumeratedCollection.Count;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
string[] r = Directory.GetFiles(enumeratedCollection[i], extension, SearchOption.TopDirectoryOnly);
|
||||
results.AddRange(r);
|
||||
}
|
||||
|
||||
return results.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1994e262a1e963479497289602e4461
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/IOs.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,89 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Various utility classes relating to floats.
|
||||
/// </summary>
|
||||
public static class Ints
|
||||
{
|
||||
private static System.Random _random = new();
|
||||
|
||||
/// <summary>
|
||||
/// Pads an index a specified value. Preferred over typical padding so that pad values used with skins can be easily found in the code.
|
||||
/// </summary>
|
||||
/// <param name = "value"></param>
|
||||
/// <param name = "padding"></param>
|
||||
/// <returns></returns>
|
||||
public static string PadInt(int value, int padding)
|
||||
{
|
||||
return value.ToString().PadLeft(padding, '0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a random inclusive int within a given range. Preferred over Unity's Random to eliminate confusion as Unity uses inclusive for floats max, and exclusive for int max.
|
||||
/// </summary>
|
||||
/// <param name = "minimum">Inclusive minimum value.</param>
|
||||
/// <param name = "maximum">Inclusive maximum value.</param>
|
||||
/// <returns></returns>
|
||||
public static int RandomInclusiveRange(int minimum, int maximum)
|
||||
{
|
||||
return _random.Next(minimum, maximum + 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Provides a random exclusive int within a given range. Preferred over Unity's Random to eliminate confusion as Unity uses inclusive for floats max, and exclusive for int max.
|
||||
/// </summary>
|
||||
/// <param name = "minimum">Inclusive minimum value.</param>
|
||||
/// <param name = "maximum">Exclusive maximum value.</param>
|
||||
/// <returns></returns>
|
||||
public static int RandomExclusiveRange(int minimum, int maximum)
|
||||
{
|
||||
return _random.Next(minimum, maximum);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clamped int within a specified range.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to clamp.</param>
|
||||
/// <param name = "minimum">Minimum value.</param>
|
||||
/// <param name = "maximum">Maximum value.</param>
|
||||
/// <returns></returns>
|
||||
public static int Clamp(int value, int minimum, int maximum)
|
||||
{
|
||||
if (value < minimum)
|
||||
value = minimum;
|
||||
else if (value > maximum)
|
||||
value = maximum;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determins if all values passed in are the same.
|
||||
/// </summary>
|
||||
/// <param name = "values">Values to check.</param>
|
||||
/// <returns>True if all values are the same.</returns>
|
||||
public static bool ValuesMatch(params int[] values)
|
||||
{
|
||||
if (values.Length == 0)
|
||||
{
|
||||
Debug.Log("Ints -> ValuesMatch -> values array is empty.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Assign first value as element in first array.
|
||||
int firstValue = values[0];
|
||||
// Check all values.
|
||||
for (int i = 1; i < values.Length; i++)
|
||||
{
|
||||
// If any value doesn't match first value return false.
|
||||
if (firstValue != values[i])
|
||||
return false;
|
||||
}
|
||||
|
||||
// If this far all values match.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c673118198f5c4b41986d52762828363
|
||||
timeCreated: 1527268448
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Ints.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Layers
|
||||
{
|
||||
/* GetInteractableLayer methods is an implementation from this
|
||||
* link: https://forum.unity.com/threads/is-there-a-way-to-get-the-layer-collision-matrix.260744/#post-3483886 */
|
||||
/// <summary>
|
||||
/// Lookup of interactable layers for each layer.
|
||||
/// </summary>
|
||||
private static Dictionary<int, int> _interactablesLayers;
|
||||
|
||||
/// <summary>
|
||||
/// Tries to initializes InteractableLayers.
|
||||
/// </summary>
|
||||
private static void TryInitializeInteractableLayers()
|
||||
{
|
||||
if (_interactablesLayers != null)
|
||||
return;
|
||||
|
||||
_interactablesLayers = new();
|
||||
for (int i = 0; i < 32; i++)
|
||||
{
|
||||
int mask = 0;
|
||||
for (int j = 0; j < 32; j++)
|
||||
{
|
||||
if (!Physics.GetIgnoreLayerCollision(i, j))
|
||||
{
|
||||
mask |= 1 << j;
|
||||
}
|
||||
}
|
||||
// Setting without add check is quicker.
|
||||
_interactablesLayers[i] = mask;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns interactable layers value for layer.
|
||||
/// </summary>
|
||||
public static int GetInteractableLayersValue(int layer)
|
||||
{
|
||||
TryInitializeInteractableLayers();
|
||||
return _interactablesLayers[layer];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns interactable layers LayerMask for a GameObject.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static LayerMask GetInteractableLayersMask(int layer) => (LayerMask)GetInteractableLayersValue(layer);
|
||||
|
||||
/// <summary>
|
||||
/// Returns interactable layers value for a GameObject.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static int GetInteractableLayersValue(GameObject go) => GetInteractableLayersValue(go.layer);
|
||||
|
||||
/// <summary>
|
||||
/// Returns interactable layers LayerMask for a GameObject.
|
||||
/// </summary>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static LayerMask GetInteractableLayersMask(GameObject go) => (LayerMask)GetInteractableLayersValue(go.layer);
|
||||
|
||||
/// <summary>
|
||||
/// Converts a layer mask to a layer number.
|
||||
/// </summary>
|
||||
/// <param name = "mask"></param>
|
||||
/// <returns></returns>
|
||||
public static int LayerMaskToLayerNumber(LayerMask mask)
|
||||
{
|
||||
return LayerValueToLayerNumber(mask.value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a layer value int to a layer int.
|
||||
/// </summary>
|
||||
/// <param name = "bitmask"></param>
|
||||
/// <returns></returns>
|
||||
public static int LayerValueToLayerNumber(int bitmask)
|
||||
{
|
||||
int result = bitmask > 0 ? 0 : 31;
|
||||
while (bitmask > 1)
|
||||
{
|
||||
bitmask = bitmask >> 1;
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a LayerMask contains a specified layer.
|
||||
/// </summary>
|
||||
/// <param name = "layerMask">LayerMask to check for layer in.</param>
|
||||
/// <param name = "layer">Layer to check within LayerMask.</param>
|
||||
/// <returns></returns>
|
||||
public static bool ContainsLayer(LayerMask layerMask, int layer)
|
||||
{
|
||||
return layerMask == (layerMask | (1 << layer));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1c18e15e44d21a94d8919f4b6b125a1f
|
||||
timeCreated: 1522349045
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Layers.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,17 @@
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class LayoutGroups
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns how many entries can fit into a GridLayoutGroup
|
||||
/// </summary>
|
||||
public static int EntriesPerWidth(this GridLayoutGroup lg)
|
||||
{
|
||||
RectTransform rectTransform = lg.GetComponent<RectTransform>();
|
||||
return Mathf.CeilToInt(rectTransform.rect.width / lg.cellSize.x);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e330113395c59ca4dba5de001e010f08
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/LayoutGroups.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class ListsFN
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Adds items to collection while preventing duplicates, returning number of items added.
|
||||
/// </summary>
|
||||
public static int AddRangeUnique<T>(this List<T> collection, IEnumerable<T> items)
|
||||
{
|
||||
int added = 0;
|
||||
|
||||
foreach (T item in items)
|
||||
{
|
||||
if (!collection.Contains(item))
|
||||
{
|
||||
collection.Add(item);
|
||||
added++;
|
||||
}
|
||||
}
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Adds item to collection while preventing duplicates, returning if added.
|
||||
/// </summary>
|
||||
public static bool AddUnique<T>(this List<T> collection, T item)
|
||||
{
|
||||
if (!collection.Contains(item))
|
||||
{
|
||||
collection.Add(item);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b5ae7a9f43f78a345839f65ff75ba384
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Lists.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,34 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Materials
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the color or tint color property for a material.
|
||||
/// </summary>
|
||||
/// <param name = "material"></param>
|
||||
/// <returns></returns>
|
||||
public static Color GetColor(this Material material)
|
||||
{
|
||||
if (material.HasProperty("_Color"))
|
||||
return material.color;
|
||||
else if (material.HasProperty("_TintColor"))
|
||||
return material.GetColor("_TintColor");
|
||||
|
||||
return Color.white;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the color or tint color property for a material.
|
||||
/// </summary>
|
||||
/// <param name = "material"></param>
|
||||
public static void SetColor(this Material material, Color color)
|
||||
{
|
||||
if (material.HasProperty("_Color"))
|
||||
material.color = color;
|
||||
else if (material.HasProperty("_TintColor"))
|
||||
material.SetColor("_TintColor", color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 27a618c551d5fdb4ca70bf07e1905580
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Materials.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,44 @@
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Maths
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns a clamped SBytte.
|
||||
/// </summary>
|
||||
public static sbyte ClampSByte(long value, sbyte min, sbyte max)
|
||||
{
|
||||
if (value < min)
|
||||
return min;
|
||||
else if (value > max)
|
||||
return max;
|
||||
else
|
||||
return (sbyte)value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clamped double.
|
||||
/// </summary>
|
||||
public static double ClampDouble(double value, double min, double max)
|
||||
{
|
||||
if (value < min)
|
||||
return min;
|
||||
else if (value > max)
|
||||
return max;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a clamped byte.
|
||||
/// </summary>
|
||||
public static byte ClampByte(byte value, byte min, byte max)
|
||||
{
|
||||
if (value < min)
|
||||
return min;
|
||||
else if (value > max)
|
||||
return max;
|
||||
else
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 18a583dc22a9a0f4cabec0c4a0219c6e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Maths.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,200 @@
|
||||
#if NEW_INPUTSYSTEM
|
||||
using UnityEngine;
|
||||
using UnityEngine.InputSystem;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class NewInput
|
||||
{
|
||||
/// <summary>
|
||||
/// Current Keyboard.
|
||||
/// </summary>
|
||||
public static Keyboard Keyboard => Keyboard.current;
|
||||
/// <summary>
|
||||
/// Current Mouse.
|
||||
/// </summary>
|
||||
public static Mouse Mouse => Mouse.current;
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a button is held on any map.
|
||||
/// </summary>
|
||||
public static bool GetButtonHeld(Key key)
|
||||
{
|
||||
return (Keyboard != null) ? Keyboard[key].isPressed : false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a button is pressed on any map.
|
||||
/// </summary>
|
||||
public static bool GetButtonPressed(Key key)
|
||||
{
|
||||
return (Keyboard != null) ? Keyboard[key].wasPressedThisFrame : false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if a button is released on any map.
|
||||
/// </summary>
|
||||
public static bool GetButtonReleased(Key key)
|
||||
{
|
||||
return (Keyboard != null) ? Keyboard[key].wasReleasedThisFrame : false;
|
||||
}
|
||||
}
|
||||
|
||||
public static class MouseExtensions
|
||||
{
|
||||
public static Vector3 GetPosition(this Mouse m)
|
||||
{
|
||||
return m.position.ReadValue();
|
||||
}
|
||||
}
|
||||
|
||||
public static class KeyboardExtensions
|
||||
{
|
||||
public static bool GetKeyPressed(this Keyboard kb, Key kc)
|
||||
{
|
||||
return kb[kc].wasPressedThisFrame;
|
||||
}
|
||||
|
||||
public static bool GetKeyHeld(this Keyboard kb, Key kc)
|
||||
{
|
||||
return kb[kc].isPressed;
|
||||
}
|
||||
|
||||
public static bool GetKeyReleased(this Keyboard kb, Key kc)
|
||||
{
|
||||
return kb[kc].wasReleasedThisFrame;
|
||||
}
|
||||
}
|
||||
|
||||
public static class InputActionMapExtensions
|
||||
{
|
||||
#region Strings.
|
||||
public static float GetAxisRaw(this InputActionMap map, string negativeName, string positiveName)
|
||||
{
|
||||
return map.GetAxisRaw(negativeName, positiveName, out _);
|
||||
}
|
||||
|
||||
public static float GetAxisRaw(this InputActionMap map, string negativeName, string positiveName, out bool found)
|
||||
{
|
||||
found = false;
|
||||
InputAction negativeIa = map.FindAction(negativeName);
|
||||
InputAction positiveIa = map.FindAction(positiveName);
|
||||
if (negativeIa == null || positiveIa == null)
|
||||
return 0f;
|
||||
|
||||
found = true;
|
||||
bool negativePressed = negativeIa.IsPressed();
|
||||
bool positivePressed = positiveIa.IsPressed();
|
||||
/* If both are pressed then they cancel each other out.
|
||||
* And if neither are pressed then result is naturally
|
||||
* 0f. */
|
||||
if (negativePressed == positivePressed)
|
||||
return 0f;
|
||||
else if (negativePressed)
|
||||
return -1f;
|
||||
else
|
||||
return 1f;
|
||||
}
|
||||
|
||||
public static float GetAxisRaw(this InputActionMap map, string inputName)
|
||||
{
|
||||
return map.GetAxisRaw(inputName, out _);
|
||||
}
|
||||
|
||||
public static float GetAxisRaw(this InputActionMap map, string inputName, out bool found)
|
||||
{
|
||||
found = false;
|
||||
InputAction ia = map.FindAction(inputName);
|
||||
if (ia == null)
|
||||
return 0f;
|
||||
|
||||
found = true;
|
||||
float axis = ia.ReadValue<float>();
|
||||
if (axis == 0f)
|
||||
return 0f;
|
||||
else
|
||||
return Mathf.Sign(axis);
|
||||
}
|
||||
|
||||
public static bool GetButtonHeld(this InputActionMap map, string inputName)
|
||||
{
|
||||
InputAction ia = map.FindAction(inputName);
|
||||
return (ia == null) ? false : ia.IsPressed();
|
||||
}
|
||||
|
||||
public static bool GetButtonPressed(this InputActionMap map, string inputName)
|
||||
{
|
||||
InputAction ia = map.FindAction(inputName);
|
||||
return (ia == null) ? false : ia.WasPressedThisFrame();
|
||||
}
|
||||
|
||||
public static bool GetButtonReleased(this InputActionMap map, string inputName)
|
||||
{
|
||||
InputAction ia = map.FindAction(inputName);
|
||||
return (ia == null) ? false : ia.WasReleasedThisFrame();
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region InputActions.
|
||||
public static float GetAxisRaw(InputAction negativeIa, InputAction positiveIa)
|
||||
{
|
||||
return GetAxisRaw(negativeIa, positiveIa, out _);
|
||||
}
|
||||
|
||||
public static float GetAxisRaw(InputAction negativeIa, InputAction positiveIa, out bool found)
|
||||
{
|
||||
found = false;
|
||||
if (negativeIa == null || positiveIa == null)
|
||||
return 0f;
|
||||
|
||||
found = true;
|
||||
bool negativePressed = negativeIa.IsPressed();
|
||||
bool positivePressed = positiveIa.IsPressed();
|
||||
/* If both are pressed then they cancel each other out.
|
||||
* And if neither are pressed then result is naturally
|
||||
* 0f. */
|
||||
if (negativePressed == positivePressed)
|
||||
return 0f;
|
||||
else if (negativePressed)
|
||||
return -1f;
|
||||
else
|
||||
return 1f;
|
||||
}
|
||||
|
||||
public static float GetAxisRaw(this InputAction ia)
|
||||
{
|
||||
return GetAxisRaw(ia, out _);
|
||||
}
|
||||
|
||||
public static float GetAxisRaw(this InputAction ia, out bool found)
|
||||
{
|
||||
found = false;
|
||||
if (ia == null)
|
||||
return 0f;
|
||||
|
||||
found = true;
|
||||
float axis = ia.ReadValue<float>();
|
||||
if (axis == 0f)
|
||||
return 0f;
|
||||
else
|
||||
return Mathf.Sign(axis);
|
||||
}
|
||||
|
||||
public static bool GetButtonHeld(this InputAction ia)
|
||||
{
|
||||
return (ia == null) ? false : ia.IsPressed();
|
||||
}
|
||||
|
||||
public static bool GetButtonPressed(this InputAction ia)
|
||||
{
|
||||
return (ia == null) ? false : ia.WasPressedThisFrame();
|
||||
}
|
||||
|
||||
public static bool GetButtonReleased(this InputAction ia)
|
||||
{
|
||||
return (ia == null) ? false : ia.WasReleasedThisFrame();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ea6d91237dc169249b4a375e7e9eef00
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/NewInput.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,892 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using GameKit.Dependencies.Utilities.Types;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
// ReSharper disable ThreadStaticFieldHasInitializesr
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Implement to use type with Caches.
|
||||
/// </summary>
|
||||
public interface IResettable
|
||||
{
|
||||
/// <summary>
|
||||
/// Resets values when being placed in a cache.
|
||||
/// </summary>
|
||||
void ResetState();
|
||||
|
||||
/// <summary>
|
||||
/// Initializes values after being retrieved from a cache.
|
||||
/// </summary>
|
||||
void InitializeState();
|
||||
}
|
||||
|
||||
#region Resettable caches.
|
||||
/// <summary>
|
||||
/// Caches collections of multiple generics.
|
||||
/// </summary>
|
||||
public static class ResettableCollectionCaches<T1, T2> where T1 : IResettable, new() where T2 : IResettable, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<T1, T2> RetrieveDictionary() => CollectionCaches<T1, T2>.RetrieveDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref Dictionary<T1, T2> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(Dictionary<T1, T2> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
foreach (KeyValuePair<T1, T2> kvp in value)
|
||||
{
|
||||
ResettableObjectCaches<T1>.Store(kvp.Key);
|
||||
ResettableObjectCaches<T2>.Store(kvp.Value);
|
||||
}
|
||||
|
||||
value.Clear();
|
||||
|
||||
CollectionCaches<T1, T2>.Store(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches collections of multiple generics.
|
||||
/// </summary>
|
||||
public static class ResettableT1CollectionCaches<T1, T2> where T1 : IResettable, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<T1, T2> RetrieveDictionary() => CollectionCaches<T1, T2>.RetrieveDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref Dictionary<T1, T2> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(Dictionary<T1, T2> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
foreach (T1 item in value.Keys)
|
||||
ResettableObjectCaches<T1>.Store(item);
|
||||
|
||||
value.Clear();
|
||||
CollectionCaches<T1, T2>.Store(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches collections of multiple generics.
|
||||
/// </summary>
|
||||
public static class ResettableT2CollectionCaches<T1, T2> where T2 : IResettable, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<T1, T2> RetrieveDictionary() => CollectionCaches<T1, T2>.RetrieveDictionary();
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref Dictionary<T1, T2> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(Dictionary<T1, T2> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
foreach (T2 item in value.Values)
|
||||
ResettableObjectCaches<T2>.Store(item);
|
||||
|
||||
value.Clear();
|
||||
CollectionCaches<T1, T2>.Store(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches collections of a single generic.
|
||||
/// </summary>
|
||||
public static class ResettableCollectionCaches<T> where T : IResettable, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache for ResettableRingBuffer.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<ResettableRingBuffer<T>> _resettableRingBufferCache = new();
|
||||
/// <summary>
|
||||
/// Maximum number of entries allowed for the cache.
|
||||
/// </summary>
|
||||
private const int MAXIMUM_CACHE_COUNT = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
public static ResettableRingBuffer<T> RetrieveRingBuffer()
|
||||
{
|
||||
ResettableRingBuffer<T> result;
|
||||
if (!_resettableRingBufferCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static T[] RetrieveArray() => CollectionCaches<T>.RetrieveArray();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<T> RetrieveList() => CollectionCaches<T>.RetrieveList();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SortedSet<T> RetrieveSortedSet() => CollectionCaches<T>.RetrieveSortedSet();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static HashSet<T> RetrieveHashSet() => CollectionCaches<T>.RetrieveHashSet();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Queue<T> RetrieveQueue() => CollectionCaches<T>.RetrieveQueue();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static BasicQueue<T> RetrieveBasicQueue() => CollectionCaches<T>.RetrieveBasicQueue();
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
/// <param name = "count">Number of entries in the array from the beginning.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref ResettableRingBuffer<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
/// <param name = "count">Number of entries in the array from the beginning.</param>
|
||||
public static void Store(ResettableRingBuffer<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.ResetState();
|
||||
|
||||
if (_resettableRingBufferCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_resettableRingBufferCache.Push(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
/// <param name = "count">Number of entries in the array from the beginning.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref T[] value, int count)
|
||||
{
|
||||
Store(value, count);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
/// <param name = "count">Number of entries in the array from the beginning.</param>
|
||||
public static void Store(T[] value, int count)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
ResettableObjectCaches<T>.Store(value[i]);
|
||||
|
||||
CollectionCaches<T>.Store(value, count);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref List<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(List<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < value.Count; i++)
|
||||
ResettableObjectCaches<T>.Store(value[i]);
|
||||
|
||||
value.Clear();
|
||||
CollectionCaches<T>.Store(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref SortedSet<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(SortedSet<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
foreach (T item in value)
|
||||
ResettableObjectCaches<T>.Store(item);
|
||||
|
||||
value.Clear();
|
||||
CollectionCaches<T>.Store(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref HashSet<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(HashSet<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
foreach (T item in value)
|
||||
ResettableObjectCaches<T>.Store(item);
|
||||
|
||||
value.Clear();
|
||||
CollectionCaches<T>.Store(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref Queue<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(Queue<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
foreach (T item in value)
|
||||
ResettableObjectCaches<T>.Store(item);
|
||||
|
||||
value.Clear();
|
||||
CollectionCaches<T>.Store(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref BasicQueue<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(BasicQueue<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
while (value.TryDequeue(out T result))
|
||||
ResettableObjectCaches<T>.Store(result);
|
||||
|
||||
value.Clear();
|
||||
CollectionCaches<T>.Store(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches objects of a single generic.
|
||||
/// </summary>
|
||||
public static class ResettableObjectCaches<T> where T : IResettable, new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves an instance of T.
|
||||
/// </summary>
|
||||
public static T Retrieve()
|
||||
{
|
||||
T result = ObjectCaches<T>.Retrieve();
|
||||
result.InitializeState();
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores an instance of T and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref T value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores an instance of T.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(T value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.ResetState();
|
||||
ObjectCaches<T>.Store(value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region NonResettable caches.
|
||||
/// <summary>
|
||||
/// Caches collections of multiple generics.
|
||||
/// </summary>
|
||||
public static class CollectionCaches<T1, T2>
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache for dictionaries.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<Dictionary<T1, T2>> _dictionaryCache = new();
|
||||
/// <summary>
|
||||
/// Maximum number of entries allowed for the cache.
|
||||
/// </summary>
|
||||
private const int MAXIMUM_CACHE_COUNT = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Dictionary<T1, T2> RetrieveDictionary()
|
||||
{
|
||||
Dictionary<T1, T2> result;
|
||||
if (!_dictionaryCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref Dictionary<T1, T2> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(Dictionary<T1, T2> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.Clear();
|
||||
if (_dictionaryCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_dictionaryCache.Push(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches collections of a single generic.
|
||||
/// </summary>
|
||||
public static partial class CollectionCaches<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Cache for arrays.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<T[]> _arrayCache;
|
||||
/// <summary>
|
||||
/// Cache for lists.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<List<T>> _listCache;
|
||||
/// <summary>
|
||||
/// Cache for sortedset.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<SortedSet<T>> _sortedSetCache;
|
||||
/// <summary>
|
||||
/// Cache for queues.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<Queue<T>> _queueCache;
|
||||
/// <summary>
|
||||
/// Cache for queues.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<BasicQueue<T>> _basicQueueCache;
|
||||
/// <summary>
|
||||
/// Cache for hashset.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<HashSet<T>> _hashSetCache;
|
||||
/// <summary>
|
||||
/// Maximum number of entries allowed for the cache.
|
||||
/// </summary>
|
||||
private const int MAXIMUM_CACHE_COUNT = 50;
|
||||
|
||||
static CollectionCaches()
|
||||
{
|
||||
_arrayCache = new();
|
||||
_listCache = new();
|
||||
_sortedSetCache = new();
|
||||
_queueCache = new();
|
||||
_basicQueueCache = new();
|
||||
_hashSetCache = new();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static T[] RetrieveArray()
|
||||
{
|
||||
T[] result;
|
||||
if (!_arrayCache.TryPop(out result))
|
||||
result = new T[0];
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<T> RetrieveList()
|
||||
{
|
||||
List<T> result;
|
||||
if (!_listCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static SortedSet<T> RetrieveSortedSet()
|
||||
{
|
||||
SortedSet<T> result;
|
||||
if (!_sortedSetCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Queue<T> RetrieveQueue()
|
||||
{
|
||||
Queue<T> result;
|
||||
if (!_queueCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static BasicQueue<T> RetrieveBasicQueue()
|
||||
{
|
||||
BasicQueue<T> result;
|
||||
if (!_basicQueueCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection adding one entry.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static Queue<T> RetrieveQueue(T entry)
|
||||
{
|
||||
Queue<T> result;
|
||||
if (!_queueCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
result.Enqueue(entry);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection adding one entry.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static List<T> RetrieveList(T entry)
|
||||
{
|
||||
List<T> result;
|
||||
if (!_listCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
result.Add(entry);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a HashSet<T>.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static HashSet<T> RetrieveHashSet()
|
||||
{
|
||||
HashSet<T> result;
|
||||
if (!_hashSetCache.TryPop(out result))
|
||||
result = new();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves a collection adding one entry.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static HashSet<T> RetrieveHashSet(T entry)
|
||||
{
|
||||
HashSet<T> result;
|
||||
if (!_hashSetCache.TryPop(out result))
|
||||
return new();
|
||||
|
||||
result.Add(entry);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
/// <param name = "count">Number of entries in the array set default, from the beginning.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref T[] value, int count)
|
||||
{
|
||||
Store(value, count);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
/// <param name = "count">Number of entries in the array from the beginning.</param>
|
||||
public static void Store(T[] value, int count)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
value[i] = default;
|
||||
|
||||
if (_arrayCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_arrayCache.Push(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref List<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(List<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.Clear();
|
||||
|
||||
if (_listCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_listCache.Push(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref SortedSet<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(SortedSet<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.Clear();
|
||||
|
||||
if (_sortedSetCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_sortedSetCache.Push(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref Queue<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(Queue<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.Clear();
|
||||
|
||||
if (_queueCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_queueCache.Push(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref BasicQueue<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(BasicQueue<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.Clear();
|
||||
|
||||
if (_basicQueueCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_basicQueueCache.Push(value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref HashSet<T> value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a collection.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
public static void Store(HashSet<T> value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
value.Clear();
|
||||
|
||||
if (_hashSetCache.Count < MAXIMUM_CACHE_COUNT)
|
||||
_hashSetCache.Push(value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Caches objects of a single generic.
|
||||
/// </summary>
|
||||
public static class ObjectCaches<T> where T : new()
|
||||
{
|
||||
/// <summary>
|
||||
/// Stack to use.
|
||||
/// </summary>
|
||||
private static readonly ConcurrentStack<T> _stack = new();
|
||||
/// <summary>
|
||||
/// Maximum number of entries allowed for the cache.
|
||||
/// </summary>
|
||||
private const int MAXIMUM_CACHE_COUNT = 50;
|
||||
|
||||
/// <summary>
|
||||
/// Returns a value from the stack or creates an instance when the stack is empty.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static T Retrieve()
|
||||
{
|
||||
T result;
|
||||
if (!_stack.TryPop(out result))
|
||||
result = new(); // Activator.CreateInstance<T>();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores an instance of T and sets the original reference to default.
|
||||
/// Method will not execute if value is null.
|
||||
/// </summary>
|
||||
/// <param name = "value">Value to store.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void StoreAndDefault(ref T value)
|
||||
{
|
||||
Store(value);
|
||||
value = default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stores a value to the stack.
|
||||
/// </summary>
|
||||
/// <param name = "value"></param>
|
||||
public static void Store(T value)
|
||||
{
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
if (_stack.Count < MAXIMUM_CACHE_COUNT)
|
||||
_stack.Push(value);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 3cb13274f7491a941b6e89a767905f56
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/ObjectCaching.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,341 @@
|
||||
// /* This implementation uses better naming as well provides
|
||||
// * a few new features.
|
||||
// *
|
||||
// * Object and Collection caches are now one class. */
|
||||
//
|
||||
// // TODO In V5 disappear ResettableRingBuffer and have regular check implementation on start -- this will let us use this class for caching ringbuffer with resettable types.
|
||||
// using System;
|
||||
// using System.Collections;
|
||||
// using System.Collections.Generic;
|
||||
// using System.Runtime.CompilerServices;
|
||||
//
|
||||
// namespace GameKit.Dependencies.Utilities
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// Implement to use type with Caches.
|
||||
// /// </summary>
|
||||
// public interface IResettable
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// Resets values when being placed in a cache.
|
||||
// /// </summary>
|
||||
// void ResetState();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Initializes values after being retrieved from a cache.
|
||||
// /// </summary>
|
||||
// void InitializeState();
|
||||
// }
|
||||
//
|
||||
// public static class ResettableObjectPool<T> where T : IResettable, new() { }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Caches collections and objects of T.
|
||||
// /// </summary>
|
||||
// public static class ObjectPool<T> where T : new()
|
||||
// {
|
||||
// /// <summary>
|
||||
// /// Cache for List<T>.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<List<T>> _listCache = new();
|
||||
// /// <summary>
|
||||
// /// Resettable cache for List<T>.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<List<T>> _resettableListCache = new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Cache for HashSet<T>.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<HashSet<T>> _hashSetCache = new();
|
||||
// /// <summary>
|
||||
// /// Resettable cache for HashSet<T>.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<HashSet<T>> _resettableHashSetCache = new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Cache for Queue<T>.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<Queue<T>> _queueCache = new();
|
||||
// /// <summary>
|
||||
// /// Resettable cache for Queue<T>.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<Queue<T>> _resettableQueueCache = new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Cache for T[].
|
||||
// /// </summary>
|
||||
// private static readonly Stack<T[]> _arrayCache = new();
|
||||
// /// <summary>
|
||||
// /// Resettable cache for T[].
|
||||
// /// </summary>
|
||||
// private static readonly Stack<T[]> _resettableArrayCache = new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Cache for T.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<T> _tCache = new();
|
||||
// /// <summary>
|
||||
// /// Resettable cache for T.
|
||||
// /// </summary>
|
||||
// private static readonly Stack<T> _resettableTCache = new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// True if T is a value type.
|
||||
// /// </summary>
|
||||
// private static readonly bool _isValueType;
|
||||
// /// <summary>
|
||||
// /// True if T implements IResettable.
|
||||
// /// </summary>
|
||||
// private static readonly bool _isResettable;
|
||||
//
|
||||
// static ObjectPool()
|
||||
// {
|
||||
// // Used at runtime to prevent nested collections.
|
||||
// bool isTCollection = typeof(ICollection).IsAssignableFrom(typeof(T));
|
||||
//
|
||||
// if (isTCollection)
|
||||
// throw new NotSupportedException($"ObjectPool element cannot be a collection. Type is [{typeof(T).FullName}].");
|
||||
//
|
||||
// _isValueType = typeof(T).IsValueType;
|
||||
// _isResettable = typeof(T).IsAssignableFrom(typeof(IResettable));
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Clears all pools for T.
|
||||
// /// </summary>
|
||||
// public static void ClearPools()
|
||||
// {
|
||||
// _listCache.Clear();
|
||||
// _resettableListCache.Clear();
|
||||
//
|
||||
// _hashSetCache.Clear();
|
||||
// _resettableHashSetCache.Clear();
|
||||
//
|
||||
// _queueCache.Clear();
|
||||
// _resettableQueueCache.Clear();
|
||||
//
|
||||
// _arrayCache.Clear();
|
||||
// _resettableArrayCache.Clear();
|
||||
//
|
||||
// _tCache.Clear();
|
||||
// _resettableTCache.Clear();
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Returns a List<T> automatically resetting entries when IResettable is implemented,
|
||||
// /// and pooling entries when they are a reference type.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static void Return(List<T> value)
|
||||
// {
|
||||
// if (value == null) return;
|
||||
//
|
||||
// Stack<List<T>> stack = _isResettable ? _resettableListCache : _listCache;
|
||||
//
|
||||
// IterateICollectionElements(value);
|
||||
//
|
||||
// value.Clear();
|
||||
// stack.Push(value);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Returns a HashSet<T> automatically resetting entries when IResettable is implemented,
|
||||
// /// and pooling entries when they are a reference type.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static void Return(HashSet<T> value)
|
||||
// {
|
||||
// if (value == null) return;
|
||||
//
|
||||
// Stack<HashSet<T>> stack = _isResettable ? _resettableHashSetCache : _hashSetCache;
|
||||
//
|
||||
// IterateICollectionElements(value);
|
||||
//
|
||||
// value.Clear();
|
||||
// stack.Push(value);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Returns a Queue<T> automatically resetting entries when IResettable is implemented,
|
||||
// /// and pooling entries when they are a reference type.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static void Return(Queue<T> value)
|
||||
// {
|
||||
// if (value == null) return;
|
||||
//
|
||||
// Stack<Queue<T>> stack = _isResettable ? _resettableQueueCache : _queueCache;
|
||||
//
|
||||
// IterateICollectionElements(value);
|
||||
//
|
||||
// value.Clear();
|
||||
// stack.Push(value);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Returns an array automatically resetting entries when IResettable is implemented,
|
||||
// /// and pools each array entry if the array element is a reference type.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static void Return(T[] value)
|
||||
// {
|
||||
// if (value == null) return;
|
||||
//
|
||||
// Stack<T[]> stack = _isResettable ? _resettableArrayCache : _arrayCache;
|
||||
//
|
||||
// IterateICollectionElements(value);
|
||||
//
|
||||
// Array.Clear(value, 0, value.Length);
|
||||
// stack.Push(value);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Returns value without resetting the state.
|
||||
// /// </summary>
|
||||
// public static void Return(T value)
|
||||
// {
|
||||
// _tCache.Push(value);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Creates a new List<T>.
|
||||
// /// </summary>
|
||||
// private static List<T> CreateList() => new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Creates a new HashSet<T>.
|
||||
// /// </summary>
|
||||
// private static HashSet<T> CreateHashSet() => new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Creates a new Queue<T>.
|
||||
// /// </summary>
|
||||
// private static Queue<T> CreateQueue() => new();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Creates a new array of length 0 (empty array).
|
||||
// /// </summary>
|
||||
// private static T[] CreateArray() => Array.Empty<T>();
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Rents a List<T>.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static List<T> RentList()
|
||||
// {
|
||||
// Stack<List<T>> stack = _isResettable ? _resettableListCache : _listCache;
|
||||
//
|
||||
// return RentCollection(stack, CreateList);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Rents a HashSet<T>.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static HashSet<T> RentHashSet()
|
||||
// {
|
||||
// Stack<HashSet<T>> stack = _isResettable ? _resettableHashSetCache : _hashSetCache;
|
||||
//
|
||||
// return RentCollection(stack, CreateHashSet);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Rents a Queue<T>.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static Queue<T> RentQueue()
|
||||
// {
|
||||
// Stack<Queue<T>> stack = _isResettable ? _resettableQueueCache : _queueCache;
|
||||
//
|
||||
// return RentCollection(stack, CreateQueue);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Rents an array.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// public static T[] RentArray()
|
||||
// {
|
||||
// Stack<T[]> stack = _isResettable ? _resettableArrayCache : _arrayCache;
|
||||
//
|
||||
// return RentCollection(stack, CreateArray);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Rents an object.
|
||||
// /// </summary>
|
||||
// public static T Rent()
|
||||
// {
|
||||
// Stack<T> stack = _isResettable ? _resettableTCache : _tCache;
|
||||
//
|
||||
// if (!stack.TryPop(out T result))
|
||||
// result = new();
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Rents a collection using the supplied stack. Returns using defaultFactory if stack is empty.
|
||||
// /// </summary>
|
||||
// private static TCollection RentCollection<TCollection>(Stack<TCollection> stack, Func<TCollection> defaultFactory)
|
||||
// {
|
||||
// if (!stack.TryPop(out TCollection result))
|
||||
// result = defaultFactory();
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Iterates ICollection elements, returning and resetting as needed.
|
||||
// /// </summary>
|
||||
// [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
// private static void IterateICollectionElements(IReadOnlyCollection<T> value)
|
||||
// {
|
||||
// // Reset T if possible.
|
||||
// if (_isResettable)
|
||||
// {
|
||||
// // Value type.
|
||||
// if (_isValueType)
|
||||
// {
|
||||
// foreach (T item in value)
|
||||
// ((IResettable)item).ResetState();
|
||||
// }
|
||||
// // Reference type.
|
||||
// else
|
||||
// {
|
||||
// foreach (T item in value)
|
||||
// ReturnReferenceIResettable(item);
|
||||
// }
|
||||
// }
|
||||
// // Type is not resettable.
|
||||
// else
|
||||
// {
|
||||
// // Only need to Return if is not a value type.
|
||||
// if (!_isValueType)
|
||||
// {
|
||||
// foreach (T item in value)
|
||||
// ReturnReference(item);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Returns value expecting it to be a reference type that does not implement IResettable.
|
||||
// /// </summary>
|
||||
// private static void ReturnReference(T value)
|
||||
// {
|
||||
// _resettableTCache.Push(value);
|
||||
// }
|
||||
//
|
||||
// /// <summary>
|
||||
// /// Returns value expecting it to be a reference type which implement IResettable.
|
||||
// /// </summary>
|
||||
// internal static void ReturnReferenceIResettable(T value)
|
||||
// {
|
||||
// ((IResettable)value).ResetState();
|
||||
//
|
||||
// _resettableTCache.Push(value);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6065d663177eb614bb52a41071982835
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/ObjectPool.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,63 @@
|
||||
using GameKit.Dependencies.Utilities.Types;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Objects
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns if an object has been destroyed from memory.
|
||||
/// </summary>
|
||||
/// <param name = "gameObject"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsDestroyed(this GameObject gameObject)
|
||||
{
|
||||
// UnityEngine overloads the == operator for the GameObject type
|
||||
// and returns null when the object has been destroyed, but
|
||||
// actually the object is still there but has not been cleaned up yet
|
||||
// if we test both we can determine if the object has been destroyed.
|
||||
return gameObject == null && !ReferenceEquals(gameObject, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds all objects in the scene of type. This method is very expensive.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "requireSceneLoaded">True if the scene must be fully loaded before trying to seek objects.</param>
|
||||
/// <returns></returns>
|
||||
public static List<T> FindAllObjectsOfType<T>(bool activeSceneOnly = true, bool requireSceneLoaded = false, bool includeDDOL = true, bool includeInactive = true)
|
||||
{
|
||||
List<T> results = new();
|
||||
for (int i = 0; i < SceneManager.sceneCount; i++)
|
||||
{
|
||||
Scene scene = SceneManager.GetSceneAt(i);
|
||||
// If to include only current scene.
|
||||
if (activeSceneOnly)
|
||||
{
|
||||
if (SceneManager.GetActiveScene() != scene)
|
||||
continue;
|
||||
}
|
||||
// If the scene must be fully loaded to seek objects within.
|
||||
if (!scene.isLoaded && requireSceneLoaded)
|
||||
continue;
|
||||
|
||||
GameObject[] allGameObjects = scene.GetRootGameObjects();
|
||||
for (int j = 0; j < allGameObjects.Length; j++)
|
||||
{
|
||||
results.AddRange(allGameObjects[j].GetComponentsInChildren<T>(includeInactive));
|
||||
}
|
||||
}
|
||||
|
||||
// If to also include DDOL.
|
||||
if (includeDDOL)
|
||||
{
|
||||
GameObject ddolGo = DDOL.GetDDOL().gameObject;
|
||||
results.AddRange(ddolGo.GetComponentsInChildren<T>(includeInactive));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4fa6d28a28dbf6b4295602abad3de328
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Objects.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,106 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Particles
|
||||
{
|
||||
/// <summary>
|
||||
/// Issues stop on the specified particle systems.
|
||||
/// </summary>
|
||||
/// <param name = "systems"></param>
|
||||
public static float StopParticleSystem(ParticleSystem[] systems, bool stopLoopingOnly)
|
||||
{
|
||||
return StopParticleSystem(systems, stopLoopingOnly, ParticleSystemStopBehavior.StopEmitting);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issues stop on the specified particle systems while returning the time required to play out.
|
||||
/// </summary>
|
||||
/// <param name = "systems"></param>
|
||||
public static float StopParticleSystem(ParticleSystem[] systems, ParticleSystemStopBehavior stopBehavior = ParticleSystemStopBehavior.StopEmitting)
|
||||
{
|
||||
return StopParticleSystem(systems, false, stopBehavior);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issues stop on the specified particle systems while returning the time required to play out.
|
||||
/// </summary>
|
||||
/// <param name = "systems"></param>
|
||||
public static float StopParticleSystem(ParticleSystem[] systems, bool stopLoopingOnly, ParticleSystemStopBehavior stopBehavior = ParticleSystemStopBehavior.StopEmitting)
|
||||
{
|
||||
if (systems == null)
|
||||
return 0f;
|
||||
|
||||
float playOutDuration = 0f;
|
||||
for (int i = 0; i < systems.Length; i++)
|
||||
playOutDuration = Mathf.Max(playOutDuration, StopParticleSystem(systems[i], stopLoopingOnly, stopBehavior));
|
||||
|
||||
return playOutDuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issues stop on the specified particle systems.
|
||||
/// </summary>
|
||||
/// <param name = "systems"></param>
|
||||
public static float StopParticleSystem(ParticleSystem system, bool stopLoopingOnly, bool stopChildren = false)
|
||||
{
|
||||
return StopParticleSystem(system, stopLoopingOnly, ParticleSystemStopBehavior.StopEmitting, stopChildren);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issues stop on the specified particle systems while returning the time required to play out.
|
||||
/// </summary>
|
||||
/// <param name = "systems"></param>
|
||||
public static float StopParticleSystem(ParticleSystem system, ParticleSystemStopBehavior stopBehavior = ParticleSystemStopBehavior.StopEmitting, bool stopChildren = false)
|
||||
{
|
||||
return StopParticleSystem(system, false, stopBehavior, stopChildren);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Issues stop on the specified particle system while returning the time required to play out.
|
||||
/// </summary>
|
||||
public static float StopParticleSystem(ParticleSystem system, bool stopLoopingOnly, ParticleSystemStopBehavior stopBehavior = ParticleSystemStopBehavior.StopEmitting, bool stopChildren = false)
|
||||
{
|
||||
if (system == null)
|
||||
return 0f;
|
||||
if (stopChildren)
|
||||
{
|
||||
ParticleSystem[] all = system.GetComponentsInChildren<ParticleSystem>();
|
||||
StopParticleSystem(all, stopLoopingOnly, stopBehavior);
|
||||
}
|
||||
|
||||
float playOutDuration = 0f;
|
||||
float timeLeft = system.main.duration - system.time;
|
||||
playOutDuration = Mathf.Max(playOutDuration, timeLeft);
|
||||
|
||||
if (stopLoopingOnly)
|
||||
{
|
||||
if (system.main.loop)
|
||||
system.Stop(false, stopBehavior);
|
||||
}
|
||||
else
|
||||
{
|
||||
system.Stop(false, stopBehavior);
|
||||
}
|
||||
|
||||
return playOutDuration;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the longest time required for all systems to stop.
|
||||
/// </summary>
|
||||
/// <param name = "systems"></param>
|
||||
/// <returns></returns>
|
||||
public static float ReturnLongestCycle(ParticleSystem[] systems)
|
||||
{
|
||||
float longestPlayTime = 0f;
|
||||
for (int i = 0; i < systems.Length; i++)
|
||||
{
|
||||
float timeLeft = systems[i].main.duration - systems[i].time;
|
||||
longestPlayTime = Mathf.Max(longestPlayTime, timeLeft);
|
||||
}
|
||||
|
||||
return longestPlayTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5f3d973dcfa06554998575e8eef0938a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Particles.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,62 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Quaternions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns how fast an object must rotate over duration to reach goal.
|
||||
/// </summary>
|
||||
/// <param name = "goal">Quaternion to measure distance against.</param>
|
||||
/// <param name = "duration">How long it should take to move to goal.</param>
|
||||
/// <param name = "interval">A multiplier applied towards interval. Typically this is used for ticks passed.</param>
|
||||
/// <returns></returns>
|
||||
public static float GetRate(this Quaternion a, Quaternion goal, float duration, out float angle, uint interval = 1, float tolerance = 0f)
|
||||
{
|
||||
angle = a.Angle(goal, true);
|
||||
return angle / (duration * interval);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subtracts b quaternion from a.
|
||||
/// </summary>
|
||||
public static Quaternion Subtract(this Quaternion a, Quaternion b) => Quaternion.Inverse(b) * a;
|
||||
|
||||
/// <summary>
|
||||
/// Adds quaternion b onto quaternion a.
|
||||
/// </summary>
|
||||
public static Quaternion Add(this Quaternion a, Quaternion b) => a * b;
|
||||
|
||||
/// <summary>
|
||||
/// Returns if two quaternions match.
|
||||
/// </summary>
|
||||
/// <param name = "precise">True to use a custom implementation with no error tolerance. False to use Unity's implementation which may return a match even when not true due to error tolerance.</param>
|
||||
/// <returns></returns>
|
||||
public static bool Matches(this Quaternion a, Quaternion b, bool precise = false)
|
||||
{
|
||||
if (precise)
|
||||
return a.w == b.w && a.x == b.x && a.y == b.y && a.z == b.z;
|
||||
else
|
||||
return a == b;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the angle between two quaterions.
|
||||
/// </summary>
|
||||
/// <param name = "precise">True to use a custom implementation with no error tolerance. False to use Unity's implementation which may return 0f due to error tolerance, even while there is a difference.</param>
|
||||
/// <returns></returns>
|
||||
public static float Angle(this Quaternion a, Quaternion b, bool precise = false)
|
||||
{
|
||||
if (precise)
|
||||
{
|
||||
// This is run Unitys implementation without the error tolerance.
|
||||
float dot = a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w;
|
||||
return Mathf.Acos(Mathf.Min(Mathf.Abs(dot), 1f)) * 2f * 57.29578f;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Quaternion.Angle(a, b);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 02a9084f4f788cd4293cdff56a49b5dd
|
||||
timeCreated: 1522043602
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Quaternions.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,120 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Strings
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to encode and decode strings.
|
||||
/// </summary>
|
||||
private static readonly UTF8Encoding _encoding = new(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true);
|
||||
/// <summary>
|
||||
/// A buffer convert data and discard.
|
||||
/// </summary>
|
||||
public static byte[] Buffer = new byte[1024];
|
||||
|
||||
/// <summary>
|
||||
/// Converts a member string text to PascalCase
|
||||
/// </summary>
|
||||
/// <remarks>A member string is expected to be in the format '_memberName'.</remarks>
|
||||
public static string MemberToPascalCase(this string txt)
|
||||
{
|
||||
if (txt.Length < 2)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Text '{txt}' is too short.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (txt[0] != '_')
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Text '{txt}' has the incorrect member prefix.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string firstLeter = txt[1].ToString().ToUpper();
|
||||
|
||||
string substring = txt.Length > 2 ? txt.Substring(2) : string.Empty;
|
||||
return $"{firstLeter}{substring}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a pascal case string to member case.
|
||||
/// </summary>
|
||||
/// <remarks>A PascalCase string is expected to be in the format 'PropertyName'.</remarks>
|
||||
public static string PascalCaseToMember(this string txt)
|
||||
{
|
||||
if (txt.Length < 1)
|
||||
{
|
||||
UnityEngine.Debug.LogError($"Text '{txt}' is too short.");
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
string firstLeter = txt[0].ToString().ToLower();
|
||||
|
||||
string subString = txt.Length > 1 ? txt.Substring(1) : string.Empty;
|
||||
return $"_{firstLeter}{subString}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attachs or detaches an suffix to a string.
|
||||
/// </summary>
|
||||
/// <param name = "text"></param>
|
||||
/// <param name = "suffix"></param>
|
||||
/// <param name = "addExtension"></param>
|
||||
public static string ReturnModifySuffix(string text, string suffix, bool addExtension)
|
||||
{
|
||||
/* Since saving to a json, add the .json extension if not present.
|
||||
* Length must be greater than 6 to contain a character and .json. */
|
||||
if (text.Length > suffix.Length + 1)
|
||||
{
|
||||
// If to add the extension.
|
||||
if (addExtension)
|
||||
{
|
||||
// If doesn't contain the extension then add it on.
|
||||
if (!text.Substring(text.Length - suffix.Length).Contains(suffix, StringComparison.CurrentCultureIgnoreCase))
|
||||
return text + suffix;
|
||||
// Already contains extension.
|
||||
else
|
||||
return text;
|
||||
}
|
||||
// Remove extension.
|
||||
else
|
||||
{
|
||||
// If contains extension.
|
||||
if (text.Substring(text.Length - suffix.Length).Contains(suffix, StringComparison.CurrentCultureIgnoreCase))
|
||||
return text.Substring(0, text.Length - suffix.Length);
|
||||
// Doesn't contain extension.
|
||||
return text;
|
||||
}
|
||||
}
|
||||
// Text isn't long enough to manipulate.
|
||||
else
|
||||
{
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string into a byte array buffer.
|
||||
/// </summary>
|
||||
/// <returns>Number of bytes written to the buffer.</returns>
|
||||
public static int ToBytes(this string value, ref byte[] buffer)
|
||||
{
|
||||
int strLength = value.Length;
|
||||
// Number of minimum bytes the buffer must be.
|
||||
int bytesNeeded = _encoding.GetMaxByteCount(strLength);
|
||||
|
||||
// Grow string buffer if needed.
|
||||
if (buffer.Length < bytesNeeded)
|
||||
Array.Resize(ref buffer, bytesNeeded * 2);
|
||||
|
||||
return _encoding.GetBytes(value, 0, strLength, buffer, 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a string to bytes while allocating.
|
||||
/// </summary>
|
||||
public static byte[] ToBytesAllocated(this string value) => Encoding.Unicode.GetBytes(value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b396f2be4de550a4e92b552650311600
|
||||
timeCreated: 1525378031
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Strings.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,195 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
public static class Transforms
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the sizeDelta halfed.
|
||||
/// </summary>
|
||||
/// <param name = "considerScale">True to multiple values by RectTransform scale.</param>
|
||||
public static Vector2 HalfSizeDelta(this RectTransform rectTransform, bool useScale = false)
|
||||
{
|
||||
Vector2 sizeDelta = useScale ? rectTransform.SizeDeltaScaled() : rectTransform.sizeDelta;
|
||||
return sizeDelta / 2f;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the sizeDelta multiplied by scale.
|
||||
/// </summary>
|
||||
public static Vector2 SizeDeltaScaled(this RectTransform rectTransform)
|
||||
{
|
||||
return rectTransform.sizeDelta * rectTransform.localScale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a position for the rectTransform ensuring it's fully on the screen.
|
||||
/// </summary>
|
||||
/// <param name = "desiredPosition">Preferred position for the rectTransform.</param>
|
||||
/// <param name = "padding">How much padding the transform must be from the screen edges.</param>
|
||||
public static Vector3 GetOnScreenPosition(this RectTransform rectTransform, Vector3 desiredPosition, Vector2 padding)
|
||||
{
|
||||
RectTransform canvasRectTransform = rectTransform.GetComponentInParent<Canvas>().transform as RectTransform;
|
||||
Vector2 clampedPos = desiredPosition;
|
||||
Vector2 localScale = canvasRectTransform.localScale;
|
||||
Vector2 oneMinusPivot = Vector2.one - rectTransform.pivot;
|
||||
|
||||
// The size has to be scaled to account for the size and scale of the Canvas it is childed to
|
||||
Vector2 scaledSize = rectTransform.sizeDelta * localScale;
|
||||
|
||||
// Calculate the minimum and maximum bounds of the canvas our object can occupy
|
||||
Vector2 minClamp = scaledSize * rectTransform.pivot + padding;
|
||||
Vector2 maxClamp = (canvasRectTransform.rect.size - (rectTransform.sizeDelta * oneMinusPivot + padding)) * localScale;
|
||||
|
||||
float clampX = Mathf.Clamp(clampedPos.x, minClamp.x, maxClamp.x);
|
||||
float clampY = Mathf.Clamp(clampedPos.y, minClamp.y, maxClamp.y);
|
||||
|
||||
return new Vector2(clampX, clampY);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a parent for src while maintaining position, rotation, and scale of src.
|
||||
/// </summary>
|
||||
/// <param name = "parent">Transform to become a child of.</param>
|
||||
public static void SetParentAndKeepTransform(this Transform src, Transform parent)
|
||||
{
|
||||
Vector3 pos = src.position;
|
||||
Quaternion rot = src.rotation;
|
||||
Vector3 scale = src.localScale;
|
||||
|
||||
src.SetParent(parent);
|
||||
src.position = pos;
|
||||
src.rotation = rot;
|
||||
src.localScale = scale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all children under the specified transform.
|
||||
/// </summary>
|
||||
public static void DestroyChildren(this Transform t, bool destroyImmediately = false)
|
||||
{
|
||||
// If destroying immediately then the iteration needs to occur only on the top-most children.
|
||||
if (destroyImmediately)
|
||||
{
|
||||
List<Transform> children = CollectionCaches<Transform>.RetrieveList();
|
||||
int childCount = t.childCount;
|
||||
|
||||
for (int i = 0; i < childCount; i++)
|
||||
children.Add(t.GetChild(i));
|
||||
|
||||
foreach (Transform child in children)
|
||||
Object.DestroyImmediate(child);
|
||||
|
||||
CollectionCaches<Transform>.Store(children);
|
||||
}
|
||||
// Iterate using Unitys enumerator.
|
||||
else
|
||||
{
|
||||
foreach (Transform child in t)
|
||||
Object.Destroy(child.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Destroys all children of a type under the specified transform.
|
||||
/// </summary>
|
||||
public static void DestroyChildren<T>(this Transform t, bool destroyImmediately = false) where T : MonoBehaviour
|
||||
{
|
||||
T[] children = t.GetComponentsInChildren<T>();
|
||||
foreach (T child in children)
|
||||
{
|
||||
if (destroyImmediately)
|
||||
MonoBehaviour.DestroyImmediate(child.gameObject);
|
||||
else
|
||||
Object.Destroy(child.gameObject);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets components in children and optionally parent.
|
||||
/// </summary>
|
||||
/// <typeparam name = "T"></typeparam>
|
||||
/// <param name = "results"></param>
|
||||
/// <param name = "parent"></param>
|
||||
/// <param name = "includeParent"></param>
|
||||
/// <param name = "includeInactive"></param>
|
||||
public static void GetComponentsInChildren<T>(this Transform parent, List<T> results, bool includeParent = true, bool includeInactive = false) where T : Component
|
||||
{
|
||||
if (!includeParent)
|
||||
{
|
||||
List<T> current = CollectionCaches<T>.RetrieveList();
|
||||
for (int i = 0; i < parent.childCount; i++)
|
||||
{
|
||||
parent.GetChild(i).GetComponentsInChildren(includeInactive, current);
|
||||
results.AddRange(current);
|
||||
}
|
||||
CollectionCaches<T>.Store(current);
|
||||
}
|
||||
else
|
||||
{
|
||||
parent.GetComponentsInChildren(includeInactive, results);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the position of this transform.
|
||||
/// </summary>
|
||||
public static Vector3 GetPosition(this Transform t, bool localSpace)
|
||||
{
|
||||
return localSpace ? t.localPosition : t.position;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the rotation of this transform.
|
||||
/// </summary>
|
||||
public static Quaternion GetRotation(this Transform t, bool localSpace)
|
||||
{
|
||||
return localSpace ? t.localRotation : t.rotation;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the scale of this transform.
|
||||
/// </summary>
|
||||
public static Vector3 GetScale(this Transform t)
|
||||
{
|
||||
return t.localScale;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position of this transform.
|
||||
/// </summary>
|
||||
/// <param name = "t"></param>
|
||||
/// <param name = "localSpace"></param>
|
||||
public static void SetPosition(this Transform t, bool localSpace, Vector3 pos)
|
||||
{
|
||||
if (localSpace)
|
||||
t.localPosition = pos;
|
||||
else
|
||||
t.position = pos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position of this transform.
|
||||
/// </summary>
|
||||
/// <param name = "t"></param>
|
||||
/// <param name = "localSpace"></param>
|
||||
public static void SetRotation(this Transform t, bool localSpace, Quaternion rot)
|
||||
{
|
||||
if (localSpace)
|
||||
t.localRotation = rot;
|
||||
else
|
||||
t.rotation = rot;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the position of this transform.
|
||||
/// </summary>
|
||||
/// <param name = "t"></param>
|
||||
/// <param name = "localSpace"></param>
|
||||
public static void SetScale(this Transform t, Vector3 scale)
|
||||
{
|
||||
t.localScale = scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ba23540de73f58b458e7d7a200f3bb30
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Transforms.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a29cd7621a70a044bb205cc8cfd96b3c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,242 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities
|
||||
{
|
||||
/// <summary>
|
||||
/// Unity 2022 has a bug where codegen will not compile when referencing a Queue type,
|
||||
/// while also targeting .Net as the framework API.
|
||||
/// As a work around this class is used for queues instead.
|
||||
/// </summary>
|
||||
public class BasicQueue<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Maximum size of the collection.
|
||||
/// </summary>
|
||||
public int Capacity => Collection.Length;
|
||||
/// <summary>
|
||||
/// Number of elements in the queue.
|
||||
/// </summary>
|
||||
public int Count => _written;
|
||||
/// <summary>
|
||||
/// Collection containing data.
|
||||
/// </summary>
|
||||
private T[] Collection = new T[4];
|
||||
/// <summary>
|
||||
/// Current write index of the collection.
|
||||
/// </summary>
|
||||
public int WriteIndex { get; private set; }
|
||||
/// <summary>
|
||||
/// Buffer for resizing.
|
||||
/// </summary>
|
||||
private T[] _resizeBuffer = new T[0];
|
||||
/// <summary>
|
||||
/// Read position of the next Dequeue.
|
||||
/// </summary>
|
||||
private int _read;
|
||||
/// <summary>
|
||||
/// Length of the queue.
|
||||
/// </summary>
|
||||
private int _written;
|
||||
|
||||
/// <summary>
|
||||
/// Enqueues an entry.
|
||||
/// </summary>
|
||||
/// <param name = "data"></param>
|
||||
public void Enqueue(T data)
|
||||
{
|
||||
if (_written == Collection.Length)
|
||||
Resize();
|
||||
|
||||
if (WriteIndex >= Collection.Length)
|
||||
WriteIndex = 0;
|
||||
Collection[WriteIndex] = data;
|
||||
|
||||
WriteIndex++;
|
||||
_written++;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to dequeue the next entry.
|
||||
/// </summary>
|
||||
/// <param name = "result">Dequeued entry.</param>
|
||||
/// <param name = "defaultArrayEntry">True to set the array entry as default.</param>
|
||||
/// <returns>True if an entry existed to dequeue.</returns>
|
||||
public bool TryDequeue(out T result, bool defaultArrayEntry = true)
|
||||
{
|
||||
if (_written == 0)
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
result = Dequeue(defaultArrayEntry);
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dequeues the next entry.
|
||||
/// </summary>
|
||||
/// <param name = "defaultArrayEntry">True to set the array entry as default.</param>
|
||||
public T Dequeue(bool defaultArrayEntry = true)
|
||||
{
|
||||
if (_written == 0)
|
||||
return default;
|
||||
|
||||
T result = Collection[_read];
|
||||
if (defaultArrayEntry)
|
||||
Collection[_read] = default;
|
||||
|
||||
_written--;
|
||||
_read++;
|
||||
if (_read >= Collection.Length)
|
||||
_read = 0;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to peek the next entry.
|
||||
/// </summary>
|
||||
/// <param name = "result">Peeked entry.</param>
|
||||
/// <returns>True if an entry existed to peek.</returns>
|
||||
public bool TryPeek(out T result)
|
||||
{
|
||||
if (_written == 0)
|
||||
{
|
||||
result = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
result = Peek();
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Peeks the next queue entry.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public T Peek()
|
||||
{
|
||||
if (_written == 0)
|
||||
throw new($"Queue of type {typeof(T).Name} is empty.");
|
||||
|
||||
return Collection[_read];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns an entry at index or default if index is invalid.
|
||||
/// </summary>
|
||||
public T GetIndexOrDefault(int simulatedIndex)
|
||||
{
|
||||
int offset = GetRealIndex(simulatedIndex, allowUnusedBuffer: false, log: false);
|
||||
if (offset != -1 && offset < Collection.Length)
|
||||
return Collection[offset];
|
||||
|
||||
return default;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the queue.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_read = 0;
|
||||
WriteIndex = 0;
|
||||
_written = 0;
|
||||
|
||||
DefaultCollection(Collection);
|
||||
DefaultCollection(_resizeBuffer);
|
||||
|
||||
void DefaultCollection(T[] array)
|
||||
{
|
||||
int count = array.Length;
|
||||
for (int i = 0; i < count; i++)
|
||||
array[i] = default;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Doubles the queue size.
|
||||
/// </summary>
|
||||
private void Resize()
|
||||
{
|
||||
int length = _written;
|
||||
int doubleLength = length * 2;
|
||||
int read = _read;
|
||||
|
||||
/* Make sure copy array is the same size as current
|
||||
* and copy contents into it. */
|
||||
// Ensure large enough to fit contents.
|
||||
T[] resizeBuffer = _resizeBuffer;
|
||||
if (resizeBuffer.Length < doubleLength)
|
||||
Array.Resize(ref resizeBuffer, doubleLength);
|
||||
// Copy from the read of queue first.
|
||||
int copyLength = length - read;
|
||||
Array.Copy(Collection, read, resizeBuffer, 0, copyLength);
|
||||
/* If read index was higher than 0
|
||||
* then copy remaining data as well from 0. */
|
||||
if (read > 0)
|
||||
Array.Copy(Collection, 0, resizeBuffer, copyLength, read);
|
||||
|
||||
// Set _array to resize.
|
||||
Collection = resizeBuffer;
|
||||
// Reset positions.
|
||||
_read = 0;
|
||||
WriteIndex = length;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns value in actual index as it relates to simulated index.
|
||||
/// </summary>
|
||||
/// <param name = "simulatedIndex">Simulated index to return. A value of 0 would return the first simulated index in the collection.</param>
|
||||
/// <returns></returns>
|
||||
public T this[int simulatedIndex]
|
||||
{
|
||||
get
|
||||
{
|
||||
int offset = GetRealIndex(simulatedIndex);
|
||||
return Collection[offset];
|
||||
}
|
||||
set
|
||||
{
|
||||
int offset = GetRealIndex(simulatedIndex);
|
||||
Collection[offset] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the real index of the collection using a simulated index.
|
||||
/// </summary>
|
||||
/// <param name = "allowUnusedBuffer">True to allow an index be returned from an unused portion of the buffer so long as it is within bounds.</param>
|
||||
private int GetRealIndex(int simulatedIndex, bool allowUnusedBuffer = false, bool log = true)
|
||||
{
|
||||
if (simulatedIndex >= Capacity)
|
||||
{
|
||||
return ReturnError();
|
||||
}
|
||||
else
|
||||
{
|
||||
int written = _written;
|
||||
// May be out of bounds if allowUnusedBuffer is false.
|
||||
if (simulatedIndex >= written)
|
||||
{
|
||||
if (!allowUnusedBuffer)
|
||||
return ReturnError();
|
||||
}
|
||||
int offset = Capacity - written + simulatedIndex + WriteIndex;
|
||||
if (offset >= Capacity)
|
||||
offset -= Capacity;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
int ReturnError()
|
||||
{
|
||||
if (log)
|
||||
Debug.LogError($"Index {simulatedIndex} is out of range. Collection count is {_written}, Capacity is {Capacity}");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f966ec63b499e77438c185b2870595cd
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/BasicQueue.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,45 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types
|
||||
{
|
||||
[System.Serializable]
|
||||
public struct ByteRange
|
||||
{
|
||||
public ByteRange(byte minimum, byte maximum)
|
||||
{
|
||||
Minimum = minimum;
|
||||
Maximum = maximum;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Minimum range.
|
||||
/// </summary>
|
||||
public byte Minimum;
|
||||
/// <summary>
|
||||
/// Maximum range.
|
||||
/// </summary>
|
||||
public byte Maximum;
|
||||
|
||||
/// <summary>
|
||||
/// Returns an exclusive random value between Minimum and Maximum.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public byte RandomExclusive() => Bytes.RandomExclusiveRange(Minimum, Maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an inclusive random value between Minimum and Maximum.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public byte RandomInclusive() => Bytes.RandomInclusiveRange(Minimum, Maximum);
|
||||
|
||||
/// <summary>
|
||||
/// Clamps value between Minimum and Maximum.
|
||||
/// </summary>
|
||||
public byte Clamp(byte value) => Bytes.Clamp(value, Minimum, Maximum);
|
||||
|
||||
/// <summary>
|
||||
/// True if value is within range of Minimum and Maximum.
|
||||
/// </summary>
|
||||
public bool InRange(byte value) => value >= Minimum && value <= Maximum;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2756054f52fbd5d4cb1871b0dd6ff5b7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/ByteRange.cs
|
||||
uploadId: 866910
|
||||
+236
@@ -0,0 +1,236 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types
|
||||
{
|
||||
public class CanvasGroupFader : MonoBehaviour
|
||||
{
|
||||
#region Types.
|
||||
/// <summary>
|
||||
/// Current fade state or goal for this class.
|
||||
/// </summary>
|
||||
public enum FadeGoalType
|
||||
{
|
||||
Unset = 0,
|
||||
Hidden = 1,
|
||||
Visible = 2
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// Current goal for the fader.
|
||||
/// </summary>
|
||||
public FadeGoalType FadeGoal { get; private set; } = FadeGoalType.Unset;
|
||||
/// <summary>
|
||||
/// True if hidden or in the process of hiding.
|
||||
/// </summary>
|
||||
public bool IsHiding => FadeGoal == FadeGoalType.Hidden;
|
||||
/// <summary>
|
||||
/// True if visible. Will be true long as the CanvasGroup has alpha. Also see IsHiding.
|
||||
/// </summary>
|
||||
public bool IsVisible => CanvasGroup.alpha > 0f;
|
||||
#endregion
|
||||
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// CanvasGroup to fade in and out.
|
||||
/// </summary>
|
||||
[Tooltip("CanvasGroup to fade in and out.")]
|
||||
[SerializeField]
|
||||
[TabGroup("Components")]
|
||||
protected CanvasGroup CanvasGroup;
|
||||
/// <summary>
|
||||
/// True to update the CanvasGroup blocking settings when showing and hiding.
|
||||
/// </summary>
|
||||
[Tooltip("True to update the CanvasGroup blocking settings when showing and hiding.")]
|
||||
[SerializeField]
|
||||
[TabGroup("Effects")]
|
||||
protected bool UpdateCanvasBlocking = true;
|
||||
/// <summary>
|
||||
/// How long it should take to fade in the CanvasGroup.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[TabGroup("Effects")]
|
||||
protected float FadeInDuration = 0.1f;
|
||||
/// <summary>
|
||||
/// How long it should take to fade out the CanvasGroup.
|
||||
/// </summary>
|
||||
[SerializeField]
|
||||
[TabGroup("Effects")]
|
||||
protected float FadeOutDuration = 0.3f;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// True if a fade cycle has completed at least once.
|
||||
/// </summary>
|
||||
private bool _completedOnce;
|
||||
#endregion
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
FadeGoal = CanvasGroup.alpha > 0f ? FadeGoalType.Visible : FadeGoalType.Hidden;
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
if (FadeGoal == FadeGoalType.Visible)
|
||||
ShowImmediately();
|
||||
else
|
||||
HideImmediately();
|
||||
}
|
||||
|
||||
protected virtual void Update()
|
||||
{
|
||||
Fade();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows CanvasGroup immediately.
|
||||
/// </summary>
|
||||
public virtual void ShowImmediately()
|
||||
{
|
||||
SetFadeGoal(true);
|
||||
CompleteFade(true);
|
||||
OnShow();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hides CanvasGroup immediately.
|
||||
/// </summary>
|
||||
public virtual void HideImmediately()
|
||||
{
|
||||
SetFadeGoal(false);
|
||||
CompleteFade(false);
|
||||
OnHide();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows CanvasGroup with a fade.
|
||||
/// </summary>
|
||||
public virtual void Show()
|
||||
{
|
||||
if (FadeInDuration <= 0f)
|
||||
{
|
||||
ShowImmediately();
|
||||
}
|
||||
else
|
||||
{
|
||||
SetFadeGoal(true);
|
||||
OnShow();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after Show or ShowImmediate.
|
||||
/// </summary>
|
||||
protected virtual void OnShow() { }
|
||||
|
||||
/// <summary>
|
||||
/// Hides CanvasGroup with a fade.
|
||||
/// </summary>
|
||||
public virtual void Hide()
|
||||
{
|
||||
if (FadeOutDuration <= 0f)
|
||||
{
|
||||
HideImmediately();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Immediately make unclickable so players cannot hit UI objects as it's fading out.
|
||||
SetCanvasGroupBlockingType(CanvasGroupBlockingType.Block);
|
||||
SetFadeGoal(false);
|
||||
OnHide();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called after Hide or HideImmediate.
|
||||
/// </summary>
|
||||
protected virtual void OnHide() { }
|
||||
|
||||
/// <summary>
|
||||
/// Sets showing and begins fading if required.
|
||||
/// </summary>
|
||||
/// <param name = "fadeIn"></param>
|
||||
private void SetFadeGoal(bool fadeIn)
|
||||
{
|
||||
FadeGoal = fadeIn ? FadeGoalType.Visible : FadeGoalType.Hidden;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fades in or out over time.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private void Fade()
|
||||
{
|
||||
// Should not be possible.
|
||||
if (FadeGoal == FadeGoalType.Unset)
|
||||
{
|
||||
Debug.LogError($"{gameObject.name} has an unset FadeGoal. This should not be possible.");
|
||||
return;
|
||||
}
|
||||
|
||||
bool fadingIn = FadeGoal == FadeGoalType.Visible;
|
||||
float duration;
|
||||
float targetAlpha;
|
||||
if (fadingIn)
|
||||
{
|
||||
targetAlpha = 1f;
|
||||
duration = FadeInDuration;
|
||||
}
|
||||
else
|
||||
{
|
||||
targetAlpha = 0f;
|
||||
duration = FadeOutDuration;
|
||||
}
|
||||
|
||||
/* Already at goal and had completed an iteration at least once.
|
||||
* This is checked because even if at alpha we want to
|
||||
* complete the cycle if not done once so that all
|
||||
* local states and canvasgroup settings are proper. */
|
||||
if (_completedOnce && CanvasGroup.alpha == targetAlpha)
|
||||
return;
|
||||
|
||||
float rate = 1f / duration;
|
||||
CanvasGroup.alpha = Mathf.MoveTowards(CanvasGroup.alpha, targetAlpha, rate * Time.deltaTime);
|
||||
|
||||
// If complete.
|
||||
if (CanvasGroup.alpha == targetAlpha)
|
||||
CompleteFade(fadingIn);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the fade completes.
|
||||
/// </summary>
|
||||
protected virtual void CompleteFade(bool fadingIn)
|
||||
{
|
||||
CanvasGroupBlockingType blockingType;
|
||||
float alpha;
|
||||
if (fadingIn)
|
||||
{
|
||||
blockingType = CanvasGroupBlockingType.Block;
|
||||
alpha = 1f;
|
||||
}
|
||||
else
|
||||
{
|
||||
blockingType = CanvasGroupBlockingType.DoNotBlock;
|
||||
alpha = 0f;
|
||||
}
|
||||
|
||||
SetCanvasGroupBlockingType(blockingType);
|
||||
CanvasGroup.alpha = alpha;
|
||||
_completedOnce = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the CanvasGroups interactable and bloacking state.
|
||||
/// </summary>
|
||||
protected virtual void SetCanvasGroupBlockingType(CanvasGroupBlockingType blockingType)
|
||||
{
|
||||
if (UpdateCanvasBlocking)
|
||||
CanvasGroup.SetBlockingType(blockingType);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6aa7bd78c33474948b74e3c7a1d97454
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/CanvasGroupFader.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f04cb37e5f34ee749b8be696cb9c6ba3
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
namespace GameKit.Dependencies.Utilities.Types.CanvasContainers
|
||||
{
|
||||
public class ButtonData : IResettable
|
||||
{
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// Text to place on the button.
|
||||
/// </summary>
|
||||
public string Text { get; protected set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// When not null this will be called when action is taken.
|
||||
/// </summary>
|
||||
/// <param name = "key">Optional key to associate with callback.</param>
|
||||
public delegate void PressedDelegate(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Optional key to include within the callback.
|
||||
/// </summary>
|
||||
public string Key { get; protected set; } = string.Empty;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Delegate to invoke when pressed.
|
||||
/// </summary>
|
||||
private PressedDelegate _delegate = null;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this for use.
|
||||
/// </summary>
|
||||
/// <param name = "text">Text to display on the button.</param>
|
||||
/// <param name = "callback">Callback when OnPressed is called.</param>
|
||||
/// <param name = "key">Optional key to include within the callback.</param>
|
||||
public void Initialize(string text, PressedDelegate callback, string key = "")
|
||||
{
|
||||
Text = text;
|
||||
Key = key;
|
||||
_delegate = callback;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called whewn the button for this data is pressed.
|
||||
/// </summary>
|
||||
public virtual void OnPressed()
|
||||
{
|
||||
_delegate?.Invoke(Key);
|
||||
}
|
||||
|
||||
public virtual void ResetState()
|
||||
{
|
||||
Text = string.Empty;
|
||||
_delegate = null;
|
||||
Key = string.Empty;
|
||||
}
|
||||
|
||||
public void InitializeState() { }
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 1baacd2a6a8a0e94b897c6b7176c7000
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/ButtonData.cs
|
||||
uploadId: 866910
|
||||
+120
@@ -0,0 +1,120 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to track generic canvases and their states.
|
||||
/// </summary>
|
||||
public static class CanvasTracker
|
||||
{
|
||||
/// <summary>
|
||||
/// Canvases which should block input.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<object> InputBlockingCanvases => _inputBlockingCanvases;
|
||||
private static List<object> _inputBlockingCanvases = new();
|
||||
/// <summary>
|
||||
/// Canvases which are currently open, in the order they were opened.
|
||||
/// </summary>
|
||||
public static IReadOnlyList<object> OpenCanvases => _openCanvases;
|
||||
private static List<object> _openCanvases = new();
|
||||
/// <summary>
|
||||
/// True if any blocking canvas is open.
|
||||
/// </summary>
|
||||
public static bool IsInputBlockingCanvasOpen => _inputBlockingCanvases.Count > 0;
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if is the last canvas opened or if no canvases are set as opened.
|
||||
/// </summary>
|
||||
public static bool IsLastOpenCanvas(object canvas) => IsEmptyCollectionOrLastEntry(canvas, _openCanvases);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if is the last canvas blocking input or if no input blocking canvases are set as opened.
|
||||
/// </summary>
|
||||
public static bool IsLastInputBlockingCanvas(object canvas) => IsEmptyCollectionOrLastEntry(canvas, _inputBlockingCanvases);
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if canvas is the last object in collection or collection is empty.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
private static bool IsEmptyCollectionOrLastEntry(object canvas, List<object> collection)
|
||||
{
|
||||
int count = collection.Count;
|
||||
if (count == 0)
|
||||
return true;
|
||||
|
||||
return collection[count - 1] == canvas;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all collections.
|
||||
/// </summary>
|
||||
public static void ClearCollections()
|
||||
{
|
||||
_openCanvases.Clear();
|
||||
_inputBlockingCanvases.Clear();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes null references of canvases.
|
||||
/// This can be used as clean-up if you were unable to remove a canvas properly.
|
||||
/// Using this method regularly could be expensive if there are hundreds of open canvases.
|
||||
/// </summary>
|
||||
public static void RemoveNullReferences()
|
||||
{
|
||||
RemoveNullEntries(_openCanvases);
|
||||
RemoveNullEntries(_inputBlockingCanvases);
|
||||
|
||||
void RemoveNullEntries(List<object> collection)
|
||||
{
|
||||
for (int i = 0; i < collection.Count; i++)
|
||||
{
|
||||
if (collection[i] == null)
|
||||
{
|
||||
collection.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if canvas is an open canvas.
|
||||
/// </summary>
|
||||
public static bool IsOpenCanvas(object canvas)
|
||||
{
|
||||
return _openCanvases.Contains(canvas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns if the canvas is an input blocking canvas.
|
||||
/// </summary>
|
||||
public static bool IsInputBlockingCanvas(object canvas)
|
||||
{
|
||||
return _inputBlockingCanvases.Contains(canvas);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds a canvas to OpenCanvases if not already added.
|
||||
/// </summary>
|
||||
/// <param name = "addToBlocking">True to also add as an input blocking canvas.</param>
|
||||
/// <returns>True if the canvas was added, false if already added.</returns>
|
||||
public static bool AddOpenCanvas(object canvas, bool addToBlocking)
|
||||
{
|
||||
bool added = _openCanvases.AddUnique(canvas);
|
||||
if (added && addToBlocking)
|
||||
_inputBlockingCanvases.Add(canvas);
|
||||
|
||||
return added;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a canvas from OpenCanvases.
|
||||
/// </summary>
|
||||
/// <returns>True if the canvas was removed, false if it was not added.</returns>
|
||||
public static bool RemoveOpenCanvas(object canvas)
|
||||
{
|
||||
_inputBlockingCanvases.Remove(canvas);
|
||||
return _openCanvases.Remove(canvas);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: bd8ee85ef5b290246b270cefc7f018ca
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/CanvasTracker.cs
|
||||
uploadId: 866910
|
||||
+233
@@ -0,0 +1,233 @@
|
||||
using GameKit.Dependencies;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.CanvasContainers
|
||||
{
|
||||
public class FloatingContainer : CanvasGroupFader
|
||||
{
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// RectTransform to move.
|
||||
/// </summary>
|
||||
[Tooltip("RectTransform to move.")]
|
||||
[SerializeField]
|
||||
[TabGroup("Components")]
|
||||
protected RectTransform RectTransform;
|
||||
/// <summary>
|
||||
/// True to use edge avoidance.
|
||||
/// </summary>
|
||||
[Tooltip("True to use edge avoidance.")]
|
||||
[SerializeField]
|
||||
[TabGroup("Sizing")]
|
||||
protected bool UseEdgeAvoidance = true;
|
||||
/// <summary>
|
||||
/// How much to avoid screen edges when being moved.
|
||||
/// </summary>
|
||||
[Tooltip("How much to avoid screen edges when being moved.")]
|
||||
[SerializeField]
|
||||
[TabGroup("Sizing")]
|
||||
[ShowIf(nameof(UseEdgeAvoidance), true)]
|
||||
protected Vector2 EdgeAvoidance;
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Desired position.
|
||||
/// </summary>
|
||||
private Vector3 _positionGoal;
|
||||
/// <summary>
|
||||
/// Desired rotation.
|
||||
/// </summary>
|
||||
private Quaternion _rotationGoal;
|
||||
/// <summary>
|
||||
/// Desired scale.
|
||||
/// </summary>
|
||||
private Vector3 _scaleGoal = Vector3.one;
|
||||
/// <summary>
|
||||
/// How much edge avoidance to use.
|
||||
/// </summary>
|
||||
private Vector2? _edgeAvoidance;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Attachs a gameObject as a child of this object and sets transform valus to default.
|
||||
/// </summary>
|
||||
/// <param name = "go">GameObject to attach.</param>
|
||||
public void AttachGameObject(GameObject go)
|
||||
{
|
||||
if (go == null)
|
||||
return;
|
||||
|
||||
Transform goT = go.transform;
|
||||
goT.SetParent(transform);
|
||||
goT.localPosition = Vector3.zero;
|
||||
goT.localRotation = Quaternion.identity;
|
||||
goT.localScale = Vector3.one;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the container.
|
||||
/// </summary>
|
||||
/// <param name = "position">Position to use.</param>
|
||||
/// <param name = "rotation">Rotation to use.</param>
|
||||
/// <param name = "scale">Scale to use.</param>
|
||||
/// <param name = "pivot">Pivot for rectTransform.</param>
|
||||
/// <param name = "edgeAvoidanceOverride">How far to keep the RectTransform from the edge. If null serialized avoidance will be used.</param>
|
||||
public virtual void Show(Vector3 position, Quaternion rotation, Vector3 scale, Vector2 pivot, Vector2? edgeAvoidanceOverride = null)
|
||||
{
|
||||
UpdateEdgeAvoidance(edgeAvoidanceOverride, false);
|
||||
UpdatePivot(pivot, false);
|
||||
UpdatePositionRotationAndScale(position, rotation, scale);
|
||||
base.Show();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the container.
|
||||
/// </summary>
|
||||
/// <param name = "position">Position to use.</param>
|
||||
/// <param name = "edgeAvoidanceOverride">How far to keep the RectTransform from the edge. If null serialized avoidance will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public virtual void Show(Vector3 position, Vector2? edgeAvoidanceOverride = null)
|
||||
{
|
||||
Show(position, Quaternion.identity, Vector3.one, RectTransform.pivot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the container.
|
||||
/// </summary>
|
||||
/// <param name = "position">Position to use.</param>
|
||||
/// <param name = "rotation">Rotation to use.</param>
|
||||
/// <param name = "edgeAvoidanceOverride">How far to keep the RectTransform from the edge. If null serialized avoidance will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public virtual void Show(Vector3 position, Quaternion rotation, Vector2? edgeAvoidanceOverride = null)
|
||||
{
|
||||
Show(position, rotation, Vector3.one, RectTransform.pivot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows the container.
|
||||
/// </summary>
|
||||
/// <param name = "startingPoint">Transform to use for position, rotation, and scale.</param>
|
||||
/// <param name = "edgeAvoidanceOverride">How far to keep the RectTransform from the edge. If null serialized avoidance will be used.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public virtual void Show(Transform startingPoint, Vector2? edgeAvoidanceOverride = null)
|
||||
{
|
||||
if (startingPoint == null)
|
||||
{
|
||||
Debug.LogError($"A null Transform cannot be used as the starting point.");
|
||||
return;
|
||||
}
|
||||
|
||||
Show(startingPoint.position, startingPoint.rotation, startingPoint.localScale, RectTransform.pivot);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the rectTransform pivot.
|
||||
/// </summary>
|
||||
/// <param name = "pivot">New pivot.</param>
|
||||
/// <param name = "move">True to move the RectTransform after updating.</param>
|
||||
public virtual void UpdatePivot(Vector2 pivot, bool move = true)
|
||||
{
|
||||
RectTransform.pivot = pivot;
|
||||
if (move)
|
||||
Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates to a new position.
|
||||
/// </summary>
|
||||
/// <param name = "position">Next position.</param>
|
||||
/// <param name = "move">True to move towards new position.</param>
|
||||
public virtual void UpdatePosition(Vector3 position, bool move = true)
|
||||
{
|
||||
_positionGoal = position;
|
||||
if (move)
|
||||
Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates to a new rotation.
|
||||
/// </summary>
|
||||
/// <param name = "rotation">Next rotation.</param>
|
||||
public virtual void UpdateRotation(Quaternion rotation, bool move = true)
|
||||
{
|
||||
_rotationGoal = rotation;
|
||||
if (move)
|
||||
Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates to a new scale.
|
||||
/// </summary>
|
||||
/// <param name = "scale">Next scale.</param>
|
||||
/// <param name = "move">True to move the RectTransform after updating.</param>
|
||||
public virtual void UpdateScale(Vector3 scale, bool move = true)
|
||||
{
|
||||
_scaleGoal = scale;
|
||||
if (move)
|
||||
Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates to a new position and rotation.
|
||||
/// </summary>
|
||||
/// <param name = "position">Next position.</param>
|
||||
/// <param name = "rotation">Next rotation.</param>
|
||||
/// <param name = "move">True to move the RectTransform after updating.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public virtual void UpdatePositionAndRotation(Vector3 position, Quaternion rotation, bool move = true)
|
||||
{
|
||||
UpdatePosition(position, false);
|
||||
UpdateRotation(rotation, false);
|
||||
if (move)
|
||||
Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates to a new position, rotation, and scale.
|
||||
/// </summary>
|
||||
/// <param name = "position">Next position.</param>
|
||||
/// <param name = "rotation">Next rotation.</param>
|
||||
/// <param name = "scale">Next scale.</param>
|
||||
/// <param name = "move">True to move the RectTransform after updating.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public virtual void UpdatePositionRotationAndScale(Vector3 position, Quaternion rotation, Vector3 scale, bool move = true)
|
||||
{
|
||||
UpdatePositionAndRotation(position, rotation, false);
|
||||
UpdateScale(scale, false);
|
||||
Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates how much edge avoidance to use. When null serialized values are used.
|
||||
/// </summary>
|
||||
/// <param name = "edgeAvoidanceOverride">How far to keep the RectTransform from the edge. If null serialized avoidance will be used.</param>
|
||||
/// <param name = "move">True to move the RectTransform after updating.</param>
|
||||
public virtual void UpdateEdgeAvoidance(Vector2? edgeAvoidanceOverride = null, bool move = true)
|
||||
{
|
||||
_edgeAvoidance = edgeAvoidanceOverride.HasValue ? edgeAvoidanceOverride.Value : EdgeAvoidance;
|
||||
if (move)
|
||||
Move();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Moves to configured goals.
|
||||
/// </summary>
|
||||
protected virtual void Move()
|
||||
{
|
||||
// Update scale first so edge avoidance takes it into consideration.
|
||||
RectTransform.localScale = _scaleGoal;
|
||||
|
||||
Vector2 position = _positionGoal;
|
||||
if (UseEdgeAvoidance)
|
||||
{
|
||||
Vector2 avoidance = _edgeAvoidance.HasValue ? _edgeAvoidance.Value : EdgeAvoidance;
|
||||
position = RectTransform.GetOnScreenPosition(_positionGoal, avoidance);
|
||||
}
|
||||
|
||||
RectTransform.SetPositionAndRotation(position, _rotationGoal);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f1fcd998728ace94ea809c34ad0d09e8
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/FloatingContainer.cs
|
||||
uploadId: 866910
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
using Sirenix.OdinInspector;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.CanvasContainers
|
||||
{
|
||||
public class FloatingImage : FloatingContainer
|
||||
{
|
||||
/// <summary>
|
||||
/// Renderer to apply sprite on.
|
||||
/// </summary>
|
||||
[Tooltip("Renderer to apply sprite on.")]
|
||||
[SerializeField]
|
||||
[TabGroup("Components")]
|
||||
protected Image Renderer;
|
||||
|
||||
/// <summary>
|
||||
/// Sets which sprite to use.
|
||||
/// </summary>
|
||||
/// <param name = "sprite">Sprite to use.</param>
|
||||
/// <param name = "sizeOverride">When has value the renderer will be set to this size. Otherwise, the size of the sprite will be used. This value assumes the sprite anchors are set to center.</param>
|
||||
public virtual void SetSprite(Sprite sprite, Vector3? sizeOverride)
|
||||
{
|
||||
Renderer.sprite = sprite;
|
||||
Vector3 size = sizeOverride == null ? sprite.bounds.size * sprite.pixelsPerUnit : sizeOverride.Value;
|
||||
|
||||
Renderer.rectTransform.sizeDelta = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2169e34ec7dd63a4e99b5cc89fd0e966
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/FloatingImage.cs
|
||||
uploadId: 866910
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
using GameKit.Dependencies.Utilities.Types.CanvasContainers;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.OptionMenuButtons
|
||||
{
|
||||
public class FloatingOptions : CanvasGroupFader
|
||||
{
|
||||
#region Protected.
|
||||
/// <summary>
|
||||
/// Current buttons.
|
||||
/// </summary>
|
||||
protected List<ButtonData> Buttons = new();
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Adds buttons.
|
||||
/// </summary>
|
||||
/// <param name = "clearExisting">True to clear existing buttons first.</param>
|
||||
/// <param name = "buttonDatas">Buttons to add.</param>
|
||||
protected virtual void AddButtons(bool clearExisting, IEnumerable<ButtonData> buttonDatas)
|
||||
{
|
||||
if (clearExisting)
|
||||
RemoveButtons();
|
||||
foreach (ButtonData item in buttonDatas)
|
||||
Buttons.Add(item);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes all buttons.
|
||||
/// </summary>
|
||||
protected virtual void RemoveButtons()
|
||||
{
|
||||
foreach (ButtonData item in Buttons)
|
||||
ResettableObjectCaches<ButtonData>.Store(item);
|
||||
Buttons.Clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cbc5b08db621303449f60b59f56eac92
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/FloatingOptions.cs
|
||||
uploadId: 866910
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.CanvasContainers
|
||||
{
|
||||
public class ImageButtonData : ButtonData
|
||||
{
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// Image to display.
|
||||
/// </summary>
|
||||
public Sprite DisplayImage { get; protected set; } = null;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Initializes this for use.
|
||||
/// </summary>
|
||||
/// <param name = "sprite">Image to use on the button.</param>
|
||||
/// <param name = "text">Text to display on the button.</param>
|
||||
/// <param name = "callback">Callback when OnPressed is called.</param>
|
||||
/// <param name = "key">Optional key to include within the callback.</param>
|
||||
public void Initialize(Sprite sprite, string text, PressedDelegate callback, string key = "")
|
||||
{
|
||||
base.Initialize(text, callback, key);
|
||||
DisplayImage = sprite;
|
||||
}
|
||||
|
||||
public override void ResetState()
|
||||
{
|
||||
base.ResetState();
|
||||
DisplayImage = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d60e355b6d09be14487df1ed91e901b2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/ImageButtonData.cs
|
||||
uploadId: 866910
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
#if TEXTMESHPRO
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
using UnityEngine.UI;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.CanvasContainers
|
||||
{
|
||||
public class OptionMenuImageButton : OptionMenuButton
|
||||
{
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// Image component to show image on.
|
||||
/// </summary>
|
||||
[Tooltip("Image component to show image on.")]
|
||||
[SerializeField]
|
||||
private Image _image;
|
||||
#endregion
|
||||
|
||||
public virtual void Initialize(ImageButtonData buttonData)
|
||||
{
|
||||
base.Initialize(buttonData);
|
||||
_image.sprite = buttonData.DisplayImage;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2fee1d5cad375e84eaab6a4cd1d6e915
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/ImageOptionButton.cs
|
||||
uploadId: 866910
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
#if TEXTMESHPRO
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.CanvasContainers
|
||||
{
|
||||
public class OptionMenuButton : MonoBehaviour
|
||||
{
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// ButtonData for this button.
|
||||
/// </summary>
|
||||
public ButtonData ButtonData { get; protected set; }
|
||||
#endregion
|
||||
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// Text component to show button text.
|
||||
/// </summary>
|
||||
[Tooltip("Text component to show button text.")]
|
||||
[SerializeField]
|
||||
private TextMeshProUGUI _text;
|
||||
#endregion
|
||||
|
||||
public virtual void Initialize(ButtonData buttonData)
|
||||
{
|
||||
ButtonData = buttonData;
|
||||
_text.text = buttonData.Text;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 22d4118a529704b49858d02b956dc48d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/OptionButton.cs
|
||||
uploadId: 866910
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types
|
||||
{
|
||||
/// <summary>
|
||||
/// Gameplay canvases register to this manager.
|
||||
/// </summary>
|
||||
public class RectTransformResizer : MonoBehaviour
|
||||
{
|
||||
#region Types.
|
||||
public class ResizeData : IResettable
|
||||
{
|
||||
public byte Remaining;
|
||||
public ResizeDelegate Delegate;
|
||||
|
||||
public ResizeData()
|
||||
{
|
||||
Remaining = 2;
|
||||
}
|
||||
|
||||
public void InitializeState() { }
|
||||
|
||||
public void ResetState()
|
||||
{
|
||||
Remaining = 2;
|
||||
Delegate = null;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// Delegate for resizing RectTransforms.
|
||||
/// </summary>
|
||||
/// <param name = "complete">True if the resize iterations are complete. Typically show your visuals when true.</param>
|
||||
public delegate void ResizeDelegate(bool complete);
|
||||
#endregion
|
||||
|
||||
#region Private.
|
||||
/// <summary>
|
||||
/// Elements to resize.
|
||||
/// </summary>
|
||||
private List<ResizeData> _resizeDatas = new();
|
||||
/// <summary>
|
||||
/// Singleton instance of this class.
|
||||
/// </summary>
|
||||
private static RectTransformResizer _instance;
|
||||
#endregion
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
foreach (ResizeData item in _resizeDatas)
|
||||
ResettableObjectCaches<ResizeData>.Store(item);
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
Resize();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls pending resizeDatas.
|
||||
/// </summary>
|
||||
private void Resize()
|
||||
{
|
||||
for (int i = 0; i < _resizeDatas.Count; i++)
|
||||
{
|
||||
_resizeDatas[i].Remaining--;
|
||||
bool complete = _resizeDatas[i].Remaining == 0;
|
||||
_resizeDatas[i].Delegate?.Invoke(complete);
|
||||
if (complete)
|
||||
{
|
||||
ResettableObjectCaches<ResizeData>.Store(_resizeDatas[i]);
|
||||
_resizeDatas.RemoveAt(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to call a delegate twice, over two frames.
|
||||
/// This is an easy way to resize RectTransforms multiple times as they will often fail after the first resize due to Unity limitations.
|
||||
/// Note: this work-around may not be required for newer Unity versions.
|
||||
/// </summary>
|
||||
/// <param name = "del">Delegate to invoke when resizing completes.</param>
|
||||
public static void Resize(ResizeDelegate del)
|
||||
{
|
||||
// Check to make a singleton instance.
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject go = new(typeof(RectTransformResizer).Name);
|
||||
_instance = go.AddComponent<RectTransformResizer>();
|
||||
DontDestroyOnLoad(go);
|
||||
}
|
||||
|
||||
_instance.Resize_Internal(del);
|
||||
}
|
||||
|
||||
private void Resize_Internal(ResizeDelegate del)
|
||||
{
|
||||
ResizeData rd = ResettableObjectCaches<ResizeData>.Retrieve();
|
||||
rd.Delegate = del;
|
||||
_instance._resizeDatas.Add(rd);
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4b4655d59b39584faed638f43d4d287
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/RectTransformResizer.cs
|
||||
uploadId: 866910
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.CanvasContainers
|
||||
{
|
||||
public class ResizableContainer : FloatingContainer
|
||||
{
|
||||
#region Serialized.
|
||||
/// <summary>
|
||||
/// Minimum and maximum range for widwth and height of the RectTransform.
|
||||
/// </summary>
|
||||
[Tooltip("Minimum and maximum range for width and height of the RectTransform.")]
|
||||
// [Foldout("Sizing")]
|
||||
public FloatRange2D SizeLimits = new()
|
||||
{
|
||||
X = new(0f, 999999f),
|
||||
Y = new(0f, 999999f)
|
||||
};
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Sets a size, and resizes if needed.
|
||||
/// Other transform values must be set separately using inherited methods.
|
||||
/// </summary>
|
||||
/// <param name = "size">New size to use.</param>
|
||||
/// <param name = "ignoreSizeLimits">True to ignore serialized Size limits.</param>
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public void SetSizeAndShow(Vector2 size, bool ignoreSizeLimits = false)
|
||||
{
|
||||
ResizeAndShow(size, ignoreSizeLimits);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resizes this canvas.
|
||||
/// </summary>
|
||||
protected virtual void ResizeAndShow(Vector2 desiredSize, bool ignoreSizeLimits)
|
||||
{
|
||||
float widthRequired = desiredSize.x;
|
||||
float heightRequired = desiredSize.y;
|
||||
// Clamp width and height.
|
||||
widthRequired = Mathf.Clamp(widthRequired, SizeLimits.X.Minimum, SizeLimits.X.Maximum);
|
||||
heightRequired = Mathf.Clamp(heightRequired, SizeLimits.Y.Minimum, SizeLimits.Y.Maximum);
|
||||
RectTransform.sizeDelta = new(widthRequired, heightRequired);
|
||||
base.Move();
|
||||
base.Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 5764e627642cf5643a3f4518d450840e
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Canvases/ResizableContainer.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types
|
||||
{
|
||||
public class DDOL : MonoBehaviour
|
||||
{
|
||||
#region Public.
|
||||
/// <summary>
|
||||
/// Created instance of DDOL.
|
||||
/// </summary>
|
||||
private static DDOL _instance;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Returns the current DDOL or creates one if not yet created.
|
||||
/// </summary>
|
||||
public static DDOL GetDDOL()
|
||||
{
|
||||
// Not yet made.
|
||||
if (_instance == null)
|
||||
{
|
||||
GameObject obj = new();
|
||||
obj.name = "FirstGearGames DDOL";
|
||||
DDOL ddol = obj.AddComponent<DDOL>();
|
||||
DontDestroyOnLoad(ddol);
|
||||
_instance = ddol;
|
||||
return ddol;
|
||||
}
|
||||
// Already made.
|
||||
else
|
||||
{
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 4e0b25628cfd4f241a22a7c0ee2b932f
|
||||
timeCreated: 1528404670
|
||||
licenseType: Store
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/DDOL.cs
|
||||
uploadId: 866910
|
||||
@@ -0,0 +1,8 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a4e1653f734aa924a947707391413c6c
|
||||
folderAsset: yes
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
|
||||
namespace GameKit.Dependencies.Utilities.Types.Editing
|
||||
{
|
||||
/* Source https://forum.unity.com/threads/how-to-link-scenes-in-the-inspector.383140/ */
|
||||
|
||||
[CustomPropertyDrawer(typeof(SceneAttribute))]
|
||||
public class SceneDrawer : PropertyDrawer
|
||||
{
|
||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
||||
{
|
||||
if (property.propertyType == SerializedPropertyType.String)
|
||||
{
|
||||
SceneAsset sceneObject = AssetDatabase.LoadAssetAtPath<SceneAsset>(property.stringValue);
|
||||
|
||||
if (sceneObject == null && !string.IsNullOrEmpty(property.stringValue))
|
||||
{
|
||||
// try to load it from the build settings for legacy compatibility
|
||||
sceneObject = GetBuildSettingsSceneObject(property.stringValue);
|
||||
}
|
||||
if (sceneObject == null && !string.IsNullOrEmpty(property.stringValue))
|
||||
{
|
||||
Debug.Log($"Could not find scene {property.stringValue} in {property.propertyPath}, assign the proper scenes in your NetworkManager");
|
||||
}
|
||||
SceneAsset scene = (SceneAsset)EditorGUI.ObjectField(position, label, sceneObject, typeof(SceneAsset), true);
|
||||
|
||||
property.stringValue = AssetDatabase.GetAssetPath(scene);
|
||||
}
|
||||
else
|
||||
{
|
||||
EditorGUI.LabelField(position, label.text, "Use [Scene] with strings.");
|
||||
}
|
||||
}
|
||||
|
||||
protected SceneAsset GetBuildSettingsSceneObject(string sceneName)
|
||||
{
|
||||
foreach (EditorBuildSettingsScene buildScene in EditorBuildSettings.scenes)
|
||||
{
|
||||
SceneAsset sceneAsset = AssetDatabase.LoadAssetAtPath<SceneAsset>(buildScene.path);
|
||||
if (sceneAsset != null && sceneAsset.name == sceneName)
|
||||
{
|
||||
return sceneAsset;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c144891e57ef5054d9b7e03b82c00cf2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 207815
|
||||
packageName: 'FishNet: Networking Evolved'
|
||||
packageVersion: 4.6.22R
|
||||
assetPath: Assets/FishNet/Runtime/Plugins/GameKit/Dependencies/Utilities/Types/Editor/SceneDrawer.cs
|
||||
uploadId: 866910
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user