//======= Copyright (c) Valve Corporation, All rights reserved. ===============
using UnityEngine;
using System.Collections;
using System;
using Valve.VR;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
namespace Valve.VR
{
///
/// Action sets are logical groupings of actions. Multiple sets can be active at one time.
///
[Serializable]
public class SteamVR_ActionSet : IEquatable, ISteamVR_ActionSet, ISerializationCallbackReceiver
{
public SteamVR_ActionSet() { }
[SerializeField]
private string actionSetPath;
[NonSerialized]
protected SteamVR_ActionSet_Data setData;
/// All actions within this set (including out actions)
public SteamVR_Action[] allActions
{
get
{
if (initialized == false)
Initialize();
return setData.allActions;
}
}
/// All IN actions within this set that are NOT pose or skeleton actions
public ISteamVR_Action_In[] nonVisualInActions
{
get
{
if (initialized == false)
Initialize();
return setData.nonVisualInActions;
}
}
/// All pose and skeleton actions within this set
public ISteamVR_Action_In[] visualActions
{
get
{
if (initialized == false)
Initialize();
return setData.visualActions;
}
}
/// All pose actions within this set
public SteamVR_Action_Pose[] poseActions
{
get
{
if (initialized == false)
Initialize();
return setData.poseActions;
}
}
/// All skeleton actions within this set
public SteamVR_Action_Skeleton[] skeletonActions
{
get
{
if (initialized == false)
Initialize();
return setData.skeletonActions;
}
}
/// All out actions within this set
public ISteamVR_Action_Out[] outActionArray
{
get
{
if (initialized == false)
Initialize();
return setData.outActionArray;
}
}
/// The full path to this action set (ex: /actions/in/default)
public string fullPath
{
get
{
if (initialized == false)
Initialize();
return setData.fullPath;
}
}
public string usage
{
get
{
if (initialized == false)
Initialize();
return setData.usage;
}
}
public ulong handle
{
get
{
if (initialized == false)
Initialize();
return setData.handle;
}
}
[NonSerialized]
protected bool initialized = false;
public static CreateType Create(string newSetPath) where CreateType : SteamVR_ActionSet, new()
{
CreateType actionSet = new CreateType();
actionSet.PreInitialize(newSetPath);
return actionSet;
}
public static CreateType CreateFromName(string newSetName) where CreateType : SteamVR_ActionSet, new()
{
CreateType actionSet = new CreateType();
actionSet.PreInitialize(SteamVR_Input_ActionFile_ActionSet.GetPathFromName(newSetName));
return actionSet;
}
public void PreInitialize(string newActionPath)
{
actionSetPath = newActionPath;
setData = new SteamVR_ActionSet_Data();
setData.fullPath = actionSetPath;
setData.PreInitialize();
initialized = true;
}
public virtual void FinishPreInitialize()
{
setData.FinishPreInitialize();
}
///
/// Initializes the handle for the action
///
public virtual void Initialize(bool createNew = false, bool throwErrors = true)
{
if (createNew)
{
setData.Initialize();
}
else
{
setData = SteamVR_Input.GetActionSetDataFromPath(actionSetPath);
if (setData == null)
{
#if UNITY_EDITOR
if (throwErrors)
{
if (string.IsNullOrEmpty(actionSetPath))
{
Debug.LogError("[SteamVR] Action has not been assigned.");
}
else
{
Debug.LogError("[SteamVR] Could not find action with path: " + actionSetPath);
}
}
#endif
}
}
initialized = true;
}
public string GetPath()
{
return actionSetPath;
}
///
/// Returns whether the set is currently active or not.
///
/// The device to check. Any means all devices here (not left or right, but all)
public bool IsActive(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
{
return setData.IsActive(source);
}
///
/// Returns the last time this action set was changed (set to active or inactive)
///
/// The device to check. Any means all devices here (not left or right, but all)
public float GetTimeLastChanged(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
{
return setData.GetTimeLastChanged(source);
}
///
/// Activate this set so its actions can be called
///
/// Disable all other action sets at the same time
/// The priority of this action set. If you have two actions bound to the same input (button) the higher priority set will override the lower priority. If they are the same priority both will execute.
/// Will activate this action set only for the specified source. Any if you want to activate for everything
public void Activate(SteamVR_Input_Sources activateForSource = SteamVR_Input_Sources.Any, int priority = 0, bool disableAllOtherActionSets = false)
{
setData.Activate(activateForSource, priority, disableAllOtherActionSets);
}
///
/// Deactivate the action set so its actions can no longer be called
///
public void Deactivate(SteamVR_Input_Sources forSource = SteamVR_Input_Sources.Any)
{
setData.Deactivate(forSource);
}
/// Gets the last part of the path for this action. Removes "actions" and direction.
public string GetShortName()
{
return setData.GetShortName();
}
public bool ReadRawSetActive(SteamVR_Input_Sources inputSource)
{
return setData.ReadRawSetActive(inputSource);
}
public float ReadRawSetLastChanged(SteamVR_Input_Sources inputSource)
{
return setData.ReadRawSetLastChanged(inputSource);
}
public int ReadRawSetPriority(SteamVR_Input_Sources inputSource)
{
return setData.ReadRawSetPriority(inputSource);
}
public SteamVR_ActionSet_Data GetActionSetData()
{
return setData;
}
public CreateType GetCopy() where CreateType : SteamVR_ActionSet, new()
{
CreateType actionSet = new CreateType();
actionSet.actionSetPath = this.actionSetPath;
actionSet.setData = this.setData;
actionSet.initialized = true;
return actionSet;
//return (CreateType)this; //no need to make copies in builds - will reduce memory alloc //todo: having this enabled was not working. all sets were the same (maybe actions too)
}
public bool Equals(SteamVR_ActionSet other)
{
if (ReferenceEquals(null, other))
return false;
return this.actionSetPath == other.actionSetPath;
}
public override bool Equals(object other)
{
if (ReferenceEquals(null, other))
{
if (string.IsNullOrEmpty(this.actionSetPath)) //if we haven't set a path, say this action set is equal to null
return true;
return false;
}
if (ReferenceEquals(this, other))
return true;
if (other is SteamVR_ActionSet)
return this.Equals((SteamVR_ActionSet)other);
return false;
}
public override int GetHashCode()
{
if (actionSetPath == null)
return 0;
else
return actionSetPath.GetHashCode();
}
public static bool operator !=(SteamVR_ActionSet set1, SteamVR_ActionSet set2)
{
return !(set1 == set2);
}
public static bool operator ==(SteamVR_ActionSet set1, SteamVR_ActionSet set2)
{
bool set1null = (ReferenceEquals(null, set1) || string.IsNullOrEmpty(set1.actionSetPath) || set1.GetActionSetData() == null);
bool set2null = (ReferenceEquals(null, set2) || string.IsNullOrEmpty(set2.actionSetPath) || set2.GetActionSetData() == null);
if (set1null && set2null)
return true;
else if (set1null != set2null)
return false;
return set1.Equals(set2);
}
void ISerializationCallbackReceiver.OnBeforeSerialize()
{
}
void ISerializationCallbackReceiver.OnAfterDeserialize()
{
if (setData != null)
{
if (setData.fullPath != actionSetPath)
{
setData = SteamVR_Input.GetActionSetDataFromPath(actionSetPath);
}
}
if (initialized == false)
Initialize(false, false);
}
}
///
/// Action sets are logical groupings of actions. Multiple sets can be active at one time.
///
public class SteamVR_ActionSet_Data : ISteamVR_ActionSet
{
public SteamVR_ActionSet_Data() { }
/// All actions within this set (including out actions)
public SteamVR_Action[] allActions { get; set; }
/// All IN actions within this set that are NOT pose or skeleton actions
public ISteamVR_Action_In[] nonVisualInActions { get; set; }
/// All pose and skeleton actions within this set
public ISteamVR_Action_In[] visualActions { get; set; }
/// All pose actions within this set
public SteamVR_Action_Pose[] poseActions { get; set; }
/// All skeleton actions within this set
public SteamVR_Action_Skeleton[] skeletonActions { get; set; }
/// All out actions within this set
public ISteamVR_Action_Out[] outActionArray { get; set; }
/// The full path to this action set (ex: /actions/in/default)
public string fullPath { get; set; }
public string usage { get; set; }
public ulong handle { get; set; }
protected Dictionary rawSetActive = new Dictionary(new SteamVR_Input_Sources_Comparer());
protected Dictionary rawSetLastChanged = new Dictionary(new SteamVR_Input_Sources_Comparer());
protected Dictionary rawSetPriority = new Dictionary(new SteamVR_Input_Sources_Comparer());
protected bool initialized = false;
public void PreInitialize()
{
SteamVR_Input_Sources[] sources = SteamVR_Input_Source.GetAllSources();
for (int sourceIndex = 0; sourceIndex < sources.Length; sourceIndex++)
{
SteamVR_Input_Sources source = sources[sourceIndex];
rawSetActive.Add(source, false);
rawSetLastChanged.Add(source, 0);
rawSetPriority.Add(source, 0);
}
}
public void FinishPreInitialize()
{
List allActionsList = new List();
List nonVisualInActionsList = new List();
List visualActionsList = new List();
List poseActionsList = new List();
List skeletonActionsList = new List();
List outActionList = new List();
if (SteamVR_Input.actions == null)
{
Debug.LogError("[SteamVR Input] Actions not initialized!");
return;
}
for (int actionIndex = 0; actionIndex < SteamVR_Input.actions.Length; actionIndex++)
{
SteamVR_Action action = SteamVR_Input.actions[actionIndex];
if (action.actionSet.GetActionSetData() == this)
{
allActionsList.Add(action);
if (action is ISteamVR_Action_Boolean || action is ISteamVR_Action_Single || action is ISteamVR_Action_Vector2 || action is ISteamVR_Action_Vector3)
{
nonVisualInActionsList.Add((ISteamVR_Action_In)action);
}
else if (action is SteamVR_Action_Pose)
{
visualActionsList.Add((ISteamVR_Action_In)action);
poseActionsList.Add((SteamVR_Action_Pose)action);
}
else if (action is SteamVR_Action_Skeleton)
{
visualActionsList.Add((ISteamVR_Action_In)action);
skeletonActionsList.Add((SteamVR_Action_Skeleton)action);
}
else if (action is ISteamVR_Action_Out)
{
outActionList.Add((ISteamVR_Action_Out)action);
}
else
{
Debug.LogError("[SteamVR Input] Action doesn't implement known interface: " + action.fullPath);
}
}
}
allActions = allActionsList.ToArray();
nonVisualInActions = nonVisualInActionsList.ToArray();
visualActions = visualActionsList.ToArray();
poseActions = poseActionsList.ToArray();
skeletonActions = skeletonActionsList.ToArray();
outActionArray = outActionList.ToArray();
}
public void Initialize()
{
ulong newHandle = 0;
EVRInputError err = OpenVR.Input.GetActionSetHandle(fullPath.ToLower(), ref newHandle);
handle = newHandle;
if (err != EVRInputError.None)
Debug.LogError("[SteamVR] GetActionSetHandle (" + fullPath + ") error: " + err.ToString());
initialized = true;
}
///
/// Returns whether the set is currently active or not.
///
/// The device to check. Any means all devices here (not left or right, but all)
public bool IsActive(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
{
if (initialized)
return rawSetActive[source] || rawSetActive[SteamVR_Input_Sources.Any];
return false;
}
///
/// Returns the last time this action set was changed (set to active or inactive)
///
/// The device to check. Any means all devices here (not left or right, but all)
public float GetTimeLastChanged(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any)
{
if (initialized)
return rawSetLastChanged[source];
return 0;
}
///
/// Activate this set so its actions can be called
///
/// Disable all other action sets at the same time
/// The priority of this action set. If you have two actions bound to the same input (button) the higher priority set will override the lower priority. If they are the same priority both will execute.
/// Will activate this action set only for the specified source. Any if you want to activate for everything
public void Activate(SteamVR_Input_Sources activateForSource = SteamVR_Input_Sources.Any, int priority = 0, bool disableAllOtherActionSets = false)
{
if (disableAllOtherActionSets)
SteamVR_ActionSet_Manager.DisableAllActionSets();
if (rawSetActive[activateForSource] == false)
{
rawSetActive[activateForSource] = true;
SteamVR_ActionSet_Manager.SetChanged();
rawSetLastChanged[activateForSource] = Time.realtimeSinceStartup;
}
if (rawSetPriority[activateForSource] != priority)
{
rawSetPriority[activateForSource] = priority;
SteamVR_ActionSet_Manager.SetChanged();
rawSetLastChanged[activateForSource] = Time.realtimeSinceStartup;
}
}
///
/// Deactivate the action set so its actions can no longer be called
///
public void Deactivate(SteamVR_Input_Sources forSource = SteamVR_Input_Sources.Any)
{
if (rawSetActive[forSource] != false)
{
rawSetLastChanged[forSource] = Time.realtimeSinceStartup;
SteamVR_ActionSet_Manager.SetChanged();
}
rawSetActive[forSource] = false;
rawSetPriority[forSource] = 0;
}
private string cachedShortName;
/// Gets the last part of the path for this action. Removes "actions" and direction.
public string GetShortName()
{
if (cachedShortName == null)
{
cachedShortName = SteamVR_Input_ActionFile.GetShortName(fullPath);
}
return cachedShortName;
}
public bool ReadRawSetActive(SteamVR_Input_Sources inputSource)
{
return rawSetActive[inputSource];
}
public float ReadRawSetLastChanged(SteamVR_Input_Sources inputSource)
{
return rawSetLastChanged[inputSource];
}
public int ReadRawSetPriority(SteamVR_Input_Sources inputSource)
{
return rawSetPriority[inputSource];
}
}
///
/// Action sets are logical groupings of actions. Multiple sets can be active at one time.
///
public interface ISteamVR_ActionSet
{
/// All actions within this set (including out actions)
SteamVR_Action[] allActions { get; }
/// All IN actions within this set that are NOT pose or skeleton actions
ISteamVR_Action_In[] nonVisualInActions { get; }
/// All pose and skeleton actions within this set
ISteamVR_Action_In[] visualActions { get; }
/// All pose actions within this set
SteamVR_Action_Pose[] poseActions { get; }
/// All skeleton actions within this set
SteamVR_Action_Skeleton[] skeletonActions { get; }
/// All out actions within this set
ISteamVR_Action_Out[] outActionArray { get; }
/// The full path to this action set (ex: /actions/in/default)
string fullPath { get; }
/// How the binding UI should display this set
string usage { get; }
ulong handle { get; }
bool ReadRawSetActive(SteamVR_Input_Sources inputSource);
float ReadRawSetLastChanged(SteamVR_Input_Sources inputSource);
int ReadRawSetPriority(SteamVR_Input_Sources inputSource);
///
/// Returns whether the set is currently active or not.
///
/// The device to check. Any means all devices here (not left or right, but all)
bool IsActive(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any);
///
/// Returns the last time this action set was changed (set to active or inactive)
///
/// The device to check. Any means all devices here (not left or right, but all)
float GetTimeLastChanged(SteamVR_Input_Sources source = SteamVR_Input_Sources.Any);
///
/// Activate this set so its actions can be called
///
/// Disable all other action sets at the same time
/// The priority of this action set. If you have two actions bound to the same input (button) the higher priority set will override the lower priority. If they are the same priority both will execute.
/// Will activate this action set only for the specified source. Any if you want to activate for everything
void Activate(SteamVR_Input_Sources activateForSource = SteamVR_Input_Sources.Any, int priority = 0, bool disableAllOtherActionSets = false);
/// Deactivate the action set so its actions can no longer be called
void Deactivate(SteamVR_Input_Sources forSource = SteamVR_Input_Sources.Any);
/// Gets the last part of the path for this action. Removes "actions" and direction.
string GetShortName();
}
}