Add StickGame Assets

This commit is contained in:
Dzejkobik007
2024-03-24 22:21:16 +01:00
parent 5a5812c0c7
commit 6c8b523d1f
6643 changed files with 596260 additions and 0 deletions

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: cd9a0ca39fab66c448fdc3e25da9d482
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,3 @@
{
"name": "GameKit.Dependencies"
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 36bccdedfe0feeb4daf43bef9e43b65b
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c8ce00cde8ada214fb582a92539f14b9
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: b43a8f6c3cc189c40ae6b248e76e2788
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: c197d238762d66b41927449d5c48b3f4
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,488 @@
#if UNITY_EDITOR
// Project : UNITY FOLDOUT
// Contacts : Pix - ask@pixeye.games
// https://github.com/PixeyeHQ/InspectorFoldoutGroup
// MIT license https://github.com/PixeyeHQ/InspectorFoldoutGroup/blob/master/LICENSE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using UnityEditor;
using UnityEngine;
using UnityEngine.UIElements;
using Object = UnityEngine.Object;
namespace GameKit.Dependencies.Inspectors
{
[CustomEditor(typeof(Object), true, isFallback = true)]
[CanEditMultipleObjects]
public class EditorOverride : Editor
{
public override VisualElement CreateInspectorGUI()
{
return base.CreateInspectorGUI();
}
//===============================//
// Members
//===============================//
Dictionary<string, CacheFoldProp> cacheFolds = new Dictionary<string, CacheFoldProp>();
List<SerializedProperty> props = new List<SerializedProperty>();
List<MethodInfo> methods = new List<MethodInfo>();
bool initialized;
//===============================//
// Logic
//===============================//
void OnEnable()
{
initialized = false;
}
void OnDisable()
{
//if (Application.wantsToQuit)
//if (applicationIsQuitting) return;
// if (Toolbox.isQuittingOrChangingScene()) return;
if (target != null)
foreach (var c in cacheFolds)
{
EditorPrefs.SetBool(string.Format($"{c.Value.atr.name}{c.Value.props[0].name}{target.GetInstanceID()}"), c.Value.expanded);
c.Value.Dispose();
}
}
public override bool RequiresConstantRepaint()
{
return EditorFramework.needToRepaint;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
Setup();
if (props.Count == 0)
{
DrawDefaultInspector();
return;
}
Header();
Body();
serializedObject.ApplyModifiedProperties();
void Header()
{
using (new EditorGUI.DisabledScope("m_Script" == props[0].propertyPath))
{
EditorGUILayout.Space();
EditorGUILayout.PropertyField(props[0], true);
EditorGUILayout.Space();
}
}
void Body()
{
foreach (var pair in cacheFolds)
{
this.UseVerticalLayout(() => Foldout(pair.Value), StyleFramework.box);
EditorGUI.indentLevel = 0;
}
EditorGUILayout.Space();
for (var i = 1; i < props.Count; i++)
{
// if (props[i].isArray)
// {
// DrawPropertySortableArray(props[i]);
// }
// else
// {
EditorGUILayout.PropertyField(props[i], true);
//}
}
EditorGUILayout.Space();
if (methods == null) return;
foreach (MethodInfo memberInfo in methods)
{
this.UseButton(memberInfo);
}
}
void Foldout(CacheFoldProp cache)
{
cache.expanded = EditorGUILayout.Foldout(cache.expanded, cache.atr.name, true,
StyleFramework.foldout);
if (cache.expanded)
{
EditorGUI.indentLevel = 1;
for (int i = 0; i < cache.props.Count; i++)
{
this.UseVerticalLayout(() => Child(i), StyleFramework.boxChild);
}
}
void Child(int i)
{
// if (cache.props[i].isArray)
// {
// DrawPropertySortableArray(cache.props[i]);
// }
// else
// {
EditorGUILayout.PropertyField(cache.props[i], new GUIContent(ObjectNames.NicifyVariableName(cache.props[i].name)), true);
//}
}
}
void Setup()
{
EditorFramework.currentEvent = Event.current;
if (!initialized)
{
// SetupButtons();
List<FieldInfo> objectFields;
GroupAttribute prevFold = default;
var length = EditorTypes.Get(target, out objectFields);
for (var i = 0; i < length; i++)
{
#region FOLDERS
var fold = Attribute.GetCustomAttribute(objectFields[i], typeof(GroupAttribute)) as GroupAttribute;
CacheFoldProp c;
if (fold == null)
{
if (prevFold != null && prevFold.foldEverything)
{
if (!cacheFolds.TryGetValue(prevFold.name, out c))
{
cacheFolds.Add(prevFold.name, new CacheFoldProp { atr = prevFold, types = new HashSet<string> { objectFields[i].Name } });
}
else
{
c.types.Add(objectFields[i].Name);
}
}
continue;
}
prevFold = fold;
if (!cacheFolds.TryGetValue(fold.name, out c))
{
var expanded = EditorPrefs.GetBool(string.Format($"{fold.name}{objectFields[i].Name}{target.GetInstanceID()}"), false);
cacheFolds.Add(fold.name, new CacheFoldProp { atr = fold, types = new HashSet<string> { objectFields[i].Name }, expanded = expanded });
}
else c.types.Add(objectFields[i].Name);
#endregion
}
var property = serializedObject.GetIterator();
var next = property.NextVisible(true);
if (next)
{
do
{
HandleFoldProp(property);
} while (property.NextVisible(false));
}
initialized = true;
}
}
// void SetupButtons()
// {
// var members = GetButtonMembers(target);
//
// foreach (var memberInfo in members)
// {
// var method = memberInfo as MethodInfo;
// if (method == null)
// {
// continue;
// }
//
// if (method.GetParameters().Length > 0)
// {
// continue;
// }
//
// if (methods == null) methods = new List<MethodInfo>();
// methods.Add(method);
// }
// }
}
public void HandleFoldProp(SerializedProperty prop)
{
bool shouldBeFolded = false;
foreach (var pair in cacheFolds)
{
if (pair.Value.types.Contains(prop.name))
{
var pr = prop.Copy();
shouldBeFolded = true;
pair.Value.props.Add(pr);
break;
}
}
if (shouldBeFolded == false)
{
var pr = prop.Copy();
props.Add(pr);
}
}
// IEnumerable<MemberInfo> GetButtonMembers(object target)
// {
// return target.GetType()
// .GetMembers(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic)
// .Where(CheckButtonAttribute);
// }
// bool CheckButtonAttribute(MemberInfo memberInfo)
// {
// return Attribute.IsDefined(memberInfo, typeof(ButtonAttribute));
// }
class CacheFoldProp
{
public HashSet<string> types = new HashSet<string>();
public List<SerializedProperty> props = new List<SerializedProperty>();
public GroupAttribute atr;
public bool expanded;
public void Dispose()
{
props.Clear();
types.Clear();
atr = null;
}
}
}
static class EditorUIHelper
{
public static void UseVerticalLayout(this Editor e, Action action, GUIStyle style)
{
EditorGUILayout.BeginVertical(style);
action();
EditorGUILayout.EndVertical();
}
public static void UseButton(this Editor e, MethodInfo m)
{
if (GUILayout.Button(m.Name))
{
m.Invoke(e.target, null);
}
}
}
static class StyleFramework
{
public static GUIStyle box;
public static GUIStyle boxChild;
public static GUIStyle foldout;
public static GUIStyle button;
public static GUIStyle text;
static StyleFramework()
{
bool pro = EditorGUIUtility.isProSkin;
var uiTex_in = UnityEngine.Resources.Load<Texture2D>("IN foldout focus-6510");
var uiTex_in_on = UnityEngine.Resources.Load<Texture2D>("IN foldout focus on-5718");
var c_on = pro ? Color.white : new Color(51 / 255f, 102 / 255f, 204 / 255f, 1);
button = new GUIStyle(EditorStyles.miniButton);
button.font = Font.CreateDynamicFontFromOSFont(new[] { "Terminus (TTF) for Windows", "Calibri" }, 17);
text = new GUIStyle(EditorStyles.label);
text.richText = true;
text.contentOffset = new Vector2(0, 5);
text.font = Font.CreateDynamicFontFromOSFont(new[] { "Terminus (TTF) for Windows", "Calibri" }, 14);
foldout = new GUIStyle(EditorStyles.foldout);
foldout.overflow = new RectOffset(-10, 0, 3, 0);
foldout.padding = new RectOffset(25, 0, -3, 0);
foldout.active.textColor = c_on;
foldout.active.background = uiTex_in;
foldout.onActive.textColor = c_on;
foldout.onActive.background = uiTex_in_on;
foldout.focused.textColor = c_on;
foldout.focused.background = uiTex_in;
foldout.onFocused.textColor = c_on;
foldout.onFocused.background = uiTex_in_on;
foldout.hover.textColor = c_on;
foldout.hover.background = uiTex_in;
foldout.onHover.textColor = c_on;
foldout.onHover.background = uiTex_in_on;
box = new GUIStyle(GUI.skin.box);
box.padding = new RectOffset(10, 0, 10, 0);
boxChild = new GUIStyle(GUI.skin.box);
boxChild.active.textColor = c_on;
boxChild.active.background = uiTex_in;
boxChild.onActive.textColor = c_on;
boxChild.onActive.background = uiTex_in_on;
boxChild.focused.textColor = c_on;
boxChild.focused.background = uiTex_in;
boxChild.onFocused.textColor = c_on;
boxChild.onFocused.background = uiTex_in_on;
EditorStyles.foldout.active.textColor = c_on;
EditorStyles.foldout.active.background = uiTex_in;
EditorStyles.foldout.onActive.textColor = c_on;
EditorStyles.foldout.onActive.background = uiTex_in_on;
EditorStyles.foldout.focused.textColor = c_on;
EditorStyles.foldout.focused.background = uiTex_in;
EditorStyles.foldout.onFocused.textColor = c_on;
EditorStyles.foldout.onFocused.background = uiTex_in_on;
EditorStyles.foldout.hover.textColor = c_on;
EditorStyles.foldout.hover.background = uiTex_in;
EditorStyles.foldout.onHover.textColor = c_on;
EditorStyles.foldout.onHover.background = uiTex_in_on;
}
public static string FirstLetterToUpperCase(this string s)
{
if (string.IsNullOrEmpty(s))
return string.Empty;
var a = s.ToCharArray();
a[0] = char.ToUpper(a[0]);
return new string(a);
}
public static IList<Type> GetTypeTree(this Type t)
{
var types = new List<Type>();
while (t.BaseType != null)
{
types.Add(t);
t = t.BaseType;
}
return types;
}
}
static class EditorTypes
{
public static Dictionary<int, List<FieldInfo>> fields = new Dictionary<int, List<FieldInfo>>(FastComparable.Default);
public static int Get(Object target, out List<FieldInfo> objectFields)
{
var t = target.GetType();
var hash = t.GetHashCode();
if (!fields.TryGetValue(hash, out objectFields))
{
var typeTree = t.GetTypeTree();
objectFields = target.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.NonPublic)
.OrderByDescending(x => typeTree.IndexOf(x.DeclaringType))
.ToList();
fields.Add(hash, objectFields);
}
return objectFields.Count;
}
}
class FastComparable : IEqualityComparer<int>
{
public static FastComparable Default = new FastComparable();
public bool Equals(int x, int y)
{
return x == y;
}
public int GetHashCode(int obj)
{
return obj.GetHashCode();
}
}
[InitializeOnLoad]
public static class EditorFramework
{
internal static bool needToRepaint;
internal static Event currentEvent;
internal static float t;
static EditorFramework()
{
EditorApplication.update += Updating;
}
static void Updating()
{
CheckMouse();
if (needToRepaint)
{
t += Time.deltaTime;
if (t >= 0.3f)
{
t -= 0.3f;
needToRepaint = false;
}
}
}
static void CheckMouse()
{
var ev = currentEvent;
if (ev == null) return;
if (ev.type == EventType.MouseMove)
needToRepaint = true;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 428419a625f80f6438c5b74beb2ac763
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: bce51828adfc9b540b10914a9ec82c31
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: 07896d08487bbb049b494e9e216360ad
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,140 @@
fileFormatVersion: 2
guid: 795626f49ade9024a86e0c1a58aa004b
TextureImporter:
internalIDToNameTable: []
externalObjects: {}
serializedVersion: 12
mipmaps:
mipMapMode: 0
enableMipMap: 0
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
flipGreenChannel: 0
isReadable: 0
streamingMipmaps: 0
streamingMipmapsPriority: 0
vTOnly: 0
ignoreMipmapLimit: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: 0
aniso: 1
mipBias: 0
wrapU: 1
wrapV: 1
wrapW: 0
nPOTScale: 0
lightmap: 0
compressionQuality: 50
spriteMode: 1
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spritePixelsToUnits: 100
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spriteGenerateFallbackPhysicsShape: 1
alphaUsage: 1
alphaIsTransparency: 1
spriteTessellationDetail: -1
textureType: 8
textureShape: 1
singleChannelComponent: 0
flipbookRows: 1
flipbookColumns: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
ignorePngGamma: 0
applyGammaDecoding: 1
swizzle: 50462976
cookieLightType: 1
platformSettings:
- serializedVersion: 3
buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: Standalone
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: WebGL
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
- serializedVersion: 3
buildTarget: Server
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
ignorePlatformSupport: 0
androidETC2FallbackOverride: 0
forceMaximumCompressionQuality_BC6H_BC7: 1
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
bones: []
spriteID: 5e97eb03825dee720800000000000000
internalID: 0
vertices: []
indices:
edges: []
weights: []
secondaryTextures: []
nameFileIdTable: {}
mipmapLimitGroupName:
pSDRemoveMatte: 0
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,25 @@
// Project : UNITY FOLDOUT
// Contacts : Pix - ask@pixeye.games
// https://github.com/PixeyeHQ/InspectorFoldoutGroup
// MIT license https://github.com/PixeyeHQ/InspectorFoldoutGroup/blob/master/LICENSE
using System;
using UnityEngine;
namespace GameKit.Dependencies.Inspectors
{
public class GroupAttribute : PropertyAttribute
{
public string name;
public bool foldEverything;
/// <summary>Adds the property to the specified foldout group.</summary>
/// <param name="name">Name of the foldout group.</param>
/// <param name="foldEverything">Toggle to put all properties to the specified group</param>
public GroupAttribute(string name, bool foldEverything = false)
{
this.foldEverything = foldEverything;
this.name = name;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e3c02d1d5545ae54687d1a313ebb2fd6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 102b5a2337dae434f989eee1a6a1c571
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a8361a4f779768242840a9c994392e20
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,118 @@
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
namespace GameKit.Dependencies.Inspectors
{
/// <summary>
/// Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
/// </summary>
[CustomPropertyDrawer(typeof(ShowIfAttribute))]
public class ShowIfPropertyDrawer : PropertyDrawer
{
#region Fields
// Reference to the attribute on the property.
ShowIfAttribute drawIf;
// Field that is being compared.
SerializedProperty comparedField;
#endregion
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
if (!ShowMe(property) && drawIf.disablingType == ShowIfAttribute.DisablingType.DontDraw)
{
return -EditorGUIUtility.standardVerticalSpacing;
}
else
{
if (property.propertyType == SerializedPropertyType.Generic)
{
int numChildren = 0;
float totalHeight = 0.0f;
IEnumerator children = property.GetEnumerator();
HashSet<SerializedProperty> drawnprops = new HashSet<SerializedProperty>();
while (children.MoveNext())
{
SerializedProperty child = children.Current as SerializedProperty;
if (drawnprops.Contains(child))
{
continue;
}
drawnprops.Add(child);
GUIContent childLabel = new GUIContent(child.displayName);
totalHeight += EditorGUI.GetPropertyHeight(child, childLabel) + EditorGUIUtility.standardVerticalSpacing;
numChildren++;
}
// Remove extra space at end, (we only want spaces between items)
totalHeight -= EditorGUIUtility.standardVerticalSpacing;
return totalHeight;
}
return EditorGUI.GetPropertyHeight(property, label);
}
}
/// <summary>
/// Errors default to showing the property.
/// </summary>
private bool ShowMe(SerializedProperty property)
{
drawIf = attribute as ShowIfAttribute;
// Replace propertyname to the value from the parameter
string path = property.propertyPath.Contains(".") ? System.IO.Path.ChangeExtension(property.propertyPath, drawIf.comparedPropertyName) : drawIf.comparedPropertyName;
comparedField = property.serializedObject.FindProperty(path);
if (comparedField == null)
{
Debug.LogError("Cannot find property with name: " + path);
return true;
}
// get the value & compare based on types
switch (comparedField.type)
{ // Possible extend cases to support your own type
case "bool":
return comparedField.boolValue.Equals(drawIf.comparedValue);
case "Enum":
return comparedField.enumValueIndex.Equals((int)drawIf.comparedValue);
default:
Debug.LogError("Error: " + comparedField.type + " is not supported of " + path);
return true;
}
}
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
// If the condition is met, simply draw the field.
if (ShowMe(property))
{
EditorGUI.PropertyField(position, property);
} //...check if the disabling type is read only. If it is, draw it disabled
else if (drawIf.disablingType == ShowIfAttribute.DisablingType.ReadOnly)
{
GUI.enabled = false;
EditorGUI.PropertyField(position, property);
GUI.enabled = true;
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1266c8c8d104aeb4faf3f1daaee87479
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using UnityEngine;
using System;
namespace GameKit.Dependencies.Inspectors
{
/// <summary>
/// Draws the field/property ONLY if the compared property compared by the comparison type with the value of comparedValue returns true.
/// Based on: https://forum.unity.com/threads/draw-a-field-only-if-a-condition-is-met.448855/
/// </summary>
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
public class ShowIfAttribute : PropertyAttribute
{
#region Fields
public string comparedPropertyName { get; private set; }
public object comparedValue { get; private set; }
public DisablingType disablingType { get; private set; }
/// <summary>
/// Types of comperisons.
/// </summary>
public enum DisablingType
{
ReadOnly = 2,
DontDraw = 3
}
#endregion
/// <summary>
/// Only draws the field only if a condition is met. Supports enum and bools.
/// </summary>
/// <param name="comparedPropertyName">The name of the property that is being compared (case sensitive).</param>
/// <param name="comparedValue">The value the property is being compared to.</param>
/// <param name="disablingType">The type of disabling that should happen if the condition is NOT met. Defaulted to DisablingType.DontDraw.</param>
public ShowIfAttribute(string comparedPropertyName, object comparedValue, DisablingType disablingType = DisablingType.DontDraw)
{
this.comparedPropertyName = comparedPropertyName;
this.comparedValue = comparedValue;
this.disablingType = disablingType;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 203e832301eed08499198358cfd13e7d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 53002e457d153bf49aad4b2b28d4353c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,83 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace GameKit.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)
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
UnityEditor.EditorApplication.isPlaying = false;
#else
Application.Quit();
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 54eb82a57a65e8548b57f5ca2a62bb76
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,97 @@
using System.Collections.Generic;
namespace GameKit.Utilities
{
public static class Arrays
{
/// <summary>
/// Randomizer used for shuffling.
/// </summary>
private static System.Random _random = new System.Random();
/// <summary>
/// Adds an entry to a list if it does not exist already.
/// </summary>
/// <returns>True if the entry was added.</returns>
public static bool AddUnique<T>(this List<T> list, T value)
{
bool contains = list.Contains((T)value);
if (!contains)
list.Add((T)value);
return !contains;
}
/// <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 (object.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[list.Count - 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;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 1b93eae9ff81b3e4b892128ca4b392ed
timeCreated: 1530140103
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,15 @@
namespace GameKit.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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 602eeac4b016b174f90ae5e85254ac86
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,93 @@
using UnityEngine;
namespace GameKit.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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c0e7937b287d3d24d807a115c1a3a464
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,33 @@
using System.Collections.Generic;
namespace GameKit.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 IDictionary<TKey, TValue> dict, TKey key, out TValue value)
{
#if ENABLE_IL2CPP && UNITY_IOS || UNITY_ANDROID
if (dict.ContainsKey(key))
{
value = dict[key];
return true;
}
else
{
value = default;
return false;
}
#else
return dict.TryGetValue(key, out value);
#endif
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9d31d19bc39eb6041bad18d8eb68ed68
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,102 @@
using System;
using System.IO;
using UnityEngine;
namespace GameKit.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 FileStream(path, FileMode.Create))
{
using (StreamWriter writer = new StreamWriter(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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a3a909760282d284591c20c873f20837
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,80 @@

#if UNITY_EDITOR
using System;
using UnityEditor;
using UnityEngine;
namespace GameKit.Utilities
{
public enum EditorLayoutEnableType
{
Enabled = 0,
Disabled = 1,
DisabledWhilePlaying = 2
}
public static class Editing
{
/// <summary>
/// Adds a property field.
/// </summary>
public static void AddPropertyField(SerializedProperty sp, GUIContent guiContent, EditorLayoutEnableType enableType = EditorLayoutEnableType.Enabled, params GUILayoutOption[] options)
{
bool disable = DisableLayout(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 = DisableLayout(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 DisableLayout(EditorLayoutEnableType enableType)
{
return (enableType == EditorLayoutEnableType.Disabled || (enableType == EditorLayoutEnableType.DisabledWhilePlaying && Application.isPlaying));
}
}
}
#endif

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: dd42f76391fc1254f82767dbf1a4bc8b
timeCreated: 1525378031
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,130 @@
using System;
namespace GameKit.Utilities
{
public static class Enums
{
/// <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 Contains(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;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: e6c66aec505f9254491b2b126a2d4745
timeCreated: 1522959833
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,232 @@
using System;
using UnityEngine;
namespace GameKit.Utilities
{
public static class Floats
{
/// <summary>
/// Used to randomize float values.
/// </summary>
private static System.Random _random = new System.Random();
/// <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);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 4ab517aa5c3b6e34ca20461339adda04
timeCreated: 1526172456
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,23 @@
{
"name": "GameKit.Utilities",
"rootNamespace": "",
"references": [
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:36bccdedfe0feeb4daf43bef9e43b65b"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.textmeshpro",
"expression": "",
"define": "TEXTMESHPRO"
}
],
"noEngineReferences": false
}

View File

@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 17013b2a21298c14ea4808251346a38a
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,85 @@
namespace GameKit.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;
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3a54dd369b7206e4f9e7716a42e53454
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,91 @@

using UnityEngine;
namespace GameKit.Utilities
{
/// <summary>
/// Various utility classes relating to floats.
/// </summary>
public static class Ints
{
private static System.Random _random = new System.Random();
/// <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;
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: c673118198f5c4b41986d52762828363
timeCreated: 1527268448
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using UnityEngine;
namespace GameKit.Utilities
{
public static class Layers
{
/// <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)));
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 1c18e15e44d21a94d8919f4b6b125a1f
timeCreated: 1522349045
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
using UnityEngine;
using UnityEngine.UI;
namespace GameKit.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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e330113395c59ca4dba5de001e010f08
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
using UnityEngine;
namespace GameKit.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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 27a618c551d5fdb4ca70bf07e1905580
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,34 @@
namespace GameKit.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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 18a583dc22a9a0f4cabec0c4a0219c6e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,548 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace GameKit.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 where T2 : IResettable
{
/// <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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(Dictionary<T1, T2> value)
{
foreach (KeyValuePair<T1, T2> kvp in value)
{
kvp.Key.ResetState();
ObjectCaches<T1>.Store(kvp.Key);
kvp.Value.ResetState();
ObjectCaches<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
{
/// <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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(Dictionary<T1, T2> value)
{
foreach (T1 item in value.Keys)
{
item.ResetState();
ObjectCaches<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
{
/// <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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(Dictionary<T1, T2> value)
{
foreach (T2 item in value.Values)
{
item.ResetState();
ObjectCaches<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
{
/// <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 HashSet<T> RetrieveHashSet() => CollectionCaches<T>.RetrieveHashSet();
/// <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)
{
if (value == null)
return;
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)
{
for (int i = 0; i < count; i++)
{
value[i].ResetState();
ObjectCaches<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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(List<T> value)
{
for (int i = 0; i < value.Count; i++)
{
value[i].ResetState();
ObjectCaches<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 HashSet<T> value)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(HashSet<T> value)
{
foreach (T item in value)
{
item.ResetState();
ObjectCaches<T>.Store(item);
}
value.Clear();
CollectionCaches<T>.Store(value);
}
}
/// <summary>
/// Caches objects of a single generic.
/// </summary>
public static class ResettableObjectCaches<T> where T : IResettable
{
/// <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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores an instance of T.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(T value)
{
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 readonly static Stack<Dictionary<T1, T2>> _dictionaryCache = new Stack<Dictionary<T1, T2>>();
/// <summary>
/// Retrieves a collection.
/// </summary>
/// <returns></returns>
public static Dictionary<T1, T2> RetrieveDictionary()
{
if (_dictionaryCache.Count == 0)
return new Dictionary<T1, T2>();
else
return _dictionaryCache.Pop();
}
/// <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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(Dictionary<T1, T2> value)
{
value.Clear();
_dictionaryCache.Push(value);
}
}
/// <summary>
/// Caches collections of a single generic.
/// </summary>
public static class CollectionCaches<T>
{
/// <summary>
/// Cache for arrays.
/// </summary>
private readonly static Stack<T[]> _arrayCache = new Stack<T[]>();
/// <summary>
/// Cache for lists.
/// </summary>
private readonly static Stack<List<T>> _listCache = new Stack<List<T>>();
/// <summary>
/// Cache for hashset.
/// </summary>
private readonly static Stack<HashSet<T>> _hashsetCache = new Stack<HashSet<T>>();
/// <summary>
/// Retrieves a collection.
/// </summary>
/// <returns></returns>
public static T[] RetrieveArray()
{
if (_arrayCache.Count == 0)
return new T[0];
else
return _arrayCache.Pop();
}
/// <summary>
/// Retrieves a collection.
/// </summary>
/// <returns></returns>
public static List<T> RetrieveList()
{
if (_listCache.Count == 0)
return new List<T>();
else
return _listCache.Pop();
}
/// <summary>
/// Retrieves a collection adding one entry.
/// </summary>
/// <returns></returns>
public static List<T> RetrieveList(T entry)
{
List<T> result;
if (_listCache.Count == 0)
result = new List<T>();
else
result = _listCache.Pop();
result.Add(entry);
return result;
}
/// <summary>
/// Retrieves a HashSet<T>.
/// </summary>
/// <returns></returns>
public static HashSet<T> RetrieveHashSet()
{
if (_hashsetCache.Count == 0)
return new HashSet<T>();
else
return _hashsetCache.Pop();
}
/// <summary>
/// Retrieves a collection adding one entry.
/// </summary>
/// <returns></returns>
public static HashSet<T> RetrieveHashSet(T entry)
{
HashSet<T> result;
if (_hashsetCache.Count == 0)
result = new HashSet<T>();
else
result = _hashsetCache.Pop();
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 from the beginning.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void StoreAndDefault(ref T[] value, int count)
{
if (value == null)
return;
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)
{
for (int i = 0; i < count; i++)
value[i] = default;
_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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(List<T> value)
{
value.Clear();
_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 HashSet<T> value)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a collection.
/// </summary>
/// <param name="value">Value to store.</param>
public static void Store(HashSet<T> value)
{
value.Clear();
_hashsetCache.Push(value);
}
}
/// <summary>
/// Caches objects of a single generic.
/// </summary>
public static class ObjectCaches<T>
{
/// <summary>
/// Stack to use.
/// </summary>
private readonly static Stack<T> _stack = new Stack<T>();
/// <summary>
/// Returns a value from the stack or creates an instance when the stack is empty.
/// </summary>
/// <returns></returns>
public static T Retrieve()
{
if (_stack.Count == 0)
return Activator.CreateInstance<T>();
else
return _stack.Pop();
}
/// <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)
{
if (value == null)
return;
Store(value);
value = default;
}
/// <summary>
/// Stores a value to the stack.
/// </summary>
/// <param name="value"></param>
public static void Store(T value)
{
_stack.Push(value);
}
}
#endregion
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 3cb13274f7491a941b6e89a767905f56
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,67 @@

using GameKit.Utilities.Types;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
namespace GameKit.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 List<T>();
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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4fa6d28a28dbf6b4295602abad3de328
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,109 @@
using UnityEngine;
namespace GameKit.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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5f3d973dcfa06554998575e8eef0938a
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
using UnityEngine;
namespace GameKit.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>
/// 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);
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 02a9084f4f788cd4293cdff56a49b5dd
timeCreated: 1522043602
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,64 @@

using System;
namespace GameKit.Utilities
{
public static class Strings
{
/// <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>
/// Returns if a string contains another string using StringComparison.
/// </summary>
/// <param name="s"></param>
/// <param name="contains"></param>
/// <param name="comp"></param>
/// <returns></returns>
public static bool Contains(this string s, string contains, StringComparison comp)
{
int index = s.IndexOf(contains, comp);
return (index >= 0);
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: b396f2be4de550a4e92b552650311600
timeCreated: 1525378031
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,177 @@
using System.Collections.Generic;
using UnityEngine;
namespace GameKit.Utilities
{
public static class Transforms
{
/// <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)
{
Vector2 scale = new Vector2(rectTransform.localScale.x, rectTransform.localScale.y);
//Value of which the tooltip would exceed screen bounds.
//If there would be overshoot then adjust to be just on the edge of the overshooting side.
float overshoot;
float halfWidthRequired = ((rectTransform.sizeDelta.x * scale.x) / 2f) + padding.x;
overshoot = (Screen.width - (desiredPosition.x + halfWidthRequired));
//If overshooting on the right.
if (overshoot < 0f)
desiredPosition.x += overshoot;
overshoot = (desiredPosition.x - halfWidthRequired);
//If overshooting on the left.
if (overshoot < 0f)
desiredPosition.x = halfWidthRequired;
float halfHeightRequired = ((rectTransform.sizeDelta.y * scale.y) / 2f) + padding.y;
overshoot = (Screen.height - (desiredPosition.y + halfHeightRequired));
//If overshooting on the right.
if (overshoot < 0f)
desiredPosition.y += overshoot;
overshoot = (desiredPosition.y - halfHeightRequired);
//If overshooting on the left.
if (overshoot < 0f)
desiredPosition.y = halfHeightRequired;
return desiredPosition;
}
/// <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>
/// <param name="t"></param>
public static void DestroyChildren(this Transform t, bool destroyImmediately = false)
{
foreach (Transform child in t)
{
if (destroyImmediately)
MonoBehaviour.DestroyImmediate(child.gameObject);
else
MonoBehaviour.Destroy(child.gameObject);
}
}
/// <summary>
/// Destroys all children of a type under the specified transform.
/// </summary>
/// <param name="t"></param>
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
MonoBehaviour.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 = GameKit.Utilities.CollectionCaches<T>.RetrieveList();
for (int i = 0; i < parent.childCount; i++)
{
parent.GetChild(i).GetComponentsInChildren(includeInactive, current);
results.AddRange(current);
}
GameKit.Utilities.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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ba23540de73f58b458e7d7a200f3bb30
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a29cd7621a70a044bb205cc8cfd96b3c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,236 @@
using GameKit.Dependencies.Inspectors;
using UnityEngine;
namespace GameKit.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, Group("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, Group("Effects")]
protected bool UpdateCanvasBlocking = true;
/// <summary>
/// How long it should take to fade in the CanvasGroup.
/// </summary>
[SerializeField, Group("Effects")]
protected float FadeInDuration = 0.1f;
/// <summary>
/// How long it should take to fade out the CanvasGroup.
/// </summary>
[SerializeField, Group("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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 6aa7bd78c33474948b74e3c7a1d97454
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: f04cb37e5f34ee749b8be696cb9c6ba3
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,59 @@
namespace GameKit.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() { }
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 1baacd2a6a8a0e94b897c6b7176c7000
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,232 @@
using GameKit.Dependencies.Inspectors;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace GameKit.Utilities.Types.CanvasContainers
{
public class FloatingContainer : CanvasGroupFader
{
#region Serialized.
/// <summary>
/// RectTransform to move.
/// </summary>
[Tooltip("RectTransform to move.")]
[SerializeField, Group("Components")]
protected RectTransform RectTransform;
/// <summary>
/// True to use edge avoidance.
/// </summary>
[Tooltip("True to use edge avoidance.")]
[SerializeField, Group("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, Group("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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f1fcd998728ace94ea809c34ad0d09e8
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,35 @@
using GameKit.Dependencies.Inspectors;
using UnityEngine;
using UnityEngine.UI;
namespace GameKit.Utilities.Types.CanvasContainers
{
public class FloatingImage : FloatingContainer
{
/// <summary>
/// Renderer to apply sprite on.
/// </summary>
[Tooltip("Renderer to apply sprite on.")]
[SerializeField, Group("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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2169e34ec7dd63a4e99b5cc89fd0e966
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,45 @@
using GameKit.Utilities.Types;
using GameKit.Utilities.Types.CanvasContainers;
using System.Collections.Generic;
namespace GameKit.Utilities.Types.OptionMenuButtons
{
public class FloatingOptions : CanvasGroupFader
{
#region Protected.
/// <summary>
/// Current buttons.
/// </summary>
protected List<ButtonData> Buttons = new List<ButtonData>();
#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)
GameKit.Utilities.ResettableObjectCaches<ButtonData>.Store(item);
Buttons.Clear();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cbc5b08db621303449f60b59f56eac92
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,37 @@
using System;
using UnityEngine;
namespace GameKit.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;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: d60e355b6d09be14487df1ed91e901b2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,29 @@
#if TEXTMESHPRO
using TMPro;
using UnityEngine;
using UnityEngine.UI;
namespace GameKit.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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 2fee1d5cad375e84eaab6a4cd1d6e915
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,36 @@
#if TEXTMESHPRO
using TMPro;
using UnityEngine;
namespace GameKit.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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 22d4118a529704b49858d02b956dc48d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,111 @@
using System.Collections.Generic;
using UnityEngine;
namespace GameKit.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 List<ResizeData>();
/// <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 GameObject(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);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c4b4655d59b39584faed638f43d4d287
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,53 @@
using System.Runtime.CompilerServices;
using UnityEngine;
namespace GameKit.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 FloatRange2D()
{
X = new FloatRange(0f, 999999f),
Y = new FloatRange(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);
base.RectTransform.sizeDelta = new Vector2(widthRequired, heightRequired);
base.Move();
base.Show();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5764e627642cf5643a3f4518d450840e
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,46 @@
using System;
using UnityEngine;
namespace GameKit.Utilities.Types
{
public class DDOL : MonoBehaviour
{
#region Public.
/// <summary>
/// Singleton instance of this class.
/// </summary>
[Obsolete("Use GetDDOL().")] //Remove on 2023/06/01.
public static DDOL Instance => GetDDOL();
/// <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 GameObject();
obj.name = "FirstGearGames DDOL";
DDOL ddol = obj.AddComponent<DDOL>();
DontDestroyOnLoad(ddol);
_instance = ddol;
return ddol;
}
//Already made.
else
{
return _instance;
}
}
}
}

View File

@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 4e0b25628cfd4f241a22a7c0ee2b932f
timeCreated: 1528404670
licenseType: Store
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a4e1653f734aa924a947707391413c6c
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
#if UNITY_EDITOR
using UnityEditor;
using UnityEngine;
namespace GameKit.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

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c144891e57ef5054d9b7e03b82c00cf2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,40 @@
using UnityEngine;
namespace GameKit.Utilities.Types
{
[System.Serializable]
public struct FloatRange
{
public FloatRange(float minimum, float maximum)
{
Minimum = minimum;
Maximum = maximum;
}
/// <summary>
/// Minimum range.
/// </summary>
public float Minimum;
/// <summary>
/// Maximum range.
/// </summary>
public float Maximum;
/// <summary>
/// Returns a random value between Minimum and Maximum.
/// </summary>
/// <returns></returns>
public float RandomInclusive()
{
return Floats.RandomInclusiveRange(Minimum, Maximum);
}
public float Lerp(float percent)
{
return Mathf.Lerp(Minimum, Maximum, percent);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 35d4414338c0ab248a1b838402887ac0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,58 @@
using UnityEngine;
namespace GameKit.Utilities.Types
{
[System.Serializable]
public struct FloatRange2D
{
public FloatRange X;
public FloatRange Y;
public FloatRange2D(FloatRange x, FloatRange y)
{
X = x;
Y = y;
}
public FloatRange2D(float xMin, float xMax, float yMin, float yMax)
{
X = new FloatRange(xMin, xMax);
Y = new FloatRange(yMin, yMax);
}
public Vector2 Clamp(Vector2 original)
{
return new Vector2(
ClampX(original.x),
ClampY(original.y)
);
}
public Vector3 Clamp(Vector3 original)
{
return new Vector3(
ClampX(original.x),
ClampY(original.y),
original.z
);
}
public float ClampX(float original)
{
return Mathf.Clamp(original, X.Minimum, X.Maximum);
}
public float ClampY(float original)
{
return Mathf.Clamp(original, Y.Minimum, Y.Maximum);
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4a2c6d65e69e9154b8f99096ed3096dc
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,55 @@
namespace GameKit.Utilities.Types
{
[System.Serializable]
public struct IntRange
{
public IntRange(int minimum, int maximum)
{
Minimum = minimum;
Maximum = maximum;
}
/// <summary>
/// Minimum range.
/// </summary>
public int Minimum;
/// <summary>
/// Maximum range.
/// </summary>
public int Maximum;
/// <summary>
/// Returns an exclusive random value between Minimum and Maximum.
/// </summary>
/// <returns></returns>
public float RandomExclusive()
{
return Ints.RandomExclusiveRange(Minimum, Maximum);
}
/// <summary>
/// Returns an inclusive random value between Minimum and Maximum.
/// </summary>
/// <returns></returns>
public float RandomInclusive()
{
return Ints.RandomInclusiveRange(Minimum, Maximum);
}
/// <summary>
/// Returns value clamped within minimum and maximum.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public int Clamp(int value)
{
if (value < Minimum)
return Minimum;
if (value > Maximum)
return Maximum;
return value;
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 16f03af589a154c47bcbcc3f82b710a6
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 05bf45e6c53189b428920bb4f1f4244d
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

Some files were not shown because too many files have changed in this diff Show More