feat: initialize Streamingle Utilities package
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[ExecuteAlways]
|
||||
[AddComponentMenu("Streamingle Utilities/Constraints/Rough Aim Constraint")]
|
||||
public class RoughAimConstraint : RoughConstraintBase
|
||||
{
|
||||
[Header("Aim")]
|
||||
public Vector3 aimAxis = Vector3.forward;
|
||||
public Vector3 upAxis = Vector3.up;
|
||||
public Vector3 worldUpVector = Vector3.up;
|
||||
public Vector3 rotationOffset;
|
||||
|
||||
protected override void ExecuteConstraint(float followT)
|
||||
{
|
||||
if (!TryGetWeightedPosition(out var targetPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var direction = targetPosition - transform.position;
|
||||
if (direction.sqrMagnitude < 0.000001f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetRotation = LookRotationForAxis(direction, worldUpVector, aimAxis, upAxis);
|
||||
targetRotation *= Quaternion.Euler(rotationOffset);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, followT * weight);
|
||||
}
|
||||
|
||||
protected override void CaptureOffsetsFromCurrentPose()
|
||||
{
|
||||
if (!TryGetWeightedPosition(out var targetPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var direction = targetPosition - transform.position;
|
||||
if (direction.sqrMagnitude < 0.000001f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var baseRotation = LookRotationForAxis(direction, worldUpVector, aimAxis, upAxis);
|
||||
rotationOffset = (Quaternion.Inverse(baseRotation) * transform.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 70b32d75aafa49d781fe9cd7389d78b5
|
||||
@@ -0,0 +1,356 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
public enum RoughConstraintUpdateMode
|
||||
{
|
||||
Update,
|
||||
LateUpdate,
|
||||
FixedUpdate,
|
||||
Manual
|
||||
}
|
||||
|
||||
[ExecuteAlways]
|
||||
public abstract class RoughConstraintBase : MonoBehaviour
|
||||
{
|
||||
[Header("Constraint")]
|
||||
public bool constraintActive = true;
|
||||
public bool locked = true;
|
||||
|
||||
[Range(0f, 1f)]
|
||||
public float weight = 1f;
|
||||
|
||||
public List<RoughConstraintSource> sources = new List<RoughConstraintSource>();
|
||||
|
||||
[Header("Rough Follow")]
|
||||
[Min(0f)]
|
||||
public float damping = 12f;
|
||||
|
||||
public RoughConstraintUpdateMode updateMode = RoughConstraintUpdateMode.LateUpdate;
|
||||
public bool useUnscaledTime;
|
||||
public bool snapOnEnable = true;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private bool editorUpdateRegistered;
|
||||
#endif
|
||||
|
||||
protected float CurrentDeltaTime
|
||||
{
|
||||
get
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return 1f / 60f;
|
||||
}
|
||||
|
||||
if (updateMode == RoughConstraintUpdateMode.FixedUpdate)
|
||||
{
|
||||
return useUnscaledTime ? Time.fixedUnscaledDeltaTime : Time.fixedDeltaTime;
|
||||
}
|
||||
|
||||
return useUnscaledTime ? Time.unscaledDeltaTime : Time.deltaTime;
|
||||
}
|
||||
}
|
||||
|
||||
protected float FollowT
|
||||
{
|
||||
get
|
||||
{
|
||||
if (damping <= 0f)
|
||||
{
|
||||
return 1f;
|
||||
}
|
||||
|
||||
return 1f - Mathf.Exp(-damping * Mathf.Max(0f, CurrentDeltaTime));
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
RegisterEditorUpdate();
|
||||
#endif
|
||||
|
||||
if (!snapOnEnable)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
SnapToSources();
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
UnregisterEditorUpdate();
|
||||
#endif
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
if (updateMode != RoughConstraintUpdateMode.Manual)
|
||||
{
|
||||
Evaluate();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateMode == RoughConstraintUpdateMode.Update)
|
||||
{
|
||||
Evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
private void LateUpdate()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateMode == RoughConstraintUpdateMode.LateUpdate)
|
||||
{
|
||||
Evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
{
|
||||
if (!Application.isPlaying)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (updateMode == RoughConstraintUpdateMode.FixedUpdate)
|
||||
{
|
||||
Evaluate();
|
||||
}
|
||||
}
|
||||
|
||||
#if UNITY_EDITOR
|
||||
private void RegisterEditorUpdate()
|
||||
{
|
||||
if (editorUpdateRegistered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditorApplication.update += EditorUpdate;
|
||||
editorUpdateRegistered = true;
|
||||
}
|
||||
|
||||
private void UnregisterEditorUpdate()
|
||||
{
|
||||
if (!editorUpdateRegistered)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
EditorApplication.update -= EditorUpdate;
|
||||
editorUpdateRegistered = false;
|
||||
}
|
||||
|
||||
private void EditorUpdate()
|
||||
{
|
||||
if (this == null)
|
||||
{
|
||||
UnregisterEditorUpdate();
|
||||
return;
|
||||
}
|
||||
|
||||
if (Application.isPlaying || updateMode == RoughConstraintUpdateMode.Manual)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Evaluate();
|
||||
}
|
||||
#endif
|
||||
|
||||
public void Evaluate()
|
||||
{
|
||||
if (!CanEvaluate())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ExecuteConstraint(FollowT);
|
||||
}
|
||||
|
||||
public void SnapToSources()
|
||||
{
|
||||
if (!CanEvaluate())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ExecuteConstraint(1f);
|
||||
}
|
||||
|
||||
public void SetLocked(bool value)
|
||||
{
|
||||
if (value && !locked)
|
||||
{
|
||||
CaptureOffsetsFromCurrentPose();
|
||||
}
|
||||
|
||||
locked = value;
|
||||
}
|
||||
|
||||
public void ActivateConstraint()
|
||||
{
|
||||
constraintActive = true;
|
||||
locked = true;
|
||||
SnapToSources();
|
||||
}
|
||||
|
||||
protected abstract void ExecuteConstraint(float followT);
|
||||
|
||||
protected virtual void CaptureOffsetsFromCurrentPose()
|
||||
{
|
||||
}
|
||||
|
||||
private bool CanEvaluate()
|
||||
{
|
||||
return constraintActive && locked && weight > 0f;
|
||||
}
|
||||
|
||||
protected bool TryGetWeightedPosition(out Vector3 position)
|
||||
{
|
||||
position = Vector3.zero;
|
||||
var totalWeight = 0f;
|
||||
|
||||
for (var i = 0; i < sources.Count; i++)
|
||||
{
|
||||
var source = sources[i];
|
||||
if (source.sourceTransform == null || source.weight <= 0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
position += source.sourceTransform.position * source.weight;
|
||||
totalWeight += source.weight;
|
||||
}
|
||||
|
||||
if (totalWeight <= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
position /= totalWeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected bool TryGetWeightedRotation(out Quaternion rotation)
|
||||
{
|
||||
rotation = Quaternion.identity;
|
||||
var hasRotation = false;
|
||||
var accumulatedWeight = 0f;
|
||||
|
||||
for (var i = 0; i < sources.Count; i++)
|
||||
{
|
||||
var source = sources[i];
|
||||
if (source.sourceTransform == null || source.weight <= 0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var sourceRotation = source.sourceTransform.rotation;
|
||||
if (!hasRotation)
|
||||
{
|
||||
rotation = sourceRotation;
|
||||
accumulatedWeight = source.weight;
|
||||
hasRotation = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
var lerpWeight = source.weight / (accumulatedWeight + source.weight);
|
||||
rotation = Quaternion.Slerp(rotation, sourceRotation, lerpWeight);
|
||||
accumulatedWeight += source.weight;
|
||||
}
|
||||
|
||||
return hasRotation;
|
||||
}
|
||||
|
||||
protected bool TryGetWeightedScale(out Vector3 scale)
|
||||
{
|
||||
scale = Vector3.zero;
|
||||
var totalWeight = 0f;
|
||||
|
||||
for (var i = 0; i < sources.Count; i++)
|
||||
{
|
||||
var source = sources[i];
|
||||
if (source.sourceTransform == null || source.weight <= 0f)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
scale += source.sourceTransform.localScale * source.weight;
|
||||
totalWeight += source.weight;
|
||||
}
|
||||
|
||||
if (totalWeight <= 0f)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
scale /= totalWeight;
|
||||
return true;
|
||||
}
|
||||
|
||||
protected static Vector3 ApplyAxisMask(Vector3 current, Vector3 target, Vector3Bool constrainedAxis)
|
||||
{
|
||||
if (!constrainedAxis.x) target.x = current.x;
|
||||
if (!constrainedAxis.y) target.y = current.y;
|
||||
if (!constrainedAxis.z) target.z = current.z;
|
||||
return target;
|
||||
}
|
||||
|
||||
protected static Vector3 ApplyEulerAxisMask(Quaternion current, Quaternion target, Vector3Bool constrainedAxis)
|
||||
{
|
||||
var currentEuler = current.eulerAngles;
|
||||
var targetEuler = target.eulerAngles;
|
||||
|
||||
if (!constrainedAxis.x) targetEuler.x = currentEuler.x;
|
||||
if (!constrainedAxis.y) targetEuler.y = currentEuler.y;
|
||||
if (!constrainedAxis.z) targetEuler.z = currentEuler.z;
|
||||
|
||||
return targetEuler;
|
||||
}
|
||||
|
||||
protected static Quaternion LookRotationForAxis(Vector3 direction, Vector3 worldUp, Vector3 localForward, Vector3 localUp)
|
||||
{
|
||||
var safeDirection = SafeNormal(direction, Vector3.forward);
|
||||
var safeWorldUp = SafeUp(safeDirection, worldUp);
|
||||
var safeLocalForward = SafeNormal(localForward, Vector3.forward);
|
||||
var safeLocalUp = SafeUp(safeLocalForward, localUp);
|
||||
|
||||
var targetWorldRotation = Quaternion.LookRotation(safeDirection, safeWorldUp);
|
||||
var localAxisRotation = Quaternion.LookRotation(safeLocalForward, safeLocalUp);
|
||||
return targetWorldRotation * Quaternion.Inverse(localAxisRotation);
|
||||
}
|
||||
|
||||
private static Vector3 SafeNormal(Vector3 value, Vector3 fallback)
|
||||
{
|
||||
return value.sqrMagnitude > 0.000001f ? value.normalized : fallback;
|
||||
}
|
||||
|
||||
private static Vector3 SafeUp(Vector3 forward, Vector3 up)
|
||||
{
|
||||
var safeUp = SafeNormal(up, Vector3.up);
|
||||
if (Mathf.Abs(Vector3.Dot(forward, safeUp)) < 0.999f)
|
||||
{
|
||||
return safeUp;
|
||||
}
|
||||
|
||||
return Mathf.Abs(Vector3.Dot(forward, Vector3.up)) < 0.999f ? Vector3.up : Vector3.right;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 113d932d171c415fa3b62ab75bdf3de7
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[Serializable]
|
||||
public struct RoughConstraintSource
|
||||
{
|
||||
public Transform sourceTransform;
|
||||
|
||||
[Range(0f, 1f)]
|
||||
public float weight;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7192f25e37a54bc385855e11d7f3abc3
|
||||
@@ -0,0 +1,52 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[ExecuteAlways]
|
||||
[AddComponentMenu("Streamingle Utilities/Constraints/Rough Look At Constraint")]
|
||||
public class RoughLookAtConstraint : RoughConstraintBase
|
||||
{
|
||||
[Header("Look At")]
|
||||
public Vector3 forwardAxis = Vector3.forward;
|
||||
public Vector3 worldUpVector = Vector3.up;
|
||||
public Vector3 targetPositionOffset;
|
||||
public Vector3 rotationOffset;
|
||||
|
||||
protected override void ExecuteConstraint(float followT)
|
||||
{
|
||||
if (!TryGetWeightedPosition(out var targetPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
targetPosition += targetPositionOffset;
|
||||
var direction = targetPosition - transform.position;
|
||||
if (direction.sqrMagnitude < 0.000001f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var targetRotation = LookRotationForAxis(direction, worldUpVector, forwardAxis, Vector3.up);
|
||||
targetRotation *= Quaternion.Euler(rotationOffset);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, followT * weight);
|
||||
}
|
||||
|
||||
protected override void CaptureOffsetsFromCurrentPose()
|
||||
{
|
||||
if (!TryGetWeightedPosition(out var targetPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
targetPosition += targetPositionOffset;
|
||||
var direction = targetPosition - transform.position;
|
||||
if (direction.sqrMagnitude < 0.000001f)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var baseRotation = LookRotationForAxis(direction, worldUpVector, forwardAxis, Vector3.up);
|
||||
rotationOffset = (Quaternion.Inverse(baseRotation) * transform.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 0ff851637cd645758f43435b7ee8fb42
|
||||
@@ -0,0 +1,67 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[ExecuteAlways]
|
||||
[AddComponentMenu("Streamingle Utilities/Constraints/Rough Parent Constraint")]
|
||||
public class RoughParentConstraint : RoughConstraintBase
|
||||
{
|
||||
[Header("Position")]
|
||||
public Vector3Bool constrainedPositionAxis = Vector3Bool.All;
|
||||
public Vector3 positionOffset;
|
||||
public bool positionOffsetInSourceSpace = true;
|
||||
|
||||
[Header("Rotation")]
|
||||
public Vector3Bool constrainedRotationAxis = Vector3Bool.All;
|
||||
public Vector3 rotationOffset;
|
||||
|
||||
protected override void ExecuteConstraint(float followT)
|
||||
{
|
||||
var blend = followT * weight;
|
||||
|
||||
if (TryGetWeightedPosition(out var targetPosition))
|
||||
{
|
||||
if (positionOffsetInSourceSpace && sources.Count > 0 && sources[0].sourceTransform != null)
|
||||
{
|
||||
targetPosition += sources[0].sourceTransform.TransformVector(positionOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPosition += positionOffset;
|
||||
}
|
||||
|
||||
targetPosition = ApplyAxisMask(transform.position, targetPosition, constrainedPositionAxis);
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, blend);
|
||||
}
|
||||
|
||||
if (TryGetWeightedRotation(out var targetRotation))
|
||||
{
|
||||
targetRotation *= Quaternion.Euler(rotationOffset);
|
||||
var maskedEuler = ApplyEulerAxisMask(transform.rotation, targetRotation, constrainedRotationAxis);
|
||||
targetRotation = Quaternion.Euler(maskedEuler);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, blend);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void CaptureOffsetsFromCurrentPose()
|
||||
{
|
||||
if (TryGetWeightedPosition(out var sourcePosition))
|
||||
{
|
||||
var delta = transform.position - sourcePosition;
|
||||
if (positionOffsetInSourceSpace && sources.Count > 0 && sources[0].sourceTransform != null)
|
||||
{
|
||||
positionOffset = sources[0].sourceTransform.InverseTransformVector(delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
positionOffset = delta;
|
||||
}
|
||||
}
|
||||
|
||||
if (TryGetWeightedRotation(out var sourceRotation))
|
||||
{
|
||||
rotationOffset = (Quaternion.Inverse(sourceRotation) * transform.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 015afbd1174749d889a7b3542929c39b
|
||||
@@ -0,0 +1,52 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[ExecuteAlways]
|
||||
[AddComponentMenu("Streamingle Utilities/Constraints/Rough Position Constraint")]
|
||||
public class RoughPositionConstraint : RoughConstraintBase
|
||||
{
|
||||
[Header("Position")]
|
||||
public Vector3Bool constrainedAxis = Vector3Bool.All;
|
||||
public Vector3 positionOffset;
|
||||
public bool offsetInSourceSpace = true;
|
||||
|
||||
protected override void ExecuteConstraint(float followT)
|
||||
{
|
||||
if (!TryGetWeightedPosition(out var targetPosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (offsetInSourceSpace && sources.Count > 0 && sources[0].sourceTransform != null)
|
||||
{
|
||||
targetPosition += sources[0].sourceTransform.TransformVector(positionOffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
targetPosition += positionOffset;
|
||||
}
|
||||
|
||||
targetPosition = ApplyAxisMask(transform.position, targetPosition, constrainedAxis);
|
||||
transform.position = Vector3.Lerp(transform.position, targetPosition, followT * weight);
|
||||
}
|
||||
|
||||
protected override void CaptureOffsetsFromCurrentPose()
|
||||
{
|
||||
if (!TryGetWeightedPosition(out var sourcePosition))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var delta = transform.position - sourcePosition;
|
||||
if (offsetInSourceSpace && sources.Count > 0 && sources[0].sourceTransform != null)
|
||||
{
|
||||
positionOffset = sources[0].sourceTransform.InverseTransformVector(delta);
|
||||
}
|
||||
else
|
||||
{
|
||||
positionOffset = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b1874b6468e0419f925ee085ce478bfb
|
||||
@@ -0,0 +1,36 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[ExecuteAlways]
|
||||
[AddComponentMenu("Streamingle Utilities/Constraints/Rough Rotation Constraint")]
|
||||
public class RoughRotationConstraint : RoughConstraintBase
|
||||
{
|
||||
[Header("Rotation")]
|
||||
public Vector3Bool constrainedAxis = Vector3Bool.All;
|
||||
public Vector3 rotationOffset;
|
||||
|
||||
protected override void ExecuteConstraint(float followT)
|
||||
{
|
||||
if (!TryGetWeightedRotation(out var targetRotation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
targetRotation *= Quaternion.Euler(rotationOffset);
|
||||
var maskedEuler = ApplyEulerAxisMask(transform.rotation, targetRotation, constrainedAxis);
|
||||
targetRotation = Quaternion.Euler(maskedEuler);
|
||||
transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, followT * weight);
|
||||
}
|
||||
|
||||
protected override void CaptureOffsetsFromCurrentPose()
|
||||
{
|
||||
if (!TryGetWeightedRotation(out var sourceRotation))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
rotationOffset = (Quaternion.Inverse(sourceRotation) * transform.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 23820ffe249c4b7bad25455ca97fc8d3
|
||||
@@ -0,0 +1,35 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[ExecuteAlways]
|
||||
[AddComponentMenu("Streamingle Utilities/Constraints/Rough Scale Constraint")]
|
||||
public class RoughScaleConstraint : RoughConstraintBase
|
||||
{
|
||||
[Header("Scale")]
|
||||
public Vector3Bool constrainedAxis = Vector3Bool.All;
|
||||
public Vector3 scaleOffset;
|
||||
|
||||
protected override void ExecuteConstraint(float followT)
|
||||
{
|
||||
if (!TryGetWeightedScale(out var targetScale))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
targetScale += scaleOffset;
|
||||
targetScale = ApplyAxisMask(transform.localScale, targetScale, constrainedAxis);
|
||||
transform.localScale = Vector3.Lerp(transform.localScale, targetScale, followT * weight);
|
||||
}
|
||||
|
||||
protected override void CaptureOffsetsFromCurrentPose()
|
||||
{
|
||||
if (!TryGetWeightedScale(out var sourceScale))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
scaleOffset = transform.localScale - sourceScale;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c58bfc39585a4c61bef1c73bf3fbc9a0
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace Streamingle.Utils.RoughConstraints
|
||||
{
|
||||
[Serializable]
|
||||
public struct Vector3Bool
|
||||
{
|
||||
public bool x;
|
||||
public bool y;
|
||||
public bool z;
|
||||
|
||||
public Vector3Bool(bool x, bool y, bool z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public static Vector3Bool All => new Vector3Bool(true, true, true);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6b3fce5b0afa436abaaba5ea0261354d
|
||||
Reference in New Issue
Block a user