123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875 |
- //======= Copyright (c) Valve Corporation, All rights reserved. ===============
- //
- // Purpose: Render model of associated tracked object
- //
- //=============================================================================
- using UnityEngine;
- using System.Collections;
- using System.Collections.Generic;
- using System.Runtime.InteropServices;
- using Valve.VR;
- namespace Valve.VR
- {
- [ExecuteInEditMode]
- public class SteamVR_RenderModel : MonoBehaviour
- {
- public SteamVR_TrackedObject.EIndex index = SteamVR_TrackedObject.EIndex.None;
- protected SteamVR_Input_Sources inputSource;
- public const string modelOverrideWarning = "Model override is really only meant to be used in " +
- "the scene view for lining things up; using it at runtime is discouraged. Use tracked device " +
- "index instead to ensure the correct model is displayed for all users.";
- [Tooltip(modelOverrideWarning)]
- public string modelOverride;
- [Tooltip("Shader to apply to model.")]
- public Shader shader;
- [Tooltip("Enable to print out when render models are loaded.")]
- public bool verbose = false;
- [Tooltip("If available, break down into separate components instead of loading as a single mesh.")]
- public bool createComponents = true;
- [Tooltip("Update transforms of components at runtime to reflect user action.")]
- public bool updateDynamically = true;
- // Additional controller settings for showing scrollwheel, etc.
- public RenderModel_ControllerMode_State_t controllerModeState;
- // Name of the sub-object which represents the "local" coordinate space for each component.
- public const string k_localTransformName = "attach";
- // Cached name of this render model for updating component transforms at runtime.
- public string renderModelName { get; private set; }
- public bool initializedAttachPoints { get; set; }
- private Dictionary<string, Transform> componentAttachPoints = new Dictionary<string, Transform>();
- private List<MeshRenderer> meshRenderers = new List<MeshRenderer>();
- // If someone knows how to keep these from getting cleaned up every time
- // you exit play mode, let me know. I've tried marking the RenderModel
- // class below as [System.Serializable] and switching to normal public
- // variables for mesh and material to get them to serialize properly,
- // as well as tried marking the mesh and material objects as
- // DontUnloadUnusedAsset, but Unity was still unloading them.
- // The hashtable is preserving its entries, but the mesh and material
- // variables are going null.
- public class RenderModel
- {
- public RenderModel(Mesh mesh, Material material)
- {
- this.mesh = mesh;
- this.material = material;
- }
- public Mesh mesh { get; private set; }
- public Material material { get; private set; }
- }
- public static Hashtable models = new Hashtable();
- public static Hashtable materials = new Hashtable();
- // Helper class to load render models interface on demand and clean up when done.
- public sealed class RenderModelInterfaceHolder : System.IDisposable
- {
- private bool needsShutdown, failedLoadInterface;
- private CVRRenderModels _instance;
- public CVRRenderModels instance
- {
- get
- {
- if (_instance == null && !failedLoadInterface)
- {
- if (Application.isEditor && Application.isPlaying == false)
- needsShutdown = SteamVR.InitializeTemporarySession();
- _instance = OpenVR.RenderModels;
- if (_instance == null)
- {
- Debug.LogError("<b>[SteamVR]</b> Failed to load IVRRenderModels interface version " + OpenVR.IVRRenderModels_Version);
- failedLoadInterface = true;
- }
- }
- return _instance;
- }
- }
- public void Dispose()
- {
- if (needsShutdown)
- SteamVR.ExitTemporarySession();
- }
- }
- private void OnModelSkinSettingsHaveChanged(VREvent_t vrEvent)
- {
- if (!string.IsNullOrEmpty(renderModelName))
- {
- renderModelName = "";
- UpdateModel();
- }
- }
- public void SetMeshRendererState(bool state)
- {
- for (int rendererIndex = 0; rendererIndex < meshRenderers.Count; rendererIndex++)
- {
- MeshRenderer renderer = meshRenderers[rendererIndex];
- if (renderer != null)
- renderer.enabled = state;
- }
- }
- private void OnHideRenderModels(bool hidden)
- {
- SetMeshRendererState(!hidden);
- }
- private void OnDeviceConnected(int i, bool connected)
- {
- if (i != (int)index)
- return;
- if (connected)
- {
- UpdateModel();
- }
- }
- public void UpdateModel()
- {
- var system = OpenVR.System;
- if (system == null || index == SteamVR_TrackedObject.EIndex.None)
- return;
- var error = ETrackedPropertyError.TrackedProp_Success;
- var capacity = system.GetStringTrackedDeviceProperty((uint)index, ETrackedDeviceProperty.Prop_RenderModelName_String, null, 0, ref error);
- if (capacity <= 1)
- {
- Debug.LogError("<b>[SteamVR]</b> Failed to get render model name for tracked object " + index);
- return;
- }
- var buffer = new System.Text.StringBuilder((int)capacity);
- system.GetStringTrackedDeviceProperty((uint)index, ETrackedDeviceProperty.Prop_RenderModelName_String, buffer, capacity, ref error);
- var s = buffer.ToString();
- if (renderModelName != s)
- {
- StartCoroutine(SetModelAsync(s));
- }
- }
- IEnumerator SetModelAsync(string newRenderModelName)
- {
- meshRenderers.Clear();
- if (string.IsNullOrEmpty(newRenderModelName))
- yield break;
- // Preload all render models before asking for the data to create meshes.
- using (RenderModelInterfaceHolder holder = new RenderModelInterfaceHolder())
- {
- CVRRenderModels renderModels = holder.instance;
- if (renderModels == null)
- yield break;
- // Gather names of render models to preload.
- string[] renderModelNames;
- uint count = renderModels.GetComponentCount(newRenderModelName);
- if (count > 0)
- {
- renderModelNames = new string[count];
- for (int componentIndex = 0; componentIndex < count; componentIndex++)
- {
- uint capacity = renderModels.GetComponentName(newRenderModelName, (uint)componentIndex, null, 0);
- if (capacity == 0)
- continue;
- var componentNameStringBuilder = new System.Text.StringBuilder((int)capacity);
- if (renderModels.GetComponentName(newRenderModelName, (uint)componentIndex, componentNameStringBuilder, capacity) == 0)
- continue;
- string componentName = componentNameStringBuilder.ToString();
- capacity = renderModels.GetComponentRenderModelName(newRenderModelName, componentName, null, 0);
- if (capacity == 0)
- continue;
- var nameStringBuilder = new System.Text.StringBuilder((int)capacity);
- if (renderModels.GetComponentRenderModelName(newRenderModelName, componentName, nameStringBuilder, capacity) == 0)
- continue;
- var s = nameStringBuilder.ToString();
- // Only need to preload if not already cached.
- RenderModel model = models[s] as RenderModel;
- if (model == null || model.mesh == null)
- {
- renderModelNames[componentIndex] = s;
- }
- }
- }
- else
- {
- // Only need to preload if not already cached.
- RenderModel model = models[newRenderModelName] as RenderModel;
- if (model == null || model.mesh == null)
- {
- renderModelNames = new string[] { newRenderModelName };
- }
- else
- {
- renderModelNames = new string[0];
- }
- }
- // Keep trying every 100ms until all components finish loading.
- while (true)
- {
- var loading = false;
- for (int renderModelNameIndex = 0; renderModelNameIndex < renderModelNames.Length; renderModelNameIndex++)
- {
- if (string.IsNullOrEmpty(renderModelNames[renderModelNameIndex]))
- continue;
- var pRenderModel = System.IntPtr.Zero;
- var error = renderModels.LoadRenderModel_Async(renderModelNames[renderModelNameIndex], ref pRenderModel);
- //Debug.Log("<b>[SteamVR]</b> renderModels.LoadRenderModel_Async(" + renderModelNames[renderModelNameIndex] + ": " + error.ToString());
- if (error == EVRRenderModelError.Loading)
- {
- loading = true;
- }
- else if (error == EVRRenderModelError.None)
- {
- // Preload textures as well.
- var renderModel = MarshalRenderModel(pRenderModel);
- // Check the cache first.
- var material = materials[renderModel.diffuseTextureId] as Material;
- if (material == null || material.mainTexture == null)
- {
- var pDiffuseTexture = System.IntPtr.Zero;
- error = renderModels.LoadTexture_Async(renderModel.diffuseTextureId, ref pDiffuseTexture);
- //Debug.Log("<b>[SteamVR]</b> renderModels.LoadRenderModel_Async(" + renderModelNames[renderModelNameIndex] + ": " + error.ToString());
- if (error == EVRRenderModelError.Loading)
- {
- loading = true;
- }
- }
- }
- }
- if (loading)
- {
- yield return new WaitForSecondsRealtime(0.1f);
- }
- else
- {
- break;
- }
- }
- }
- bool success = SetModel(newRenderModelName);
- this.renderModelName = newRenderModelName;
- SteamVR_Events.RenderModelLoaded.Send(this, success);
- }
- private bool SetModel(string renderModelName)
- {
- StripMesh(gameObject);
- using (var holder = new RenderModelInterfaceHolder())
- {
- if (createComponents)
- {
- componentAttachPoints.Clear();
- if (LoadComponents(holder, renderModelName))
- {
- UpdateComponents(holder.instance);
- return true;
- }
- Debug.Log("<b>[SteamVR]</b> [" + gameObject.name + "] Render model does not support components, falling back to single mesh.");
- }
- if (!string.IsNullOrEmpty(renderModelName))
- {
- var model = models[renderModelName] as RenderModel;
- if (model == null || model.mesh == null)
- {
- var renderModels = holder.instance;
- if (renderModels == null)
- return false;
- if (verbose)
- Debug.Log("<b>[SteamVR]</b> Loading render model " + renderModelName);
- model = LoadRenderModel(renderModels, renderModelName, renderModelName);
- if (model == null)
- return false;
- models[renderModelName] = model;
- }
- gameObject.AddComponent<MeshFilter>().mesh = model.mesh;
- MeshRenderer newRenderer = gameObject.AddComponent<MeshRenderer>();
- newRenderer.sharedMaterial = model.material;
- meshRenderers.Add(newRenderer);
- return true;
- }
- }
- return false;
- }
- RenderModel LoadRenderModel(CVRRenderModels renderModels, string renderModelName, string baseName)
- {
- var pRenderModel = System.IntPtr.Zero;
- EVRRenderModelError error;
- while (true)
- {
- error = renderModels.LoadRenderModel_Async(renderModelName, ref pRenderModel);
- if (error != EVRRenderModelError.Loading)
- break;
- Sleep();
- }
- if (error != EVRRenderModelError.None)
- {
- Debug.LogError(string.Format("<b>[SteamVR]</b> Failed to load render model {0} - {1}", renderModelName, error.ToString()));
- return null;
- }
- var renderModel = MarshalRenderModel(pRenderModel);
- var vertices = new Vector3[renderModel.unVertexCount];
- var normals = new Vector3[renderModel.unVertexCount];
- var uv = new Vector2[renderModel.unVertexCount];
- var type = typeof(RenderModel_Vertex_t);
- for (int iVert = 0; iVert < renderModel.unVertexCount; iVert++)
- {
- var ptr = new System.IntPtr(renderModel.rVertexData.ToInt64() + iVert * Marshal.SizeOf(type));
- var vert = (RenderModel_Vertex_t)Marshal.PtrToStructure(ptr, type);
- vertices[iVert] = new Vector3(vert.vPosition.v0, vert.vPosition.v1, -vert.vPosition.v2);
- normals[iVert] = new Vector3(vert.vNormal.v0, vert.vNormal.v1, -vert.vNormal.v2);
- uv[iVert] = new Vector2(vert.rfTextureCoord0, vert.rfTextureCoord1);
- }
- int indexCount = (int)renderModel.unTriangleCount * 3;
- var indices = new short[indexCount];
- Marshal.Copy(renderModel.rIndexData, indices, 0, indices.Length);
- var triangles = new int[indexCount];
- for (int iTri = 0; iTri < renderModel.unTriangleCount; iTri++)
- {
- triangles[iTri * 3 + 0] = (int)indices[iTri * 3 + 2];
- triangles[iTri * 3 + 1] = (int)indices[iTri * 3 + 1];
- triangles[iTri * 3 + 2] = (int)indices[iTri * 3 + 0];
- }
- var mesh = new Mesh();
- mesh.vertices = vertices;
- mesh.normals = normals;
- mesh.uv = uv;
- mesh.triangles = triangles;
- #if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0)
- mesh.Optimize();
- #endif
- //mesh.hideFlags = HideFlags.DontUnloadUnusedAsset;
- // Check cache before loading texture.
- var material = materials[renderModel.diffuseTextureId] as Material;
- if (material == null || material.mainTexture == null)
- {
- var pDiffuseTexture = System.IntPtr.Zero;
- while (true)
- {
- error = renderModels.LoadTexture_Async(renderModel.diffuseTextureId, ref pDiffuseTexture);
- if (error != EVRRenderModelError.Loading)
- break;
- Sleep();
- }
- if (error == EVRRenderModelError.None)
- {
- var diffuseTexture = MarshalRenderModel_TextureMap(pDiffuseTexture);
- var texture = new Texture2D(diffuseTexture.unWidth, diffuseTexture.unHeight, TextureFormat.RGBA32, false);
- if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D11)
- {
- texture.Apply();
- System.IntPtr texturePointer = texture.GetNativeTexturePtr();
- while (true)
- {
- error = renderModels.LoadIntoTextureD3D11_Async(renderModel.diffuseTextureId, texturePointer);
- if (error != EVRRenderModelError.Loading)
- break;
- Sleep();
- }
- }
- else
- {
- var textureMapData = new byte[diffuseTexture.unWidth * diffuseTexture.unHeight * 4]; // RGBA
- Marshal.Copy(diffuseTexture.rubTextureMapData, textureMapData, 0, textureMapData.Length);
- var colors = new Color32[diffuseTexture.unWidth * diffuseTexture.unHeight];
- int iColor = 0;
- for (int iHeight = 0; iHeight < diffuseTexture.unHeight; iHeight++)
- {
- for (int iWidth = 0; iWidth < diffuseTexture.unWidth; iWidth++)
- {
- var r = textureMapData[iColor++];
- var g = textureMapData[iColor++];
- var b = textureMapData[iColor++];
- var a = textureMapData[iColor++];
- colors[iHeight * diffuseTexture.unWidth + iWidth] = new Color32(r, g, b, a);
- }
- }
- texture.SetPixels32(colors);
- texture.Apply();
- }
- #if UNITY_URP
- material = new Material(shader != null ? shader : Shader.Find("Universal Render Pipeline/Lit"));
- #else
- material = new Material(shader != null ? shader : Shader.Find("Standard"));
- #endif
- material.mainTexture = texture;
- //material.hideFlags = HideFlags.DontUnloadUnusedAsset;
- materials[renderModel.diffuseTextureId] = material;
- renderModels.FreeTexture(pDiffuseTexture);
- }
- else
- {
- Debug.Log("<b>[SteamVR]</b> Failed to load render model texture for render model " + renderModelName + ". Error: " + error.ToString());
- }
- }
- // Delay freeing when we can since we'll often get multiple requests for the same model right
- // after another (e.g. two controllers or two basestations).
- #if UNITY_EDITOR
- if (!Application.isPlaying)
- renderModels.FreeRenderModel(pRenderModel);
- else
- #endif
- StartCoroutine(FreeRenderModel(pRenderModel));
- return new RenderModel(mesh, material);
- }
- IEnumerator FreeRenderModel(System.IntPtr pRenderModel)
- {
- yield return new WaitForSeconds(1.0f);
- using (var holder = new RenderModelInterfaceHolder())
- {
- var renderModels = holder.instance;
- renderModels.FreeRenderModel(pRenderModel);
- }
- }
- public Transform FindTransformByName(string componentName, Transform inTransform = null)
- {
- if (inTransform == null)
- inTransform = this.transform;
- for (int childIndex = 0; childIndex < inTransform.childCount; childIndex++)
- {
- Transform child = inTransform.GetChild(childIndex);
- if (child.name == componentName)
- return child;
- }
- return null;
- }
- public Transform GetComponentTransform(string componentName)
- {
- if (componentName == null)
- return this.transform;
- if (componentAttachPoints.ContainsKey(componentName))
- return componentAttachPoints[componentName];
- return null;
- }
- private void StripMesh(GameObject go)
- {
- var meshRenderer = go.GetComponent<MeshRenderer>();
- if (meshRenderer != null)
- DestroyImmediate(meshRenderer);
- var meshFilter = go.GetComponent<MeshFilter>();
- if (meshFilter != null)
- DestroyImmediate(meshFilter);
- }
- private bool LoadComponents(RenderModelInterfaceHolder holder, string renderModelName)
- {
- // Disable existing components (we will re-enable them if referenced by this new model).
- // Also strip mesh filter and renderer since these will get re-added if the new component needs them.
- var t = transform;
- for (int childIndex = 0; childIndex < t.childCount; childIndex++)
- {
- var child = t.GetChild(childIndex);
- child.gameObject.SetActive(false);
- StripMesh(child.gameObject);
- }
- // If no model specified, we're done; return success.
- if (string.IsNullOrEmpty(renderModelName))
- return true;
- var renderModels = holder.instance;
- if (renderModels == null)
- return false;
- var count = renderModels.GetComponentCount(renderModelName);
- if (count == 0)
- return false;
- for (int i = 0; i < count; i++)
- {
- var capacity = renderModels.GetComponentName(renderModelName, (uint)i, null, 0);
- if (capacity == 0)
- continue;
- System.Text.StringBuilder componentNameStringBuilder = new System.Text.StringBuilder((int)capacity);
- if (renderModels.GetComponentName(renderModelName, (uint)i, componentNameStringBuilder, capacity) == 0)
- continue;
- string componentName = componentNameStringBuilder.ToString();
- // Create (or reuse) a child object for this component (some components are dynamic and don't have meshes).
- t = FindTransformByName(componentName);
- if (t != null)
- {
- t.gameObject.SetActive(true);
- componentAttachPoints[componentName] = FindTransformByName(k_localTransformName, t);
- }
- else
- {
- t = new GameObject(componentName).transform;
- t.parent = transform;
- t.gameObject.layer = gameObject.layer;
- // Also create a child 'attach' object for attaching things.
- var attach = new GameObject(k_localTransformName).transform;
- attach.parent = t;
- attach.localPosition = Vector3.zero;
- attach.localRotation = Quaternion.identity;
- attach.localScale = Vector3.one;
- attach.gameObject.layer = gameObject.layer;
- componentAttachPoints[componentName] = attach;
- }
- // Reset transform.
- t.localPosition = Vector3.zero;
- t.localRotation = Quaternion.identity;
- t.localScale = Vector3.one;
- capacity = renderModels.GetComponentRenderModelName(renderModelName, componentName, null, 0);
- if (capacity == 0)
- continue;
- var componentRenderModelNameStringBuilder = new System.Text.StringBuilder((int)capacity);
- if (renderModels.GetComponentRenderModelName(renderModelName, componentName, componentRenderModelNameStringBuilder, capacity) == 0)
- continue;
- string componentRenderModelName = componentRenderModelNameStringBuilder.ToString();
- // Check the cache or load into memory.
- var model = models[componentRenderModelName] as RenderModel;
- if (model == null || model.mesh == null)
- {
- if (verbose)
- Debug.Log("<b>[SteamVR]</b> Loading render model " + componentRenderModelName);
- model = LoadRenderModel(renderModels, componentRenderModelName, renderModelName);
- if (model == null)
- continue;
- models[componentRenderModelName] = model;
- }
- t.gameObject.AddComponent<MeshFilter>().mesh = model.mesh;
- MeshRenderer newRenderer = t.gameObject.AddComponent<MeshRenderer>();
- newRenderer.sharedMaterial = model.material;
- meshRenderers.Add(newRenderer);
- }
- return true;
- }
- SteamVR_Events.Action deviceConnectedAction, hideRenderModelsAction, modelSkinSettingsHaveChangedAction;
- SteamVR_RenderModel()
- {
- deviceConnectedAction = SteamVR_Events.DeviceConnectedAction(OnDeviceConnected);
- hideRenderModelsAction = SteamVR_Events.HideRenderModelsAction(OnHideRenderModels);
- modelSkinSettingsHaveChangedAction = SteamVR_Events.SystemAction(EVREventType.VREvent_ModelSkinSettingsHaveChanged, OnModelSkinSettingsHaveChanged);
- }
- void OnEnable()
- {
- #if UNITY_EDITOR
- if (!Application.isPlaying)
- return;
- #endif
- if (!string.IsNullOrEmpty(modelOverride))
- {
- Debug.Log("<b>[SteamVR]</b> " + modelOverrideWarning);
- enabled = false;
- return;
- }
- var system = OpenVR.System;
- if (system != null && system.IsTrackedDeviceConnected((uint)index))
- {
- UpdateModel();
- }
- deviceConnectedAction.enabled = true;
- hideRenderModelsAction.enabled = true;
- modelSkinSettingsHaveChangedAction.enabled = true;
- }
- void OnDisable()
- {
- #if UNITY_EDITOR
- if (!Application.isPlaying)
- return;
- #endif
- deviceConnectedAction.enabled = false;
- hideRenderModelsAction.enabled = false;
- modelSkinSettingsHaveChangedAction.enabled = false;
- }
- #if UNITY_EDITOR
- Hashtable values;
- #endif
- void Update()
- {
- #if UNITY_EDITOR
- if (!Application.isPlaying)
- {
- // See if anything has changed since this gets called whenever anything gets touched.
- var fields = GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
- bool modified = false;
- if (values == null)
- {
- modified = true;
- }
- else
- {
- foreach (var f in fields)
- {
- if (!values.Contains(f))
- {
- modified = true;
- break;
- }
- var v0 = values[f];
- var v1 = f.GetValue(this);
- if (v1 != null)
- {
- if (!v1.Equals(v0))
- {
- modified = true;
- break;
- }
- }
- else if (v0 != null)
- {
- modified = true;
- break;
- }
- }
- }
- if (modified)
- {
- if (renderModelName != modelOverride)
- {
- renderModelName = modelOverride;
- SetModel(modelOverride);
- }
- values = new Hashtable();
- foreach (var f in fields)
- values[f] = f.GetValue(this);
- }
- return; // Do not update transforms (below) when not playing in Editor (to avoid keeping OpenVR running all the time).
- }
- #endif
- // Update component transforms dynamically.
- if (updateDynamically)
- UpdateComponents(OpenVR.RenderModels);
- }
- Dictionary<int, string> nameCache;
- public void UpdateComponents(CVRRenderModels renderModels)
- {
- if (renderModels == null)
- return;
- if (transform.childCount == 0)
- return;
- if (nameCache == null)
- nameCache = new Dictionary<int, string>();
- for (int childIndex = 0; childIndex < transform.childCount; childIndex++)
- {
- Transform child = transform.GetChild(childIndex);
- // Cache names since accessing an object's name allocates memory.
- string componentName;
- if (!nameCache.TryGetValue(child.GetInstanceID(), out componentName))
- {
- componentName = child.name;
- nameCache.Add(child.GetInstanceID(), componentName);
- }
- var componentState = new RenderModel_ComponentState_t();
- if (!renderModels.GetComponentStateForDevicePath(renderModelName, componentName, SteamVR_Input_Source.GetHandle(inputSource), ref controllerModeState, ref componentState))
- continue;
- child.localPosition = componentState.mTrackingToComponentRenderModel.GetPosition();
- child.localRotation = componentState.mTrackingToComponentRenderModel.GetRotation();
- Transform attach = null;
- for (int childChildIndex = 0; childChildIndex < child.childCount; childChildIndex++)
- {
- Transform childChild = child.GetChild(childChildIndex);
- int childInstanceID = childChild.GetInstanceID();
- string childName;
- if (!nameCache.TryGetValue(childInstanceID, out childName))
- {
- childName = childChild.name;
- nameCache.Add(childInstanceID, componentName);
- }
- if (childName == SteamVR_RenderModel.k_localTransformName)
- attach = childChild;
- }
- if (attach != null)
- {
- attach.position = transform.TransformPoint(componentState.mTrackingToComponentLocal.GetPosition());
- attach.rotation = transform.rotation * componentState.mTrackingToComponentLocal.GetRotation();
- initializedAttachPoints = true;
- }
- bool visible = (componentState.uProperties & (uint)EVRComponentProperty.IsVisible) != 0;
- if (visible != child.gameObject.activeSelf)
- {
- child.gameObject.SetActive(visible);
- }
- }
- }
- public void SetDeviceIndex(int newIndex)
- {
- this.index = (SteamVR_TrackedObject.EIndex)newIndex;
- modelOverride = "";
- if (enabled)
- {
- UpdateModel();
- }
- }
- public void SetInputSource(SteamVR_Input_Sources newInputSource)
- {
- inputSource = newInputSource;
- }
- private static void Sleep()
- {
- #if !UNITY_METRO
- //System.Threading.Thread.SpinWait(1); //faster napping
- System.Threading.Thread.Sleep(1);
- #endif
- }
- /// <summary>
- /// Helper function to handle the inconvenient fact that the packing for RenderModel_t is
- /// different on Linux/OSX (4) than it is on Windows (8)
- /// </summary>
- /// <param name="pRenderModel">native pointer to the RenderModel_t</param>
- /// <returns></returns>
- private RenderModel_t MarshalRenderModel(System.IntPtr pRenderModel)
- {
- if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||
- (System.Environment.OSVersion.Platform == System.PlatformID.Unix))
- {
- var packedModel = (RenderModel_t_Packed)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t_Packed));
- RenderModel_t model = new RenderModel_t();
- packedModel.Unpack(ref model);
- return model;
- }
- else
- {
- return (RenderModel_t)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t));
- }
- }
- /// <summary>
- /// Helper function to handle the inconvenient fact that the packing for RenderModel_TextureMap_t is
- /// different on Linux/OSX (4) than it is on Windows (8)
- /// </summary>
- /// <param name="pRenderModel">native pointer to the RenderModel_TextureMap_t</param>
- /// <returns></returns>
- private RenderModel_TextureMap_t MarshalRenderModel_TextureMap(System.IntPtr pRenderModel)
- {
- if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||
- (System.Environment.OSVersion.Platform == System.PlatformID.Unix))
- {
- var packedModel = (RenderModel_TextureMap_t_Packed)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_TextureMap_t_Packed));
- RenderModel_TextureMap_t model = new RenderModel_TextureMap_t();
- packedModel.Unpack(ref model);
- return model;
- }
- else
- {
- return (RenderModel_TextureMap_t)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_TextureMap_t));
- }
- }
- }
- }
|