using Autohand;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace Autohand
{
public static class AutoHandExtensions
{
static Transform _transformRuler = null;
//This is a "ruler" tool used to help calculate parent child calculations without doing parenting/childing
public static Transform transformRuler
{
get {
if(_transformRuler == null)
_transformRuler = new GameObject() { name = "Ruler" }.transform;
if (_transformRuler.parent != transformParent)
_transformRuler.parent = transformParent;
if (_transformRuler.localScale != Vector3.one)
_transformRuler.localScale = Vector3.one;
if (IsPositionNan(_transformRuler.position))
_transformRuler.position = Vector3.zero;
if (IsRotationNan(_transformRuler.rotation))
_transformRuler.rotation = Quaternion.identity;
return _transformRuler;
}
}
static Transform _transformRulerChild = null;
//This is a "ruler" tool used to help calculate parent child calculations without doing parenting/childing
public static Transform transformRulerChild
{
get {
if (_transformRulerChild == null)
{
_transformRulerChild = new GameObject() { name = "RulerChild" }.transform;
_transformRulerChild.parent = _transformRuler;
}
if (_transformRulerChild.parent != _transformRuler)
_transformRulerChild.parent = _transformRuler;
if (_transformRulerChild.localScale != Vector3.one)
_transformRulerChild.localScale = Vector3.one;
if (IsPositionNan(_transformRulerChild.position))
_transformRulerChild.position = Vector3.zero;
if (IsRotationNan(_transformRulerChild.rotation))
_transformRulerChild.rotation = Quaternion.identity;
return _transformRulerChild;
}
}
static bool IsPositionNan(Vector3 pos)
{
return float.IsNaN(pos.x) || float.IsNaN(pos.y) || float.IsNaN(pos.z);
}
static bool IsRotationNan(Quaternion rot)
{
return float.IsNaN(rot.x) || float.IsNaN(rot.y) || float.IsNaN(rot.z) || float.IsNaN(rot.w);
}
static Transform _transformParent = null;
// Holds all the Auto Hand Generated GameObjects
public static Transform transformParent {
get {
if(Application.isEditor)
return null;
if(_transformParent == null)
_transformParent = new GameObject() { name="Auto Hand Generated" }.transform;
return _transformParent;
}
}
public static void RotateAround(this Transform target, Transform center, Quaternion deltaRotation) {
transformRuler.SetPositionAndRotation(center.position, center.rotation);
transformRulerChild.SetPositionAndRotation(target.position, target.rotation);
transformRuler.rotation *= deltaRotation;
target.SetPositionAndRotation(transformRulerChild.position, transformRulerChild.rotation);
}
public static float Round(this float value, int digits)
{
float mult = Mathf.Pow(10.0f, (float)digits);
return Mathf.Round(value * mult) / mult;
}
/// Returns true if there is a grabbable or link, out null if there is none
public static bool HasGrabbable(this Hand hand, GameObject obj, out Grabbable grabbable)
{
return HasGrabbable(obj, out grabbable);
}
/// Returns true if there is a grabbable or link, out null if there is none
public static bool HasGrabbable(this GameObject obj, out Grabbable grabbable, bool includeDisabled = false)
{
if (obj == null)
{
grabbable = null;
return false;
}
if(obj.CanGetComponent(out IGrabbableEvents grabbableEvents)) {
if(grabbableEvents.GetGrabbable() != null && (includeDisabled || grabbableEvents.GetGrabbable().enabled)) {
grabbable = grabbableEvents.GetGrabbable();
return true;
}
}
if (obj.CanGetComponent(out grabbable) && (includeDisabled || grabbable.enabled))
{
return true;
}
GrabbableChild grabChild;
if (obj.CanGetComponent(out grabChild) && (includeDisabled || grabChild.grabParent.enabled))
{
grabbable = grabChild.grabParent;
return true;
}
grabbable = null;
return false;
}
public static T GetCopyOf(this Component comp, T other) where T : Component{
Type type = comp.GetType();
if (type != other.GetType()) return null; // type mis-match
BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Default | BindingFlags.DeclaredOnly;
PropertyInfo[] pinfos = type.GetProperties(flags);
foreach (var pinfo in pinfos)
{
if (pinfo.CanWrite)
{
try
{
pinfo.SetValue(comp, pinfo.GetValue(other, null), null);
}
catch { } // In case of NotImplementedException being thrown. For some reason specifying that exception didn't seem to catch it, so I didn't catch anything specific.
}
}
FieldInfo[] finfos = type.GetFields(flags);
foreach (var finfo in finfos)
{
finfo.SetValue(comp, finfo.GetValue(other));
}
return comp as T;
}
/// Autohand extension method, used so I can use TryGetComponent for newer versions and GetComponent for older versions
public static bool CanGetComponent(this Component componentClass, out T component)
{
#if UNITY_2019_1 || UNITY_2018 || UNITY_2017
var tempComponent = componentClass.GetComponent();
if(tempComponent != null){
component = tempComponent;
return true;
}
else {
component = tempComponent;
return false;
}
#else
var value = componentClass.TryGetComponent(out component);
return value;
#endif
}
/// Autohand extension method, used so I can use TryGetComponent for newer versions and GetComponent for older versions
public static bool CanGetComponent(this GameObject componentClass, out T component) {
#if UNITY_2019_1 || UNITY_2018 || UNITY_2017
var tempComponent = componentClass.GetComponent();
if(tempComponent != null){
component = tempComponent;
return true;
}
else {
component = tempComponent;
return false;
}
#else
var value = componentClass.TryGetComponent(out component);
return value;
#endif
}
/// Autohand extension method, used so I can use TryGetComponent for newer versions and GetComponent for older versions
public static T CanFindObjectOfType(bool includeInactive = false) where T : Component {
#if UNITY_2023_1_OR_NEWER
return GameObject.FindFirstObjectByType((includeInactive ? FindObjectsInactive.Include : FindObjectsInactive.Exclude));
#elif (UNITY_2020_3_OR_NEWER)
return GameObject.FindObjectOfType(includeInactive);
#else
return GameObject.FindObjectOfType();
#endif
}
/// Autohand extension method, used so I can use TryGetComponent for newer versions and GetComponent for older versions
public static T[] CanFindObjectsOfType(bool includeInactive = false) where T : Component {
#if UNITY_2023
return GameObject.FindObjectsByType((includeInactive ? FindObjectsInactive.Include : FindObjectsInactive.Exclude), FindObjectsSortMode.None);
#elif (UNITY_2020_3_OR_NEWER)
return GameObject.FindObjectsOfType(includeInactive);
#else
return GameObject.FindObjectsOfType();
#endif
}
#if UNITY_EDITOR
public static void TextDebug(this Vector3 vector3, string name = "") {
Debug.Log(name + ": " + vector3.x + ", " + vector3.y + ", " + vector3.z);
}
public static GUIStyle LabelStyle(TextAnchor textAnchor = TextAnchor.MiddleLeft, FontStyle fontStyle = FontStyle.Normal, int fontSize = 13) {
var style = new GUIStyle(GUI.skin.label);
style.font = (Font)Resources.Load("Righteous-Regular", typeof(Font));
style.fontSize = fontSize;
style.alignment = textAnchor;
style.fontStyle = fontStyle;
return style;
}
public static GUIStyle LabelStyle(Color textColor, TextAnchor textAnchor = TextAnchor.MiddleLeft, FontStyle fontStyle = FontStyle.Normal, int fontSize = 13) {
var style = new GUIStyle(GUI.skin.label);
style.font = (Font)Resources.Load("Righteous-Regular", typeof(Font));
style.fontSize = fontSize;
style.alignment = textAnchor;
style.fontStyle = fontStyle;
style.normal.textColor = textColor;
return style;
}
public static GUIStyle LabelStyleB(Color textColor, TextAnchor textAnchor = TextAnchor.MiddleLeft, FontStyle fontStyle = FontStyle.Normal, int fontSize = 13) {
var style = new GUIStyle(GUI.skin.toggle);
style.font = (Font)Resources.Load("Righteous-Regular", typeof(Font));
style.fontSize = fontSize;
style.alignment = textAnchor;
style.fontStyle = fontStyle;
style.normal.textColor = textColor;
return style;
}
#endif
public static LayerMask GetPhysicsLayerMask(int currentLayer) {
int finalMask = 0;
for (int i=0; i<32; i++) {
if (!Physics.GetIgnoreLayerCollision(currentLayer, i)) finalMask = finalMask | (1 << i);
}
return finalMask;
}
public static void AddTorqueAtPoint(this Rigidbody rigidbody, Vector3 torque, Vector3 point) {
// Apply the torque
rigidbody.AddTorque(torque, ForceMode.VelocityChange);
// Calculate the force direction (perpendicular to the torque and line from center of mass to point)
Vector3 forceDir = Vector3.Cross(torque, point - rigidbody.worldCenterOfMass).normalized;
// Calculate the magnitude of the force
Vector3 pointVelocity = rigidbody.GetPointVelocity(point);
Vector3 angularVelocityContribution = Vector3.Cross(rigidbody.angularVelocity, point - rigidbody.worldCenterOfMass);
float forceMagnitude = (pointVelocity - angularVelocityContribution).magnitude;
// Apply the force at the point
rigidbody.AddForceAtPosition(forceDir * forceMagnitude, point, ForceMode.VelocityChange);
}
}
}