ViveSoftware / ViveInputUtility-Unity

A toolkit that helps developing/prototyping VR apps.
http://u3d.as/uF7
Other
353 stars 82 forks source link

Unexpected results coming from IVRModuleDeviceState #25

Closed wirelessdreamer closed 6 years ago

wirelessdreamer commented 6 years ago

Creating a function to disable ViveRoleSetter game objects that are not active on successful bind using OnIsValidChanged. all ViveRoleSetter game objects are children of the transform. I initially expected to be able to check if deviceState.isConnectined, and if not, disable the game object, but all game objects showed they were connected, I then was going to work around it by checking if transform.position, x, y, and z were zero, inspecting the gameobjects showed them as zero, but the debug output of their values showed incorrect values, not the 0 values they had. Its not behaving at all like I would expect. Am I using it wrong?

    [ContextMenu("toggle children")]
    public void ToggleChildren() {
        foreach (Transform item in transform) {
            ViveRoleSetter VRS = item.GetComponent<ViveRoleSetter>();
            if (VRS) {
                ViveRoleProperty VRProps = ViveRoleProperty.New(VRS.viveRole);
                IVRModuleDeviceState deviceState = VRModule.GetCurrentDeviceState(VRProps.GetDeviceIndex());
                Debug.Log(VRS.viveRole + " " + VRS.transform.position.x + " " + VRS.transform.position.y + " " + VRS.transform.position.z + " " + deviceState.isConnected);
                if (VRS.transform.position.x == 0f && VRS.transform.position.y == 0f && VRS.transform.position.z == 0f)
                {
                    VRS.gameObject.SetActive(false);
                    Debug.Log("Disable: " + VRS.viveRole);            
                }
            }
        }
    }
wirelessdreamer commented 6 years ago

When accessing devices like this all of them are returning the same orientation data. image

wirelessdreamer commented 6 years ago

Related to all this, OnIsValidChanged is being called on objects with a role, that doesn't have any tracked objects bound to it.

lawwong commented 6 years ago

Sorry, more un-documented usage here...

  1. If you need to copy role from another ViveRoleProperty, you should use void ViveRoleProperty.Set(ViveRoleProperty prop), or static ViveRoleProperty ViveRoleProperty.New(Type type, int value)

    public class TestCopyRole : MonoBehaviour
    {
    ViveRoleProperty m_role = ViveRoleProperty.New(HandRole.RightHand);
    
    [ContextMenu("Copy Role")]
    public void CopyRoleFromFirstChild()
    {
        var childRole = transform.GetChild(0).GetComponent<ViveRoleSetter>().viveRole;
        // use Set(ViveRoleProperty prop) to copy
        m_role.Set(childRole);
    
        // use New(Type type, int value) to create and copy
        var newRole = ViveRoleProperty.New(childRole.roleType, childRole.roleValue);
    }
    }

    The way you were calling

    ViveRoleSetter VRS = item.GetComponent<ViveRoleSetter>();
    // ...
    ViveRoleProperty VRProps = ViveRoleProperty.New(VRS.viveRole);

    is actually calling the overloaded static method New\(TRole role), where it only works if TRole is an enum type defined with ViveRoleEnumAttribute. (VRProps is set to default role HandRole.RightHand because it got invalid argument) Since it doesn't popup any compile/run-time errors and is confusing, in future will add some run-time warning message and at least "struct" constrain on TRole. (Any one knows how to constrain generic type by enum?)

  2. And here is another way to achieve your OnIsValidChanged event

    
    using HTC.UnityPlugin.Vive;
    using HTC.UnityPlugin.VRModuleManagement;
    using UnityEngine;

public class TestValidRoleActivator : MonoBehaviour { private ViveRoleProperty viveRole;

private void Awake()
{
    // ViveRoleProperty is class, just get its reference no need to create new one
    viveRole = GetComponent<ViveRoleSetter>().viveRole;
    // onDeviceIndexChanged called whenever role mapping is changed
    viveRole.onDeviceIndexChanged += SetActiveOnValid;
    SetActiveOnValid(viveRole.GetDeviceIndex());
}

private void OnDestroy()
{
    viveRole.onDeviceIndexChanged -= SetActiveOnValid;
}

private void SetActiveOnValid(uint deviceIndex)
{
    // notice that role will never mapping to a valid deviceIndex
    // which is a disconnected device
    gameObject.SetActive(VRModule.IsValidDeviceIndex(deviceIndex));
}

}

wirelessdreamer commented 6 years ago

That was the cause of my issue. Thanks again.