1
0
mirror of https://github.com/originalnicodr/CinematicUnityExplorer.git synced 2025-07-18 09:27:57 +08:00

Added gizmos (Mono compatibility only for now).

This commit is contained in:
originalnicodr
2024-06-23 17:17:30 -03:00
parent d2d22de66c
commit edc188cf68
23 changed files with 1597 additions and 1 deletions

View File

@ -62,7 +62,10 @@ namespace UnityExplorer.UI.Panels
}
public void ResetAnimation(){
if (bonesManager != null) bonesManager.turnOffAnimatorToggle.isOn = true;
if (bonesManager != null){
bonesManager.turnOffAnimatorToggle.isOn = true;
bonesManager.DisableGizmos();
}
// Let the game change animations again
animator.StopPlayback();
if (originalAnimatorController != null && animator.wrappedObject != null){

View File

@ -17,6 +17,7 @@ namespace UnityExplorer.UI.Panels
public AxisComponentControl CurrentSlidingAxisControl { get; set; }
public BonesManager Owner;
private ButtonRef inspectButton;
private Dropdown gizmoDropdown;
// ICell
public float DefaultHeight => 25f;
@ -52,6 +53,20 @@ namespace UnityExplorer.UI.Panels
UIFactory.SetLayoutElement(inspectButton.GameObject, minWidth: 150, minHeight: 25);
inspectButton.OnClick += () => InspectorManager.Inspect(bone.gameObject);
GameObject gizmoObj = UIFactory.CreateDropdown(header, "Gizmo_Dropdown", out gizmoDropdown, null, 14, (idx) => {
if (Owner.turnOffAnimatorToggle.isOn) Owner.turnOffAnimatorToggle.isOn = false;
ExplorerBehaviour.GizmoTools.targetTransform = bone;
ExplorerBehaviour.GizmoTools.ChangeGizmo((GizmoType)idx);
}
);
UIFactory.SetLayoutElement(gizmoObj, minHeight: 25, minWidth: 150);
gizmoDropdown.options.Add(new Dropdown.OptionData("No Gizmo"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Local Position"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Local Rotation"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Global Position"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Global Rotation"));
gizmoDropdown.captionText.text = "No Gizmo";
GameObject headerButtons = UIFactory.CreateUIObject("BoneHeader", header);
UIFactory.SetLayoutGroup<HorizontalLayoutGroup>(headerButtons, false, false, true, true, 4, childAlignment: TextAnchor.MiddleRight);
UIFactory.SetLayoutElement(headerButtons, minHeight: 25, flexibleWidth: 9999, flexibleHeight: 800);
@ -75,6 +90,12 @@ namespace UnityExplorer.UI.Panels
bone.gameObject.SetActive(value);
}
public void DisableGizmo(){
if (gizmoDropdown.value != 0){
gizmoDropdown.value = 0;
}
}
// TransformControls-like functions
public void UpdateTransformControlValues(bool force){
positionControl.Update(force);

View File

@ -18,6 +18,7 @@ namespace UnityExplorer
public class ExplorerBehaviour : MonoBehaviour
{
internal static ExplorerBehaviour Instance { get; private set; }
static public ExtendedTransformTools GizmoTools { get; private set; }
#if CPP
public ExplorerBehaviour(System.IntPtr ptr) : base(ptr) { }
@ -33,6 +34,7 @@ namespace UnityExplorer
DontDestroyOnLoad(obj);
obj.hideFlags = HideFlags.HideAndDontSave;
Instance = obj.AddComponent<ExplorerBehaviour>();
GizmoTools = obj.AddComponent<ExtendedTransformTools>();
}
internal void Update()

View File

@ -0,0 +1,126 @@
// Credits to https://github.com/Vesper-Works/Unity-Explorer-For-Outer-Wilds/
using System.Collections.Generic;
using UnityEngine;
using GizmosLibraryPlugin;
using UnityExplorer.Inspectors;
using UnityExplorer.TransformGizmos;
using UniverseLib.Input;
#if INTEROP
using Il2CppInterop.Runtime.Injection;
#endif
namespace UnityExplorer
{
public enum GizmoType
{
None,
LocalPosition,
LocalRotation,
GlobalPosition,
GlobalRotation
}
public class ExtendedTransformTools : MonoBehaviour
{
#if CPP
static ExtendedTransformTools()
{
ClassInjector.RegisterTypeInIl2Cpp<ExtendedTransformTools>();
}
public ExtendedTransformTools(IntPtr ptr) : base(ptr) { }
#endif
public Transform targetTransform;
float maxDistanceToSelect = 0.05f;
private List<BaseTransformGizmo> EnabledGizmos = new();
private List<BaseTransformGizmo> NewGizmo(GizmoType type){
List<BaseTransformGizmo> returnList = new List<BaseTransformGizmo>();
switch(type){
case GizmoType.LocalPosition:
returnList.Add(new LocalPositionGizmo());
break;
case GizmoType.LocalRotation:
returnList.Add(new LocalEulerAngleGizmo());
break;
case GizmoType.GlobalPosition:
returnList.Add(new TransformOrientationGizmo());
break;
case GizmoType.GlobalRotation:
returnList.Add(new LocalEulerAngleGizmo());
returnList.Add(new FromCameraViewRotationGizmo());
break;
}
return returnList;
}
public void ChangeGizmo(GizmoType type) {
EnabledGizmos.Clear();
if (type != GizmoType.None){
EnabledGizmos.AddRange(NewGizmo(type));
}
}
private void Update()
{
if (targetTransform == null){
EnabledGizmos.ForEach((gizmo) => gizmo.Reset());
return;
}
float scale = Vector3.Distance(Camera.current.transform.position, targetTransform.position) / 5f;
EnabledGizmos.ForEach((gizmo) =>
{
gizmo.SetScale(scale);
gizmo.Set(targetTransform);
});
Ray ray = Camera.current.ScreenPointToRay(IInputManager.MousePosition);
if (IInputManager.GetMouseButtonDown(0))
{
bool noneIsSelected = EnabledGizmos.TrueForAll((gizmo) => !gizmo.IsSelected());
if (noneIsSelected)
{
EnabledGizmos.ForEach((gizmo) => gizmo.CheckSelected(ray, maxDistanceToSelect * scale));
}
}
else if (IInputManager.GetMouseButton(0))
{
EnabledGizmos.ForEach((gizmo) =>
{
if (gizmo.IsSelected())
{
gizmo.OnSelected(ray);
}
});
}
else
{
EnabledGizmos.ForEach((gizmo) => gizmo.Reset());
}
}
public void OnRenderObject()
{
if (targetTransform == null)
return;
GL.wireframe = true;
GLHelper.SetDefaultMaterialPass(0, true);
EnabledGizmos.ForEach((gizmo) => gizmo.OnRender());
GL.wireframe = false;
}
}
}

View File

@ -0,0 +1,289 @@
using System;
using UnityEngine;
using UnityExplorer;
namespace GizmosLibraryPlugin
{
public static class GLDraw
{
//GL.LINES = 1
/// <summary>
/// Draws a cube that follows the Vector.foward, Vector.up and Vector.right axis with center in offset.
/// </summary>
/// <param name="offset"></param>
/// <param name="color"></param>
public static void SimpleWireframeCube(Vector3 offset, Color color)
{
WireframeCube(Vector3.forward, Vector3.up, Vector3.right, offset, color);
}
/// <summary>
/// Draws a cube that follows the specified axis with center in offset.
/// </summary>
/// <param name="foward"></param>
/// <param name="up"></param>
/// <param name="right"></param>
/// <param name="offset"></param>
/// <param name="color"></param>
public static void WireframeCube(Vector3 foward, Vector3 up, Vector3 right, Vector3 offset, Color color)
{
Vector3[] vertex = new Vector3[4];
vertex[0] = (foward + right) / 2f;
vertex[1] = (-foward + right) / 2f;
vertex[2] = (-foward - right) / 2f;
vertex[3] = (foward - right) / 2f;
//GL.Begin(GL.LINE_STRIP);
GL.Begin(GL.LINES);
GL.Color(color);
for (int i = 0; i < 4; i++)
{
GL.Vertex(vertex[i] + offset - up / 2f);
}
GL.Vertex(vertex[0] + offset - up / 2f); ;
GL.End();
//GL.Begin(GL.LINE_STRIP);
GL.Begin(GL.LINES);
GL.Color(color);
for (int i = 0; i < 4; i++)
{
GL.Vertex(vertex[i] + offset + up / 2f);
}
GL.Vertex(vertex[0] + offset + up / 2f);
GL.End();
GL.Begin(GL.LINES);
for (int i = 0; i < 4; i++)
{
GL.Color(color);
GL.Vertex(vertex[i] + offset - up / 2f);
GL.Vertex(vertex[i] + offset + up / 2f);
}
GL.End();
}
/// <summary>
/// Draws a circle on a plane facing the specified normal, centered in offset with the angle 0 meaning the same direction as up.
/// </summary>
/// <param name="radius"></param>
/// <param name="normal"></param>
/// <param name="up"></param>
/// <param name="offset"></param>
/// <param name="color"></param>
/// <param name="resolution"></param>
/// <param name="startAngle"></param>
/// <param name="endAngle"></param>
/// <param name="isWholeCircle">If it is a 2 PI circle you then need to set this to true</param>
public static void WireframeCircle(float radius, Vector3 normal, Vector3 up, Vector3 offset, Color color, int resolution = 3, float startAngle = 0f, float endAngle = 2f * Mathf.PI, bool isWholeCircle = true)
{
if (resolution < 3 || radius <= 0f)
return;
normal = normal.normalized;
up = up.normalized;
//GL.Begin(GL.LINE_STRIP);
GL.Begin(GL.LINES);
float angleStep = (endAngle - startAngle) / resolution;
int aditionalSteps = isWholeCircle ? 1 : 0;
GL.Color(color);
Vector3 rotationVector = Vector3MathUtils.GetRotationVector(normal, up);
for (int i = 0; i <= resolution + aditionalSteps; i++)
{
Vector3 radiusVector = Vector3MathUtils.GetRotatedVectorComponent(rotationVector, up, angleStep * i + startAngle);
GL.Vertex(radiusVector * radius + offset);
}
GL.End();
}
/// <summary>
/// Draws a sphere centered on offset following the Vector.foward, Vector.up and Vector.right axis.
/// </summary>
/// <param name="radius"></param>
/// <param name="offset"></param>
/// <param name="color"></param>
/// <param name="resolution"></param>
public static void SimpleWireframeSphere(float radius, Vector3 offset, Color color, int resolution)
{
WireframeCircle(radius, Vector3.up, Vector3.forward, offset, color, resolution);
WireframeCircle(radius, Vector3.forward, Vector3.right, offset, color, resolution);
WireframeCircle(radius, Vector3.right, Vector3.up, offset, color, resolution);
}
/// <summary>
/// Draws a sphere centered on offset following the specified axis.
/// </summary>
/// <param name="radius"></param>
/// <param name="offset"></param>
/// <param name="foward"></param>
/// <param name="up"></param>
/// <param name="color"></param>
/// <param name="resolution"></param>
public static void WireframeSphere(float radius, Vector3 offset, Vector3 foward, Vector3 up, Color color, int resolution = 3)
{
Vector3 right = Vector3.Cross(foward, up);
WireframeCircle(radius, up, foward, offset, color, resolution);
WireframeCircle(radius, foward, right, offset, color, resolution);
WireframeCircle(radius, right, up, offset, color, resolution);
}
/// <summary>
/// Draws half a sphere centered on offset facing the up direction.
/// </summary>
/// <param name="radius"></param>
/// <param name="offset"></param>
/// <param name="foward"></param>
/// <param name="up"></param>
/// <param name="color"></param>
/// <param name="resolution"></param>
public static void WireframeHemisphere(float radius, Vector3 offset, Vector3 foward, Vector3 up, Color color, int resolution = 3)
{
Vector3 right = Vector3.Cross(foward, up);
WireframeCircle(radius, up, foward, offset, color, resolution, -Mathf.PI / 2f, Mathf.PI / 2f, false);
WireframeCircle(radius, foward, right, offset, color, resolution);
WireframeCircle(radius, right, foward, offset, color, resolution, -Mathf.PI / 2f, Mathf.PI / 2f, false);
}
/// <summary>
/// Draws a capsule with the startPoint and endPoint being the center of the spheres on its extreme.
/// </summary>
/// <param name="radius"></param>
/// <param name="startPoint"></param>
/// <param name="endPoint"></param>
/// <param name="color"></param>
/// <param name="resolution"></param>
public static void WireframeCapsule(float radius, Vector3 startPoint, Vector3 endPoint, Color color, int resolution = 3)
{
Vector3 direction = startPoint - endPoint;
Vector3 randomUpVector = Vector3MathUtils.GetArbitraryPerpendicularVector(direction);
//Top and bottom Spheres
WireframeHemisphere(radius, startPoint, direction, randomUpVector, color, resolution);
WireframeHemisphere(radius, endPoint, -direction, -randomUpVector, color, resolution);
GL.Begin(GL.LINES);
float angleStep = 2f * Mathf.PI / resolution;
Vector3 rotationVector = Vector3MathUtils.GetRotationVector(direction.normalized, randomUpVector);
for (int i = 0; i <= resolution; i++)
{
Vector3 radiusVector = Vector3MathUtils.GetRotatedVectorComponent(rotationVector, randomUpVector, angleStep * i);
Vector3 vertex1 = radiusVector * radius + startPoint;
Vector3 vertex2 = radiusVector * radius + endPoint;
GL.Color(color);
GL.Vertex(vertex1);
GL.Vertex(vertex2);
}
GL.End();
}
/// <summary>
/// Draws a capsule oriented with the Vector.up direction.
/// </summary>
/// <param name="radius"></param>
/// <param name="height"></param>
/// <param name="up"></param>
/// <param name="offset"></param>
/// <param name="color"></param>
/// <param name="resolution"></param>
public static void SimpleWireframeCapsule(float radius, float height, Vector3 up, Vector3 offset, Color color, int resolution = 3)
{
Vector3 randomFowardVector = Vector3MathUtils.GetArbitraryPerpendicularVector(up);
//Top and bottom Spheres
WireframeSphere(radius, offset - up * height / 2f, randomFowardVector, up, color, resolution);
WireframeSphere(radius, offset + up * height / 2f, randomFowardVector, up, color, resolution);
GL.Begin(GL.LINES);
float angleStep = 2f * Mathf.PI / resolution;
Vector3 rotationVector = Vector3MathUtils.GetRotationVector(up.normalized, randomFowardVector);
for (int i = 0; i <= resolution; i++)
{
Vector3 radiusVector = Vector3MathUtils.GetRotatedVectorComponent(rotationVector, randomFowardVector, angleStep * i);
Vector3 vertex1 = radiusVector * radius + offset - up * height / 2f;
Vector3 vertex2 = radiusVector * radius + offset + up * height / 2f;
GL.Color(color);
GL.Vertex(vertex1);
GL.Vertex(vertex2);
}
GL.End();
}
/// <summary>
/// Draws a cone with specifiend star and end positions as well as start and end radius (for cone trunks). It can be used to draw cylinder too.
/// </summary>
/// <param name="coneRadiusStart"></param>
/// <param name="coneRadiusEnd"></param>
/// <param name="coneStart"></param>
/// <param name="coneEnd"></param>
/// <param name="color"></param>
/// <param name="resolution"></param>
public static void WireframeCone(float coneRadiusStart, float coneRadiusEnd, Vector3 coneStart, Vector3 coneEnd, Color color, int resolution = 3)
{
Vector3 direction = coneEnd - coneStart;
Vector3 randomFowardVector = Vector3MathUtils.GetArbitraryPerpendicularVector(direction);
//Start Circle
WireframeCircle(coneRadiusStart, direction, randomFowardVector, coneStart, color, resolution);
//End Circle
WireframeCircle(coneRadiusEnd, direction, randomFowardVector, coneEnd, color, resolution);
//Connecting Lines
GL.Begin(GL.LINES);
float angleStep = 2f * Mathf.PI / resolution;
Vector3 rotationVector = Vector3MathUtils.GetRotationVector(direction.normalized, randomFowardVector);
for (int i = 0; i <= resolution; i++)
{
Vector3 radiusVector = Vector3MathUtils.GetRotatedVectorComponent(rotationVector, randomFowardVector, angleStep * i);
Vector3 vertex1 = radiusVector * coneRadiusStart + coneStart;
Vector3 vertex2 = radiusVector * coneRadiusEnd + coneEnd;
GL.Color(color);
GL.Vertex(vertex1);
GL.Vertex(vertex2);
}
GL.End();
}
/// <summary>
/// Draws the direction of a vector as a 3d arrow starting on the offset.
/// </summary>
/// <param name="vector"></param>
/// <param name="headSize"></param>
/// <param name="offset"></param>
/// <param name="color"></param>
public static void Vector(Vector3 vector, float headSize, Vector3 offset, Color color)
{
if (vector.magnitude <= 0f)
return;
GL.Begin(GL.LINES);
GL.Color(color);
//Main arrow body
GL.Vertex(offset);
Vector3 endPoint = vector + offset;
GL.Vertex(endPoint);
//Head of the arrow
Vector3 direction = vector.normalized;
Vector3 firstHeadDirection = Vector3MathUtils.GetArbitraryPerpendicularVector(vector);
Vector3 secondHeadDirection = Vector3.Cross(direction, firstHeadDirection);
GL.Vertex(endPoint);
GL.Vertex((firstHeadDirection - direction).normalized * headSize + endPoint);
GL.Vertex(endPoint);
GL.Vertex(-(firstHeadDirection + direction).normalized * headSize + endPoint);
GL.Vertex(endPoint);
GL.Vertex((secondHeadDirection - direction).normalized * headSize + endPoint);
GL.Vertex(endPoint);
GL.Vertex(-(secondHeadDirection + direction).normalized * headSize + endPoint);
GL.End();
}
}
}

View File

@ -0,0 +1,128 @@
using System;
using UnityEngine;
namespace GizmosLibraryPlugin
{
public static class GLHelper
{
static Material defaultGizmosMaterial;
static Material alwaysDrawOnTopDefaultGizmosMaterial;
public static Material GetDefaultMaterial()
{
if (!defaultGizmosMaterial)
{
Shader shader = Shader.Find("Hidden/Internal-Colored");
defaultGizmosMaterial = new Material(shader)
{
hideFlags = HideFlags.HideAndDontSave
};
// Turn on alpha blending
defaultGizmosMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
defaultGizmosMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
defaultGizmosMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
defaultGizmosMaterial.SetInt("_ZWrite", 0);
}
return defaultGizmosMaterial;
}
public static void SetDefaultMaterialPass(int pass = 0, bool alwaysDrawOnTop = false)
{
if(!alwaysDrawOnTop)
GetDefaultMaterial().SetPass(pass);
else
GetAlwaysDrawOnTopDefaultMaterial().SetPass(pass);
}
public static Material GetAlwaysDrawOnTopDefaultMaterial()
{
if (!alwaysDrawOnTopDefaultGizmosMaterial)
{
Shader shader = Shader.Find("Hidden/Internal-Colored");
alwaysDrawOnTopDefaultGizmosMaterial = new Material(shader)
{
hideFlags = HideFlags.HideAndDontSave
};
// Turn on alpha blending
alwaysDrawOnTopDefaultGizmosMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
alwaysDrawOnTopDefaultGizmosMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
// Turn backface culling off
alwaysDrawOnTopDefaultGizmosMaterial.SetInt("_Cull", (int)UnityEngine.Rendering.CullMode.Off);
// Turn off depth writes
//From https://answers.unity.com/questions/1674373/rendering-gl-lines-z-order-manipulation.html
alwaysDrawOnTopDefaultGizmosMaterial.SetInt("_ZWrite", -10);
alwaysDrawOnTopDefaultGizmosMaterial.SetInt("_ZTest", (int)UnityEngine.Rendering.CompareFunction.Disabled);
}
return alwaysDrawOnTopDefaultGizmosMaterial;
}
public static void DrawWithReference(Transform reference, Action drawMethod)
{
GL.PushMatrix();
GL.MultMatrix(reference.localToWorldMatrix);
drawMethod?.Invoke();
GL.PopMatrix();
}
public static void DrawOnGlobalReference(Action drawMethod)
{
GL.PushMatrix();
GL.MultMatrix(Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one));
drawMethod?.Invoke();
GL.PopMatrix();
}
public static void DrawWithOrthoProjection(Action drawMethod)
{
GL.PushMatrix();
GL.LoadOrtho();
drawMethod?.Invoke();
GL.PopMatrix();
}
public static void DrawAxis(float headSize, Color color, Vector3 offset)
{
GLDraw.Vector(Vector3.up, headSize, offset, color);
GLDraw.Vector(Vector3.forward, headSize, offset, color);
GLDraw.Vector(Vector3.right, headSize, offset, color);
}
public static void DrawAxis(float headSize, Color upColor, Color fowardColor, Color rightColor, Vector3 offset)
{
GLDraw.Vector(Vector3.up, headSize, offset, upColor);
GLDraw.Vector(Vector3.forward, headSize, offset, fowardColor);
GLDraw.Vector(Vector3.right, headSize, offset, rightColor);
}
public static void DrawTransform(Transform transform, float headSize, Color color)
{
GLDraw.Vector(transform.up * transform.lossyScale.x, headSize, transform.position, color);
GLDraw.Vector(transform.forward * transform.lossyScale.z, headSize, transform.position, color);
GLDraw.Vector(transform.right * transform.lossyScale.y, headSize, transform.position, color);
}
public static void DrawTransform(Transform transform, float headSize, Color upColor, Color fowardColor, Color rightColor)
{
GLDraw.Vector(transform.up * transform.lossyScale.x, headSize, transform.position, upColor);
GLDraw.Vector(transform.forward * transform.lossyScale.z, headSize, transform.position, fowardColor);
GLDraw.Vector(transform.right * transform.lossyScale.y, headSize, transform.position, rightColor);
}
public static void DrawColliderBoundingBox(Collider collider, Color color)
{
Bounds box = collider.bounds;
GLDraw.WireframeCube(Vector3.forward * box.size.z, Vector3.up * box.size.y, Vector3.right * box.size.z, box.center, color);
}
public static void DrawCollider(Collider collider, Color color)
{
const int resolution = 12;
if (collider is BoxCollider)
{
BoxCollider box = collider as BoxCollider;
GLDraw.WireframeCube(Vector3.forward * box.size.z, Vector3.up * box.size.y, Vector3.right * box.size.z, box.center, color);
}
else if (collider is SphereCollider)
{
SphereCollider sphere = collider as SphereCollider;
GLDraw.WireframeSphere(sphere.radius, sphere.center, Vector3.forward, Vector3.up, color, resolution);
}
else if (collider is CapsuleCollider)
{
CapsuleCollider capsule = collider as CapsuleCollider;
GLDraw.WireframeCapsule(capsule.radius, capsule.center + capsule.height * Vector3.up / 2f, capsule.center - capsule.height * Vector3.up / 2f, color, resolution);
}
}
}
}

View File

@ -0,0 +1,56 @@
using System;
using UnityEngine;
using GizmosLibraryPlugin;
namespace UnityExplorer.GizmoControls
{
internal class ArrowControl : BaseControl<Vector3>
{
private Vector3 selectedPosition;
public Transform Transform;
public Func<Transform, Vector3> Direction = (t) => Vector3.up;
public float Lenght;
public float HeadLenght;
public float MaxDistanceToSelect;
public Color Color;
public Color SelectedColor;
public override Vector3 GetValue(Ray ray)
{
Vector3 direction = Direction(Transform);
Vector3MathUtils.GetClosestPointFromLines(ray.direction, ray.origin, direction, Transform.position, out _, out Vector3 currentSelectedPosition);
currentSelectedPosition = Vector3MathUtils.GetPositionWithReferencial(Transform, currentSelectedPosition);
float distanceWihReference = Vector3.Dot(currentSelectedPosition - selectedPosition, Vector3MathUtils.GetDirectionWithReferencial(Transform, direction));
return distanceWihReference * Vector3MathUtils.GetDirectionWithReferencial(Transform, direction);
}
public override bool IsSelected(Ray ray)
{
Vector3 direction = Direction(Transform);
if (Vector3MathUtils.GetDistanceFromLineToLineSegment(ray.direction, ray.origin, Transform.position, Transform.position + direction * Lenght * Scale) <= MaxDistanceToSelect)
{
Selected = true;
Vector3MathUtils.GetClosestPointFromLines(ray.direction, ray.origin, direction, Transform.position, out _, out selectedPosition);
selectedPosition = Vector3MathUtils.GetPositionWithReferencial(Transform, selectedPosition);
}
return Selected;
}
public override void Draw()
{
Vector3 direction = Direction(Transform);
GLHelper.DrawOnGlobalReference(() =>
{
Color color = Selected ? SelectedColor : Color;
GLDraw.Vector(direction * Lenght * Scale, HeadLenght * Scale, Transform.position, color);
});
}
}
}

View File

@ -0,0 +1,17 @@
using UnityEngine;
namespace UnityExplorer.GizmoControls
{
public abstract class BaseControl<T>
{
public float Scale = 1f;
public bool Selected { get; protected set; } = false;
public abstract bool IsSelected(Ray ray);
public abstract void Draw();
public abstract T GetValue(Ray ray);
public virtual void Reset()
{
Selected = false;
}
}
}

View File

@ -0,0 +1,64 @@
using System;
using UnityEngine;
using GizmosLibraryPlugin;
namespace UnityExplorer.GizmoControls
{
public class CircleControl : BaseControl<float>
{
private Vector3 selectedPosition;
private Vector3 selectedFowardDirection;
public Transform Transform;
public float DistanceForFullRevolution = 4f;
public Func<Transform, Vector3> Normal = (t) => Vector3.up;
public float Radius;
public float MaxDistanceToSelect;
public Color Color;
public Color SelectedColor;
public override float GetValue(Ray ray)
{
Vector3 foward = Vector3MathUtils.ReturnDirectionWithReferencial(Transform, selectedFowardDirection);
Vector3MathUtils.GetClosestPointFromLines(ray.direction, ray.origin, foward, Transform.position, out _, out Vector3 currentXSelectedPosition);
currentXSelectedPosition = Vector3MathUtils.GetPositionWithReferencial(Transform, currentXSelectedPosition);
float distanceWihReference = Vector3.Dot(currentXSelectedPosition - selectedPosition, selectedFowardDirection);
return distanceWihReference * 360f / DistanceForFullRevolution;
}
public override bool IsSelected(Ray ray)
{
Vector3 normal = Normal(Transform);
if (Vector3MathUtils.GetClosestPointFromLineToCircle(ray.direction, ray.origin, Transform.position, normal, Radius * Scale, out bool lineParalelToCircle, out bool isEquidistant, out Vector3 selectedPoint) <= MaxDistanceToSelect)
{
if (!lineParalelToCircle && !isEquidistant)
{
selectedPosition = selectedPoint;
selectedPosition = Vector3MathUtils.GetPositionWithReferencial(Transform, selectedPosition);
selectedFowardDirection = Vector3.Cross(normal, (selectedPoint - Transform.position).normalized);
selectedFowardDirection = Vector3MathUtils.GetDirectionWithReferencial(Transform, selectedFowardDirection);
Selected = true;
}
}
return Selected;
}
public override void Draw()
{
Vector3 normal = Normal(Transform);
GLHelper.DrawOnGlobalReference(() =>
{
Vector3 randomUp = Vector3MathUtils.GetArbitraryPerpendicularVector(normal);
Color color = Selected ? SelectedColor : Color;
GLDraw.WireframeCircle(Radius * Scale, normal, randomUp, Transform.position, color, 16);
});
}
}
}

View File

@ -0,0 +1,40 @@
using System;
using UnityEngine;
namespace GizmosLibraryPlugin
{
public static class GizmosAPI
{
//GLHelper
public static Material GetDefaultMaterial() => GLHelper.GetDefaultMaterial();
public static void SetDefaultMaterialPass(int pass = 0) => GLHelper.SetDefaultMaterialPass(pass);
public static void DrawWithReference(Transform reference, Action drawMethod) => GLHelper.DrawWithReference(reference, drawMethod);
public static void DrawOnGlobalReference(Action drawMethod) => GLHelper.DrawOnGlobalReference(drawMethod);
public static void DrawWithOrthoProjection(Action drawMethod) => GLHelper.DrawWithOrthoProjection(drawMethod);
public static void DrawAxis(float headSize, Color color, Vector3 offset) => GLHelper.DrawAxis(headSize, color, offset);
public static void DrawAxis(float headSize, Color upColor, Color fowardColor, Color rightColor, Vector3 offset) => GLHelper.DrawAxis(headSize, upColor, fowardColor, rightColor, offset);
public static void DrawTransform(Transform transform, float headSize, Color color) => GLHelper.DrawTransform(transform, headSize, color);
public static void DrawTransform(Transform transform, float headSize, Color upColor, Color fowardColor, Color rightColor) => GLHelper.DrawTransform(transform, headSize, upColor, fowardColor, rightColor);
public static void DrawCollider(Collider collider, Color color) => GLHelper.DrawCollider(collider, color);
public static void DrawColliderBoundingBox(Collider collider, Color color) => GLHelper.DrawColliderBoundingBox(collider, color);
//GLDraw
public static void DrawSimpleWireframeCube(Vector3 offset, Color color) => GLDraw.SimpleWireframeCube(offset, color);
public static void DrawWireframeCube(Vector3 foward, Vector3 up, Vector3 right, Vector3 offset, Color color) => GLDraw.WireframeCube(foward, up, right, offset, color);
public static void DrawWireframeCircle(float radius, Vector3 normal, Vector3 up, Vector3 offset, Color color, int resolution = 3, float startAngle = 0f, float endAngle = 2f * Mathf.PI, bool isWholeCircle = true)
=> GLDraw.WireframeCircle(radius, normal, up, offset, color, resolution, startAngle, endAngle, isWholeCircle);
public static void DrawSimpleWireframeSphere(float radius, Vector3 offset, Color color, int resolution)
=> GLDraw.SimpleWireframeSphere(radius, offset, color, resolution);
public static void DrawWireframeSphere(float radius, Vector3 offset, Vector3 foward, Vector3 up, Color color, int resolution = 3)
=> GLDraw.WireframeSphere(radius, offset, foward, up, color, resolution);
public static void DrawWireframeHemisphere(float radius, Vector3 offset, Vector3 foward, Vector3 up, Color color, int resolution = 3)
=> GLDraw.WireframeHemisphere(radius, offset, foward, up, color, resolution);
public static void DrawWireframeCapsule(float radius, Vector3 startPoint, Vector3 endPoint, Color color, int resolution = 3)
=> GLDraw.WireframeCapsule(radius, startPoint, endPoint, color, resolution);
public static void DrawSimpleWireframeCapsule(float radius, float height, Vector3 up, Vector3 offset, Color color, int resolution = 3)
=> GLDraw.SimpleWireframeCapsule(radius, height, up, offset, color, resolution);
public static void DrawWireframeCone(float coneRadiusStart, float coneRadiusEnd, Vector3 coneStart, Vector3 coneEnd, Color color, int resolution = 3)
=> GLDraw.WireframeCone(coneRadiusStart, coneRadiusEnd, coneStart, coneEnd, color, resolution);
public static void DrawVector(Vector3 vector, float headSize, Vector3 offset, Color color) => GLDraw.Vector(vector, headSize, offset, color);
}
}

View File

@ -0,0 +1,113 @@
using UnityEngine;
using UnityExplorer.GizmoControls;
namespace UnityExplorer.TransformGizmos
{
public abstract class BaseInteractablePositionGizmo : BaseTransformGizmo
{
ArrowControl x = new();
ArrowControl y = new();
ArrowControl z = new();
Vector3 initialPosition;
protected float LineLenght;
protected float HeadLenght;
public override void SetScale(float scale)
{
base.SetScale(scale);
x.Scale = scale;
y.Scale = scale;
z.Scale = scale;
}
public void SetLineLenght(float lenght, float headLenght)
{
LineLenght = lenght;
HeadLenght = headLenght;
x.Lenght = lenght;
x.HeadLenght = headLenght;
y.Lenght = lenght;
y.HeadLenght = headLenght;
z.Lenght = lenght;
z.HeadLenght = headLenght;
}
public abstract Vector3 GetXDirection();
public abstract Vector3 GetYDirection();
public abstract Vector3 GetZDirection();
public override void Set(Transform transform)
{
base.Set(transform);
x.Lenght = LineLenght;
x.HeadLenght = HeadLenght;
x.Transform = transform;
x.Color = Color.red;
x.SelectedColor = Color.Lerp(Color.red, Color.white, 0.8f);
x.Direction = (t) => GetXDirection();
y.Lenght = LineLenght;
y.HeadLenght = HeadLenght;
y.Transform = transform;
y.Color = Color.yellow;
y.SelectedColor = Color.Lerp(Color.yellow, Color.white, 0.8f);
y.Direction = (t) => GetYDirection();
z.Lenght = LineLenght;
z.HeadLenght = HeadLenght;
z.Transform = transform;
z.Color = Color.cyan;
z.SelectedColor = Color.Lerp(Color.cyan, Color.white, 0.8f);
z.Direction = (t) => GetZDirection();
}
public override bool CheckSelected(Ray ray, float maxDistanceToSelect)
{
x.MaxDistanceToSelect = maxDistanceToSelect;
y.MaxDistanceToSelect = maxDistanceToSelect;
z.MaxDistanceToSelect = maxDistanceToSelect;
x.IsSelected(ray);
y.IsSelected(ray);
z.IsSelected(ray);
initialPosition = Vector3MathUtils.GetPositionWithReferencial(transform, transform.position);
return IsSelected();
}
public override void OnRender()
{
x.Draw();
y.Draw();
z.Draw();
}
public override void OnSelected(Ray ray)
{
Vector3 aditionToPosition = Vector3.zero;
if (x.Selected)
aditionToPosition += x.GetValue(ray);
if (y.Selected)
aditionToPosition += y.GetValue(ray);
if (z.Selected)
aditionToPosition += z.GetValue(ray);
transform.position = Vector3MathUtils.ReturnPositionFromReferencial(transform, initialPosition + aditionToPosition);
}
public override bool IsSelected()
{
return x.Selected || y.Selected || z.Selected;
}
public override void Reset()
{
x.Reset();
y.Reset();
z.Reset();
}
}
}

View File

@ -0,0 +1,27 @@
using UnityEngine;
namespace UnityExplorer.TransformGizmos
{
public abstract class BaseTransformGizmo
{
protected Transform transform;
protected float Scale;
public virtual void SetScale(float scale)
{
Scale = scale;
}
public virtual void Set(Transform transform)
{
this.transform = transform;
}
public abstract void Reset();
public abstract bool CheckSelected(Ray ray,float maxDistanceToSelect);
public abstract void OnSelected(Ray ray);
public abstract bool IsSelected();
public abstract void OnRender();
}
}

View File

@ -0,0 +1,74 @@
using UnityEngine;
using UnityExplorer.GizmoControls;
namespace UnityExplorer.TransformGizmos
{
public class FromCameraViewRotationGizmo : BaseTransformGizmo
{
CircleControl control = new();
float distanceForFullRevolution = 4f;
Vector3 rotationAxis;
Quaternion initialLocalRotation;
public override void SetScale(float scale)
{
base.SetScale(scale);
control.Scale = scale;
}
public override void Set(Transform transform)
{
base.Set(transform);
control.DistanceForFullRevolution = distanceForFullRevolution;
control.Color = Color.blue;
control.SelectedColor = Color.Lerp(Color.blue, Color.white, 0.8f);
control.Radius = 1.5f;
control.Transform = transform;
control.Normal = (t) => rotationAxis;
}
public override bool CheckSelected(Ray ray, float maxDistanceToSelect)
{
control.MaxDistanceToSelect = maxDistanceToSelect;
control.IsSelected(ray);
rotationAxis = (Camera.current.transform.position - transform.position).normalized;
initialLocalRotation = transform.localRotation;
return IsSelected();
}
public override bool IsSelected()
{
return control.Selected;
}
public override void OnRender()
{
if (!control.Selected)
{
rotationAxis = (Camera.current.transform.position - transform.position).normalized;
}
control.Draw();
}
public override void OnSelected(Ray ray)
{
float angle = control.GetValue(ray);
transform.localRotation = initialLocalRotation * Quaternion.AngleAxis(angle, Vector3MathUtils.GetDirectionWithReferencial(transform, rotationAxis));
}
public override void Reset()
{
control.Reset();
}
}
}

View File

@ -0,0 +1,50 @@
using UnityEngine;
using GizmosLibraryPlugin;
namespace UnityExplorer.TransformGizmos
{
public class GlobalEulerAnglesGizmo : BaseTransformGizmo
{
public override bool CheckSelected(Ray ray, float maxDistanceToSelect)
{
return false;
}
public override bool IsSelected()
{
return false;
}
public override void OnRender()
{
GLHelper.DrawOnGlobalReference(() =>
{
//Global position axis
Vector3 localFowardAxis = transform.forward;
Vector3 localRightAxis = transform.right;
//Local Euler Rotation
Vector3 yRotationAxis = Vector3.Cross(Vector3.up, localFowardAxis);
//if (yRotationAxis.ApproxEquals(Vector3.zero))
if (Math.Abs(yRotationAxis.x) < 0.0001 && Math.Abs(yRotationAxis.y) < 0.0001 && Math.Abs(yRotationAxis.z) < 0.0001)
{
yRotationAxis = localRightAxis;
}
GLDraw.WireframeCircle(1f, yRotationAxis, localFowardAxis, transform.position, Color.red, 16);
GLDraw.WireframeCircle(1f, Vector3.up, Vector3.forward, transform.position, Color.yellow, 16);
GLDraw.WireframeCircle(1f, localFowardAxis, transform.up, transform.position, Color.cyan, 16);
});
}
public override void OnSelected(Ray ray)
{
return;
}
public override void Reset()
{
return;
}
}
}

View File

@ -0,0 +1,38 @@
using UnityEngine;
using GizmosLibraryPlugin;
namespace UnityExplorer.TransformGizmos
{
public class GlobalPositionGizmo : BaseTransformGizmo
{
public override bool CheckSelected(Ray ray, float maxDistanceToSelect)
{
return false;
}
public override bool IsSelected()
{
return false;
}
public override void OnRender()
{
GLHelper.DrawOnGlobalReference(() =>
{
GLDraw.Vector(Vector3.right, 0.25f, transform.position, Color.red);
GLDraw.Vector(Vector3.up, 0.25f, transform.position, Color.yellow);
GLDraw.Vector(Vector3.forward, 0.25f, transform.position, Color.cyan);
});
}
public override void OnSelected(Ray ray)
{
return;
}
public override void Reset()
{
return;
}
}
}

View File

@ -0,0 +1,115 @@
using UnityEngine;
using UnityExplorer.GizmoControls;
namespace UnityExplorer.TransformGizmos
{
internal class LocalEulerAngleGizmo : BaseTransformGizmo
{
CircleControl x = new();
CircleControl y = new();
CircleControl z = new();
float distanceForFullRevolution = 4f;
Vector3 initialLocalEulerRotation;
public override void SetScale(float scale)
{
base.SetScale(scale);
x.Scale = scale;
y.Scale = scale;
z.Scale = scale;
}
public override void Set(Transform transform)
{
base.Set(transform);
x.DistanceForFullRevolution = distanceForFullRevolution;
x.Color = Color.red;
x.SelectedColor = Color.Lerp(Color.red, Color.white, 0.8f);
x.Radius = 1f;
x.Transform = transform;
x.Normal = (t) =>
{
Vector3 localFowardAxis = t.forward;
Vector3 localUp = Vector3MathUtils.ReturnDirectionWithReferencial(t, Vector3.up);
Vector3 yRotationAxis = Vector3.Cross(localUp, localFowardAxis);
//if (yRotationAxis.ApproxEquals(Vector3.zero))
if (Math.Abs(yRotationAxis.x) < 0.0001 && Math.Abs(yRotationAxis.y) < 0.0001 && Math.Abs(yRotationAxis.z) < 0.0001)
{
yRotationAxis = t.right;
}
return yRotationAxis;
};
y.DistanceForFullRevolution = distanceForFullRevolution;
y.Color = Color.yellow;
y.SelectedColor = Color.Lerp(Color.yellow, Color.white, 0.8f);
y.Radius = 1f;
y.Transform = transform;
y.Normal = (t) =>
{
Vector3 localUp = Vector3MathUtils.ReturnDirectionWithReferencial(t, Vector3.up);
return localUp;
};
z.DistanceForFullRevolution = distanceForFullRevolution;
z.Color = Color.cyan;
z.SelectedColor = Color.Lerp(Color.cyan, Color.white, 0.8f);
z.Radius = 1f;
z.Transform = transform;
z.Normal = (t) =>
{
return t.forward;
};
}
public override bool CheckSelected(Ray ray, float maxDistanceToSelect)
{
x.MaxDistanceToSelect = maxDistanceToSelect;
y.MaxDistanceToSelect = maxDistanceToSelect;
z.MaxDistanceToSelect = maxDistanceToSelect;
x.IsSelected(ray);
y.IsSelected(ray);
z.IsSelected(ray);
initialLocalEulerRotation = transform.localEulerAngles;
return IsSelected();
}
public override bool IsSelected()
{
return x.Selected || y.Selected || z.Selected;
}
public override void OnRender()
{
x.Draw();
y.Draw();
z.Draw();
}
public override void OnSelected(Ray ray)
{
Vector3 aditionToAngle = Vector3.zero;
if (x.Selected)
aditionToAngle.x = x.GetValue(ray);
if (y.Selected)
aditionToAngle.y = y.GetValue(ray);
if (z.Selected)
aditionToAngle.z = z.GetValue(ray);
transform.localEulerAngles = initialLocalEulerRotation + aditionToAngle;
}
public override void Reset()
{
x.Reset();
y.Reset();
z.Reset();
}
}
}

View File

@ -0,0 +1,37 @@
using UnityEngine;
namespace UnityExplorer.TransformGizmos
{
public class LocalPositionGizmo : BaseInteractablePositionGizmo
{
public override void Set(Transform transform)
{
LineLenght = 1.1f;
HeadLenght = 0.25f;
base.Set(transform);
}
public override Vector3 GetXDirection()
{
if (transform.parent == null)
return Vector3.right;
return transform.parent.right;
}
public override Vector3 GetYDirection()
{
if (transform.parent == null)
return Vector3.up;
return transform.parent.up;
}
public override Vector3 GetZDirection()
{
if (transform.parent == null)
return Vector3.forward;
return transform.parent.forward;
}
}
}

View File

@ -0,0 +1,191 @@
using UnityEngine;
using GizmosLibraryPlugin;
namespace UnityExplorer.TransformGizmos
{
//TODO recreate this with GizmoControls and fix bug when radius = 0 -> position = NaN
public class LocalPositionCylindricalCoordinates : BaseTransformGizmo
{
// x = radius
// y = y
// z = theta
bool selectedRadius = false;
bool selectedTheta = false;
bool selectedY = false;
float lineSegmentDistance = 0.25f;
Vector3 selectedRadiusPosition;
float aditionalThetaRotation;
Vector3 selectedYPosition;
Vector3 initialLocalPositionCylindrical;
protected Vector3 GetPositionWithReferencial(Transform transform, Vector3 position)
{
if (transform.parent == null)
return position;
return transform.parent.InverseTransformPoint(position);
}
protected Vector3 ReturnPositionFromReferencial(Transform transform, Vector3 position)
{
if (transform.parent == null)
return position;
return transform.parent.TransformPoint(position);
}
protected Vector3 GetDirectionWithReferencial(Transform transform, Vector3 direction)
{
if (transform.parent == null)
return direction;
return transform.parent.InverseTransformDirection(direction);
}
protected Vector3 ReturnDirectionFromReferencial(Transform transform, Vector3 direction)
{
if (transform.parent == null)
return direction;
return transform.parent.TransformDirection(direction);
}
public Vector3 GetRadiusDirection(Transform transform)
{
if (transform.parent == null)
return new Vector3(transform.position.x, 0f, transform.position.y).normalized;
return transform.parent.TransformDirection(new Vector3(transform.localPosition.x, 0f, transform.localPosition.z).normalized);
}
public Vector3 GetUpDirection(Transform transform)
{
Vector3 up = Vector3.up;
if (transform.parent != null)
{
up = transform.parent.up;
}
return up;
}
public Vector3 GetThetaDirection(Vector3 radiusDirection, Vector3 upDirection)
{
return Vector3.Cross(upDirection, radiusDirection);
}
public static Vector3 FromCylindricalToCartesian(Vector3 cylindrical)
{
if(cylindrical.x < 0f)
{
cylindrical.x = 0f;
//cylindrical.z += Mathf.PI;
}
return new Vector3(cylindrical.x * Mathf.Cos(cylindrical.z), cylindrical.y, cylindrical.x * Mathf.Sin(cylindrical.z));
}
public static Vector3 FromCartesianToCylindrical(Vector3 cartesian)
{
float y = cartesian.y;
Vector2 polar = new(cartesian.z, cartesian.x);
float radius = polar.magnitude;
float theta = 0f;
if (!( Mathf.Abs(polar.x) < 1e-2f || Mathf.Abs(polar.y) < 1e-2f))
{
theta = Mathf.Atan2(polar.x, polar.y);
}
return new Vector3(radius, y, theta);
}
public override bool CheckSelected(Ray ray, float maxDistanceToSelect)
{
Vector3 radius = GetRadiusDirection(transform);
Vector3 up = GetUpDirection(transform);
Vector3 centerAxis = ReturnPositionFromReferencial(transform, new Vector3(0f, transform.localPosition.y, 0f));
float radiusValue = ReturnDirectionFromReferencial(transform, new Vector3(transform.localPosition.x, 0f, transform.localPosition.z)).magnitude;
if (Vector3MathUtils.GetDistanceFromLineToLineSegment(ray.direction, ray.origin, transform.position, transform.position + radius * lineSegmentDistance) <= maxDistanceToSelect)
{
selectedRadius = true;
Vector3MathUtils.GetClosestPointFromLines(ray.direction, ray.origin, radius, transform.position, out _, out selectedRadiusPosition);
selectedRadiusPosition = GetPositionWithReferencial(transform, selectedRadiusPosition);
}
if (Vector3MathUtils.GetClosestPointFromLineToCircle(ray.direction, ray.origin, centerAxis, up, radiusValue, out bool lineParalelToCircle, out _, out _) <= maxDistanceToSelect)
{
if (!lineParalelToCircle)
{
selectedTheta = true;
aditionalThetaRotation = 0f;
}
}
if (Vector3MathUtils.GetDistanceFromLineToLineSegment(ray.direction, ray.origin, transform.position, transform.position + up * lineSegmentDistance) <= maxDistanceToSelect)
{
selectedY = true;
Vector3MathUtils.GetClosestPointFromLines(ray.direction, ray.origin, up, transform.position, out _, out selectedYPosition);
selectedYPosition = GetPositionWithReferencial(transform, selectedYPosition);
}
initialLocalPositionCylindrical = FromCartesianToCylindrical(GetPositionWithReferencial(transform, transform.position));
return IsSelected();
}
public override void OnRender()
{
Vector3 radius = GetRadiusDirection(transform);
Vector3 up = GetUpDirection(transform);
Vector3 centerAxis = ReturnPositionFromReferencial(transform, new Vector3(0f, transform.localPosition.y, 0f));
float radiusValue = ReturnDirectionFromReferencial(transform, new Vector3(transform.localPosition.x, 0f, transform.localPosition.z)).magnitude;
GLHelper.DrawOnGlobalReference(() =>
{
GLDraw.Vector(radius, lineSegmentDistance, transform.position, selectedRadius ? Color.Lerp(Color.red, Color.white, 0.8f) : Color.red);
GLDraw.Vector(up, lineSegmentDistance, transform.position, selectedY ? Color.Lerp(Color.yellow, Color.white, 0.8f) : Color.yellow);
GLDraw.WireframeCircle(radiusValue, up, radius, centerAxis, selectedTheta ? Color.Lerp(Color.cyan, Color.white, 0.8f) : Color.cyan, 16);
});
}
public override void OnSelected(Ray ray)
{
Vector3 radius = GetRadiusDirection(transform);
Vector3 up = GetUpDirection(transform);
float mouseScrollDelta = UniverseLib.Input.InputManager.MouseScrollDelta.y * 0.1f;
Vector3 cylindricalAditionToPosition = Vector3.zero;
if (selectedRadius)
{
Vector3MathUtils.GetClosestPointFromLines(ray.direction, ray.origin, radius, transform.position, out _, out Vector3 currentRadiusSelectedPosition);
currentRadiusSelectedPosition = GetPositionWithReferencial(transform, currentRadiusSelectedPosition);
float distanceWihReference = Vector3.Dot(currentRadiusSelectedPosition - selectedRadiusPosition, GetDirectionWithReferencial(transform, radius));
cylindricalAditionToPosition.x = distanceWihReference;
}
if (selectedTheta)
{
aditionalThetaRotation += mouseScrollDelta * Mathf.Deg2Rad;
cylindricalAditionToPosition.z = aditionalThetaRotation;
}
if (selectedY)
{
Vector3MathUtils.GetClosestPointFromLines(ray.direction, ray.origin, up, transform.position, out _, out Vector3 currentYSelectedPosition);
currentYSelectedPosition = GetPositionWithReferencial(transform, currentYSelectedPosition);
float distanceWihReference = Vector3.Dot(currentYSelectedPosition - selectedYPosition, GetDirectionWithReferencial(transform, up));
cylindricalAditionToPosition.y = distanceWihReference;
}
transform.position = ReturnPositionFromReferencial(transform, FromCylindricalToCartesian(initialLocalPositionCylindrical + cylindricalAditionToPosition));
}
public override bool IsSelected()
{
return selectedRadius || selectedTheta || selectedY;
}
public override void Reset()
{
aditionalThetaRotation = 0f;
selectedRadius = false;
selectedTheta = false;
selectedY = false;
}
}
}

View File

@ -0,0 +1,28 @@
using UnityEngine;
namespace UnityExplorer.TransformGizmos
{
public class TransformOrientationGizmo : BaseInteractablePositionGizmo
{
public override void Set(Transform transform)
{
LineLenght = 1.1f;
HeadLenght = 0.25f;
base.Set(transform);
}
public override Vector3 GetXDirection()
{
return transform.right;
}
public override Vector3 GetYDirection()
{
return transform.up;
}
public override Vector3 GetZDirection()
{
return transform.forward;
}
}
}

View File

@ -0,0 +1,144 @@
using UnityEngine;
namespace UnityExplorer
{
public static class Vector3MathUtils
{
public static Vector3 GetPositionWithReferencial(Transform t, Vector3 position)
{
if (t.parent == null)
return position;
return t.parent.InverseTransformPoint(position);
}
public static Vector3 ReturnPositionFromReferencial(Transform t, Vector3 position)
{
if (t.parent == null)
return position;
return t.parent.TransformPoint(position);
}
public static Vector3 GetDirectionWithReferencial(Transform t, Vector3 direction)
{
if (t.parent == null)
return direction;
return t.parent.InverseTransformDirection(direction);
}
public static Vector3 ReturnDirectionWithReferencial(Transform t, Vector3 direction)
{
if (t.parent == null)
return direction;
return t.parent.TransformDirection(direction);
}
//From https://math.stackexchange.com/questions/511370/how-to-rotate-one-vector-about-another
public static void GetParalelAndPerpendicularComponent(Vector3 axis, Vector3 v, out Vector3 paralel, out Vector3 perpendicular)
{
paralel = Vector3.Dot(v, axis) * axis / axis.magnitude;
perpendicular = v - paralel;
}
public static Vector3 GetRotationVector(Vector3 axis, Vector3 perpendicularComponent)
{
return Vector3.Cross(axis, perpendicularComponent);
}
public static Vector3 GetRotatedVectorComponent(Vector3 rotationVector, Vector3 perpendicularComponent, float angle)
{
float x1 = Mathf.Cos(angle) / perpendicularComponent.sqrMagnitude;
float x2 = Mathf.Sin(angle);
return perpendicularComponent.sqrMagnitude * (x1 * perpendicularComponent + x2 * rotationVector);
}
//From https://codereview.stackexchange.com/questions/43928/algorithm-to-get-an-arbitrary-perpendicular-vector
public static Vector3 GetArbitraryPerpendicularVector(Vector3 v)
{
if (v.magnitude == 0f)
{
return Vector3.forward;
}
Vector3 firstAttempt = Vector3.Cross(v, Vector3.forward);
if (firstAttempt.magnitude != 0f)
{
return firstAttempt.normalized;
}
else
{
return Vector3.Cross(v, Vector3.up).normalized;
}
}
//From https://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line
public static float GetDistanceFromLine(Vector3 point, Vector3 direction, Vector3 lineStartingPoint)
{
return Vector3.Cross(point - lineStartingPoint, direction).magnitude / direction.magnitude;
}
//From https://en.wikipedia.org/wiki/Skew_lines#Distance
public static float GetDistanceFromLineToLineSegment(Vector3 direction, Vector3 lineStartingPoint, Vector3 segmentStartingPoint, Vector3 segmentEndPoint)
{
Vector3 directionOfSegment = segmentEndPoint - segmentStartingPoint;
Vector3 n = Vector3.Cross(direction, directionOfSegment);
Vector3 n2 = Vector3.Cross(directionOfSegment, n);
Vector3 closestPointFromLineToSegment = lineStartingPoint + Vector3.Dot(segmentStartingPoint - lineStartingPoint, n2) / (Vector3.Dot(direction, n2)) * direction;
return GetDistanceFromLineSegment(closestPointFromLineToSegment, segmentStartingPoint, segmentEndPoint);
}
public static void GetClosestPointFromLines(Vector3 directionOne, Vector3 lineStartingPointOne, Vector3 directionTwo, Vector3 lineStartingPointTwo, out Vector3 closesPointOnLineOne, out Vector3 closesPointOnLineTwo)
{
Vector3 n = Vector3.Cross(directionOne, directionTwo);
Vector3 n2 = Vector3.Cross(directionTwo, n);
closesPointOnLineOne = lineStartingPointOne + Vector3.Dot(lineStartingPointTwo - lineStartingPointOne, n2) / (Vector3.Dot(directionOne, n2)) * directionOne;
Vector3 n1 = Vector3.Cross(directionOne, n);
closesPointOnLineTwo = lineStartingPointTwo + Vector3.Dot(lineStartingPointOne - lineStartingPointTwo, n1) / (Vector3.Dot(directionTwo, n1)) * directionTwo;
}
public static float GetDistanceFromLineSegment(Vector3 point, Vector3 startingPoint, Vector3 endPoint)
{
float distanceFromStartingPoint = Vector3.Distance(point, startingPoint);
float distanceFromEndPoint = Vector3.Distance(point, endPoint);
float distanceFromLine = GetDistanceFromLine(point, endPoint - startingPoint, startingPoint);
return Mathf.Min(distanceFromStartingPoint, distanceFromEndPoint, distanceFromLine);
}
//From https://www.geometrictools.com/Documentation/DistanceToCircle3.pdf
public static float GetClosestPointToCircle(Vector3 point, Vector3 center, Vector3 normal, float radius,out bool isEquidistant, out Vector3 closestPoint)
{
Vector3 delta = point - center;
float dotND = Vector3.Dot(normal, delta);
Vector3 QmC = delta - dotND * normal;
float lenghtQmC = QmC.magnitude;
if (lenghtQmC > 0f)
{
closestPoint = center + radius * (QmC / lenghtQmC);
isEquidistant = false;
return (point - closestPoint).magnitude;
}
else
{
closestPoint = Vector3.zero;
isEquidistant = true;
return delta.sqrMagnitude + radius * radius;
}
}
//From https://en.wikipedia.org/wiki/Line%E2%80%93plane_intersection
public static float GetClosestPointFromLineToCircle(Vector3 direction, Vector3 point, Vector3 center, Vector3 normal, float radius, out bool lineParalelToCircle, out bool isEquidistant, out Vector3 closestPoint)
{
float ln = Vector3.Dot(direction, normal);
if(ln == 0f) //Yes, I know we are ignoring when the line and the circle are on the same plane, I just don't want to write a proper GetClosestPointFromLineToCircle
{
lineParalelToCircle = true;
isEquidistant = false;
closestPoint = Vector3.zero;
return 0f;
}
float d = Vector3.Dot((center - point), normal) / ln;
Vector3 intersectionPoint = point + direction * d;
lineParalelToCircle = false;
return GetClosestPointToCircle(intersectionPoint, center, normal, radius, out isEquidistant, out closestPoint);
}
}
}

View File

@ -64,6 +64,7 @@ namespace UnityExplorer.Inspectors
public override void CloseInspector()
{
Controls.TransformControl.DisableGizmo();
InspectorManager.ReleaseInspector(this);
}

View File

@ -39,6 +39,10 @@ namespace UnityExplorer.UI.Panels
boneScrollPool.Initialize(this);
DoneScrollPoolInit = true;
}
if (!active){
DisableGizmos();
}
}
protected override void ConstructPanelContent()
@ -79,6 +83,13 @@ namespace UnityExplorer.UI.Panels
animator.enabled = value;
}
public void DisableGizmos(){
// TODO: Create a structure for each cell data instead
foreach (BonesCell cell in boneScrollPool.CellPool){
cell.DisableGizmo();
}
}
public void RestoreBoneState(string boneName)
{
foreach (Transform bone in bones){

View File

@ -12,6 +12,8 @@ namespace UnityExplorer.UI.Widgets
public AxisControl CurrentSlidingAxisControl { get; set; }
Dropdown gizmoDropdown;
Vector3Control PositionControl;
Vector3Control LocalPositionControl;
Vector3Control RotationControl;
@ -98,6 +100,25 @@ namespace UnityExplorer.UI.Widgets
LocalPositionControl = Vector3Control.Create(this, transformGroup, "Local Position:", TransformType.LocalPosition);
RotationControl = Vector3Control.Create(this, transformGroup, "Rotation:", TransformType.Rotation);
ScaleControl = Vector3Control.Create(this, transformGroup, "Scale:", TransformType.Scale);
GameObject gizmoObj = UIFactory.CreateDropdown(transformGroup, "Gizmo_Dropdown", out gizmoDropdown, null, 14, (idx) => {
ExplorerBehaviour.GizmoTools.targetTransform = Target.transform;
ExplorerBehaviour.GizmoTools.ChangeGizmo((GizmoType)idx);
}
);
UIFactory.SetLayoutElement(gizmoObj, minHeight: 25, minWidth: 150);
gizmoDropdown.options.Add(new Dropdown.OptionData("No Gizmo"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Local Position"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Local Rotation"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Global Position"));
gizmoDropdown.options.Add(new Dropdown.OptionData("Global Rotation"));
gizmoDropdown.captionText.text = "No Gizmo";
}
public void DisableGizmo(){
if (gizmoDropdown.value != 0){
gizmoDropdown.value = 0;
}
}
}
}