Initialer Upload neues Unity-Projekt
This commit is contained in:
@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus SDK
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Oculus.Interaction;
|
||||
using Oculus.Interaction.Input;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Oculus.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// HandFingerMaskGenerator creates a finger mask from the hand model currently used (check diff that added this script)
|
||||
/// It projects the hand model into a 2d space using the object space positions of the hand model
|
||||
/// and line positions using the hand visuals Joint Poses.
|
||||
/// </summary>
|
||||
public class HandFingerMaskGenerator
|
||||
{
|
||||
private static readonly int[] _fingerLinesID =
|
||||
{
|
||||
Shader.PropertyToID("_ThumbLine"), Shader.PropertyToID("_IndexLine"),
|
||||
Shader.PropertyToID("_MiddleLine"), Shader.PropertyToID("_RingLine"),
|
||||
Shader.PropertyToID("_PinkyLine")
|
||||
};
|
||||
|
||||
private static readonly int[] _palmFingerLinesID =
|
||||
{
|
||||
Shader.PropertyToID("_PalmThumbLine"), Shader.PropertyToID("_PalmIndexLine"),
|
||||
Shader.PropertyToID("_PalmMiddleLine"), Shader.PropertyToID("_PalmRingLine"),
|
||||
Shader.PropertyToID("_PalmPinkyLine")
|
||||
};
|
||||
|
||||
private static float HandednessMultiplier(Handedness hand) =>
|
||||
hand != Handedness.Right ? -1.0f : 1.0f;
|
||||
|
||||
private static List<Vector2> GenerateModelUV(Handedness hand, Mesh sharedHandMesh,
|
||||
out Vector2 minPosition,
|
||||
out Vector2 maxPosition)
|
||||
{
|
||||
List<Vector3> mVertices = new List<Vector3>();
|
||||
sharedHandMesh.GetVertices(mVertices);
|
||||
minPosition = new Vector2(mVertices[0].x, mVertices[0].z);
|
||||
maxPosition = new Vector2(mVertices[0].x, mVertices[0].z);
|
||||
for (int i = 0; i < mVertices.Count; i++)
|
||||
{
|
||||
var vertex = mVertices[i] * HandednessMultiplier(hand);
|
||||
var vertex2d = new Vector2(vertex.x, vertex.z);
|
||||
minPosition = Vector2.Min(minPosition, vertex2d);
|
||||
maxPosition = Vector2.Max(maxPosition, vertex2d);
|
||||
mVertices[i] = vertex;
|
||||
}
|
||||
|
||||
List<Vector2> mUVs = new List<Vector2>();
|
||||
Vector2 regionSize = maxPosition - minPosition;
|
||||
float maxLength = Mathf.Max(regionSize.x, regionSize.y);
|
||||
foreach (var vertex in mVertices)
|
||||
{
|
||||
var vertex2d = new Vector2(vertex.x, vertex.z);
|
||||
var vertexUV = (vertex2d - minPosition) / maxLength;
|
||||
mUVs.Add(vertexUV);
|
||||
}
|
||||
|
||||
return mUVs;
|
||||
}
|
||||
|
||||
private static Vector2 getPositionOnRegion(HandVisual handVisual, HandJointId jointId,
|
||||
Vector2 minRegion,
|
||||
float sideLength)
|
||||
{
|
||||
var lineStartPose = handVisual.GetJointPose(jointId, Space.World);
|
||||
var lineStartLocalPosition =
|
||||
handVisual.transform.InverseTransformPoint(lineStartPose.position);
|
||||
Vector2 point = new Vector2(lineStartLocalPosition.x, lineStartLocalPosition.z);
|
||||
point *= HandednessMultiplier(handVisual.Hand.Handedness);
|
||||
return (point - minRegion) / sideLength;
|
||||
}
|
||||
|
||||
private static Vector4 GenerateLineData(HandVisual handVisual, HandJointId jointIdStart,
|
||||
HandJointId jointIdEnd,
|
||||
Vector2 minRegion, float sideLength, float lineScale)
|
||||
{
|
||||
Vector2 startPosition =
|
||||
getPositionOnRegion(handVisual, jointIdStart, minRegion, sideLength);
|
||||
Vector2 endPosition =
|
||||
getPositionOnRegion(handVisual, jointIdEnd, minRegion, sideLength);
|
||||
endPosition = Vector2.LerpUnclamped(startPosition, endPosition, lineScale);
|
||||
return new Vector4(startPosition.x, startPosition.y, endPosition.x, endPosition.y);
|
||||
}
|
||||
|
||||
private static Vector4[] GenerateFingerLines(HandVisual handVisual, Vector2 minPosition,
|
||||
float maxLength, float[] lineScale)
|
||||
{
|
||||
Vector4 thumbLine = GenerateLineData(handVisual, HandJointId.HandThumbTip,
|
||||
HandJointId.HandThumb1, minPosition, maxLength, lineScale[0]);
|
||||
Vector4 indexLine = GenerateLineData(handVisual, HandJointId.HandIndexTip,
|
||||
HandJointId.HandIndex1, minPosition, maxLength, lineScale[1]);
|
||||
Vector4 middleLine = GenerateLineData(handVisual, HandJointId.HandMiddleTip,
|
||||
HandJointId.HandMiddle1, minPosition, maxLength, lineScale[2]);
|
||||
Vector4 ringLine = GenerateLineData(handVisual, HandJointId.HandRingTip,
|
||||
HandJointId.HandRing1, minPosition, maxLength, lineScale[3]);
|
||||
Vector4 pinkyLine = GenerateLineData(handVisual, HandJointId.HandPinkyTip,
|
||||
HandJointId.HandPinky1, minPosition, maxLength, lineScale[4]);
|
||||
|
||||
return new Vector4[5] { thumbLine, indexLine, middleLine, ringLine, pinkyLine };
|
||||
}
|
||||
|
||||
private static void SetGlowModelUV(SkinnedMeshRenderer handRenderer, HandVisual handVisual,
|
||||
out Vector2 minPosition, out Vector2 maxPosition)
|
||||
{
|
||||
Mesh sharedHandMesh = handRenderer.sharedMesh;
|
||||
|
||||
var mUVs = GenerateModelUV(handVisual.Hand.Handedness, sharedHandMesh,
|
||||
out minPosition,
|
||||
out maxPosition);
|
||||
|
||||
sharedHandMesh.SetUVs(1, mUVs);
|
||||
sharedHandMesh.UploadMeshData(false);
|
||||
}
|
||||
|
||||
private static void SetFingerMaskUniforms(HandVisual handVisual, MaterialPropertyBlock materialPropertyBlock, Vector2 minPosition, Vector2 maxPosition)
|
||||
{
|
||||
Vector2 regionSize = maxPosition - minPosition;
|
||||
float maxLength = Mathf.Max(regionSize.x, regionSize.y);
|
||||
|
||||
//The following numbers generate good looking lines for the current hand model
|
||||
var fingerLineScales = new float[5] { 0.9f, 0.91f, 0.9f, 0.87f, 0.87f };
|
||||
var fingerLines = GenerateFingerLines(handVisual, minPosition, maxLength, fingerLineScales);
|
||||
//The thumb line is going to be perpendicularly aligned to the wrist direction
|
||||
fingerLines[0].z = Mathf.Lerp(fingerLines[0].z, fingerLines[0].x, 0.3f);
|
||||
fingerLines[0].x = fingerLines[0].z;
|
||||
|
||||
var palmFingerLineScales = new float[5] { 1.2f, 1.25f, 1.25f, 1.25f, 1.25f };
|
||||
var palmFingerLines =
|
||||
GenerateFingerLines(handVisual, minPosition, maxLength, palmFingerLineScales);
|
||||
//The thumb line is going to be perpendicularly aligned to the wrist direction
|
||||
float thumbOffset = Mathf.Abs(palmFingerLines[0].x - palmFingerLines[0].z) * 0.1f;
|
||||
palmFingerLines[0].z += thumbOffset;
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
materialPropertyBlock.SetVector(_fingerLinesID[i], fingerLines[i]);
|
||||
materialPropertyBlock.SetVector(_palmFingerLinesID[i], palmFingerLines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public static void GenerateFingerMask(SkinnedMeshRenderer handRenderer, HandVisual handVisual, MaterialPropertyBlock materialPropertyBlock)
|
||||
{
|
||||
SetGlowModelUV(handRenderer, handVisual, out Vector2 minPosition,
|
||||
out Vector2 maxPosition);
|
||||
SetFingerMaskUniforms(handVisual, materialPropertyBlock, minPosition, maxPosition);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f0f79a90296794205969ef8ab2256883
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus SDK
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using UnityEngine;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Oculus.Interaction.Grab;
|
||||
using Oculus.Interaction.GrabAPI;
|
||||
using Oculus.Interaction.Input;
|
||||
using System;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Serialization;
|
||||
using Oculus.Interaction.HandGrab;
|
||||
|
||||
namespace Oculus.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// HandGrabGlow controls the glow properties of the OculusHand material to get a glow effect
|
||||
/// when pinch / palm grabbing objects depending on the per finger pinch / palm strength.
|
||||
/// To achive the glow effect, it also generates a custom UV channel and using the joints
|
||||
/// in the hand visual component adds per finger mask information.
|
||||
/// </summary>
|
||||
public class HandGrabGlow : MonoBehaviour
|
||||
{
|
||||
#region Inspector
|
||||
|
||||
[SerializeField, Interface(typeof(IHandGrabInteractor), typeof(IInteractor))]
|
||||
private UnityEngine.Object _handGrabInteractor;
|
||||
|
||||
[SerializeField]
|
||||
private SkinnedMeshRenderer _handRenderer;
|
||||
|
||||
[SerializeField]
|
||||
private MaterialPropertyBlockEditor _materialEditor;
|
||||
|
||||
[SerializeField]
|
||||
private HandVisual _handVisual;
|
||||
|
||||
[SerializeField]
|
||||
private Color _glowColorGrabing;
|
||||
|
||||
[SerializeField]
|
||||
private Color _glowColorHover;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
private float _colorChangeSpeed = 0.5f;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 0.25f)]
|
||||
private float _glowFadeStartTime = 0.2f;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
private float _glowStrengthChangeSpeed = 0.5f;
|
||||
|
||||
[SerializeField]
|
||||
private bool _fadeOut;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
[Tooltip("Recommended from 0.7 to 1.0")]
|
||||
private float _gradientLength = 0.85f;
|
||||
|
||||
[SerializeField]
|
||||
private GlowType _glowType = GlowType.Outline;
|
||||
|
||||
#endregion
|
||||
|
||||
public enum GlowType
|
||||
{
|
||||
Fill = 27,
|
||||
Outline = 28,
|
||||
Both = 29
|
||||
}
|
||||
|
||||
enum GlowState
|
||||
{
|
||||
None,
|
||||
Hover,
|
||||
Selected,
|
||||
SelectedGlowOut,
|
||||
}
|
||||
|
||||
private GlowState _state;
|
||||
private float _accumulatedSelectedTime;
|
||||
|
||||
enum GrabState
|
||||
{
|
||||
None,
|
||||
Pinch,
|
||||
Palm
|
||||
}
|
||||
|
||||
private GrabState _grabState;
|
||||
|
||||
private float _glowFadeValue;
|
||||
private Color _currentColor;
|
||||
|
||||
private IHandGrabInteractor HandGrabInteractor;
|
||||
private IInteractor Interactor;
|
||||
|
||||
private float[] _glowStregth = { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f };
|
||||
|
||||
#region ShaderPropertyIDs
|
||||
|
||||
private readonly int _generateGlowID = Shader.PropertyToID("_GenerateGlow");
|
||||
private readonly int _glowColorID = Shader.PropertyToID("_GlowColor");
|
||||
private readonly int _glowTypeID = Shader.PropertyToID("_GlowType");
|
||||
private readonly int _glowParameterID = Shader.PropertyToID("_GlowParameter");
|
||||
|
||||
private readonly int[] _fingersGlowIDs =
|
||||
{
|
||||
Shader.PropertyToID("_ThumbGlowValue"), Shader.PropertyToID("_IndexGlowValue"),
|
||||
Shader.PropertyToID("_MiddleGlowValue"), Shader.PropertyToID("_RingGlowValue"),
|
||||
Shader.PropertyToID("_PinkyGlowValue"),
|
||||
};
|
||||
|
||||
#endregion
|
||||
|
||||
protected bool _started = false;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
_glowFadeValue = 1.0f;
|
||||
_state = GlowState.None;
|
||||
_grabState = GrabState.None;
|
||||
HandGrabInteractor = _handGrabInteractor as IHandGrabInteractor;
|
||||
Interactor = _handGrabInteractor as IInteractor;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
this.BeginStart(ref _started);
|
||||
|
||||
Assert.IsNotNull(_materialEditor);
|
||||
Assert.IsNotNull(HandGrabInteractor);
|
||||
Assert.IsNotNull(Interactor);
|
||||
Assert.IsNotNull(_handVisual);
|
||||
HandFingerMaskGenerator.GenerateFingerMask(_handRenderer, _handVisual,
|
||||
_materialEditor.MaterialPropertyBlock);
|
||||
|
||||
this.EndStart(ref _started);
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
Interactor.WhenPostprocessed += UpdateVisual;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
Interactor.WhenPostprocessed -= UpdateVisual;
|
||||
}
|
||||
}
|
||||
|
||||
private void SetMaterialPropertyBlockValues()
|
||||
{
|
||||
MaterialPropertyBlock block = _materialEditor.MaterialPropertyBlock;
|
||||
if (block == null) return;
|
||||
block.SetInt(_generateGlowID, 1);
|
||||
block.SetColor(_glowColorID, _currentColor);
|
||||
if (_glowType == GlowType.Fill || _glowType == GlowType.Both)
|
||||
{
|
||||
float glowParam = _gradientLength;
|
||||
if (_fadeOut)
|
||||
{
|
||||
glowParam *= _glowFadeValue;
|
||||
}
|
||||
|
||||
block.SetFloat(_glowParameterID, glowParam);
|
||||
}
|
||||
else
|
||||
{
|
||||
block.SetFloat(_glowParameterID, _glowFadeValue);
|
||||
}
|
||||
|
||||
for (int i = 0; i < _fingersGlowIDs.Length; i++)
|
||||
{
|
||||
block.SetFloat(_fingersGlowIDs[i], Mathf.Clamp01(_glowStregth[i]));
|
||||
}
|
||||
|
||||
block.SetInt(_glowTypeID, (int) _glowType);
|
||||
}
|
||||
|
||||
private void UpdateFingerGlowStrength(int fingerIndex, float strength)
|
||||
{
|
||||
float glowStrength =
|
||||
Mathf.Lerp(_glowStregth[fingerIndex], strength, _glowStrengthChangeSpeed);
|
||||
_glowStregth[fingerIndex] = glowStrength;
|
||||
}
|
||||
|
||||
private bool FingerOptionalOrRequired(GrabbingRule rules, HandFinger finger)
|
||||
{
|
||||
return rules[finger] == FingerRequirement.Optional ||
|
||||
rules[finger] == FingerRequirement.Required;
|
||||
}
|
||||
|
||||
private void UpdateGlowStrength()
|
||||
{
|
||||
float maxStrength = 0.0f;
|
||||
for (int i = 1; i < Input.Constants.NUM_FINGERS; i++)
|
||||
{
|
||||
Input.HandFinger finger = (Input.HandFinger)i;
|
||||
bool isPinchOptionalOrRequired =
|
||||
FingerOptionalOrRequired(HandGrabInteractor.TargetInteractable.PinchGrabRules, finger);
|
||||
float pinchStrength = TargetSupportsPinch() && isPinchOptionalOrRequired
|
||||
? HandGrabInteractor.HandGrabApi.GetFingerPinchStrength(finger)
|
||||
: 0.0f;
|
||||
bool isPalmOptionalOrRequired =
|
||||
FingerOptionalOrRequired(HandGrabInteractor.TargetInteractable.PalmGrabRules, finger);
|
||||
float palmStrength = TargetSupportsPalm() && isPalmOptionalOrRequired
|
||||
? HandGrabInteractor.HandGrabApi.GetFingerPalmStrength(finger)
|
||||
: 0.0f;
|
||||
float strength = Mathf.Max(pinchStrength, palmStrength);
|
||||
UpdateFingerGlowStrength(i, strength);
|
||||
maxStrength = Mathf.Max(pinchStrength, maxStrength);
|
||||
}
|
||||
|
||||
//Set thumb strength
|
||||
bool isPalmOptionalOrRequiredThumb =
|
||||
FingerOptionalOrRequired(HandGrabInteractor.TargetInteractable.PalmGrabRules,
|
||||
HandFinger.Thumb);
|
||||
var thumbStrength = TargetSupportsPalm() && isPalmOptionalOrRequiredThumb
|
||||
? HandGrabInteractor.HandGrabApi.GetFingerPalmStrength(HandFinger.Thumb)
|
||||
: 0.0f;
|
||||
//Not getting the pinch thumb strength because it might not give the correct value
|
||||
UpdateFingerGlowStrength(0, Mathf.Max(thumbStrength, maxStrength));
|
||||
}
|
||||
|
||||
private void UpdateGlowState()
|
||||
{
|
||||
if (Interactor.State == InteractorState.Hover)
|
||||
{
|
||||
_state = GlowState.Hover;
|
||||
}
|
||||
else if (Interactor.State == InteractorState.Select)
|
||||
{
|
||||
if (_state == GlowState.Hover || _state == GlowState.None)
|
||||
{
|
||||
_accumulatedSelectedTime = 0.0f;
|
||||
_state = GlowState.Selected;
|
||||
}
|
||||
else if (_state == GlowState.Selected)
|
||||
{
|
||||
_accumulatedSelectedTime += Time.deltaTime;
|
||||
if (_fadeOut && _accumulatedSelectedTime >= _glowFadeStartTime)
|
||||
{
|
||||
_state = GlowState.SelectedGlowOut;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_state = GlowState.None;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGlowColorAndFade()
|
||||
{
|
||||
if (_state == GlowState.Hover)
|
||||
{
|
||||
_glowFadeValue = 1.0f;
|
||||
_currentColor = Color.Lerp(_currentColor,
|
||||
_fadeOut ? _glowColorGrabing : _glowColorHover, _colorChangeSpeed);
|
||||
}
|
||||
else if (_state == GlowState.Selected)
|
||||
{
|
||||
if (_fadeOut)
|
||||
{
|
||||
_glowFadeValue = Mathf.Lerp(_glowFadeValue, 0.5f, 0.8f);
|
||||
_currentColor = _glowColorGrabing;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glowFadeValue = 1.0f;
|
||||
_currentColor = Color.Lerp(_currentColor, _glowColorGrabing, _colorChangeSpeed);
|
||||
}
|
||||
}
|
||||
else if (_state == GlowState.SelectedGlowOut)
|
||||
{
|
||||
_glowFadeValue = Mathf.Lerp(_glowFadeValue, 1.15f, 0.3f);
|
||||
_currentColor = _glowColorGrabing;
|
||||
}
|
||||
else
|
||||
{
|
||||
_glowFadeValue = Mathf.Lerp(_glowFadeValue, 0.0f, 0.15f);
|
||||
}
|
||||
}
|
||||
|
||||
private bool TargetSupportsPinch()
|
||||
{
|
||||
if (HandGrabInteractor.TargetInteractable == null) return false;
|
||||
|
||||
return (HandGrabInteractor.SupportedGrabTypes &
|
||||
HandGrabInteractor.TargetInteractable.SupportedGrabTypes &
|
||||
GrabTypeFlags.Pinch) != 0;
|
||||
}
|
||||
|
||||
private bool TargetSupportsPalm()
|
||||
{
|
||||
if (HandGrabInteractor.TargetInteractable == null) return false;
|
||||
|
||||
return (HandGrabInteractor.SupportedGrabTypes &
|
||||
HandGrabInteractor.TargetInteractable.SupportedGrabTypes &
|
||||
GrabTypeFlags.Palm) != 0;
|
||||
}
|
||||
|
||||
private void UpdateGrabState()
|
||||
{
|
||||
if (HandGrabInteractor.TargetInteractable == null)
|
||||
{
|
||||
_grabState = GrabState.None;
|
||||
return;
|
||||
}
|
||||
|
||||
GrabbingRule pinchGrabRules = HandGrabInteractor.TargetInteractable.PinchGrabRules;
|
||||
bool pinchGestureActive = HandGrabInteractor.HandGrabApi.IsHandPinchGrabbing(pinchGrabRules);
|
||||
if (TargetSupportsPinch() && pinchGestureActive)
|
||||
{
|
||||
if (_grabState == GrabState.None || _grabState == GrabState.Pinch)
|
||||
{
|
||||
_grabState = GrabState.Pinch;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GrabbingRule palmGrabRules = HandGrabInteractor.TargetInteractable.PalmGrabRules;
|
||||
bool palmGestureActive = HandGrabInteractor.HandGrabApi.IsHandPalmGrabbing(palmGrabRules);
|
||||
if (TargetSupportsPalm() && palmGestureActive)
|
||||
{
|
||||
if (_grabState == GrabState.None || _grabState == GrabState.Palm)
|
||||
{
|
||||
_grabState = GrabState.Palm;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
_grabState = GrabState.None;
|
||||
}
|
||||
|
||||
private void ClearGlow()
|
||||
{
|
||||
var block = _materialEditor.MaterialPropertyBlock;
|
||||
foreach (var fingerID in _fingersGlowIDs) block.SetFloat(fingerID, 0.0f);
|
||||
block.SetInt(_generateGlowID, 0);
|
||||
}
|
||||
|
||||
private void UpdateVisual()
|
||||
{
|
||||
GlowState prevGlowState = _state;
|
||||
UpdateGrabState();
|
||||
UpdateGlowState();
|
||||
if (prevGlowState != _state && _state == GlowState.None)
|
||||
{
|
||||
ClearGlow();
|
||||
}
|
||||
else if (_state != GlowState.None)
|
||||
{
|
||||
UpdateGlowStrength();
|
||||
UpdateGlowColorAndFade();
|
||||
SetMaterialPropertyBlockValues();
|
||||
}
|
||||
}
|
||||
|
||||
#region Inject
|
||||
|
||||
public void InjectAllHandGrabGlow(IHandGrabInteractor handGrabInteractor,
|
||||
SkinnedMeshRenderer handRenderer, MaterialPropertyBlockEditor materialEditor,
|
||||
HandVisual handVisual, Color grabbingColor, Color hoverColor, float colorChangeSpeed,
|
||||
float fadeStartTime, float glowStrengthChangeSpeed, bool fadeOut,
|
||||
float gradientLength, GlowType glowType)
|
||||
{
|
||||
InjectHandGrabInteractor(handGrabInteractor);
|
||||
InjectHandRenderer(handRenderer);
|
||||
InjectMaterialPropertyBlockEditor(materialEditor);
|
||||
InjectHandVisual(handVisual);
|
||||
InjectGlowColors(grabbingColor, hoverColor);
|
||||
InjectVisualChangeSpeed(colorChangeSpeed, fadeStartTime,
|
||||
glowStrengthChangeSpeed);
|
||||
InjectFadeOut(fadeOut);
|
||||
InjectGradientLength(gradientLength);
|
||||
InjectGlowType(glowType);
|
||||
}
|
||||
|
||||
public void InjectHandGrabInteractor(IHandGrabInteractor handGrabInteractor)
|
||||
{
|
||||
_handGrabInteractor = handGrabInteractor as UnityEngine.Object;
|
||||
Interactor = handGrabInteractor as IInteractor;
|
||||
HandGrabInteractor = handGrabInteractor;
|
||||
}
|
||||
|
||||
public void InjectHandRenderer(SkinnedMeshRenderer handRenderer)
|
||||
{
|
||||
_handRenderer = handRenderer;
|
||||
}
|
||||
|
||||
public void InjectMaterialPropertyBlockEditor(MaterialPropertyBlockEditor materialEditor)
|
||||
{
|
||||
_materialEditor = materialEditor;
|
||||
}
|
||||
|
||||
public void InjectHandVisual(HandVisual handVisual)
|
||||
{
|
||||
_handVisual = handVisual;
|
||||
}
|
||||
|
||||
public void InjectGlowColors(Color grabbingColor, Color hoverColor)
|
||||
{
|
||||
_glowColorGrabing = grabbingColor;
|
||||
_glowColorHover = hoverColor;
|
||||
}
|
||||
|
||||
public void InjectVisualChangeSpeed(float colorChangeSpeed, float fadeStartTime, float glowStrengthChangeSpeed)
|
||||
{
|
||||
_colorChangeSpeed = colorChangeSpeed;
|
||||
_glowFadeStartTime = fadeStartTime;
|
||||
_glowStrengthChangeSpeed = glowStrengthChangeSpeed;
|
||||
}
|
||||
|
||||
public void InjectFadeOut(bool fadeOut)
|
||||
{
|
||||
_fadeOut = fadeOut;
|
||||
}
|
||||
|
||||
/// <param name="gradientLength">Clamped 0.0 to 1.0</param>
|
||||
public void InjectGradientLength(float gradientLength)
|
||||
{
|
||||
_gradientLength = Mathf.Clamp01(gradientLength);
|
||||
}
|
||||
|
||||
public void InjectGlowType(GlowType glowType)
|
||||
{
|
||||
_glowType = glowType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b8667bbf66117438986bafc711f920ed
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus SDK
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Oculus.Interaction.Input;
|
||||
using UnityEngine;
|
||||
using UnityEngine.Assertions;
|
||||
using UnityEngine.Rendering;
|
||||
|
||||
namespace Oculus.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// HandPokeOvershootGlow controls the glow properties of the OculusHand material to
|
||||
/// get a glow effect when the real hand and the virtual hand are not in the same position in 3d
|
||||
/// space. This can only happen when a synthetic hand is used and wrist locking is enabled.
|
||||
/// It generates a sphere gradient with the wrist position as the center and a 0.144 units of radius.
|
||||
/// </summary>
|
||||
public class HandPokeOvershootGlow : MonoBehaviour
|
||||
{
|
||||
[SerializeField, Interface(typeof(IHand))]
|
||||
private UnityEngine.Object _hand;
|
||||
|
||||
[SerializeField]
|
||||
private PokeInteractor _pokeInteractor;
|
||||
|
||||
[SerializeField]
|
||||
private HandVisual _handVisual;
|
||||
|
||||
[SerializeField]
|
||||
private SkinnedMeshRenderer _handRenderer;
|
||||
|
||||
[SerializeField]
|
||||
private MaterialPropertyBlockEditor _materialEditor;
|
||||
|
||||
[SerializeField]
|
||||
private Color _glowColor;
|
||||
|
||||
[SerializeField]
|
||||
private float _overshootMaxDistance = 0.15f;
|
||||
|
||||
[SerializeField]
|
||||
private HandFinger _pokeFinger = HandFinger.Index;
|
||||
|
||||
[SerializeField]
|
||||
[Range(0.0f, 1.0f)]
|
||||
private float _maxGradientLength;
|
||||
|
||||
public enum GlowType
|
||||
{
|
||||
Fill = 30,
|
||||
Outline = 31,
|
||||
Both = 32
|
||||
}
|
||||
|
||||
[SerializeField]
|
||||
private GlowType _glowType = GlowType.Outline;
|
||||
|
||||
private IHand Hand;
|
||||
private bool _glowEnabled;
|
||||
|
||||
private readonly int _glowFingerIndexID = Shader.PropertyToID("_FingerGlowIndex");
|
||||
private readonly int _generateGlowID = Shader.PropertyToID("_GenerateGlow");
|
||||
private readonly int _glowColorID = Shader.PropertyToID("_GlowColor");
|
||||
private readonly int _glowTypeID = Shader.PropertyToID("_GlowType");
|
||||
private readonly int _glowParameterID = Shader.PropertyToID("_GlowParameter");
|
||||
private readonly int _glowMaxLengthID = Shader.PropertyToID("_GlowMaxLength");
|
||||
|
||||
protected bool _started = false;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Hand = _hand as IHand;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
_glowEnabled = false;
|
||||
this.BeginStart(ref _started);
|
||||
Assert.IsNotNull(Hand);
|
||||
Assert.IsNotNull(_pokeInteractor);
|
||||
Assert.IsNotNull(_materialEditor);
|
||||
HandFingerMaskGenerator.GenerateFingerMask(_handRenderer, _handVisual, _materialEditor.MaterialPropertyBlock);
|
||||
this.EndStart(ref _started);
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
_pokeInteractor.WhenPostprocessed += UpdateVisual;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
_pokeInteractor.WhenPostprocessed -= UpdateVisual;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateOvershoot(float normalizedDistance )
|
||||
{
|
||||
if (_materialEditor == null) return;
|
||||
var _block = _materialEditor.MaterialPropertyBlock;
|
||||
_block.SetFloat(_glowParameterID, Mathf.Clamp01(normalizedDistance));
|
||||
_block.SetInt(_generateGlowID, 1);
|
||||
_block.SetColor(_glowColorID, _glowColor);
|
||||
_block.SetInt(_glowTypeID, (int)_glowType);
|
||||
_block.SetInt(_glowFingerIndexID, (int)_pokeFinger);
|
||||
_block.SetFloat(_glowMaxLengthID, _maxGradientLength);
|
||||
}
|
||||
|
||||
private void UpdateVisual()
|
||||
{
|
||||
if (_pokeInteractor.State == InteractorState.Select)
|
||||
{
|
||||
_glowEnabled = true;
|
||||
Vector3 planeCenter = _pokeInteractor.TouchPoint;
|
||||
Vector3 pokeOrigin = _pokeInteractor.Origin;
|
||||
float normalizedDistance =
|
||||
Mathf.Clamp01(Vector3.Distance(planeCenter, pokeOrigin) /
|
||||
_overshootMaxDistance);
|
||||
UpdateOvershoot(normalizedDistance);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_glowEnabled)
|
||||
{
|
||||
if (_materialEditor == null) return;
|
||||
var _block = _materialEditor.MaterialPropertyBlock;
|
||||
_block.SetInt(_generateGlowID, 0);
|
||||
_glowEnabled = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region Inject
|
||||
|
||||
public void InjectAllHandPokeOvershootGlow(IHand hand, PokeInteractor pokeInteractor,
|
||||
MaterialPropertyBlockEditor materialEditor, Color glowColor, float distanceMultiplier,
|
||||
Transform wristTransform, GlowType glowType)
|
||||
{
|
||||
InjectHand(hand);
|
||||
InjectPokeInteractor(pokeInteractor);
|
||||
InjectMaterialPropertyBlockEditor(materialEditor);
|
||||
InjectGlowColor(glowColor);
|
||||
InjectOvershootMaxDistance(distanceMultiplier);
|
||||
InjectGlowType(glowType);
|
||||
}
|
||||
|
||||
public void InjectAllHandPokeOvershootGlow(IHand hand, PokeInteractor pokeInteractor, HandVisual handVisual, SkinnedMeshRenderer handRenderer, MaterialPropertyBlockEditor materialEditor)
|
||||
{
|
||||
InjectHand(hand);
|
||||
InjectPokeInteractor(pokeInteractor);
|
||||
InjectHandVisual(handVisual);
|
||||
InjectHandRenderer(handRenderer);
|
||||
InjectMaterialPropertyBlockEditor(materialEditor);
|
||||
}
|
||||
|
||||
public void InjectHand(IHand hand)
|
||||
{
|
||||
_hand = hand as UnityEngine.Object;
|
||||
Hand = hand;
|
||||
}
|
||||
|
||||
public void InjectPokeInteractor(PokeInteractor pokeInteractor)
|
||||
{
|
||||
_pokeInteractor = pokeInteractor;
|
||||
}
|
||||
|
||||
public void InjectHandRenderer(SkinnedMeshRenderer handRenderer)
|
||||
{
|
||||
_handRenderer = handRenderer;
|
||||
}
|
||||
|
||||
public void InjectHandVisual(HandVisual handVisual)
|
||||
{
|
||||
_handVisual = handVisual;
|
||||
}
|
||||
|
||||
public void InjectMaterialPropertyBlockEditor(MaterialPropertyBlockEditor materialEditor)
|
||||
{
|
||||
_materialEditor = materialEditor;
|
||||
}
|
||||
|
||||
public void InjectGlowColor(Color glowColor)
|
||||
{
|
||||
_glowColor = glowColor;
|
||||
}
|
||||
|
||||
public void InjectOvershootMaxDistance(float overshootMaxDistance)
|
||||
{
|
||||
_overshootMaxDistance = overshootMaxDistance;
|
||||
}
|
||||
|
||||
public void InjectGlowType(GlowType glowType)
|
||||
{
|
||||
_glowType = glowType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b07be626a8e824a5aaed89fffbde2fc7
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Licensed under the Oculus SDK License Agreement (the "License");
|
||||
* you may not use the Oculus SDK except in compliance with the License,
|
||||
* which is provided at the time of installation or download, or which
|
||||
* otherwise accompanies this software in either electronic or hard copy form.
|
||||
*
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://developer.oculus.com/licenses/oculussdk/
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, the Oculus SDK
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
using Oculus.Interaction.Input;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
namespace Oculus.Interaction
|
||||
{
|
||||
/// <summary>
|
||||
/// HandRayPinchGlow controls the glow properties of the OculusHand material to get a glow effect
|
||||
/// when the user is using Pinch Ray
|
||||
/// </summary>
|
||||
public class HandRayPinchGlow : MonoBehaviour
|
||||
{
|
||||
[SerializeField, Interface(typeof(IHand))]
|
||||
private UnityEngine.Object _hand;
|
||||
|
||||
[SerializeField]
|
||||
private RayInteractor _rayInteractor;
|
||||
|
||||
[SerializeField]
|
||||
private MaterialPropertyBlockEditor _materialEditor;
|
||||
|
||||
[SerializeField]
|
||||
private Color _glowColor;
|
||||
|
||||
[SerializeField]
|
||||
private GlowType _glowType = GlowType.Outline;
|
||||
|
||||
public enum GlowType
|
||||
{
|
||||
Fill = 17,
|
||||
Outline = 18,
|
||||
Both = 16
|
||||
}
|
||||
|
||||
private IHand Hand;
|
||||
|
||||
private readonly int _generateGlowID = Shader.PropertyToID("_GenerateGlow");
|
||||
private readonly int _glowPositionID = Shader.PropertyToID("_GlowPosition");
|
||||
private readonly int _glowColorID = Shader.PropertyToID("_GlowColor");
|
||||
private readonly int _glowTypeID = Shader.PropertyToID("_GlowType");
|
||||
private readonly int _glowParameterID = Shader.PropertyToID("_GlowParameter");
|
||||
private readonly int _glowMaxLengthID = Shader.PropertyToID("_GlowMaxLength");
|
||||
|
||||
private bool _glowEnabled;
|
||||
protected bool _started = false;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
Hand = _hand as IHand;
|
||||
}
|
||||
|
||||
protected virtual void Start()
|
||||
{
|
||||
_glowEnabled = false;
|
||||
this.BeginStart(ref _started);
|
||||
this.AssertField(Hand, nameof(Hand));
|
||||
this.AssertField(_rayInteractor, nameof(_rayInteractor));
|
||||
this.EndStart(ref _started);
|
||||
}
|
||||
|
||||
protected virtual void OnEnable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
_rayInteractor.WhenPostprocessed += UpdateVisual;
|
||||
_rayInteractor.WhenStateChanged += UpdateVisualState;
|
||||
UpdateVisual();
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnDisable()
|
||||
{
|
||||
if (_started)
|
||||
{
|
||||
_rayInteractor.WhenPostprocessed -= UpdateVisual;
|
||||
_rayInteractor.WhenStateChanged -= UpdateVisualState;
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateVisualState(InteractorStateChangeArgs args) => UpdateVisual();
|
||||
|
||||
private void UpdateGlow(Vector3 glowPosition, float pinchStrength, float glowMaxLength)
|
||||
{
|
||||
if (_materialEditor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var block = _materialEditor.MaterialPropertyBlock;
|
||||
block.SetInt(_generateGlowID, 1);
|
||||
block.SetColor(_glowColorID, _glowColor);
|
||||
block.SetFloat(_glowParameterID, pinchStrength);
|
||||
block.SetFloat(_glowMaxLengthID, glowMaxLength);
|
||||
|
||||
block.SetInt(_glowTypeID, (int) _glowType);
|
||||
block.SetVector(_glowPositionID, glowPosition);
|
||||
}
|
||||
|
||||
private void UpdateVisual()
|
||||
{
|
||||
if (_rayInteractor.State == InteractorState.Disabled)
|
||||
{
|
||||
if (_glowEnabled)
|
||||
{
|
||||
if (_materialEditor == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var block = _materialEditor.MaterialPropertyBlock;
|
||||
block.SetInt(_generateGlowID, 0);
|
||||
_glowEnabled = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_glowEnabled = true;
|
||||
if (!Hand.GetJointPose(HandJointId.HandThumbTip, out Pose thumbPose))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Hand.GetJointPose(HandJointId.HandIndexTip, out Pose indexPose))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Hand.GetRootPose(out Pose wristPose))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var pinchStrength = Hand.GetFingerPinchStrength(HandFinger.Index);
|
||||
Vector3 glowPosition = (thumbPose.position + indexPose.position) / 2.0f;
|
||||
float glowPosToWrist = Vector3.Distance(wristPose.position, glowPosition) * 0.9f;
|
||||
UpdateGlow(glowPosition, pinchStrength, glowPosToWrist);
|
||||
}
|
||||
}
|
||||
|
||||
#region Inject
|
||||
|
||||
public void InjectAllHandRayPinchGlow(IHand hand, RayInteractor interactor,
|
||||
MaterialPropertyBlockEditor materialEditor, Color color, GlowType glowType)
|
||||
{
|
||||
InjectHand(hand);
|
||||
InjectRayInteractor(interactor);
|
||||
InjectMaterialPropertyBlockEditor(materialEditor);
|
||||
InjectGlowColor(color);
|
||||
InjectGlowType(glowType);
|
||||
}
|
||||
|
||||
public void InjectHand(IHand hand)
|
||||
{
|
||||
_hand = hand as UnityEngine.Object;
|
||||
Hand = hand;
|
||||
}
|
||||
|
||||
public void InjectRayInteractor(RayInteractor interactor)
|
||||
{
|
||||
_rayInteractor = interactor;
|
||||
}
|
||||
|
||||
public void InjectMaterialPropertyBlockEditor(MaterialPropertyBlockEditor materialEditor)
|
||||
{
|
||||
_materialEditor = materialEditor;
|
||||
}
|
||||
|
||||
public void InjectGlowColor(Color color)
|
||||
{
|
||||
_glowColor = color;
|
||||
}
|
||||
|
||||
public void InjectGlowType(GlowType glowType)
|
||||
{
|
||||
_glowType = glowType;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d3ea8c2b38a2e4abbaaa9caec105388a
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user