架构大更

This commit is contained in:
SoulliesOfficial
2026-03-20 11:56:50 -04:00
parent e60ef64d01
commit d09b58fd80
3663 changed files with 15232012 additions and 105579 deletions

View File

@@ -46,7 +46,7 @@
.mm-toolbar {
margin-top: 5px;
border-width: 0px;
}
.mm-toolbar ToolbarButton {
@@ -60,20 +60,17 @@
-unity-text-align: middle-center;
}
.mm-fixed-width-floatfield FloatInput TextElement
{
.mm-fixed-width-floatfield FloatInput TextElement {
width: 50px;
}
.mm-fixed-width-floatfield Label
{
.mm-fixed-width-floatfield Label {
min-width: 50px;
}
/* Spring */
/* Spring */
.mm-spring-debug-track-background
{
.mm-spring-debug-track-background {
margin-top: 5px;
background-color: rgba(0, 0, 0, 0.5);
height: 20px;
@@ -82,16 +79,14 @@
justify-content: flex-start;
}
.mm-spring-debug-track-foreground
{
.mm-spring-debug-track-foreground {
background-color: rgba(255, 196, 0, 1);
height: 20px;
width: 10px;
margin-top: -20px;
margin-top: -20px;
}
.mm-spring-debug-track-foreground-container-left
{
.mm-spring-debug-track-foreground-container-left {
background-color: green;
height: 20px;
width: 50%;
@@ -101,8 +96,7 @@
justify-content: flex-end;
}
.mm-spring-debug-track-foreground-container-right
{
.mm-spring-debug-track-foreground-container-right {
background-color: blue;
height: 20px;
width: 50%;

View File

@@ -1,102 +1,110 @@
using UnityEngine;
using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace MoreMountains.Tools
{
[CustomPropertyDrawer(typeof(MMVectorAttribute))]
public class MMVectorLabelsAttributeDrawer : PropertyDrawer
{
protected static readonly GUIContent[] originalLabels = new GUIContent[] { new GUIContent("X"), new GUIContent("Y"), new GUIContent("Z"), new GUIContent("W") };
protected const int padding = 375;
[CustomPropertyDrawer(typeof(MMVectorAttribute))]
public class MMVectorLabelsAttributeDrawer : PropertyDrawer
{
protected const int padding = 375;
protected static readonly GUIContent[] originalLabels = { new("X"), new("Y"), new("Z"), new("W") };
public override float GetPropertyHeight(SerializedProperty property, GUIContent guiContent)
{
int ratio = (padding > Screen.width) ? 2 : 1;
return ratio * base.GetPropertyHeight(property, guiContent);
}
#if UNITY_EDITOR
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent guiContent)
{
MMVectorAttribute vector = (MMVectorAttribute)attribute;
if (property.propertyType == SerializedPropertyType.Vector2)
{
float[] fieldArray = new float[] { property.vector2Value.x, property.vector2Value.y };
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name), EditorGUI.FloatField, vector, guiContent);
property.vector2Value = new Vector2(fieldArray[0], fieldArray[1]);
}
else if (property.propertyType == SerializedPropertyType.Vector3)
{
float[] fieldArray = new float[] { property.vector3Value.x, property.vector3Value.y, property.vector3Value.z };
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name), EditorGUI.FloatField, vector, guiContent);
property.vector3Value = new Vector3(fieldArray[0], fieldArray[1], fieldArray[2]);
}
else if (property.propertyType == SerializedPropertyType.Vector4)
{
float[] fieldArray = new float[] { property.vector4Value.x, property.vector4Value.y, property.vector4Value.z, property.vector4Value.w };
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name), EditorGUI.FloatField, vector, guiContent);
property.vector4Value = new Vector4(fieldArray[0], fieldArray[1], fieldArray[2]);
}
else if (property.propertyType == SerializedPropertyType.Vector2Int)
{
int[] fieldArray = new int[] { property.vector2IntValue.x, property.vector2IntValue.y };
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name), EditorGUI.IntField, vector, guiContent);
property.vector2IntValue = new Vector2Int(fieldArray[0], fieldArray[1]);
}
else if (property.propertyType == SerializedPropertyType.Vector3Int)
{
int[] array = new int[] { property.vector3IntValue.x, property.vector3IntValue.y, property.vector3IntValue.z };
array = DrawFields(rect, array, ObjectNames.NicifyVariableName(property.name), EditorGUI.IntField, vector, guiContent);
property.vector3IntValue = new Vector3Int(array[0], array[1], array[2]);
}
}
#endif
public override float GetPropertyHeight(SerializedProperty property, GUIContent guiContent)
{
var ratio = padding > Screen.width ? 2 : 1;
return ratio * base.GetPropertyHeight(property, guiContent);
}
protected T[] DrawFields<T>(Rect rect, T[] vector, string mainLabel, System.Func<Rect, GUIContent, T, T> fieldDrawer, MMVectorAttribute vectors, GUIContent originalGuiContent)
{
T[] result = vector;
#if UNITY_EDITOR
public override void OnGUI(Rect rect, SerializedProperty property, GUIContent guiContent)
{
var vector = (MMVectorAttribute)attribute;
bool shortSpace = (Screen.width < padding);
if (property.propertyType == SerializedPropertyType.Vector2)
{
var fieldArray = new[] { property.vector2Value.x, property.vector2Value.y };
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name),
EditorGUI.FloatField, vector, guiContent);
property.vector2Value = new Vector2(fieldArray[0], fieldArray[1]);
}
else if (property.propertyType == SerializedPropertyType.Vector3)
{
var fieldArray = new[] { property.vector3Value.x, property.vector3Value.y, property.vector3Value.z };
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name),
EditorGUI.FloatField, vector, guiContent);
property.vector3Value = new Vector3(fieldArray[0], fieldArray[1], fieldArray[2]);
}
else if (property.propertyType == SerializedPropertyType.Vector4)
{
var fieldArray = new[]
{
property.vector4Value.x, property.vector4Value.y, property.vector4Value.z, property.vector4Value.w
};
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name),
EditorGUI.FloatField, vector, guiContent);
property.vector4Value = new Vector4(fieldArray[0], fieldArray[1], fieldArray[2]);
}
else if (property.propertyType == SerializedPropertyType.Vector2Int)
{
var fieldArray = new[] { property.vector2IntValue.x, property.vector2IntValue.y };
fieldArray = DrawFields(rect, fieldArray, ObjectNames.NicifyVariableName(property.name),
EditorGUI.IntField, vector, guiContent);
property.vector2IntValue = new Vector2Int(fieldArray[0], fieldArray[1]);
}
else if (property.propertyType == SerializedPropertyType.Vector3Int)
{
var array = new[]
{ property.vector3IntValue.x, property.vector3IntValue.y, property.vector3IntValue.z };
array = DrawFields(rect, array, ObjectNames.NicifyVariableName(property.name), EditorGUI.IntField,
vector, guiContent);
property.vector3IntValue = new Vector3Int(array[0], array[1], array[2]);
}
}
#endif
Rect mainLabelRect = rect;
mainLabelRect.width = EditorGUIUtility.labelWidth;
if (shortSpace)
{
mainLabelRect.height *= 0.5f;
}
protected T[] DrawFields<T>(Rect rect, T[] vector, string mainLabel, Func<Rect, GUIContent, T, T> fieldDrawer,
MMVectorAttribute vectors, GUIContent originalGuiContent)
{
var result = vector;
Rect fieldRect = rect;
if (shortSpace)
{
fieldRect.height *= 0.5f;
fieldRect.y += fieldRect.height;
fieldRect.width = rect.width / vector.Length;
}
else
{
fieldRect.x += mainLabelRect.width;
fieldRect.width = (rect.width - mainLabelRect.width) / vector.Length;
}
GUIContent mainLabelContent = new GUIContent();
mainLabelContent.text = mainLabel;
mainLabelContent.tooltip = originalGuiContent.tooltip;
EditorGUI.LabelField(mainLabelRect, mainLabelContent);
var shortSpace = Screen.width < padding;
for (int i = 0; i < vector.Length; i++)
{
GUIContent label = vectors.Labels.Length > i ? new GUIContent(vectors.Labels[i]) : originalLabels[i];
Vector2 labelSize = EditorStyles.label.CalcSize(label);
EditorGUIUtility.labelWidth = Mathf.Max(labelSize.x + 5, 0.3f * fieldRect.width);
result[i] = fieldDrawer(fieldRect, label, vector[i]);
fieldRect.x += fieldRect.width;
}
var mainLabelRect = rect;
mainLabelRect.width = EditorGUIUtility.labelWidth;
if (shortSpace) mainLabelRect.height *= 0.5f;
EditorGUIUtility.labelWidth = 0;
return result;
}
}
var fieldRect = rect;
if (shortSpace)
{
fieldRect.height *= 0.5f;
fieldRect.y += fieldRect.height;
fieldRect.width = rect.width / vector.Length;
}
else
{
fieldRect.x += mainLabelRect.width;
fieldRect.width = (rect.width - mainLabelRect.width) / vector.Length;
}
var mainLabelContent = new GUIContent();
mainLabelContent.text = mainLabel;
mainLabelContent.tooltip = originalGuiContent.tooltip;
EditorGUI.LabelField(mainLabelRect, mainLabelContent);
for (var i = 0; i < vector.Length; i++)
{
var label = vectors.Labels.Length > i ? new GUIContent(vectors.Labels[i]) : originalLabels[i];
var labelSize = EditorStyles.label.CalcSize(label);
EditorGUIUtility.labelWidth = Mathf.Max(labelSize.x + 5, 0.3f * fieldRect.width);
result[i] = fieldDrawer(fieldRect, label, vector[i]);
fieldRect.x += fieldRect.width;
}
EditorGUIUtility.labelWidth = 0;
return result;
}
}
}

View File

@@ -1,36 +1,36 @@
using UnityEngine;
using System.Collections;
using UnityEditor;
using MoreMountains.Tools;
using UnityEditor;
using UnityEngine;
namespace MoreMountains.Tools
{
[CustomEditor(typeof(MMObjectBounds),true)]
public class ObjectBoundsEditor : Editor
{
protected MMObjectBounds _objectBounds;
{
[CustomEditor(typeof(MMObjectBounds), true)]
public class ObjectBoundsEditor : Editor
{
protected MMObjectBounds _objectBounds;
public override void OnInspectorGUI()
{
_objectBounds = (MMObjectBounds)target;
public override void OnInspectorGUI()
{
_objectBounds = (MMObjectBounds)target;
DrawDefaultInspector();
DrawDefaultInspector();
if (_objectBounds.GetComponent<Renderer>()==null && _objectBounds.BoundsBasedOn==MMObjectBounds.WaysToDetermineBounds.Renderer)
{
EditorGUILayout.HelpBox("You've defined this object as having Renderer defined bounds, but no renderer is attached to the object. Add a Renderer, or switch to collider based bounds. The bounds are the dimensions that will be used when spawning your object and to determine when it should be recycled.",MessageType.Warning);
}
if (_objectBounds.GetComponent<Renderer>() == null &&
_objectBounds.BoundsBasedOn == MMObjectBounds.WaysToDetermineBounds.Renderer)
EditorGUILayout.HelpBox(
"You've defined this object as having Renderer defined bounds, but no renderer is attached to the object. Add a Renderer, or switch to collider based bounds. The bounds are the dimensions that will be used when spawning your object and to determine when it should be recycled.",
MessageType.Warning);
if (_objectBounds.GetComponent<Collider>()==null && _objectBounds.BoundsBasedOn==MMObjectBounds.WaysToDetermineBounds.Collider)
{
EditorGUILayout.HelpBox("You've defined this object as having Collider defined bounds, but no Collider is attached to the object. Add a Collider, or switch to renderer based bounds. The bounds are the dimensions that will be used when spawning your object and to determine when it should be recycled.",MessageType.Warning);
}
if (_objectBounds.GetComponent<Collider>() == null &&
_objectBounds.BoundsBasedOn == MMObjectBounds.WaysToDetermineBounds.Collider)
EditorGUILayout.HelpBox(
"You've defined this object as having Collider defined bounds, but no Collider is attached to the object. Add a Collider, or switch to renderer based bounds. The bounds are the dimensions that will be used when spawning your object and to determine when it should be recycled.",
MessageType.Warning);
if (_objectBounds.GetComponent<Collider2D>()==null && _objectBounds.BoundsBasedOn==MMObjectBounds.WaysToDetermineBounds.Collider2D)
{
EditorGUILayout.HelpBox("You've defined this object as having Collider2D defined bounds, but no Collider2D is attached to the object. Add a Collider2D, or switch to renderer based bounds. The bounds are the dimensions that will be used when spawning your object and to determine when it should be recycled.",MessageType.Warning);
}
}
}
if (_objectBounds.GetComponent<Collider2D>() == null &&
_objectBounds.BoundsBasedOn == MMObjectBounds.WaysToDetermineBounds.Collider2D)
EditorGUILayout.HelpBox(
"You've defined this object as having Collider2D defined bounds, but no Collider2D is attached to the object. Add a Collider2D, or switch to renderer based bounds. The bounds are the dimensions that will be used when spawning your object and to determine when it should be recycled.",
MessageType.Warning);
}
}
}

View File

@@ -4,98 +4,97 @@ using UnityEngine;
namespace MoreMountains.Tools
{
[CustomPropertyDrawer(typeof(MMReorderableAttributeAttribute))]
public class ReorderableDrawer : PropertyDrawer {
[CustomPropertyDrawer(typeof(MMReorderableAttributeAttribute))]
public class ReorderableDrawer : PropertyDrawer
{
private static readonly Dictionary<int, MMReorderableList> lists = new();
private static Dictionary<int, MMReorderableList> lists = new Dictionary<int, MMReorderableList>();
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
var list = GetList(property, attribute as MMReorderableAttributeAttribute);
public override float GetPropertyHeight(SerializedProperty property, GUIContent label) {
return list != null ? list.GetHeight() : EditorGUIUtility.singleLineHeight;
}
MMReorderableList list = GetList(property, attribute as MMReorderableAttributeAttribute);
#if UNITY_EDITOR
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
var list = GetList(property, attribute as MMReorderableAttributeAttribute);
return list != null ? list.GetHeight() : EditorGUIUtility.singleLineHeight;
}
#if UNITY_EDITOR
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) {
if (list != null)
list.DoList(EditorGUI.IndentedRect(position), label);
else
GUI.Label(position, "Array must extend from ReorderableArray", EditorStyles.label);
}
#endif
MMReorderableList list = GetList(property, attribute as MMReorderableAttributeAttribute);
public static int GetListId(SerializedProperty property)
{
if (property != null)
{
var h1 = property.serializedObject.targetObject.GetHashCode();
var h2 = property.propertyPath.GetHashCode();
if (list != null) {
return ((h1 << 5) + h1) ^ h2;
}
list.DoList(EditorGUI.IndentedRect(position), label);
}
else {
return 0;
}
GUI.Label(position, "Array must extend from ReorderableArray", EditorStyles.label);
}
}
#endif
public static MMReorderableList GetList(SerializedProperty property)
{
return GetList(property, null, GetListId(property));
}
public static int GetListId(SerializedProperty property) {
public static MMReorderableList GetList(SerializedProperty property, MMReorderableAttributeAttribute attrib)
{
return GetList(property, attrib, GetListId(property));
}
if (property != null) {
public static MMReorderableList GetList(SerializedProperty property, int id)
{
return GetList(property, null, id);
}
int h1 = property.serializedObject.targetObject.GetHashCode();
int h2 = property.propertyPath.GetHashCode();
public static MMReorderableList GetList(SerializedProperty property, MMReorderableAttributeAttribute attrib,
int id)
{
if (property == null) return null;
return (((h1 << 5) + h1) ^ h2);
}
MMReorderableList list = null;
var array = property.FindPropertyRelative("array");
return 0;
}
if (array != null && array.isArray)
{
if (!lists.TryGetValue(id, out list))
{
if (attrib != null)
{
var icon = !string.IsNullOrEmpty(attrib.elementIconPath)
? AssetDatabase.GetCachedIcon(attrib.elementIconPath)
: null;
public static MMReorderableList GetList(SerializedProperty property) {
var displayType = attrib.singleLine
? MMReorderableList.ElementDisplayType.SingleLine
: MMReorderableList.ElementDisplayType.Auto;
return GetList(property, null, GetListId(property));
}
list = new MMReorderableList(array, attrib.add, attrib.remove, attrib.draggable, displayType,
attrib.elementNameProperty, attrib.elementNameOverride, icon);
}
else
{
list = new MMReorderableList(array, true, true, true);
}
public static MMReorderableList GetList(SerializedProperty property, MMReorderableAttributeAttribute attrib) {
lists.Add(id, list);
}
else
{
list.List = array;
}
}
return GetList(property, attrib, GetListId(property));
}
public static MMReorderableList GetList(SerializedProperty property, int id) {
return GetList(property, null, id);
}
public static MMReorderableList GetList(SerializedProperty property, MMReorderableAttributeAttribute attrib, int id) {
if (property == null) {
return null;
}
MMReorderableList list = null;
SerializedProperty array = property.FindPropertyRelative("array");
if (array != null && array.isArray) {
if (!lists.TryGetValue(id, out list)) {
if (attrib != null) {
Texture icon = !string.IsNullOrEmpty(attrib.elementIconPath) ? AssetDatabase.GetCachedIcon(attrib.elementIconPath) : null;
MMReorderableList.ElementDisplayType displayType = attrib.singleLine ? MMReorderableList.ElementDisplayType.SingleLine : MMReorderableList.ElementDisplayType.Auto;
list = new MMReorderableList(array, attrib.add, attrib.remove, attrib.draggable, displayType, attrib.elementNameProperty, attrib.elementNameOverride, icon);
}
else {
list = new MMReorderableList(array, true, true, true);
}
lists.Add(id, list);
}
else {
list.List = array;
}
}
return list;
}
}
return list;
}
}
}

View File

@@ -1,24 +1,24 @@
{
"name": "MoreMountains.Tools.Editor",
"rootNamespace": "",
"references": [
"GUID:4a1cb1490dc4df8409b2580d6b44e75e"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.modules.physics2d",
"expression": "1.0.0",
"define": "MM_PHYSICS2D"
}
],
"noEngineReferences": false
"name": "MoreMountains.Tools.Editor",
"rootNamespace": "",
"references": [
"GUID:4a1cb1490dc4df8409b2580d6b44e75e"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.modules.physics2d",
"expression": "1.0.0",
"define": "MM_PHYSICS2D"
}
],
"noEngineReferences": false
}

View File

@@ -1,34 +1,39 @@
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace MoreMountains.Tools
{
public class MMInformationAttribute : PropertyAttribute
{
public enum InformationType { Error, Info, None, Warning }
{
public class MMInformationAttribute : PropertyAttribute
{
public enum InformationType
{
Error,
Info,
None,
Warning
}
#if UNITY_EDITOR
public string Message;
public MessageType Type;
public bool MessageAfterProperty;
#if UNITY_EDITOR
public string Message;
public MessageType Type;
public bool MessageAfterProperty;
public MMInformationAttribute(string message, InformationType type, bool messageAfterProperty)
{
this.Message = message;
if (type==InformationType.Error) { this.Type = UnityEditor.MessageType.Error;}
if (type==InformationType.Info) { this.Type = UnityEditor.MessageType.Info;}
if (type==InformationType.Warning) { this.Type = UnityEditor.MessageType.Warning;}
if (type==InformationType.None) { this.Type = UnityEditor.MessageType.None;}
this.MessageAfterProperty = messageAfterProperty;
}
#else
public MMInformationAttribute(string message, InformationType type, bool messageAfterProperty)
{
Message = message;
if (type == InformationType.Error) Type = MessageType.Error;
if (type == InformationType.Info) Type = MessageType.Info;
if (type == InformationType.Warning) Type = MessageType.Warning;
if (type == InformationType.None) Type = MessageType.None;
MessageAfterProperty = messageAfterProperty;
}
#else
public MMInformationAttribute(string message, InformationType type, bool messageAfterProperty)
{
}
#endif
}
#endif
}
}

View File

@@ -6,49 +6,44 @@ using UnityEditor;
namespace MoreMountains.Tools
{
/// <summary>
/// This class will automatically destroy the object when entering play mode, and will destroy it again when exiting play mode.
/// This is used for instance by the sound feedbacks to ensure that test audio sources created outside of play mode don't persist in your scene
/// This class will automatically destroy the object when entering play mode, and will destroy it again when exiting
/// play mode.
/// This is used for instance by the sound feedbacks to ensure that test audio sources created outside of play mode
/// don't persist in your scene
/// </summary>
public class MMForceDestroyInPlayMode : MonoBehaviour
{
#if UNITY_EDITOR
static MMForceDestroyInPlayMode()
{
EditorApplication.playModeStateChanged += ModeChanged;
}
{
private void Awake()
{
if (Application.isPlaying) Delete();
}
private static void ModeChanged(PlayModeStateChange playModeState)
{
switch (playModeState)
{
case PlayModeStateChange.EnteredEditMode:
DeleteAll();
break;
}
}
private void Delete()
{
DestroyImmediate(gameObject);
}
#if UNITY_EDITOR
static MMForceDestroyInPlayMode()
{
EditorApplication.playModeStateChanged += ModeChanged;
}
static void DeleteAll()
{
MMForceDestroyInPlayMode[] sounds = FindObjectsByType<MMForceDestroyInPlayMode>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (var sound in sounds)
{
sound.Delete();
}
}
#endif
void Awake()
{
if (Application.isPlaying)
{
Delete();
}
}
void Delete()
{
DestroyImmediate(this.gameObject);
}
}
}
private static void ModeChanged(PlayModeStateChange playModeState)
{
switch (playModeState)
{
case PlayModeStateChange.EnteredEditMode:
DeleteAll();
break;
}
}
private static void DeleteAll()
{
var sounds =
FindObjectsByType<MMForceDestroyInPlayMode>(FindObjectsInactive.Include, FindObjectsSortMode.None);
foreach (var sound in sounds) sound.Delete();
}
#endif
}
}

View File

@@ -1,26 +1,27 @@
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace MoreMountains.Tools
{
/// <summary>
/// A simple struct used to store information about the sounds played by the MMSoundManager
/// A simple struct used to store information about the sounds played by the MMSoundManager
/// </summary>
[Serializable]
public struct MMSoundManagerSound
{
/// the ID of the sound
public int ID;
/// the track the sound is being played on
public MMSoundManager.MMSoundManagerTracks Track;
/// the associated audiosource
public AudioSource Source;
/// whether or not this sound will play over multiple scenes
public bool Persistent;
public struct MMSoundManagerSound
{
/// the ID of the sound
public int ID;
public float PlaybackTime;
public float PlaybackDuration;
}
/// the track the sound is being played on
public MMSoundManager.MMSoundManagerTracks Track;
/// the associated audiosource
public AudioSource Source;
/// whether or not this sound will play over multiple scenes
public bool Persistent;
public float PlaybackTime;
public float PlaybackDuration;
}
}

View File

@@ -1,115 +1,105 @@
using UnityEngine;
using System.Collections;
namespace MoreMountains.Tools
{
{
/// <summary>
/// Bounds helpers
/// Bounds helpers
/// </summary>
public class MMBoundsExtensions : MonoBehaviour
{
/// <summary>
/// Returns a random point within the bounds set as parameter
/// </summary>
/// <param name="bounds"></param>
/// <returns></returns>
public static Vector3 MMRandomPointInBounds(Bounds bounds)
{
return new Vector3(
Random.Range(bounds.min.x, bounds.max.x),
Random.Range(bounds.min.y, bounds.max.y),
Random.Range(bounds.min.z, bounds.max.z)
);
}
public class MMBoundsExtensions : MonoBehaviour
{
/// <summary>
/// Returns a random point within the bounds set as parameter
/// </summary>
/// <param name="bounds"></param>
/// <returns></returns>
public static Vector3 MMRandomPointInBounds(Bounds bounds)
{
return new Vector3(
Random.Range(bounds.min.x, bounds.max.x),
Random.Range(bounds.min.y, bounds.max.y),
Random.Range(bounds.min.z, bounds.max.z)
);
}
/// <summary>
/// Gets collider bounds for an object (from Collider2D)
/// </summary>
/// <param name="theObject"></param>
/// <returns></returns>
public static Bounds GetColliderBounds(GameObject theObject)
{
Bounds returnBounds;
/// <summary>
/// Gets collider bounds for an object (from Collider2D)
/// </summary>
/// <param name="theObject"></param>
/// <returns></returns>
public static Bounds GetColliderBounds(GameObject theObject)
{
Bounds returnBounds;
// if the object has a collider at root level, we base our calculations on that
if (theObject.GetComponent<Collider>()!=null)
{
returnBounds = theObject.GetComponent<Collider>().bounds;
return returnBounds;
}
// if the object has a collider at root level, we base our calculations on that
if (theObject.GetComponent<Collider>() != null)
{
returnBounds = theObject.GetComponent<Collider>().bounds;
return returnBounds;
}
// if the object has a collider2D at root level, we base our calculations on that
#if MM_PHYSICS2D
if (theObject.GetComponent<Collider2D>()!=null)
{
returnBounds = theObject.GetComponent<Collider2D>().bounds;
return returnBounds;
}
#endif
// if the object has a collider2D at root level, we base our calculations on that
#if MM_PHYSICS2D
if (theObject.GetComponent<Collider2D>() != null)
{
returnBounds = theObject.GetComponent<Collider2D>().bounds;
return returnBounds;
}
#endif
// if the object contains at least one Collider we'll add all its children's Colliders bounds
if (theObject.GetComponentInChildren<Collider>()!=null)
{
Bounds totalBounds = theObject.GetComponentInChildren<Collider>().bounds;
Collider[] colliders = theObject.GetComponentsInChildren<Collider>();
foreach (Collider col in colliders)
{
totalBounds.Encapsulate(col.bounds);
}
returnBounds = totalBounds;
return returnBounds;
}
// if the object contains at least one Collider we'll add all its children's Colliders bounds
if (theObject.GetComponentInChildren<Collider>() != null)
{
var totalBounds = theObject.GetComponentInChildren<Collider>().bounds;
var colliders = theObject.GetComponentsInChildren<Collider>();
foreach (var col in colliders) totalBounds.Encapsulate(col.bounds);
returnBounds = totalBounds;
return returnBounds;
}
#if MM_PHYSICS2D
// if the object contains at least one Collider2D we'll add all its children's Collider2Ds bounds
if (theObject.GetComponentInChildren<Collider2D>()!=null)
{
Bounds totalBounds = theObject.GetComponentInChildren<Collider2D>().bounds;
Collider2D[] colliders = theObject.GetComponentsInChildren<Collider2D>();
foreach (Collider2D col in colliders)
{
totalBounds.Encapsulate(col.bounds);
}
returnBounds = totalBounds;
return returnBounds;
}
#endif
#if MM_PHYSICS2D
// if the object contains at least one Collider2D we'll add all its children's Collider2Ds bounds
if (theObject.GetComponentInChildren<Collider2D>() != null)
{
var totalBounds = theObject.GetComponentInChildren<Collider2D>().bounds;
var colliders = theObject.GetComponentsInChildren<Collider2D>();
foreach (var col in colliders) totalBounds.Encapsulate(col.bounds);
returnBounds = totalBounds;
return returnBounds;
}
#endif
returnBounds = new Bounds(Vector3.zero, Vector3.zero);
return returnBounds;
}
returnBounds = new Bounds(Vector3.zero, Vector3.zero);
return returnBounds;
}
/// <summary>
/// Gets bounds of a renderer
/// </summary>
/// <param name="theObject"></param>
/// <returns></returns>
public static Bounds GetRendererBounds(GameObject theObject)
{
Bounds returnBounds;
/// <summary>
/// Gets bounds of a renderer
/// </summary>
/// <param name="theObject"></param>
/// <returns></returns>
public static Bounds GetRendererBounds(GameObject theObject)
{
Bounds returnBounds;
// if the object has a renderer at root level, we base our calculations on that
if (theObject.GetComponent<Renderer>()!=null)
{
returnBounds = theObject.GetComponent<Renderer>().bounds;
return returnBounds;
}
// if the object has a renderer at root level, we base our calculations on that
if (theObject.GetComponent<Renderer>() != null)
{
returnBounds = theObject.GetComponent<Renderer>().bounds;
return returnBounds;
}
// if the object contains at least one renderer we'll add all its children's renderer bounds
if (theObject.GetComponentInChildren<Renderer>()!=null)
{
Bounds totalBounds = theObject.GetComponentInChildren<Renderer>().bounds;
Renderer[] renderers = theObject.GetComponentsInChildren<Renderer>();
foreach (Renderer renderer in renderers)
{
totalBounds.Encapsulate(renderer.bounds);
}
returnBounds = totalBounds;
return returnBounds;
}
// if the object contains at least one renderer we'll add all its children's renderer bounds
if (theObject.GetComponentInChildren<Renderer>() != null)
{
var totalBounds = theObject.GetComponentInChildren<Renderer>().bounds;
var renderers = theObject.GetComponentsInChildren<Renderer>();
foreach (var renderer in renderers) totalBounds.Encapsulate(renderer.bounds);
returnBounds = totalBounds;
return returnBounds;
}
returnBounds = new Bounds(Vector3.zero, Vector3.zero);
return returnBounds;
}
}
returnBounds = new Bounds(Vector3.zero, Vector3.zero);
return returnBounds;
}
}
}

View File

@@ -3,46 +3,38 @@
namespace MoreMountains.Tools
{
/// <summary>
/// Camera extensions
/// Camera extensions
/// </summary>
public static class MMCameraExtensions
{
/// <summary>
/// Returns the width of the camera in world space units, at the specified depths for perspective cameras, everywhere for orthographic ones
/// </summary>
/// <param name="camera"></param>
/// <param name="depth"></param>
/// <returns></returns>
public static float MMCameraWorldSpaceWidth(this Camera camera, float depth = 0f)
{
if (camera.orthographic)
{
return camera.aspect * camera.orthographicSize * 2f;
}
else
{
float fieldOfView = camera.fieldOfView * Mathf.Deg2Rad;
return camera.aspect * depth * Mathf.Tan(fieldOfView);
}
}
{
/// <summary>
/// Returns the width of the camera in world space units, at the specified depths for perspective cameras, everywhere
/// for orthographic ones
/// </summary>
/// <param name="camera"></param>
/// <param name="depth"></param>
/// <returns></returns>
public static float MMCameraWorldSpaceWidth(this Camera camera, float depth = 0f)
{
if (camera.orthographic) return camera.aspect * camera.orthographicSize * 2f;
/// <summary>
/// Returns the height of the camera in world space units, at the specified depths for perspective cameras, everywhere for orthographic ones
/// </summary>
/// <param name="camera"></param>
/// <param name="depth"></param>
/// <returns></returns>
public static float MMCameraWorldSpaceHeight(this Camera camera, float depth = 0f)
{
if (camera.orthographic)
{
return camera.orthographicSize * 2f;
}
else
{
float fieldOfView = camera.fieldOfView * Mathf.Deg2Rad;
return depth * Mathf.Tan(fieldOfView);
}
}
}
var fieldOfView = camera.fieldOfView * Mathf.Deg2Rad;
return camera.aspect * depth * Mathf.Tan(fieldOfView);
}
/// <summary>
/// Returns the height of the camera in world space units, at the specified depths for perspective cameras, everywhere
/// for orthographic ones
/// </summary>
/// <param name="camera"></param>
/// <param name="depth"></param>
/// <returns></returns>
public static float MMCameraWorldSpaceHeight(this Camera camera, float depth = 0f)
{
if (camera.orthographic) return camera.orthographicSize * 2f;
var fieldOfView = camera.fieldOfView * Mathf.Deg2Rad;
return depth * Mathf.Tan(fieldOfView);
}
}
}

View File

@@ -3,19 +3,20 @@
namespace MoreMountains.Tools
{
/// <summary>
/// Rect extensions
/// Rect extensions
/// </summary>
public static class RectExtensions
{
/// <summary>
/// Returns true if this rectangle intersects the other specified rectangle
/// </summary>
/// <param name="thisRectangle"></param>
/// <param name="otherRectangle"></param>
/// <returns></returns>
public static bool MMIntersects(this Rect thisRectangle, Rect otherRectangle)
{
return !((thisRectangle.x > otherRectangle.xMax) || (thisRectangle.xMax < otherRectangle.x) || (thisRectangle.y > otherRectangle.yMax) || (thisRectangle.yMax < otherRectangle.y));
}
}
{
/// <summary>
/// Returns true if this rectangle intersects the other specified rectangle
/// </summary>
/// <param name="thisRectangle"></param>
/// <param name="otherRectangle"></param>
/// <returns></returns>
public static bool MMIntersects(this Rect thisRectangle, Rect otherRectangle)
{
return !(thisRectangle.x > otherRectangle.xMax || thisRectangle.xMax < otherRectangle.x ||
thisRectangle.y > otherRectangle.yMax || thisRectangle.yMax < otherRectangle.y);
}
}
}

View File

@@ -1,127 +1,103 @@
using UnityEngine;
using System.Collections.Generic;
using System.Collections.Generic;
using UnityEngine;
namespace MoreMountains.Tools
{
/// <summary>
/// Transform extensions
/// Transform extensions
/// </summary>
public static class TransformExtensions
{
/// <summary>
/// Destroys a transform's children
/// </summary>
/// <param name="transform"></param>
public static void MMDestroyAllChildren(this Transform transform)
{
for (int t = transform.childCount - 1; t >= 0; t--)
{
if (Application.isPlaying)
{
UnityEngine.Object.Destroy(transform.GetChild(t).gameObject);
}
else
{
UnityEngine.Object.DestroyImmediate(transform.GetChild(t).gameObject);
}
}
}
{
/// <summary>
/// Destroys a transform's children
/// </summary>
/// <param name="transform"></param>
public static void MMDestroyAllChildren(this Transform transform)
{
for (var t = transform.childCount - 1; t >= 0; t--)
if (Application.isPlaying)
Object.Destroy(transform.GetChild(t).gameObject);
else
Object.DestroyImmediate(transform.GetChild(t).gameObject);
}
/// <summary>
/// Finds children by name, breadth first
/// </summary>
/// <param name="parent"></param>
/// <param name="transformName"></param>
/// <returns></returns>
public static Transform MMFindDeepChildBreadthFirst(this Transform parent, string transformName)
{
Queue<Transform> queue = new Queue<Transform>();
queue.Enqueue(parent);
while (queue.Count > 0)
{
Transform child = queue.Dequeue();
if (child.name == transformName)
{
return child;
}
foreach (Transform t in child)
{
queue.Enqueue(t);
}
}
return null;
}
/// <summary>
/// Finds children by name, breadth first
/// </summary>
/// <param name="parent"></param>
/// <param name="transformName"></param>
/// <returns></returns>
public static Transform MMFindDeepChildBreadthFirst(this Transform parent, string transformName)
{
var queue = new Queue<Transform>();
queue.Enqueue(parent);
while (queue.Count > 0)
{
var child = queue.Dequeue();
if (child.name == transformName) return child;
foreach (Transform t in child) queue.Enqueue(t);
}
/// <summary>
/// Finds children by name, depth first
/// </summary>
/// <param name="parent"></param>
/// <param name="transformName"></param>
/// <returns></returns>
public static Transform MMFindDeepChildDepthFirst(this Transform parent, string transformName)
{
foreach (Transform child in parent)
{
if (child.name == transformName)
{
return child;
}
return null;
}
Transform result = child.MMFindDeepChildDepthFirst(transformName);
if (result != null)
{
return result;
}
}
return null;
}
/// <summary>
/// Finds children by name, depth first
/// </summary>
/// <param name="parent"></param>
/// <param name="transformName"></param>
/// <returns></returns>
public static Transform MMFindDeepChildDepthFirst(this Transform parent, string transformName)
{
foreach (Transform child in parent)
{
if (child.name == transformName) return child;
/// <summary>
/// Changes the layer of a transform and all its children to the new one
/// </summary>
/// <param name="transform"></param>
/// <param name="layerName"></param>
public static void ChangeLayersRecursively(this Transform transform, string layerName)
{
transform.gameObject.layer = LayerMask.NameToLayer(layerName);
foreach (Transform child in transform)
{
child.ChangeLayersRecursively(layerName);
}
}
var result = child.MMFindDeepChildDepthFirst(transformName);
if (result != null) return result;
}
/// <summary>
/// Changes the layer of a transform and all its children to the new one
/// </summary>
/// <param name="transform"></param>
/// <param name="layerIndex"></param>
public static void ChangeLayersRecursively(this Transform transform, int layerIndex)
{
transform.gameObject.layer = layerIndex;
foreach (Transform child in transform)
{
child.ChangeLayersRecursively(layerIndex);
}
}
/// <summary>
/// Enumerates all parents of a transform
/// </summary>
/// <param name="targetTransform"></param>
/// <param name="includeSelf"></param>
/// <returns></returns>
public static IEnumerable<Transform> MMEnumerateAllParents(this Transform targetTransform, bool includeSelf = false)
{
if (!includeSelf)
{
targetTransform = targetTransform?.parent;
}
while (targetTransform)
{
yield return targetTransform;
targetTransform = targetTransform.parent;
}
}
}
return null;
}
/// <summary>
/// Changes the layer of a transform and all its children to the new one
/// </summary>
/// <param name="transform"></param>
/// <param name="layerName"></param>
public static void ChangeLayersRecursively(this Transform transform, string layerName)
{
transform.gameObject.layer = LayerMask.NameToLayer(layerName);
foreach (Transform child in transform) child.ChangeLayersRecursively(layerName);
}
/// <summary>
/// Changes the layer of a transform and all its children to the new one
/// </summary>
/// <param name="transform"></param>
/// <param name="layerIndex"></param>
public static void ChangeLayersRecursively(this Transform transform, int layerIndex)
{
transform.gameObject.layer = layerIndex;
foreach (Transform child in transform) child.ChangeLayersRecursively(layerIndex);
}
/// <summary>
/// Enumerates all parents of a transform
/// </summary>
/// <param name="targetTransform"></param>
/// <param name="includeSelf"></param>
/// <returns></returns>
public static IEnumerable<Transform> MMEnumerateAllParents(this Transform targetTransform,
bool includeSelf = false)
{
if (!includeSelf) targetTransform = targetTransform?.parent;
while (targetTransform)
{
yield return targetTransform;
targetTransform = targetTransform.parent;
}
}
}
}

View File

@@ -3,119 +3,119 @@
namespace MoreMountains.Tools
{
/// <summary>
/// Vector4 Extensions
/// Vector4 Extensions
/// </summary>
public static class MMVector4Extensions
{
/// <summary>
/// Returns the sum of all components of a vector4
/// </summary>
/// <param name="vector"></param>
/// <returns></returns>
public static float SumComponents(this Vector4 vector)
{
return vector.x + vector.y + vector.z + vector.w;
}
/// <summary>
/// Sets the x value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetX(this Vector4 vector, float newValue)
{
vector.x = newValue;
return vector;
}
{
/// <summary>
/// Returns the sum of all components of a vector4
/// </summary>
/// <param name="vector"></param>
/// <returns></returns>
public static float SumComponents(this Vector4 vector)
{
return vector.x + vector.y + vector.z + vector.w;
}
/// <summary>
/// Sets the y value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetY(this Vector4 vector, float newValue)
{
vector.y = newValue;
return vector;
}
/// <summary>
/// Sets the x value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetX(this Vector4 vector, float newValue)
{
vector.x = newValue;
return vector;
}
/// <summary>
/// Sets the z value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetZ(this Vector4 vector, float newValue)
{
vector.z = newValue;
return vector;
}
/// <summary>
/// Sets the y value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetY(this Vector4 vector, float newValue)
{
vector.y = newValue;
return vector;
}
/// <summary>
/// Sets the z value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetW(this Vector4 vector, float newValue)
{
vector.w = newValue;
return vector;
}
/// <summary>
/// Sets the z value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetZ(this Vector4 vector, float newValue)
{
vector.z = newValue;
return vector;
}
/// <summary>
/// Inverts a vector
/// </summary>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMInvert(this Vector4 newValue)
{
return new Vector4
(
1.0f / newValue.x,
1.0f / newValue.y,
1.0f / newValue.z,
1.0f / newValue.w
);
}
/// <summary>
/// Sets the z value of a vector
/// </summary>
/// <param name="vector"></param>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMSetW(this Vector4 vector, float newValue)
{
vector.w = newValue;
return vector;
}
/// <summary>
/// Projects a vector on another
/// </summary>
/// <param name="vector"></param>
/// <param name="projectedVector"></param>
/// <returns></returns>
public static Vector4 MMProject(this Vector4 vector, Vector4 projectedVector)
{
float _dot = Vector4.Dot(vector, projectedVector);
return _dot * projectedVector;
}
/// <summary>
/// Inverts a vector
/// </summary>
/// <param name="newValue"></param>
/// <returns></returns>
public static Vector4 MMInvert(this Vector4 newValue)
{
return new Vector4
(
1.0f / newValue.x,
1.0f / newValue.y,
1.0f / newValue.z,
1.0f / newValue.w
);
}
/// <summary>
/// Rejects a vector on another
/// </summary>
/// <param name="vector"></param>
/// <param name="rejectedVector"></param>
/// <returns></returns>
public static Vector4 MMReject(this Vector4 vector, Vector4 rejectedVector)
{
return vector - vector.MMProject(rejectedVector);
}
/// <summary>
/// Projects a vector on another
/// </summary>
/// <param name="vector"></param>
/// <param name="projectedVector"></param>
/// <returns></returns>
public static Vector4 MMProject(this Vector4 vector, Vector4 projectedVector)
{
var _dot = Vector4.Dot(vector, projectedVector);
return _dot * projectedVector;
}
/// <summary>
/// Rounds all components of a vector
/// </summary>
/// <param name="vector"></param>
/// <returns></returns>
public static Vector4 MMRound(this Vector4 vector)
{
vector.x = Mathf.Round(vector.x);
vector.y = Mathf.Round(vector.y);
vector.z = Mathf.Round(vector.z);
vector.w = Mathf.Round(vector.w);
return vector;
}
}
/// <summary>
/// Rejects a vector on another
/// </summary>
/// <param name="vector"></param>
/// <param name="rejectedVector"></param>
/// <returns></returns>
public static Vector4 MMReject(this Vector4 vector, Vector4 rejectedVector)
{
return vector - vector.MMProject(rejectedVector);
}
/// <summary>
/// Rounds all components of a vector
/// </summary>
/// <param name="vector"></param>
/// <returns></returns>
public static Vector4 MMRound(this Vector4 vector)
{
vector.x = Mathf.Round(vector.x);
vector.y = Mathf.Round(vector.y);
vector.z = Mathf.Round(vector.z);
vector.w = Mathf.Round(vector.w);
return vector;
}
}
}

View File

@@ -1,130 +1,123 @@
using UnityEngine;
#if MM_UI
#if MM_UI
using UnityEngine.UI;
using System.Collections;
using System;
using UnityEngine;
namespace MoreMountains.Tools
{
/// <summary>
/// Fade helpers
/// Fade helpers
/// </summary>
public static class MMFade
{
{
/// <summary>
/// Fades the specified image to the target opacity and duration.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="opacity">Opacity.</param>
/// <param name="duration">Duration.</param>
public static IEnumerator FadeImage(Image target, float duration, Color color)
{
if (target == null)
yield break;
/// <summary>
/// Fades the specified image to the target opacity and duration.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="opacity">Opacity.</param>
/// <param name="duration">Duration.</param>
public static IEnumerator FadeImage(Image target, float duration, Color color)
{
if (target==null)
yield break;
var alpha = target.color.a;
float alpha = target.color.a;
for (var t = 0.0f; t < 1.0f; t += Time.deltaTime / duration)
{
if (target == null)
yield break;
var newColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha, color.a, t));
target.color = newColor;
yield return null;
}
for (float t = 0.0f; t < 1.0f; t += Time.deltaTime / duration)
{
if (target==null)
yield break;
Color newColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha,color.a,t));
target.color=newColor;
yield return null;
}
target.color=color;
target.color = color;
}
}
/// <summary>
/// Fades the specified image to the target opacity and duration.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="opacity">Opacity.</param>
/// <param name="duration">Duration.</param>
public static IEnumerator FadeText(Text target, float duration, Color color)
{
if (target==null)
yield break;
/// <summary>
/// Fades the specified image to the target opacity and duration.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="opacity">Opacity.</param>
/// <param name="duration">Duration.</param>
public static IEnumerator FadeText(Text target, float duration, Color color)
{
if (target == null)
yield break;
float alpha = target.color.a;
var alpha = target.color.a;
for (float t = 0.0f; t < 1.0f; t += Time.deltaTime / duration)
{
if (target==null)
yield break;
Color newColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha,color.a,t));
target.color=newColor;
yield return null;
}
target.color=color;
}
/// <summary>
/// Fades the specified image to the target opacity and duration.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="opacity">Opacity.</param>
/// <param name="duration">Duration.</param>
public static IEnumerator FadeSprite(SpriteRenderer target, float duration, Color color)
{
if (target==null)
yield break;
for (var t = 0.0f; t < 1.0f; t += Time.deltaTime / duration)
{
if (target == null)
yield break;
var newColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha, color.a, t));
target.color = newColor;
yield return null;
}
float alpha = target.material.color.a;
target.color = color;
}
float t=0f;
while (t<1.0f)
{
if (target==null)
yield break;
/// <summary>
/// Fades the specified image to the target opacity and duration.
/// </summary>
/// <param name="target">Target.</param>
/// <param name="opacity">Opacity.</param>
/// <param name="duration">Duration.</param>
public static IEnumerator FadeSprite(SpriteRenderer target, float duration, Color color)
{
if (target == null)
yield break;
Color newColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha,color.a,t));
target.material.color=newColor;
var alpha = target.material.color.a;
t += Time.deltaTime / duration;
var t = 0f;
while (t < 1.0f)
{
if (target == null)
yield break;
yield return null;
var newColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha, color.a, t));
target.material.color = newColor;
}
Color finalColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha,color.a,t));
if (target != null)
{
target.material.color=finalColor;
}
}
t += Time.deltaTime / duration;
public static IEnumerator FadeCanvasGroup(CanvasGroup target, float duration, float targetAlpha, bool unscaled = true)
{
if (target==null)
yield break;
yield return null;
}
float currentAlpha = target.alpha;
var finalColor = new Color(color.r, color.g, color.b, Mathf.SmoothStep(alpha, color.a, t));
if (target != null) target.material.color = finalColor;
}
float t=0f;
while (t<1.0f)
{
if (target==null)
yield break;
public static IEnumerator FadeCanvasGroup(CanvasGroup target, float duration, float targetAlpha,
bool unscaled = true)
{
if (target == null)
yield break;
float newAlpha = Mathf.SmoothStep(currentAlpha,targetAlpha,t);
target.alpha=newAlpha;
var currentAlpha = target.alpha;
if (unscaled)
{
t += Time.unscaledDeltaTime / duration;
}
else
{
t += Time.deltaTime / duration;
}
var t = 0f;
while (t < 1.0f)
{
if (target == null)
yield break;
yield return null;
}
var newAlpha = Mathf.SmoothStep(currentAlpha, targetAlpha, t);
target.alpha = newAlpha;
target.alpha=targetAlpha;
}
if (unscaled)
t += Time.unscaledDeltaTime / duration;
else
t += Time.deltaTime / duration;
}
yield return null;
}
target.alpha = targetAlpha;
}
}
}
#endif

View File

@@ -4,67 +4,66 @@ using UnityEngine.Events;
namespace MoreMountains.Tools
{
/// <summary>
/// Add this class to an object that you expect to pool from an objectPooler.
/// Note that these objects can't be destroyed by calling Destroy(), they'll just be set inactive (that's the whole point).
/// Add this class to an object that you expect to pool from an objectPooler.
/// Note that these objects can't be destroyed by calling Destroy(), they'll just be set inactive (that's the whole
/// point).
/// </summary>
[AddComponentMenu("More Mountains/Tools/Object Pool/MM Poolable Object")]
public class MMPoolableObject : MMObjectBounds
{
[Header("Events")]
public UnityEvent ExecuteOnEnable;
public UnityEvent ExecuteOnDisable;
public delegate void Events();
public event Events OnSpawnComplete;
public class MMPoolableObject : MMObjectBounds
{
public delegate void Events();
[Header("Poolable Object")]
/// The life time, in seconds, of the object. If set to 0 it'll live forever, if set to any positive value it'll be set inactive after that time.
public float LifeTime = 0f;
[Header("Events")] public UnityEvent ExecuteOnEnable;
/// <summary>
/// Turns the instance inactive, in order to eventually reuse it.
/// </summary>
public virtual void Destroy()
{
gameObject.SetActive(false);
}
public UnityEvent ExecuteOnDisable;
/// <summary>
/// Called every frame
/// </summary>
protected virtual void Update()
{
[Header("Poolable Object")]
/// The life time, in seconds, of the object. If set to 0 it'll live forever, if set to any positive value it'll be set inactive after that time.
public float LifeTime;
}
/// <summary>
/// Called every frame
/// </summary>
protected virtual void Update()
{
}
/// <summary>
/// When the objects get enabled (usually after having been pooled from an ObjectPooler, we initiate its death countdown.
/// </summary>
protected virtual void OnEnable()
{
Size = GetBounds().extents * 2;
if (LifeTime > 0f)
{
Invoke("Destroy", LifeTime);
}
ExecuteOnEnable?.Invoke();
}
/// <summary>
/// When the objects get enabled (usually after having been pooled from an ObjectPooler, we initiate its death
/// countdown.
/// </summary>
protected virtual void OnEnable()
{
Size = GetBounds().extents * 2;
if (LifeTime > 0f) Invoke("Destroy", LifeTime);
ExecuteOnEnable?.Invoke();
}
/// <summary>
/// When the object gets disabled (maybe it got out of bounds), we cancel its programmed death
/// </summary>
protected virtual void OnDisable()
{
ExecuteOnDisable?.Invoke();
CancelInvoke();
}
/// <summary>
/// When the object gets disabled (maybe it got out of bounds), we cancel its programmed death
/// </summary>
protected virtual void OnDisable()
{
ExecuteOnDisable?.Invoke();
CancelInvoke();
}
/// <summary>
/// Triggers the on spawn complete event
/// </summary>
public virtual void TriggerOnSpawnComplete()
{
OnSpawnComplete?.Invoke();
}
}
public event Events OnSpawnComplete;
/// <summary>
/// Turns the instance inactive, in order to eventually reuse it.
/// </summary>
public virtual void Destroy()
{
gameObject.SetActive(false);
}
/// <summary>
/// Triggers the on spawn complete event
/// </summary>
public virtual void TriggerOnSpawnComplete()
{
OnSpawnComplete?.Invoke();
}
}
}

View File

@@ -1,138 +1,130 @@
using UnityEngine;
using System;
using System;
namespace MoreMountains.Tools
{
/// <summary>
/// Bool property setter
/// Bool property setter
/// </summary>
public class MMPropertyLinkBool : MMPropertyLink
{
public Func<bool> GetBoolDelegate;
public Action<bool> SetBoolDelegate;
{
protected bool _initialValue;
protected bool _newValue;
public Func<bool> GetBoolDelegate;
public Action<bool> SetBoolDelegate;
protected bool _initialValue;
protected bool _newValue;
/// <summary>
/// On init we grab our initial value
/// </summary>
/// <param name="property"></param>
public override void Initialization(MMProperty property)
{
base.Initialization(property);
_initialValue = (bool)GetPropertyValue(property);
}
/// <summary>
/// On init we grab our initial value
/// </summary>
/// <param name="property"></param>
public override void Initialization(MMProperty property)
{
base.Initialization(property);
_initialValue = (bool)GetPropertyValue(property);
}
/// <summary>
/// Creates cached getter and setters for properties
/// </summary>
/// <param name="property"></param>
public override void CreateGettersAndSetters(MMProperty property)
{
base.CreateGettersAndSetters(property);
if (property.MemberType == MMProperty.MemberTypes.Property)
{
var firstArgument = property.TargetScriptableObject == null
? property.TargetComponent
: (object)property.TargetScriptableObject;
/// <summary>
/// Creates cached getter and setters for properties
/// </summary>
/// <param name="property"></param>
public override void CreateGettersAndSetters(MMProperty property)
{
base.CreateGettersAndSetters(property);
if (property.MemberType == MMProperty.MemberTypes.Property)
{
object firstArgument = (property.TargetScriptableObject == null) ? (object)property.TargetComponent : (object)property.TargetScriptableObject;
if (property.MemberPropertyInfo.GetGetMethod() != null)
GetBoolDelegate = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>),
firstArgument,
property.MemberPropertyInfo.GetGetMethod());
if (property.MemberPropertyInfo.GetSetMethod() != null)
SetBoolDelegate = (Action<bool>)Delegate.CreateDelegate(typeof(Action<bool>),
firstArgument,
property.MemberPropertyInfo.GetSetMethod());
_getterSetterInitialized = true;
}
}
if (property.MemberPropertyInfo.GetGetMethod() != null)
{
GetBoolDelegate = (Func<bool>)Delegate.CreateDelegate(typeof(Func<bool>),
firstArgument,
property.MemberPropertyInfo.GetGetMethod());
}
if (property.MemberPropertyInfo.GetSetMethod() != null)
{
SetBoolDelegate = (Action<bool>)Delegate.CreateDelegate(typeof(Action<bool>),
firstArgument,
property.MemberPropertyInfo.GetSetMethod());
}
_getterSetterInitialized = true;
}
}
/// <summary>
/// Gets the raw value of the property, a normalized float value, caching the operation if possible
/// </summary>
/// <param name="emitter"></param>
/// <param name="property"></param>
/// <returns></returns>
public override object GetValue(MMPropertyEmitter emitter, MMProperty property)
{
return GetValueOptimized(property);
}
/// <summary>
/// Gets the raw value of the property, a normalized float value, caching the operation if possible
/// </summary>
/// <param name="emitter"></param>
/// <param name="property"></param>
/// <returns></returns>
public override object GetValue(MMPropertyEmitter emitter, MMProperty property)
{
return GetValueOptimized(property);
}
/// <summary>
/// Sets the raw property value, float normalized, caching the operation if possible
/// </summary>
/// <param name="receiver"></param>
/// <param name="property"></param>
/// <param name="level"></param>
public override void SetValue(MMPropertyReceiver receiver, MMProperty property, object newValue)
{
SetValueOptimized(property, (bool)newValue);
}
/// <summary>
/// Sets the raw property value, float normalized, caching the operation if possible
/// </summary>
/// <param name="receiver"></param>
/// <param name="property"></param>
/// <param name="level"></param>
public override void SetValue(MMPropertyReceiver receiver, MMProperty property, object newValue)
{
SetValueOptimized(property, (bool)newValue);
}
/// <summary>
/// Returns this property link's level between 0 and 1
/// </summary>
/// <param name="receiver"></param>
/// <param name="property"></param>
/// <param name="level"></param>
/// <returns></returns>
public override float GetLevel(MMPropertyEmitter emitter, MMProperty property)
{
var boolValue = GetValueOptimized(property);
var returnValue = boolValue ? emitter.BoolRemapTrue : emitter.BoolRemapFalse;
emitter.Level = returnValue;
return returnValue;
}
/// <summary>
/// Returns this property link's level between 0 and 1
/// </summary>
/// <param name="receiver"></param>
/// <param name="property"></param>
/// <param name="level"></param>
/// <returns></returns>
public override float GetLevel(MMPropertyEmitter emitter, MMProperty property)
{
bool boolValue = GetValueOptimized(property);
float returnValue = (boolValue == true) ? emitter.BoolRemapTrue : emitter.BoolRemapFalse;
emitter.Level = returnValue;
return returnValue;
}
public override float GetLevel(MMPropertyReceiver receiver, MMProperty property)
{
bool boolValue = GetValueOptimized(property);
float returnValue = (boolValue == true) ? 1f : 0f;
return returnValue;
}
public override float GetLevel(MMPropertyReceiver receiver, MMProperty property)
{
var boolValue = GetValueOptimized(property);
var returnValue = boolValue ? 1f : 0f;
return returnValue;
}
/// <summary>
/// Set the level (more than the link's Threshold > true, less > false)
/// </summary>
/// <param name="receiver"></param>
/// <param name="property"></param>
/// <param name="level"></param>
public override void SetLevel(MMPropertyReceiver receiver, MMProperty property, float level)
{
base.SetLevel(receiver, property, level);
_newValue = (level > receiver.Threshold) ? receiver.BoolRemapOne : receiver.BoolRemapZero;
SetValueOptimized(property, _newValue);
}
/// <summary>
/// Set the level (more than the link's Threshold > true, less > false)
/// </summary>
/// <param name="receiver"></param>
/// <param name="property"></param>
/// <param name="level"></param>
public override void SetLevel(MMPropertyReceiver receiver, MMProperty property, float level)
{
base.SetLevel(receiver, property, level);
_newValue = level > receiver.Threshold ? receiver.BoolRemapOne : receiver.BoolRemapZero;
SetValueOptimized(property, _newValue);
}
/// <summary>
/// Gets either the cached value or the raw value
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
protected virtual bool GetValueOptimized(MMProperty property)
{
return _getterSetterInitialized ? GetBoolDelegate() : (bool)GetPropertyValue(property);
}
/// <summary>
/// Gets either the cached value or the raw value
/// </summary>
/// <param name="property"></param>
/// <returns></returns>
protected virtual bool GetValueOptimized(MMProperty property)
{
return _getterSetterInitialized ? GetBoolDelegate() : (bool)GetPropertyValue(property);
}
/// <summary>
/// Sets either the cached value or the raw value
/// </summary>
/// <param name="property"></param>
/// <param name="newValue"></param>
protected virtual void SetValueOptimized(MMProperty property, bool newValue)
{
if (_getterSetterInitialized)
{
SetBoolDelegate(_newValue);
}
else
{
SetPropertyValue(property, _newValue);
}
}
}
/// <summary>
/// Sets either the cached value or the raw value
/// </summary>
/// <param name="property"></param>
/// <param name="newValue"></param>
protected virtual void SetValueOptimized(MMProperty property, bool newValue)
{
if (_getterSetterInitialized)
SetBoolDelegate(_newValue);
else
SetPropertyValue(property, _newValue);
}
}
}

View File

@@ -1,82 +1,82 @@
{
"name": "MoreMountains.Tools",
"rootNamespace": "",
"references": [
"GUID:75469ad4d38634e559750d17036d5f7c",
"GUID:4307f53044263cf4b835bd812fc161a4",
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:457756d89b35d2941b3e7b37b4ece6f1",
"GUID:15fc0a57446b3144c949da3e2b9737a9",
"GUID:df380645f10b7bc4b97d4f5eb6303d95",
"GUID:d60799ab2a985554ea1a39cd38695018",
"GUID:57a0b9bc628ab4740af4b6f1f0b2e134",
"GUID:d04eb9c554ad44ceab303cecf0c0cf82",
"GUID:516a5277b8c3b4f4c8cc86b77b1591ff",
"GUID:2bafac87e7f4b9b418d9448d219b01ab"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.inputsystem",
"expression": "1.0.0",
"define": "MM_INPUTSYSTEM"
},
{
"name": "com.unity.cinemachine",
"expression": "[1.0.0,3.0.0-pre]",
"define": "MM_CINEMACHINE"
},
{
"name": "com.unity.cinemachine",
"expression": "3.0.0",
"define": "MM_CINEMACHINE3"
},
{
"name": "com.unity.textmeshpro",
"expression": "1.0.0",
"define": "MM_TEXTMESHPRO"
},
{
"name": "com.unity.render-pipelines.universal",
"expression": "1.0.0",
"define": "MM_URP"
},
{
"name": "com.unity.render-pipelines.high-definition",
"expression": "1.0.0",
"define": "MM_HDRP"
},
{
"name": "com.unity.postprocessing",
"expression": "1.0.0",
"define": "MM_POSTPROCESSING"
},
{
"name": "com.unity.visualeffectgraph",
"expression": "1.0.0",
"define": "MM_VISUALEFFECTGRAPH"
},
{
"name": "com.unity.ugui",
"expression": "2.0.0",
"define": "MM_UGUI2"
},
{
"name": "com.unity.ugui",
"expression": "1.0.0",
"define": "MM_UI"
},
{
"name": "com.unity.modules.physics2d",
"expression": "1.0.0",
"define": "MM_PHYSICS2D"
}
],
"noEngineReferences": false
"name": "MoreMountains.Tools",
"rootNamespace": "",
"references": [
"GUID:75469ad4d38634e559750d17036d5f7c",
"GUID:4307f53044263cf4b835bd812fc161a4",
"GUID:6055be8ebefd69e48b49212b09b47b2f",
"GUID:457756d89b35d2941b3e7b37b4ece6f1",
"GUID:15fc0a57446b3144c949da3e2b9737a9",
"GUID:df380645f10b7bc4b97d4f5eb6303d95",
"GUID:d60799ab2a985554ea1a39cd38695018",
"GUID:57a0b9bc628ab4740af4b6f1f0b2e134",
"GUID:d04eb9c554ad44ceab303cecf0c0cf82",
"GUID:516a5277b8c3b4f4c8cc86b77b1591ff",
"GUID:2bafac87e7f4b9b418d9448d219b01ab"
],
"includePlatforms": [],
"excludePlatforms": [],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [],
"versionDefines": [
{
"name": "com.unity.inputsystem",
"expression": "1.0.0",
"define": "MM_INPUTSYSTEM"
},
{
"name": "com.unity.cinemachine",
"expression": "[1.0.0,3.0.0-pre]",
"define": "MM_CINEMACHINE"
},
{
"name": "com.unity.cinemachine",
"expression": "3.0.0",
"define": "MM_CINEMACHINE3"
},
{
"name": "com.unity.textmeshpro",
"expression": "1.0.0",
"define": "MM_TEXTMESHPRO"
},
{
"name": "com.unity.render-pipelines.universal",
"expression": "1.0.0",
"define": "MM_URP"
},
{
"name": "com.unity.render-pipelines.high-definition",
"expression": "1.0.0",
"define": "MM_HDRP"
},
{
"name": "com.unity.postprocessing",
"expression": "1.0.0",
"define": "MM_POSTPROCESSING"
},
{
"name": "com.unity.visualeffectgraph",
"expression": "1.0.0",
"define": "MM_VISUALEFFECTGRAPH"
},
{
"name": "com.unity.ugui",
"expression": "2.0.0",
"define": "MM_UGUI2"
},
{
"name": "com.unity.ugui",
"expression": "1.0.0",
"define": "MM_UI"
},
{
"name": "com.unity.modules.physics2d",
"expression": "1.0.0",
"define": "MM_PHYSICS2D"
}
],
"noEngineReferences": false
}