TaiZhouCangChu_VRanime/Assets/HTC.UnityPlugin/ViveInputUtility/Scripts/Misc/ExternalCameraHook.cs

415 lines
14 KiB
C#

//========= Copyright 2016-2023, HTC Corporation. All rights reserved. ===========
using HTC.UnityPlugin.Utility;
using HTC.UnityPlugin.VRModuleManagement;
using System;
using System.IO;
using UnityEngine;
#if VIU_STEAMVR_2_0_0_OR_NEWER && UNITY_STANDALONE
using Valve.VR;
#endif
namespace HTC.UnityPlugin.Vive
{
// This script creates and handles SteamVR_ExternalCamera using viveRole property
[AddComponentMenu("VIU/Hooks/External Camera Hook", 9)]
[DisallowMultipleComponent]
public class ExternalCameraHook : SingletonBehaviour<ExternalCameraHook>, INewPoseListener, IViveRoleComponent
{
[Obsolete("Use VIUSettings.EXTERNAL_CAMERA_CONFIG_FILE_PATH_DEFAULT_VALUE instead.")]
public const string AUTO_LOAD_CONFIG_PATH = "externalcamera.cfg";
[SerializeField]
private ViveRoleProperty m_viveRole = ViveRoleProperty.New(HandRole.ExternalCamera);
[SerializeField]
private Transform m_origin;
[SerializeField]
private string m_configPath = string.Empty;
private bool m_quadViewSwitch = false;
private bool m_configInterfaceSwitch = true;
private GameObject m_configUI = null;
public ViveRoleProperty viveRole { get { return m_viveRole; } }
public Transform origin { get { return m_origin; } set { m_origin = value; } }
public bool isTrackingDevice { get { return isActiveAndEnabled && VRModule.IsValidDeviceIndex(m_viveRole.GetDeviceIndex()); } }
public string configPath
{
get
{
return m_configPath;
}
set
{
m_configPath = value;
#if VIU_STEAMVR && UNITY_STANDALONE
if (m_externalCamera != null && !string.IsNullOrEmpty(m_configPath) && File.Exists(m_configPath))
{
m_externalCamera.configPath = m_configPath;
m_externalCamera.ReadConfig();
}
#endif
}
}
public bool quadViewEnabled
{
get { return m_quadViewSwitch; }
set
{
if (IsInstance && m_quadViewSwitch != value)
{
m_quadViewSwitch = value;
UpdateActivity();
}
}
}
public bool configInterfaceEnabled
{
get { return m_configInterfaceSwitch; }
set
{
if (IsInstance && m_configInterfaceSwitch != value)
{
m_configInterfaceSwitch = value;
UpdateActivity();
}
}
}
public bool isQuadViewActive
{
get
{
#if VIU_STEAMVR && UNITY_STANDALONE
return isActiveAndEnabled && m_externalCamera != null && m_externalCamera.isActiveAndEnabled;
#else
return false;
#endif
}
}
public bool isConfigInterfaceActive
{
get
{
return isActiveAndEnabled && m_configUI != null && m_configUI.activeSelf;
}
}
static ExternalCameraHook()
{
SetDefaultInitGameObjectGetter(DefaultInitGameObject);
}
private static GameObject DefaultInitGameObject()
{
var go = new GameObject("[ExternalCamera]");
go.transform.SetParent(VRModule.Instance.transform, false);
return go;
}
#if UNITY_EDITOR
private void Reset()
{
m_configPath = VIUSettings.EXTERNAL_CAMERA_CONFIG_FILE_PATH_DEFAULT_VALUE;
}
private void OnValidate()
{
if (Application.isPlaying && isActiveAndEnabled)
{
UpdateActivity();
}
}
#endif
#if VIU_STEAMVR && UNITY_STANDALONE
private SteamVR_ExternalCamera m_externalCamera;
private RigidPose m_staticExCamPose = RigidPose.identity;
public SteamVR_ExternalCamera externalCamera { get { return m_externalCamera; } }
[RuntimeInitializeOnLoadMethod]
private static void OnLoad()
{
if (VIUSettings.autoLoadExternalCameraConfigOnStart)
{
if (VRModule.Active && VRModule.activeModule != VRModuleActiveEnum.Uninitialized)
{
AutoLoadConfig();
}
else
{
VRModule.onActiveModuleChanged += OnActiveModuleChanged;
}
}
}
private static void OnActiveModuleChanged(VRModuleActiveEnum activatedModule)
{
if (activatedModule != VRModuleActiveEnum.Uninitialized)
{
VRModule.onActiveModuleChanged -= OnActiveModuleChanged;
AutoLoadConfig();
}
}
private static void AutoLoadConfig()
{
Initialize();
if (string.IsNullOrEmpty(Instance.m_configPath))
{
Instance.m_configPath = VIUSettings.externalCameraConfigFilePath;
}
LoadConfigFromFile(Instance.m_configPath);
}
/// <summary>
/// Load config form file if the file exist.
/// Will create an ExternalCameraHook instance into scene if config is availabile and there was no instance.
/// </summary>
/// <param name="">The config file path.</param>
/// <returns>true if config file loaded and external camera instance is created successfully.</returns>
public static bool LoadConfigFromFile(string path)
{
if (!SteamVR.active || string.IsNullOrEmpty(path) || !File.Exists(path))
{
return false;
}
Instance.configPath = path;
Instance.UpdateActivity();
return true;
}
private static bool m_defaultExCamResolved;
private static void ResolveDefaultExCam()
{
if (m_defaultExCamResolved || VRModule.activeModule != VRModuleActiveEnum.SteamVR || !SteamVR.active)
{
if (Active && (VRModule.activeModule != VRModuleActiveEnum.SteamVR || !SteamVR.active)) { Instance.m_quadViewSwitch = false; }
return;
}
m_defaultExCamResolved = true;
SteamVR_Render.instance.externalCameraConfigPath = string.Empty;
var oldExternalCam = SteamVR_Render.instance.externalCamera;
if (oldExternalCam != null)
{
SteamVR_Render.instance.externalCamera = null;
// To prevent SteamVR_ExternalCamera from setting invalid(0f) sceneResolutionScale value in OnDisable()
oldExternalCam.config.sceneResolutionScale = 0f;
#if !VIU_STEAMVR_2_0_0_OR_NEWER
if (oldExternalCam.transform.parent != null && oldExternalCam.transform.parent.GetComponent<SteamVR_ControllerManager>() != null)
#else
if (oldExternalCam.transform.parent != null && oldExternalCam.transform.parent.GetComponentInChildren<SteamVR_TrackedObject>() != null)
#endif
{
Destroy(oldExternalCam.transform.parent.gameObject);
}
else
{
Destroy(oldExternalCam.gameObject);
}
}
}
private void OnEnable()
{
if (IsInstance)
{
m_viveRole.onDeviceIndexChanged += OnDeviceIndexChanged;
OnDeviceIndexChanged(m_viveRole.GetDeviceIndex());
}
}
private void OnDisable()
{
if (IsInstance)
{
m_viveRole.onDeviceIndexChanged -= OnDeviceIndexChanged;
OnDeviceIndexChanged(VRModule.INVALID_DEVICE_INDEX);
}
}
private void OnDeviceIndexChanged(uint deviceIndex)
{
if (IsInstance)
{
m_quadViewSwitch = isTrackingDevice;
UpdateActivity();
}
}
public virtual void BeforeNewPoses() { }
public virtual void OnNewPoses()
{
var deviceIndex = m_viveRole.GetDeviceIndex();
if (VRModule.IsValidDeviceIndex(deviceIndex))
{
m_staticExCamPose = VivePose.GetPose(deviceIndex);
}
if (isQuadViewActive)
{
RigidPose.SetPose(transform, m_staticExCamPose, m_origin);
}
}
public virtual void AfterNewPoses() { }
private void Update()
{
if (VIUSettings.enableExternalCameraSwitch && Input.GetKeyDown(VIUSettings.externalCameraSwitchKey) && (VIUSettings.externalCameraSwitchKeyModifier != KeyCode.None && Input.GetKey(VIUSettings.externalCameraSwitchKeyModifier)))
{
if (!isQuadViewActive)
{
m_quadViewSwitch = true;
m_configInterfaceSwitch = true;
}
else
{
if (m_configInterfaceSwitch)
{
m_configInterfaceSwitch = false;
}
else
{
m_quadViewSwitch = false;
m_configInterfaceSwitch = false;
}
}
UpdateActivity();
}
}
private void UpdateActivity()
{
ResolveDefaultExCam();
if (!isActiveAndEnabled)
{
InternalSetQuadViewActive(false);
InternalSetConfigInterfaceActive(false);
}
else
{
InternalSetQuadViewActive(m_quadViewSwitch);
InternalSetConfigInterfaceActive(isQuadViewActive && m_configInterfaceSwitch);
}
}
private void InternalSetQuadViewActive(bool value)
{
if (value && m_externalCamera == null && !string.IsNullOrEmpty(m_configPath) && File.Exists(m_configPath))
{
// don't know why SteamVR_ExternalCamera must be instantiated from the prefab
// when create SteamVR_ExternalCamera using AddComponent, errors came out when disabling
var prefab = Resources.Load<GameObject>("SteamVR_ExternalCamera");
if (prefab == null)
{
Debug.LogError("SteamVR_ExternalCamera prefab not found!");
}
else
{
var ctrlMgr = Instantiate(prefab);
var extCam = ctrlMgr.transform.GetChild(0);
extCam.gameObject.name = "SteamVR External Camera";
extCam.SetParent(transform, false);
DestroyImmediate(extCam.GetComponent<SteamVR_TrackedObject>());
DestroyImmediate(ctrlMgr);
m_externalCamera = extCam.GetComponent<SteamVR_ExternalCamera>();
SteamVR_Render.instance.externalCamera = m_externalCamera;
// resolve config file
m_externalCamera.enabled = false;
m_externalCamera.configPath = m_configPath;
m_externalCamera.ReadConfig();
m_externalCamera.enabled = true; // to preserve sceneResolutionScale on enabled
// resolve RenderTexture
m_externalCamera.AttachToCamera(SteamVR_Render.Top());
var w = Screen.width / 2;
var h = Screen.height / 2;
var cam = m_externalCamera.GetComponentInChildren<Camera>();
if (cam.targetTexture == null || cam.targetTexture.width != w || cam.targetTexture.height != h)
{
var tex = new RenderTexture(w, h, 24, RenderTextureFormat.ARGB32, QualitySettings.activeColorSpace == ColorSpace.Linear ? RenderTextureReadWrite.Linear : RenderTextureReadWrite.Default);
tex.antiAliasing = QualitySettings.antiAliasing == 0 ? 1 : QualitySettings.antiAliasing;
cam.targetTexture = tex;
}
}
}
if (m_externalCamera != null)
{
m_externalCamera.gameObject.SetActive(value);
if (value)
{
VivePose.AddNewPosesListener(this);
}
else
{
VivePose.RemoveNewPosesListener(this);
}
}
}
private void InternalSetConfigInterfaceActive(bool value)
{
if (value && m_configUI == null)
{
var prefab = Resources.Load<GameObject>("VIUExCamConfigInterface");
if (prefab == null)
{
Debug.LogError("VIUExCamConfigInterface prefab not found!");
}
else
{
m_configUI = Instantiate(prefab);
}
}
if (m_configUI != null)
{
m_configUI.SetActive(value);
}
}
public void Recenter()
{
m_staticExCamPose = RigidPose.identity;
}
#else
protected virtual void Start()
{
Debug.LogWarning("SteamVR plugin not found! install it to enable ExternalCamera!");
}
private void UpdateActivity() { }
public virtual void BeforeNewPoses() { }
public virtual void OnNewPoses() { }
public virtual void AfterNewPoses() { }
public void Recenter() { }
#endif
}
}