// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System;
using System.Collections.Generic;
using UnityEngine;
namespace Microsoft.MixedReality.Toolkit.UI
{
///
/// ThemeEngine to control initialized GameObject's scale based on associated Interactable grab state and related state changes
///
public class InteractableGrabScaleTheme : InteractableThemeBase
{
protected Vector3 originalLocalScale = Vector3.zero;
protected float timer = 0;
protected bool hasGrab;
protected float grabPercentage;
protected bool grabTransition;
protected Interactable targetInteractable;
public InteractableGrabScaleTheme()
{
Types = new Type[] { typeof(Transform) };
Name = "Grab Scale Theme";
}
///
public override ThemeDefinition GetDefaultThemeDefinition()
{
return new ThemeDefinition()
{
ThemeType = GetType(),
StateProperties = new List()
{
new ThemeStateProperty()
{
Name = "Scale",
Type = ThemePropertyTypes.Vector3,
Values = new List(),
Default = new ThemePropertyValue(){ Vector3 = Vector3.one}
},
},
CustomProperties = new List()
{
new ThemeProperty()
{
Name = "ScaleMagnifier",
Type = ThemePropertyTypes.Vector3,
Value = new ThemePropertyValue() { Vector3 = Vector3.one }
},
new ThemeProperty()
{
Name = "GrabTimer",
Type = ThemePropertyTypes.Float,
Value = new ThemePropertyValue() { Float = 0.3f }
},
},
};
}
///
public override void Init(GameObject host, ThemeDefinition settings)
{
if (host != null)
{
originalLocalScale = host.transform.localScale;
#pragma warning disable 0618
// Keep initializing property to support consumers who have not migrated.
startScaleValue = new ThemePropertyValue();
startScaleValue.Vector3 = host.transform.localScale;
#pragma warning restore 0618
}
timer = Ease.LerpTime;
base.Init(host, settings);
}
///
public override ThemePropertyValue GetProperty(ThemeStateProperty property)
{
if (Host == null)
{
return new ThemePropertyValue()
{
Vector3 = originalLocalScale
};
}
ThemePropertyValue prop = new ThemePropertyValue();
prop.Vector3 = Host.transform.localScale;
return prop;
}
///
public override void OnUpdate(int state, bool force = false)
{
base.OnUpdate(state, force);
if (Host == null)
{
return;
}
Vector3 maxGrabScale = Properties[0].Value.Vector3;
float grabTime = Properties[1].Value.Float;
Vector3 grabScale = Vector3.Scale(originalLocalScale, maxGrabScale);
var targetInteractable = Host.FindAncestorComponent(true);
if (targetInteractable.HasGrab)
{
if (!hasGrab)
{
timer = 0;
}
timer += Time.deltaTime;
grabPercentage = Mathf.Clamp01(timer / grabTime);
Host.transform.localScale = Vector3.Lerp(originalLocalScale, grabScale, grabPercentage);
hasGrab = true;
grabTransition = true;
}
else
{
if (grabTransition)
{
// ending
grabTransition = false;
if (!Ease.Enabled)
{
Host.transform.localScale = originalLocalScale;
grabPercentage = 0;
}
else
{
timer = Ease.LerpTime - Ease.LerpTime * grabPercentage;
}
}
else if (Ease.Enabled && timer < Ease.LerpTime && grabPercentage > 0)
{
timer += Time.deltaTime;
float percent = 1 - Mathf.Clamp01(timer / Ease.LerpTime);
Host.transform.localScale = Vector3.Lerp(originalLocalScale, grabScale, Ease.Curve.Evaluate(percent));
}
// is there a transition from physical press?
hasGrab = timer < Ease.LerpTime;
}
}
///
public override void SetValue(ThemeStateProperty property, int index, float percentage)
{
if (!hasGrab && Host != null)
{
Host.transform.localScale = Vector3.Lerp(property.StartValue.Vector3, Vector3.Scale(originalLocalScale, property.Values[index].Vector3), percentage);
}
else
{
// there is near interaction grab so make sure Ease is not running
Ease.Stop();
}
}
///
protected override void SetValue(ThemeStateProperty property, ThemePropertyValue value)
{
if (Host != null)
{
Host.transform.localScale = value.Vector3;
}
}
#region Obsolete
[System.Obsolete("startScaleValue is no longer supported. Use originalLocalScale instead.")]
protected ThemePropertyValue startScaleValue = new ThemePropertyValue();
#endregion
}
}