diff --git a/Assets/Oculus.meta b/Assets/Oculus.meta new file mode 100644 index 0000000..721ce43 --- /dev/null +++ b/Assets/Oculus.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a0a0bd2b6c0d93b42a8788ed13d2bb94 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager.meta b/Assets/Oculus/AudioManager.meta new file mode 100644 index 0000000..533eb36 --- /dev/null +++ b/Assets/Oculus/AudioManager.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3b5e85298c67f4a64bdd2fe534ccc158 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Audio.meta b/Assets/Oculus/AudioManager/Audio.meta new file mode 100644 index 0000000..fd0cfe8 --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 29ab7e927676ef74a93aeedf4146f1ac +folderAsset: yes +timeCreated: 1470780399 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds.meta b/Assets/Oculus/AudioManager/Audio/TestSounds.meta new file mode 100644 index 0000000..9aed85d --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 180c8a539f95cce428f820b0ba392c1f +folderAsset: yes +timeCreated: 1468506676 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav new file mode 100644 index 0000000..17d8c5d --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:02df2b7172e6dcd2abb2d1a69eebb86046f29f225d7bc3f2aff9cbb07b79bd7b +size 40180 diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav.meta b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav.meta new file mode 100644 index 0000000..518c3e3 --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 485ac48a563e2bf44bb4de7ead5a1f68 +timeCreated: 1461716881 +licenseType: Pro +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav new file mode 100644 index 0000000..2886843 --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e5410447a888bd7d8938b3bdc328dbe0d1272469eab88b81c336d899c2e7d2e8 +size 40178 diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav.meta b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav.meta new file mode 100644 index 0000000..712313d --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: d3994560fb567c34a821fd9355c10eef +timeCreated: 1461716882 +licenseType: Pro +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav new file mode 100644 index 0000000..8ff899b --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:56851dede6d1079545702e92d44ce73048277b5daaeb1168f309945cc0fccfcc +size 47956 diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav.meta b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav.meta new file mode 100644 index 0000000..7ff557e --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 7000b4d67a1320940b363f3cf891dfff +timeCreated: 1461716881 +licenseType: Pro +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav new file mode 100644 index 0000000..fd10e79 --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf859666893d89be742948896fec030f0eafa304dc2b028e8cf03561878e1b98 +size 51014 diff --git a/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav.meta b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav.meta new file mode 100644 index 0000000..b8b81c9 --- /dev/null +++ b/Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav.meta @@ -0,0 +1,22 @@ +fileFormatVersion: 2 +guid: 8198ccc08475a764daaf226b841a55f1 +timeCreated: 1461716882 +licenseType: Pro +AudioImporter: + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scenes.meta b/Assets/Oculus/AudioManager/Scenes.meta new file mode 100644 index 0000000..a979191 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scenes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6d597fe114807b54a99033a3dae9ce0d +folderAsset: yes +timeCreated: 1470780399 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scenes/Scripts.meta b/Assets/Oculus/AudioManager/Scenes/Scripts.meta new file mode 100644 index 0000000..4388996 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scenes/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7ee6cbebddf12044c95f9d6eb6e40823 +folderAsset: yes +timeCreated: 1470780399 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scenes/Scripts/TestScript.cs b/Assets/Oculus/AudioManager/Scenes/Scripts/TestScript.cs new file mode 100644 index 0000000..b7bc36f --- /dev/null +++ b/Assets/Oculus/AudioManager/Scenes/Scripts/TestScript.cs @@ -0,0 +1,36 @@ +using UnityEngine; +using System.Collections; + +namespace OVR +{ + +public class TestScript : MonoBehaviour { + + [InspectorNote( "Sound Setup", "Press '1' to play testSound1 and '2' to play testSound2")] + + public SoundFXRef testSound1; + public SoundFXRef testSound2; + + // Use this for initialization + void Start () { + + } + + + // Update is called once per frame + void Update () + { + // use attached game object location + if ( Input.GetKeyDown( KeyCode.Alpha1 ) ) + { + testSound1.PlaySoundAt( transform.position ); + } + + // hard code information + if ( Input.GetKeyDown( KeyCode.Alpha2 ) ) { + testSound2.PlaySoundAt( new Vector3( 5.0f, 0.0f, 0.0f ) ); + } + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scenes/Scripts/TestScript.cs.meta b/Assets/Oculus/AudioManager/Scenes/Scripts/TestScript.cs.meta new file mode 100644 index 0000000..ca4ee1a --- /dev/null +++ b/Assets/Oculus/AudioManager/Scenes/Scripts/TestScript.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: cfae243ecd01edd49bd439c56a8b18cf +timeCreated: 1468506975 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scenes/Test.unity b/Assets/Oculus/AudioManager/Scenes/Test.unity new file mode 100644 index 0000000..ecce042 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scenes/Test.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b963783f3fab815b1b382d65ebecd6b017388fdab7355a7c31b2f90077d2d8e5 +size 11647 diff --git a/Assets/Oculus/AudioManager/Scenes/Test.unity.meta b/Assets/Oculus/AudioManager/Scenes/Test.unity.meta new file mode 100644 index 0000000..67855d0 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scenes/Test.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 600e5d49b0a68254286400e32c53addc +timeCreated: 1468506358 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts.meta b/Assets/Oculus/AudioManager/Scripts.meta new file mode 100644 index 0000000..65521c2 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 25be027379f7fce4d97ba2bcaf313019 +folderAsset: yes +timeCreated: 1470780399 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio.meta b/Assets/Oculus/AudioManager/Scripts/Audio.meta new file mode 100644 index 0000000..808f358 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b8c0d722519c64144a78f8fc99cd40b5 +folderAsset: yes +timeCreated: 1468505670 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/AmbienceEmitter.cs b/Assets/Oculus/AudioManager/Scripts/Audio/AmbienceEmitter.cs new file mode 100644 index 0000000..740639f --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/AmbienceEmitter.cs @@ -0,0 +1,118 @@ +using UnityEngine; +using System.Collections; + +namespace OVR +{ + +/* +----------------------- + + AmbienceEmitter() + +----------------------- +*/ +public class AmbienceEmitter : MonoBehaviour { + + public SoundFXRef[] ambientSounds = new SoundFXRef[0]; + public bool autoActivate = true; + [Tooltip("Automatically play the sound randomly again when checked. Should be OFF for looping sounds")] + public bool autoRetrigger = true; + [MinMax( 2.0f, 4.0f, 0.1f, 10.0f )] + public Vector2 randomRetriggerDelaySecs = new Vector2( 2.0f, 4.0f ); + [Tooltip( "If defined, the sounds will randomly play from these transform positions, otherwise the sound will play from this transform" )] + public Transform[] playPositions = new Transform[0]; + private bool activated = false; + private int playingIdx = -1; + private float nextPlayTime = 0.0f; + private float fadeTime = 0.25f; + private int lastPosIdx = -1; + + /* + ----------------------- + Awake() + ----------------------- + */ + void Awake() { + if ( autoActivate ) { + activated = true; + nextPlayTime = Time.time + Random.Range( randomRetriggerDelaySecs.x, randomRetriggerDelaySecs.y ); + } + // verify all the play positions are valid + foreach ( Transform t in playPositions ) { + if ( t == null ) { + Debug.LogWarning( "[AmbienceEmitter] Invalid play positions in " + name ); + playPositions = new Transform[0]; + break; + } + } + } + + /* + ----------------------- + Update() + ----------------------- + */ + void Update() { + if ( activated ) { + if ( ( playingIdx == -1 ) || autoRetrigger ) { + if ( Time.time >= nextPlayTime ) { + Play(); + if ( !autoRetrigger ) { + activated = false; + } + } + } + } + } + + /* + ----------------------- + OnTriggerEnter() + ----------------------- + */ + public void OnTriggerEnter( Collider col ) { + activated = !activated; + } + + /* + ----------------------- + Play() + ----------------------- + */ + public void Play() { + Transform transformToPlayFrom = transform; + if ( playPositions.Length > 0 ) { + int idx = Random.Range( 0, playPositions.Length ); + while ( ( playPositions.Length > 1 ) && ( idx == lastPosIdx ) ) { + idx = Random.Range( 0, playPositions.Length ); + } + transformToPlayFrom = playPositions[idx]; + lastPosIdx = idx; + } + playingIdx = ambientSounds[Random.Range(0, ambientSounds.Length)].PlaySoundAt( transformToPlayFrom.position ); + if ( playingIdx != -1 ) { + AudioManager.FadeInSound( playingIdx, fadeTime ); + nextPlayTime = Time.time + Random.Range( randomRetriggerDelaySecs.x, randomRetriggerDelaySecs.y ); + } + } + + /* + ----------------------- + EnableEmitter() + ----------------------- + */ + public void EnableEmitter( bool enable ) { + activated = enable; + if ( enable ) { + Play(); + } else { + if ( playingIdx != -1 ) { + AudioManager.FadeOutSound( playingIdx, fadeTime ); + } + } + + } + +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/AmbienceEmitter.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/AmbienceEmitter.cs.meta new file mode 100644 index 0000000..4152573 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/AmbienceEmitter.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c11944691f6b9cf44a391c95cb3f7dea +timeCreated: 1455050294 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager.cs b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager.cs new file mode 100644 index 0000000..4a1608d --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager.cs @@ -0,0 +1,429 @@ +using UnityEngine; +using UnityEngine.Audio; +using System.Collections; +using System.Collections.Generic; +#if UNITY_EDITOR +using UnityEditor; +using System; +using System.Reflection; +#endif + +namespace OVR +{ + +public enum PreloadSounds { + Default, // default unity behavior + Preload, // audio clips are forced to preload + ManualPreload, // audio clips are forced to not preload, preloading must be done manually +} + +public enum Fade +{ + In, + Out +} + +[System.Serializable] +public class SoundGroup { + public SoundGroup( string name ) { + this.name = name; + } + public SoundGroup() { + mixerGroup = null; + maxPlayingSounds = 0; + preloadAudio = PreloadSounds.Default; + volumeOverride = 1.0f; + } + public void IncrementPlayCount() { + playingSoundCount = Mathf.Clamp( ++playingSoundCount, 0, maxPlayingSounds ); + } + public void DecrementPlayCount() { + playingSoundCount = Mathf.Clamp( --playingSoundCount, 0, maxPlayingSounds ); + } + public bool CanPlaySound() { + return ( maxPlayingSounds == 0 ) || ( playingSoundCount < maxPlayingSounds ); + } + + public string name = string.Empty; + public SoundFX[] soundList = new SoundFX[0]; + public AudioMixerGroup mixerGroup = null; // default = AudioManager.defaultMixerGroup + [Range(0,64)] + public int maxPlayingSounds = 0; // default = 0, unlimited + // TODO: this preload behavior is not yet implemented + public PreloadSounds preloadAudio = PreloadSounds.Default; // default = true, audio clip data will be preloaded + public float volumeOverride = 1.0f; // default = 1.0 + + [HideInInspector] + public int playingSoundCount = 0; +} + +/* +----------------------- + + AudioManager + +----------------------- +*/ +public partial class AudioManager : MonoBehaviour { + + [Tooltip("Make the audio manager persistent across all scene loads")] + public bool makePersistent = true; // true = don't destroy on load + [Tooltip("Enable the OSP audio plugin features")] + public bool enableSpatializedAudio = true; // true = enable spatialized audio + [Tooltip("Always play spatialized sounds with no reflections (Default)")] + public bool enableSpatializedFastOverride = false; // true = disable spatialized reflections override + [Tooltip("The audio mixer asset used for snapshot blends, etc.")] + public AudioMixer audioMixer = null; + [Tooltip( "The audio mixer group used for the pooled emitters" )] + public AudioMixerGroup defaultMixerGroup = null; + [Tooltip( "The audio mixer group used for the reserved pool emitter" )] + public AudioMixerGroup reservedMixerGroup = null; + [Tooltip( "The audio mixer group used for voice chat" )] + public AudioMixerGroup voiceChatMixerGroup = null; + [Tooltip("Log all PlaySound calls to the Unity console")] + public bool verboseLogging = false; // true = log all PlaySounds + [Tooltip("Maximum sound emitters")] + public int maxSoundEmitters = 32; // total number of sound emitters created + [Tooltip("Default volume for all sounds modulated by individual sound FX volumes")] + public float volumeSoundFX = 1.0f; // user pref: volume of all sound FX + [Tooltip("Sound FX fade time")] + public float soundFxFadeSecs = 1.0f; // sound FX fade time + + public float audioMinFallOffDistance = 1.0f; // minimum falloff distance + public float audioMaxFallOffDistance = 25.0f; // maximum falloff distance + + public SoundGroup[] soundGroupings = new SoundGroup[0]; + + private Dictionary soundFXCache = null; + + static private AudioManager theAudioManager = null; + static private FastList names = new FastList(); + static private string[] defaultSound = new string[1] { "Default Sound" }; + static private SoundFX nullSound = new SoundFX(); + static private bool hideWarnings = false; + static public bool enableSpatialization { get { return ( theAudioManager !=null ) ? theAudioManager.enableSpatializedAudio : false; } } + + static public AudioManager Instance { get { return theAudioManager; } } + static public float NearFallOff { get { return theAudioManager.audioMinFallOffDistance; } } + static public float FarFallOff { get { return theAudioManager.audioMaxFallOffDistance; } } + static public AudioMixerGroup EmitterGroup { get { return theAudioManager.defaultMixerGroup; } } + static public AudioMixerGroup ReservedGroup { get { return theAudioManager.reservedMixerGroup; } } + static public AudioMixerGroup VoipGroup { get { return theAudioManager.voiceChatMixerGroup; } } + + /* + ----------------------- + Awake() + ----------------------- + */ + void Awake() { + Init(); + } + + /* + ----------------------- + OnDestroy() + ----------------------- + */ + void OnDestroy() { + // we only want the initialized audio manager instance cleaning up the sound emitters + if ( theAudioManager == this ) { + if ( soundEmitterParent != null ) { + Destroy( soundEmitterParent ); + } + } + ///TODO - if you change scenes you'll want to call OnPreSceneLoad to detach the sound emitters + ///from anything they might be parented to or they will get destroyed with that object + ///there should only be one instance of the AudioManager across the life of the game/app + ///GameManager.OnPreSceneLoad -= OnPreSceneLoad; + } + + /* + ----------------------- + Init() + ----------------------- + */ + void Init() { + if ( theAudioManager != null ) { + if ( Application.isPlaying && ( theAudioManager != this ) ) { + enabled = false; + } + return; + } + theAudioManager = this; + + ///TODO - if you change scenes you'll want to call OnPreSceneLoad to detach the sound emitters + ///from anything they might be parented to or they will get destroyed with that object + ///there should only be one instance of the AudioManager across the life of the game/app + ///GameManager.OnPreSceneLoad += OnPreSceneLoad; + + // make sure the first one is a null sound + nullSound.name = "Default Sound"; + + // build the sound FX cache + RebuildSoundFXCache(); + + // create the sound emitters + if ( Application.isPlaying ) { + InitializeSoundSystem(); + if ( makePersistent && ( transform.parent == null ) ) { + // don't destroy the audio manager on scene loads + DontDestroyOnLoad( gameObject ); + } + } + +#if UNITY_EDITOR + Debug.Log( "[AudioManager] Initialized..." ); +#endif + } + + /* + ----------------------- + Update() + ----------------------- + */ + void Update() { + // update the free and playing lists + UpdateFreeEmitters(); + } + + /* + ----------------------- + RebuildSoundFXCache() + ----------------------- + */ + void RebuildSoundFXCache() { + // build the SoundFX dictionary for quick name lookups + int count = 0; + for ( int group = 0; group < soundGroupings.Length; group++ ) { + count += soundGroupings[group].soundList.Length; + } + soundFXCache = new Dictionary( count + 1 ); + // add the null sound + soundFXCache.Add( nullSound.name, nullSound ); + // add the rest + for ( int group = 0; group < soundGroupings.Length; group++ ) { + for ( int i = 0; i < soundGroupings[group].soundList.Length; i++ ) { + if ( soundFXCache.ContainsKey( soundGroupings[group].soundList[i].name ) ) { + Debug.LogError( "ERROR: Duplicate Sound FX name in the audio manager: '" + soundGroupings[group].name + "' > '" + soundGroupings[group].soundList[i].name + "'" ); + } else { + soundGroupings[group].soundList[i].Group = soundGroupings[group]; + soundFXCache.Add( soundGroupings[group].soundList[i].name, soundGroupings[group].soundList[i] ); + } + } + soundGroupings[group].playingSoundCount = 0; + } + } + + /* + ----------------------- + FindSoundFX() + ----------------------- + */ + static public SoundFX FindSoundFX( string name, bool rebuildCache = false ) { +#if UNITY_EDITOR + if ( theAudioManager == null ) { + Debug.LogError( "ERROR: audio manager not yet initialized or created!" + " Time: " + Time.time ); + return null; + } +#endif + if ( string.IsNullOrEmpty( name ) ) { + return nullSound; + } + if ( rebuildCache ) { + theAudioManager.RebuildSoundFXCache(); + } + if ( !theAudioManager.soundFXCache.ContainsKey( name ) ) { +#if DEBUG_BUILD || UNITY_EDITOR + Debug.LogError( "WARNING: Missing Sound FX in cache: " + name ); +#endif + return nullSound; + } + return theAudioManager.soundFXCache[name]; + } + + /* + ----------------------- + FindAudioManager() + ----------------------- + */ + static private bool FindAudioManager() { + GameObject audioManagerObject = GameObject.Find( "AudioManager" ); + if ( ( audioManagerObject == null ) || ( audioManagerObject.GetComponent() == null ) ) { + if ( !hideWarnings ) { + Debug.LogError( "[ERROR] AudioManager object missing from hierarchy!" ); + hideWarnings = true; + } + return false; + } else { + audioManagerObject.GetComponent().Init(); + } + return true; + } + + /* + ----------------------- + GetGameObject() + ----------------------- + */ + static public GameObject GetGameObject() { + if ( theAudioManager == null ) { + if ( !FindAudioManager() ) { + return null; + } + } + return theAudioManager.gameObject; + } + + /* + ----------------------- + NameMinusGroup() + strip off the sound group from the inspector dropdown + ----------------------- + */ + static public string NameMinusGroup( string name ) { + if ( name.IndexOf( "/" ) > -1 ) { + return name.Substring( name.IndexOf( "/" ) + 1 ); + } + return name; + } + + /* + ----------------------- + GetSoundFXNames() + used by the inspector + ----------------------- + */ + static public string[] GetSoundFXNames( string currentValue, out int currentIdx ) { + currentIdx = 0; + names.Clear(); + if ( theAudioManager == null ) { + if ( !FindAudioManager() ) { + return defaultSound; + } + } + names.Add( nullSound.name ); + for ( int group = 0; group < theAudioManager.soundGroupings.Length; group++ ) { + for ( int i = 0; i < theAudioManager.soundGroupings[group].soundList.Length; i++ ) { + if ( string.Compare( currentValue, theAudioManager.soundGroupings[group].soundList[i].name, true ) == 0 ) { + currentIdx = names.Count; + } + names.Add( theAudioManager.soundGroupings[group].name + "/" + theAudioManager.soundGroupings[group].soundList[i].name ); + } + } + //names.Sort( delegate( string s1, string s2 ) { return s1.CompareTo( s2 ); } ); + return names.ToArray(); + + } +#if UNITY_EDITOR + /* + ----------------------- + OnPrefabReimported() + ----------------------- + */ + static public void OnPrefabReimported() { + if ( theAudioManager != null ) { + Debug.Log( "[AudioManager] Reimporting the sound FX cache." ); + theAudioManager.RebuildSoundFXCache(); + } + } + + /* + ----------------------- + PlaySound() + used in the editor + ----------------------- + */ + static public void PlaySound( string soundFxName ) { + if ( theAudioManager == null ) { + if ( !FindAudioManager() ) { + return; + } + } + SoundFX soundFX = FindSoundFX( soundFxName, true ); + if ( soundFX == null ) { + return; + } + AudioClip clip = soundFX.GetClip(); + if ( clip != null ) { + Assembly unityEditorAssembly = typeof(AudioImporter).Assembly; + Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil"); + MethodInfo method = audioUtilClass.GetMethod( + "PlayClip", + BindingFlags.Static | BindingFlags.Public, + null, + new System.Type[] { typeof(AudioClip) }, + null ); + method.Invoke( null, new object[] { clip } ); + } + } + + /* + ----------------------- + IsSoundPlaying() + used in the editor + ----------------------- + */ + static public bool IsSoundPlaying( string soundFxName ) { + if ( theAudioManager == null ) { + if ( !FindAudioManager() ) { + return false; + } + } + SoundFX soundFX = FindSoundFX( soundFxName, true ); + if ( soundFX == null ) { + return false; + } + AudioClip clip = soundFX.GetClip(); + if ( clip != null ) { + Assembly unityEditorAssembly = typeof(AudioImporter).Assembly; + Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil"); + MethodInfo method = audioUtilClass.GetMethod( + "IsClipPlaying", + BindingFlags.Static | BindingFlags.Public, + null, + new System.Type[] { typeof(AudioClip) }, + null ); + return Convert.ToBoolean( method.Invoke( null, new object[] { clip } ) ); + } + + return false; + } + + /* + ----------------------- + StopSound() + used in the editor + ----------------------- + */ + static public void StopSound(string soundFxName) + { + if (theAudioManager == null) + { + if (!FindAudioManager()) + { + return; + } + } + SoundFX soundFX = FindSoundFX(soundFxName, true); + if (soundFX == null) + { + return; + } + AudioClip clip = soundFX.GetClip(); + if (clip != null) + { + Assembly unityEditorAssembly = typeof(AudioImporter).Assembly; + Type audioUtilClass = unityEditorAssembly.GetType("UnityEditor.AudioUtil"); + MethodInfo method = audioUtilClass.GetMethod( + "StopClip", + BindingFlags.Static | BindingFlags.Public, + null, + new System.Type[] { typeof(AudioClip) }, + null); + method.Invoke(null, new object[] { clip }); + } + } +#endif +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager.cs.meta new file mode 100644 index 0000000..55df52e --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6d1d30b41806244fca035fdae2896fb7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager_Sound.cs b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager_Sound.cs new file mode 100644 index 0000000..36530e3 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager_Sound.cs @@ -0,0 +1,787 @@ +using UnityEngine; +using UnityEngine.Audio; + +namespace OVR +{ + +//------------------------------------------------------------------------- +// Types +//------------------------------------------------------------------------- + +public enum EmitterChannel { + None = -1, + Reserved = 0, // plays on the single reserved emitter + Any // queues to the next available emitter +} + +[System.Serializable] +public class MixerSnapshot { + public AudioMixerSnapshot snapshot = null; + public float transitionTime = 0.25f; +} + +/* +----------------------- + + GameManager Sound Routines + +----------------------- +*/ +public partial class AudioManager : MonoBehaviour { + + public enum Fade { + In, + Out + } + + private float audioMaxFallOffDistanceSqr = 25.0f * 25.0f; // past this distance, sounds are ignored for the local player + + private SoundEmitter[] soundEmitters = null; // pool of sound emitters to play sounds through + + private FastList playingEmitters = new FastList(); + private FastList nextFreeEmitters = new FastList(); + + private MixerSnapshot currentSnapshot = null; + + static private GameObject soundEmitterParent = null; // parent object for the sound emitters + static private Transform staticListenerPosition = null; // play position for regular 2D sounds + + static private bool showPlayingEmitterCount = false; + static private bool forceShowEmitterCount = false; + + static private bool soundEnabled = true; + static public bool SoundEnabled { get { return soundEnabled; } } + + static readonly AnimationCurve defaultReverbZoneMix = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } ); + + /* + ----------------------- + InitializeSoundSystem() + initialize persistent sound emitter objects that live across scene loads + ----------------------- + */ + void InitializeSoundSystem() { + + int bufferLength = 960; + int numBuffers = 4; + AudioSettings.GetDSPBufferSize( out bufferLength, out numBuffers ); + if ( Application.isPlaying ) { + Debug.Log( "[AudioManager] Audio Sample Rate: " + AudioSettings.outputSampleRate ); + Debug.Log( "[AudioManager] Audio Buffer Length: " + bufferLength + " Size: " + numBuffers ); + } + + // find the audio listener for playing regular 2D sounds + AudioListener audioListenerObject = GameObject.FindObjectOfType() as AudioListener; + if ( audioListenerObject == null ) { + Debug.LogError( "[AudioManager] Missing AudioListener object! Add one to the scene." ); + } else { + staticListenerPosition = audioListenerObject.transform; + } + + // we allocate maxSoundEmitters + reserved channels + soundEmitters = new SoundEmitter[maxSoundEmitters+(int)EmitterChannel.Any]; + + // see if the sound emitters have already been created, if so, nuke it, it shouldn't exist in the scene upon load + soundEmitterParent = GameObject.Find( "__SoundEmitters__" ); + if ( soundEmitterParent != null ) { + // delete any sound emitters hanging around + Destroy( soundEmitterParent ); + } + + // create them all + soundEmitterParent = new GameObject( "__SoundEmitters__" ); + for ( int i = 0; i < maxSoundEmitters + (int)EmitterChannel.Any; i++ ) { + GameObject emitterObject = new GameObject( "SoundEmitter_" + i ); + emitterObject.transform.parent = soundEmitterParent.transform; + emitterObject.transform.position = Vector3.zero; + // don't ever save this to the scene + emitterObject.hideFlags = HideFlags.DontSaveInEditor; + // add the sound emitter components + soundEmitters[i] = emitterObject.AddComponent(); + soundEmitters[i].SetDefaultParent( soundEmitterParent.transform ); + soundEmitters[i].SetChannel( i ); + soundEmitters[i].Stop(); + // save off the original index + soundEmitters[i].originalIdx = i; + } + // reset the free emitter lists + ResetFreeEmitters(); + soundEmitterParent.hideFlags = HideFlags.DontSaveInEditor; + + audioMaxFallOffDistanceSqr = audioMaxFallOffDistance * audioMaxFallOffDistance; + } + + /* + ----------------------- + UpdateFreeEmitters() + ----------------------- + */ + void UpdateFreeEmitters() { + if ( verboseLogging ) { + if ( Input.GetKeyDown( KeyCode.A ) ) { + forceShowEmitterCount = !forceShowEmitterCount; + } + if ( forceShowEmitterCount ) { + showPlayingEmitterCount = true; + } + } + // display playing emitter count when the sound system is overwhelmed + int total = 0, veryLow = 0, low = 0, def = 0, high = 0, veryHigh = 0; + + // find emitters that are done playing and add them to the nextFreeEmitters list + for ( int i = 0; i < playingEmitters.size; ) { + if ( playingEmitters[i] == null ) { + Debug.LogError( "[AudioManager] ERROR: playingEmitters list had a null emitter! Something nuked a sound emitter!!!" ); + playingEmitters.RemoveAtFast( i ); + return; + } + if ( !playingEmitters[i].IsPlaying() ) { + // add to the free list and remove from the playing list + if ( verboseLogging ) { + if ( nextFreeEmitters.Contains( playingEmitters[i] ) ) { + Debug.LogError( "[AudioManager] ERROR: playing sound emitter already in the free emitters list!" ); + } + } + playingEmitters[i].Stop(); + nextFreeEmitters.Add( playingEmitters[i] ); + playingEmitters.RemoveAtFast( i ); + continue; + } + // debugging/profiling + if ( verboseLogging && showPlayingEmitterCount ) { + total++; + switch ( playingEmitters[i].priority ) { + case SoundPriority.VeryLow: veryLow++; break; + case SoundPriority.Low: low++; break; + case SoundPriority.Default: def++; break; + case SoundPriority.High: high++; break; + case SoundPriority.VeryHigh: veryHigh++; break; + } + } + i++; + } + if ( verboseLogging && showPlayingEmitterCount ) { + Debug.LogWarning( string.Format( "[AudioManager] Playing sounds: Total {0} | VeryLow {1} | Low {2} | Default {3} | High {4} | VeryHigh {5} | Free {6}", Fmt( total ), Fmt( veryLow ), Fmt( low ), Fmt( def ), Fmt( high ), Fmt( veryHigh ), FmtFree( nextFreeEmitters.Count ) ) ); + showPlayingEmitterCount = false; + } + } + + /* + ----------------------- + Fmt() + ----------------------- + */ + string Fmt( int count ) { + float t = count / (float)theAudioManager.maxSoundEmitters; + if ( t < 0.5f ) { + return "" + count.ToString() + ""; + } else if ( t < 0.7 ) { + return "" + count.ToString() + ""; + } else { + return "" + count.ToString() + ""; + } + } + + /* + ----------------------- + FmtFree() + ----------------------- + */ + string FmtFree( int count ) { + float t = count / (float)theAudioManager.maxSoundEmitters; + if ( t < 0.2f ) { + return "" + count.ToString() + ""; + } else if ( t < 0.3 ) { + return "" + count.ToString() + ""; + } else { + return "" + count.ToString() + ""; + } + } + + /* + ----------------------- + OnPreSceneLoad() + ----------------------- + */ + void OnPreSceneLoad() { + // move any attached sounds back to the sound emitters parent before changing levels so they don't get destroyed + Debug.Log( "[AudioManager] OnPreSceneLoad cleanup" ); + for ( int i = 0; i < soundEmitters.Length; i++ ) { + soundEmitters[i].Stop(); + soundEmitters[i].ResetParent( soundEmitterParent.transform ); + } + // reset our emitter lists + ResetFreeEmitters(); + } + + /* + ----------------------- + ResetFreeEmitters() + ----------------------- + */ + void ResetFreeEmitters() { + nextFreeEmitters.Clear(); + playingEmitters.Clear(); + for ( int i = (int)EmitterChannel.Any; i < soundEmitters.Length; i++ ) { + nextFreeEmitters.Add( soundEmitters[i] ); + } + } + + /* + ----------------------- + FadeOutSoundChannel() + utility function to fade out a playing sound channel + ----------------------- + */ + static public void FadeOutSoundChannel( int channel, float delaySecs, float fadeTime ) { + theAudioManager.soundEmitters[channel].FadeOutDelayed( delaySecs, fadeTime ); + } + + /* + ----------------------- + StopSound() + ----------------------- + */ + static public bool StopSound( int idx, bool fadeOut = true, bool stopReserved = false ) { + if ( !stopReserved && ( idx == (int)EmitterChannel.Reserved ) ) { + return false; + } + if ( !fadeOut ) { + theAudioManager.soundEmitters[idx].Stop(); + } + else { + theAudioManager.soundEmitters[idx].FadeOut( theAudioManager.soundFxFadeSecs ); + } + + return true; + } + + /* + ----------------------- + FadeInSound() + ----------------------- + */ + public static void FadeInSound( int idx, float fadeTime, float volume ) { + theAudioManager.soundEmitters[idx].FadeIn( fadeTime, volume ); + } + + /* + ----------------------- + FadeInSound() + ----------------------- + */ + public static void FadeInSound( int idx, float fadeTime ) { + theAudioManager.soundEmitters[idx].FadeIn( fadeTime ); + } + + /* + ----------------------- + FadeOutSound() + ----------------------- + */ + public static void FadeOutSound( int idx, float fadeTime ) { + theAudioManager.soundEmitters[idx].FadeOut( fadeTime ); + } + + /* + ----------------------- + StopAllSounds() + ----------------------- + */ + public static void StopAllSounds( bool fadeOut, bool stopReserved = false ) { + for ( int i = 0; i < theAudioManager.soundEmitters.Length; i++ ) { + StopSound( i, fadeOut, stopReserved ); + } + } + + /* + ----------------------- + MuteAllSounds() + ----------------------- + */ + public void MuteAllSounds( bool mute, bool muteReserved = false ) { + for ( int i = 0; i < soundEmitters.Length; i++ ) { + if ( !muteReserved && ( i == (int)EmitterChannel.Reserved ) ) { + continue; + } + soundEmitters[i].audioSource.mute = true; + } + } + + /* + ----------------------- + UnMuteAllSounds() + ----------------------- + */ + public void UnMuteAllSounds( bool unmute, bool unmuteReserved = false ) { + for ( int i = 0; i < soundEmitters.Length; i++ ) { + if ( !unmuteReserved && ( i == (int)EmitterChannel.Reserved ) ) { + continue; + } + if ( soundEmitters[i].audioSource.isPlaying ) { + soundEmitters[i].audioSource.mute = false; + } + } + } + + /* + ----------------------- + GetEmitterEndTime() + ----------------------- + */ + static public float GetEmitterEndTime( int idx ) { + return theAudioManager.soundEmitters[idx].endPlayTime; + } + + /* + ----------------------- + SetEmitterTime() + ----------------------- + */ + static public float SetEmitterTime( int idx, float time ) { + return theAudioManager.soundEmitters[idx].time = time; + } + + /* + ----------------------- + PlaySound() + ----------------------- + */ + static public int PlaySound( AudioClip clip, float volume, EmitterChannel src = EmitterChannel.Any, float delay = 0.0f, float pitchVariance = 1.0f, bool loop = false ) { + if ( !SoundEnabled ) { + return -1; + } + return PlaySoundAt( ( staticListenerPosition != null ) ? staticListenerPosition.position : Vector3.zero, clip, volume, src, delay, pitchVariance, loop ); + } + + /* + ----------------------- + FindFreeEmitter() + ----------------------- + */ + static private int FindFreeEmitter( EmitterChannel src, SoundPriority priority ) { + // default to the reserved emitter + SoundEmitter next = theAudioManager.soundEmitters[0]; + if ( src == EmitterChannel.Any ) { + // pull from the free emitter list if possible + if ( theAudioManager.nextFreeEmitters.size > 0 ) { + // return the first in the list + next = theAudioManager.nextFreeEmitters[0]; + // remove it from the free list + theAudioManager.nextFreeEmitters.RemoveAtFast( 0 ); + } else { + // no free emitters available so pull from the lowest priority sound + if ( priority == SoundPriority.VeryLow ) { + // skip low priority sounds + return -1; + } else { + // find a playing emitter that has a lower priority than what we're requesting + // TODO - we could first search for Very Low, then Low, etc ... TBD if it's worth the effort + next = theAudioManager.playingEmitters.Find( item => item != null && item.priority < priority ); + if ( next == null ) { + // last chance to find a free emitter + if ( priority < SoundPriority.Default ) { + // skip sounds less than the default priority + if ( theAudioManager.verboseLogging ) { + Debug.LogWarning( "[AudioManager] skipping sound " + priority ); + } + return -1; + } else { + // grab a default priority emitter so that we don't cannabalize a high priority sound + next = theAudioManager.playingEmitters.Find( item => item != null && item.priority <= SoundPriority.Default ); ; + } + } + if ( next != null ) { + if ( theAudioManager.verboseLogging ) { + Debug.LogWarning( "[AudioManager] cannabalizing " + next.originalIdx + " Time: " + Time.time ); + } + // remove it from the playing list + next.Stop(); + theAudioManager.playingEmitters.RemoveFast( next ); + } + } + } + } + if ( next == null ) { + Debug.LogError( "[AudioManager] ERROR - absolutely couldn't find a free emitter! Priority = " + priority + " TOO MANY PlaySound* calls!" ); + showPlayingEmitterCount = true; + return -1; + } + return next.originalIdx; + } + + /* + ----------------------- + PlaySound() + ----------------------- + */ + static public int PlaySound( SoundFX soundFX, EmitterChannel src = EmitterChannel.Any, float delay = 0.0f ) { + if ( !SoundEnabled ) { + return -1; + } + return PlaySoundAt( ( staticListenerPosition != null ) ? staticListenerPosition.position : Vector3.zero, soundFX, src, delay ); + } + + /* + ----------------------- + PlaySoundAt() + ----------------------- + */ + static public int PlaySoundAt( Vector3 position, SoundFX soundFX, EmitterChannel src = EmitterChannel.Any, float delay = 0.0f, float volumeOverride = 1.0f, float pitchMultiplier = 1.0f ) { + if ( !SoundEnabled ) { + return -1; + } + + AudioClip clip = soundFX.GetClip(); + if ( clip == null ) { + return -1; + } + + // check the distance from the local player and ignore sounds out of range + if ( staticListenerPosition != null ) { + float distFromListener = ( staticListenerPosition.position - position ).sqrMagnitude; + if ( distFromListener > theAudioManager.audioMaxFallOffDistanceSqr ) { + return -1; + } + if ( distFromListener > soundFX.MaxFalloffDistSquared ) { + return -1; + } + } + + // check max playing sounds + if ( soundFX.ReachedGroupPlayLimit() ) { + if ( theAudioManager.verboseLogging ) { + Debug.Log( "[AudioManager] PlaySoundAt() with " + soundFX.name + " skipped due to group play limit" ); + } + return -1; + } + + int idx = FindFreeEmitter( src, soundFX.priority ); + if ( idx == -1 ) { + // no free emitters - should only happen on very low priority sounds + return -1; + } + SoundEmitter emitter = theAudioManager.soundEmitters[idx]; + + // make sure to detach the emitter from a previous parent + emitter.ResetParent( soundEmitterParent.transform ); + emitter.gameObject.SetActive( true ); + + // set up the sound emitter + AudioSource audioSource = emitter.audioSource; + ONSPAudioSource osp = emitter.osp; + + audioSource.enabled = true; + audioSource.volume = Mathf.Clamp01( Mathf.Clamp01( theAudioManager.volumeSoundFX * soundFX.volume ) * volumeOverride * soundFX.GroupVolumeOverride ); + audioSource.pitch = soundFX.GetPitch() * pitchMultiplier; + audioSource.time = 0.0f; + audioSource.spatialBlend = 1.0f; + audioSource.rolloffMode = soundFX.falloffCurve; + if ( soundFX.falloffCurve == AudioRolloffMode.Custom ) { + audioSource.SetCustomCurve( AudioSourceCurveType.CustomRolloff, soundFX.volumeFalloffCurve ); + } + audioSource.SetCustomCurve( AudioSourceCurveType.ReverbZoneMix, soundFX.reverbZoneMix ); + audioSource.dopplerLevel = 0; + audioSource.clip = clip; + audioSource.spread = soundFX.spread; + audioSource.loop = soundFX.looping; + audioSource.mute = false; + audioSource.minDistance = soundFX.falloffDistance.x; + audioSource.maxDistance = soundFX.falloffDistance.y; + audioSource.outputAudioMixerGroup = soundFX.GetMixerGroup( AudioManager.EmitterGroup ); + // set the play time so we can check when sounds are done + emitter.endPlayTime = Time.time + clip.length + delay; + // cache the default volume for fading + emitter.defaultVolume = audioSource.volume; + // sound priority + emitter.priority = soundFX.priority; + // reset this + emitter.onFinished = null; + // update the sound group limits + emitter.SetPlayingSoundGroup( soundFX.Group ); + // add to the playing list + if ( src == EmitterChannel.Any ) { + theAudioManager.playingEmitters.AddUnique( emitter ); + } + + // OSP properties + if ( osp != null ) { + osp.EnableSpatialization = soundFX.ospProps.enableSpatialization; + osp.EnableRfl = theAudioManager.enableSpatializedFastOverride || soundFX.ospProps.useFastOverride ? true : false; + osp.Gain = soundFX.ospProps.gain; + osp.UseInvSqr = soundFX.ospProps.enableInvSquare; + osp.Near = soundFX.ospProps.invSquareFalloff.x; + osp.Far = soundFX.ospProps.invSquareFalloff.y; + audioSource.spatialBlend = (soundFX.ospProps.enableSpatialization) ? 1.0f : 0.8f; + + // make sure to set the properties in the audio source before playing + osp.SetParameters(ref audioSource); + } + + audioSource.transform.position = position; + + if ( theAudioManager.verboseLogging ) { + Debug.Log( "[AudioManager] PlaySoundAt() channel = " + idx + " soundFX = " + soundFX.name + " volume = " + emitter.volume + " Delay = " + delay + " time = " + Time.time + "\n" ); + } + + // play the sound + if ( delay > 0f ) { + audioSource.PlayDelayed( delay ); + } else { + audioSource.Play(); + } + + return idx; + } + + /* + ----------------------- + PlayRandomSoundAt() + ----------------------- + */ + static public int PlayRandomSoundAt( Vector3 position, AudioClip[] clips, float volume, EmitterChannel src = EmitterChannel.Any, float delay = 0.0f, float pitch = 1.0f, bool loop = false ) { + if ( ( clips == null ) || ( clips.Length == 0 ) ) { + return -1; + } + int idx = Random.Range( 0, clips.Length ); + return PlaySoundAt( position, clips[idx], volume, src, delay, pitch, loop ); + } + + /* + ----------------------- + PlaySoundAt() + ----------------------- + */ + static public int PlaySoundAt( Vector3 position, AudioClip clip, float volume = 1.0f, EmitterChannel src = EmitterChannel.Any, float delay = 0.0f, float pitch = 1.0f, bool loop = false ) { + if ( !SoundEnabled ) { + return -1; + } + + if ( clip == null ) { + return -1; + } + + // check the distance from the local player and ignore sounds out of range + if ( staticListenerPosition != null ) { + if ( ( staticListenerPosition.position - position ).sqrMagnitude > theAudioManager.audioMaxFallOffDistanceSqr ) { + // no chance of being heard + return -1; + } + } + + int idx = FindFreeEmitter( src, 0 ); + if ( idx == -1 ) { + // no free emitters - should only happen on very low priority sounds + return -1; + } + SoundEmitter emitter = theAudioManager.soundEmitters[idx]; + + // make sure to detach the emitter from a previous parent + emitter.ResetParent( soundEmitterParent.transform ); + emitter.gameObject.SetActive( true ); + + // set up the sound emitter + AudioSource audioSource = emitter.audioSource; + ONSPAudioSource osp = emitter.osp; + + audioSource.enabled = true; + audioSource.volume = Mathf.Clamp01( theAudioManager.volumeSoundFX * volume ); + audioSource.pitch = pitch; + audioSource.spatialBlend = 0.8f; + audioSource.rolloffMode = AudioRolloffMode.Linear; + audioSource.SetCustomCurve( AudioSourceCurveType.ReverbZoneMix, defaultReverbZoneMix ); + audioSource.dopplerLevel = 0.0f; + audioSource.clip = clip; + audioSource.spread = 0.0f; + audioSource.loop = loop; + audioSource.mute = false; + audioSource.minDistance = theAudioManager.audioMinFallOffDistance; + audioSource.maxDistance = theAudioManager.audioMaxFallOffDistance; + audioSource.outputAudioMixerGroup = AudioManager.EmitterGroup; + // set the play time so we can check when sounds are done + emitter.endPlayTime = Time.time + clip.length + delay; + // cache the default volume for fading + emitter.defaultVolume = audioSource.volume; + // default priority + emitter.priority = 0; + // reset this + emitter.onFinished = null; + // update the sound group limits + emitter.SetPlayingSoundGroup( null ); + // add to the playing list + if ( src == EmitterChannel.Any ) { + theAudioManager.playingEmitters.AddUnique( emitter ); + } + + // disable spatialization (by default for regular AudioClips) + if ( osp != null ) { + osp.EnableSpatialization = false; + } + + audioSource.transform.position = position; + + if ( theAudioManager.verboseLogging ) { + Debug.Log( "[AudioManager] PlaySoundAt() channel = " + idx + " clip = " + clip.name + " volume = " + emitter.volume + " Delay = " + delay + " time = " + Time.time + "\n" ); + } + + // play the sound + if ( delay > 0f ) { + audioSource.PlayDelayed( delay ); + } else { + audioSource.Play(); + } + + return idx; + } + + /* + ----------------------- + SetOnFinished() + ----------------------- + */ + public static void SetOnFinished( int emitterIdx, System.Action onFinished ) { + if ( emitterIdx >= 0 && emitterIdx < theAudioManager.maxSoundEmitters ) { + theAudioManager.soundEmitters[emitterIdx].SetOnFinished( onFinished ); + } + } + + /* + ----------------------- + SetOnFinished() + ----------------------- + */ + public static void SetOnFinished( int emitterIdx, System.Action onFinished, object obj ) { + if ( emitterIdx >= 0 && emitterIdx < theAudioManager.maxSoundEmitters ) { + theAudioManager.soundEmitters[emitterIdx].SetOnFinished( onFinished, obj ); + } + } + + /* + ----------------------- + AttachSoundToParent() + ----------------------- + */ + public static void AttachSoundToParent( int idx, Transform parent ) { + if ( theAudioManager.verboseLogging ) { + string parentName = parent.name; + if ( parent.parent != null ) { + parentName = parent.parent.name + "/" + parentName; + } + Debug.Log( "[AudioManager] ATTACHING INDEX " + idx + " to " + parentName ); + } + theAudioManager.soundEmitters[idx].ParentTo( parent ); + } + + /* + ----------------------- + DetachSoundFromParent() + ----------------------- + */ + public static void DetachSoundFromParent( int idx ) { + if ( theAudioManager.verboseLogging ) { + Debug.Log( "[AudioManager] DETACHING INDEX " + idx ); + } + theAudioManager.soundEmitters[idx].DetachFromParent(); + } + + /* + ----------------------- + DetachSoundsFromParent() + ----------------------- + */ + public static void DetachSoundsFromParent( SoundEmitter[] emitters, bool stopSounds = true ) { + if ( emitters == null ) { + return; + } + foreach ( SoundEmitter emitter in emitters ) { + if ( emitter.defaultParent != null ) { + if ( stopSounds ) { + emitter.Stop(); + } + emitter.DetachFromParent(); + // make sure it's active + emitter.gameObject.SetActive( true ); + } else { + if ( stopSounds ) { + emitter.Stop(); + } + } + } + } + + /* + ----------------------- + SetEmitterMixerGroup() + ----------------------- + */ + public static void SetEmitterMixerGroup( int idx, AudioMixerGroup mixerGroup ) { + if ( ( theAudioManager != null ) && ( idx > -1 ) ) { + theAudioManager.soundEmitters[idx].SetAudioMixer( mixerGroup ); + } + } + + /* + ----------------------- + GetActiveSnapshot() + ----------------------- + */ + public static MixerSnapshot GetActiveSnapshot() { + return ( theAudioManager != null ) ? theAudioManager.currentSnapshot : null; + } + + /* + ----------------------- + SetCurrentSnapshot() + ----------------------- + */ + public static void SetCurrentSnapshot( MixerSnapshot mixerSnapshot ) { +#if UNITY_EDITOR + if ( mixerSnapshot == null || mixerSnapshot.snapshot == null ) { + Debug.LogError( "[AudioManager] ERROR setting empty mixer snapshot!" ); + } else { + Debug.Log( "[AudioManager] Setting audio mixer snapshot: " + ( ( mixerSnapshot != null && mixerSnapshot.snapshot != null ) ? mixerSnapshot.snapshot.name : "None" ) + " Time: " + Time.time ); + } +#endif + if ( theAudioManager != null ) { + if ( ( mixerSnapshot != null ) && ( mixerSnapshot.snapshot != null ) ) { + mixerSnapshot.snapshot.TransitionTo( mixerSnapshot.transitionTime ); + } else { + mixerSnapshot = null; + } + theAudioManager.currentSnapshot = mixerSnapshot; + } + } + + /* + ----------------------- + BlendWithCurrentSnapshot() + ----------------------- + */ + public static void BlendWithCurrentSnapshot( MixerSnapshot blendSnapshot, float weight, float blendTime = 0.0f ) { + if ( theAudioManager != null ) { + if ( theAudioManager.audioMixer == null ) { + Debug.LogWarning( "[AudioManager] can't call BlendWithCurrentSnapshot if the audio mixer is not set!" ); + return; + } + if ( blendTime == 0.0f ) { + blendTime = Time.deltaTime; + } + if ( ( theAudioManager.currentSnapshot != null ) && (theAudioManager.currentSnapshot.snapshot != null ) ) { + if ( ( blendSnapshot != null ) && ( blendSnapshot.snapshot != null ) ) { + weight = Mathf.Clamp01( weight ); + if ( weight == 0.0f ) { + // revert to the default snapshot + theAudioManager.currentSnapshot.snapshot.TransitionTo( blendTime ); + } else { + AudioMixerSnapshot[] snapshots = new AudioMixerSnapshot[] { theAudioManager.currentSnapshot.snapshot, blendSnapshot.snapshot }; + float[] weights = new float[] { 1.0f - weight, weight }; + theAudioManager.audioMixer.TransitionToSnapshots( snapshots, weights, blendTime ); + } + } + } + } + } + +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager_Sound.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager_Sound.cs.meta new file mode 100644 index 0000000..a39fd98 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/AudioManager_Sound.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 41cb0f893e9a44e83b09a66c55bd7856 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor.meta new file mode 100644 index 0000000..b0b346b --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor.meta @@ -0,0 +1,5 @@ +fileFormatVersion: 2 +guid: 02213405caaf04aeea7876974c06fa5a +folderAsset: yes +DefaultImporter: + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioImportPostProcessor.cs b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioImportPostProcessor.cs new file mode 100644 index 0000000..af520a2 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioImportPostProcessor.cs @@ -0,0 +1,46 @@ +using UnityEngine; +using UnityEditor; + +namespace OVR +{ + +/* +----------------------- +AudioImportPostProcessor() +----------------------- +*/ +public class AudioImportPostProcessor : AssetPostprocessor { + + static void OnPostprocessAllAssets( string[] importedAssets, string[] deletedAssets, string[] movedAssets, string[] movedFromAssetPaths ) { + AudioManager audioManager = AudioManager.Instance; + if ( audioManager != null ) { + // find the asset path to the loaded audio manager prefab +#if UNITY_2018_2_OR_NEWER + Object prefabObject = PrefabUtility.GetCorrespondingObjectFromSource(audioManager); +#else + Object prefabObject = PrefabUtility.GetPrefabParent( audioManager ); +#endif + if ( prefabObject != null ) { + string path = AssetDatabase.GetAssetPath( prefabObject ); + // check to see if the AudioManager prefab has been reimported. + // if so, rebuild everything + foreach ( string asset in importedAssets ) { + if ( asset.ToLower() == path.ToLower() ) { + // in the event the audio manager is selected, deselect it first before reloading + Debug.Log( "[AudioManager] AudioManager prefab reloaded: " + path ); + Selection.objects = new Object[0] { }; + // unfortunately even saving the audio manager prefab will trigger this action + //string msg = "The Audio Manager was reloaded. If you are going to be making modifications to the Audio Manager, "; + //msg += "please verify you have the latest version before proceeding. If in doubt, restart Unity before making modifications."; + //EditorUtility.DisplayDialog( "Audio Manager Prefab Reloaded", msg, "OK" ); + // do the actual reload + AudioManager.OnPrefabReimported(); + break; + } + } + } + } + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioImportPostProcessor.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioImportPostProcessor.cs.meta new file mode 100644 index 0000000..fe93f66 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioImportPostProcessor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 48902580b26e3554d992bad48087eee5 +timeCreated: 1471010515 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioManagerInspector.cs b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioManagerInspector.cs new file mode 100644 index 0000000..079c01b --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioManagerInspector.cs @@ -0,0 +1,631 @@ +using UnityEngine; +using UnityEditor; +using System.Collections.Generic; + +namespace OVR +{ + +/* +----------------------- + + AudioManagerInspector + +----------------------- +*/ +[CustomEditor(typeof(AudioManager))] +public class AudioManagerInspector : Editor { + + private AudioManager audioManager = null; + private string dragDropIdentifier = "MoveSoundFX"; + private GUIStyle customDividerStyle = null; + + /* + ----------------------- + OnInspectorGUI() + ----------------------- + */ + public override void OnInspectorGUI() { + + audioManager = target as AudioManager; + + Event e = Event.current; + + // draw the default properties + DrawDefaultProperties(); + + // draw the categories section + DrawCategories( e ); + + serializedObject.Update(); + + // draw the sound effects for the selected category + DrawSoundEffects( e ); + + serializedObject.ApplyModifiedProperties(); + + CreateStyles(); + } + + /* + ----------------------- + MarkDirty() + ----------------------- + */ + void MarkDirty() { + serializedObject.SetIsDifferentCacheDirty(); + EditorUtility.SetDirty( audioManager ); + } + + static private int selectedGroup = 0; + private int nextGroup = -1; + private int editGroup = -1; + private FastList soundGroups = new FastList(); + private FastList groups = new FastList(); + private Rect dropArea = new Rect(); + private bool addSound = false; + private int deleteSoundIdx = -1; + private int dupeSoundIdx = -1; + private bool sortSounds = false; + private bool moveQueued = false; + private int origGroup = -1; + private int origIndex = -1; + private int moveToGroup = -1; + + /* + ----------------------- + DrawDefaultProperties() + ----------------------- + */ + void DrawDefaultProperties() { + + BeginContents(); + if ( DrawHeader( "Default Properties", true ) ) { + EditorGUILayout.BeginVertical( GUI.skin.box ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "makePersistent" ), new GUIContent( "Don't Destroy on Load" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "enableSpatializedAudio" ), new GUIContent( "Enable Spatialized Audio" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "enableSpatializedFastOverride" ), new GUIContent( "Force Disable Reflections" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "audioMixer" ), new GUIContent( "Master Audio Mixer" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "defaultMixerGroup" ), new GUIContent( "Pooled Emitter Mixer Group" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "reservedMixerGroup" ), new GUIContent( "Reserved Emitter Mixer Group" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "voiceChatMixerGroup" ), new GUIContent( "Voice Chat Mixer Group" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "verboseLogging" ), new GUIContent( "Verbose Logging" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "maxSoundEmitters" ), new GUIContent( "Max Sound Emitters" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "volumeSoundFX" ), new GUIContent( "Default Volume" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "soundFxFadeSecs" ), new GUIContent( "Sound FX Fade Secs" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "audioMinFallOffDistance" ), new GUIContent( "Minimum Falloff Distance" ) ); + EditorGUILayout.PropertyField( serializedObject.FindProperty( "audioMaxFallOffDistance" ), new GUIContent( "Maximum Falloff Distance" ) ); + EditorGUILayout.EndVertical(); + serializedObject.ApplyModifiedProperties(); + } + EndContents(); + } + + /* + ----------------------- + DrawSoundGroupProperties() + ----------------------- + */ + void DrawSoundGroupProperties() { + if ( selectedGroup == -1 ) { + return; + } + + SerializedProperty soundGroupsArray = serializedObject.FindProperty( "soundGroupings" ); + if ( selectedGroup >= soundGroupsArray.arraySize ) { + return; + } + SerializedProperty soundGroup = soundGroupsArray.GetArrayElementAtIndex( selectedGroup ); + string soundGroupName = soundGroup.FindPropertyRelative( "name" ).stringValue; + if ( DrawHeader( string.Format( "{0} Properties", soundGroupName ), true ) ) { + EditorGUILayout.BeginVertical( GUI.skin.box ); + EditorGUILayout.PropertyField( soundGroup.FindPropertyRelative( "mixerGroup" ), new GUIContent( "Override Mixer Group", "Leave empty to use the Audio Manager's default mixer group" ) ); + if ( !Application.isPlaying ) { + EditorGUILayout.PropertyField( soundGroup.FindPropertyRelative( "maxPlayingSounds" ), new GUIContent( "Max Playing Sounds Limit", "Max playing sounds for this sound group, 0 = no limit" ) ); + } else { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.PropertyField( soundGroup.FindPropertyRelative( "maxPlayingSounds" ), new GUIContent( "Max Playing Sounds Limit", "Max playing sounds for this sound group, 0 = no limit" ) ); + // cast to the actual object + int playingSounds = soundGroup.FindPropertyRelative( "playingSoundCount" ).intValue; + EditorGUILayout.LabelField( string.Format( "Playing: {0}", playingSounds ), GUILayout.Width( 80.0f ) ); + EditorGUILayout.EndHorizontal(); + } + EditorGUILayout.PropertyField( soundGroup.FindPropertyRelative( "preloadAudio" ), new GUIContent( "Preload Audio Clips", "Default = No special preloading, Preload = Audio clips are set to 'Preload', Manual Preload = Audio clips are set to not 'Preload'" ) ); + EditorGUILayout.PropertyField( soundGroup.FindPropertyRelative( "volumeOverride" ), new GUIContent( "Volume Override", "All sounds played in this group will have volume scaled by this amount" ) ); + if ( soundGroup.FindPropertyRelative( "volumeOverride" ).floatValue == 0.0f ) { + EditorGUILayout.HelpBox( "With a volumeOverride of 0.0, these sounds will not play!", MessageType.Warning ); + } + EditorGUILayout.EndVertical(); + serializedObject.ApplyModifiedProperties(); + } + } + + /* + ----------------------- + DrawCategories() + ----------------------- + */ + void DrawCategories( Event e ) { + + // do any housework before we start drawing + if ( moveQueued ) { + // make a temp copy + List origSoundList = new List( audioManager.soundGroupings[origGroup].soundList ); + SoundFX temp = origSoundList[origIndex]; + List moveToSoundList = new List( audioManager.soundGroupings[moveToGroup].soundList ); + // add it to the move to group + moveToSoundList.Add( temp ); + audioManager.soundGroupings[moveToGroup].soundList = moveToSoundList.ToArray(); + // and finally, remove it from the original group + origSoundList.RemoveAt( origIndex ); + audioManager.soundGroupings[origGroup].soundList = origSoundList.ToArray(); + Debug.Log( "> Moved '" + temp.name + "' from " + "'" + audioManager.soundGroupings[origGroup].name + "' to '" + audioManager.soundGroupings[moveToGroup].name ); + MarkDirty(); + moveQueued = false; + } + // switch to the next group + if ( nextGroup > -1 ) { + selectedGroup = nextGroup; + nextGroup = -1; + } + // add a sound + if ( addSound ) { + List soundList = new List( audioManager.soundGroupings[selectedGroup].soundList ); + SoundFX soundFX = new SoundFX(); + soundFX.name = audioManager.soundGroupings[selectedGroup].name.ToLower() + "_new_unnamed_sound_fx"; + soundList.Add( soundFX ); + audioManager.soundGroupings[selectedGroup].soundList = soundList.ToArray(); + MarkDirty(); + addSound = false; + } + // sort the sounds + if ( sortSounds ) { + List soundList = new List( audioManager.soundGroupings[selectedGroup].soundList ); + soundList.Sort( delegate ( SoundFX sfx1, SoundFX sfx2 ) { return string.Compare( sfx1.name, sfx2.name ); } ); + audioManager.soundGroupings[selectedGroup].soundList = soundList.ToArray(); + MarkDirty(); + sortSounds = false; + } + // delete a sound + if ( deleteSoundIdx > -1 ) { + List soundList = new List( audioManager.soundGroupings[selectedGroup].soundList ); + soundList.RemoveAt( deleteSoundIdx ); + audioManager.soundGroupings[selectedGroup].soundList = soundList.ToArray(); + MarkDirty(); + deleteSoundIdx = -1; + } + // duplicate a sound + if ( dupeSoundIdx > -1 ) { + List soundList = new List( audioManager.soundGroupings[selectedGroup].soundList ); + SoundFX origSoundFX = soundList[dupeSoundIdx]; + // clone this soundFX + string json = JsonUtility.ToJson( origSoundFX ); + SoundFX soundFX = JsonUtility.FromJson( json ); + soundFX.name += "_duplicated"; + soundList.Insert( dupeSoundIdx + 1, soundFX ); + audioManager.soundGroupings[selectedGroup].soundList = soundList.ToArray(); + MarkDirty(); + dupeSoundIdx = -1; + } + + if ( e.type == EventType.Repaint ) { + groups.Clear(); + } + + GUILayout.Space( 6f ); + + Color defaultColor = GUI.contentColor; + BeginContents(); + + if ( DrawHeader( "Sound FX Groups", true ) ) { + EditorGUILayout.BeginVertical( GUI.skin.box ); + soundGroups.Clear(); + for ( int i = 0; i < audioManager.soundGroupings.Length; i++ ) { + soundGroups.Add( audioManager.soundGroupings[i] ); + } + for ( int i = 0; i < soundGroups.size; i++ ) { + EditorGUILayout.BeginHorizontal(); + { + if ( i == selectedGroup ) { + GUI.contentColor = ( i == editGroup ) ? Color.white : Color.yellow; + } else { + GUI.contentColor = defaultColor; + } + if ( ( e.type == EventType.KeyDown ) && ( ( e.keyCode == KeyCode.Return ) || ( e.keyCode == KeyCode.KeypadEnter ) ) ) { + // toggle editing + if ( editGroup >= 0 ) { + editGroup = -1; + } + Event.current.Use(); + } + if ( i == editGroup ) { + soundGroups[i].name = GUILayout.TextField( soundGroups[i].name, GUILayout.MinWidth( Screen.width - 80f ) ); + } else { + GUILayout.Label( soundGroups[i].name, ( i == selectedGroup ) ? EditorStyles.whiteLabel : EditorStyles.label, GUILayout.ExpandWidth( true ) ); + } + GUILayout.FlexibleSpace(); + if ( GUILayout.Button( GUIContent.none, "OL Minus", GUILayout.Width(17f) ) ) { // minus button + if ( EditorUtility.DisplayDialog( "Delete '" + soundGroups[i].name + "'", "Are you sure you want to delete the selected sound group?", "Continue", "Cancel" ) ) { + soundGroups.RemoveAt( i ); + MarkDirty(); + } + } + } + EditorGUILayout.EndHorizontal(); + // build a list of items + Rect lastRect = GUILayoutUtility.GetLastRect(); + if ( e.type == EventType.Repaint ) { + groups.Add ( new ItemRect( i, lastRect, null ) ); + } + if ( ( e.type == EventType.MouseDown ) && lastRect.Contains( e.mousePosition ) ) { + if ( ( i != selectedGroup ) || ( e.clickCount == 2 ) ) { + nextGroup = i; + if ( e.clickCount == 2 ) { + editGroup = i; + } else if ( editGroup != nextGroup ) { + editGroup = -1; + } + Repaint(); + } + } + } + // add the final plus button + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if ( GUILayout.Button( GUIContent.none, "OL Plus", GUILayout.Width(17f) ) ) { // plus button + soundGroups.Add( new SoundGroup( "unnamed sound group" ) ); + selectedGroup = editGroup = soundGroups.size - 1; + MarkDirty(); + } + EditorGUILayout.EndHorizontal(); + EditorGUILayout.EndVertical(); + + // reset the color + GUI.contentColor = defaultColor; + + // the sort and import buttons + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if ( GUILayout.Button( "Sort", GUILayout.Width( 70f ) ) ) { + soundGroups.Sort( delegate( SoundGroup sg1, SoundGroup sg2 ) { return string.Compare( sg1.name, sg2.name ); } ); + MarkDirty(); + } + EditorGUILayout.EndHorizontal(); + + // draw a rect around the selected item + if ( ( selectedGroup >= 0 ) && ( selectedGroup < groups.size ) ) { + EditorGUI.DrawRect( groups[selectedGroup].rect, new Color( 1f, 1f, 1f, 0.06f ) ); + } + + // finally move the sound groups back into the audio manager + if ( soundGroups.size > 0 ) { + audioManager.soundGroupings = soundGroups.ToArray(); + } + + // calculate the drop area rect + if ( ( e.type == EventType.Repaint ) && ( groups.size > 0 ) ) { + dropArea.x = groups[0].rect.x; + dropArea.y = groups[0].rect.y; + dropArea.width = groups[0].rect.width; + dropArea.height = ( groups[groups.size-1].rect.y - groups[0].rect.y ) + groups[groups.size-1].rect.height; + } + } + // draw the sound group properties now + DrawSoundGroupProperties(); + + EndContents(); + + EditorGUILayout.HelpBox("Create and delete sound groups by clicking + and - respectively. Double click to rename sound groups. Drag and drop sounds from below to the groups above to move them.", MessageType.Info); + + } + + public class CustomDragData{ + public int originalGroupIndex; + public int originalIndex; + public SerializedProperty originalProperty; + } + + public class ItemRect { + public ItemRect( int index, Rect rect, SerializedProperty prop ) { + this.index = index; + this.rect = rect; + this.prop = prop; + } + public int index; + public Rect rect; + public SerializedProperty prop; + } + + private FastList items = new FastList(); + + /* + ----------------------- + CreateStyles() + ----------------------- + */ + void CreateStyles() { + if ( customDividerStyle == null ) { + customDividerStyle = new GUIStyle( EditorStyles.label ); + customDividerStyle.normal.background = MakeTex( 4, 4, new Color( 0.5f, 0.5f, 0.5f, 0.25f ) ); + customDividerStyle.margin.right -= 16; + } + } + + /* + ----------------------- + MakeTex() + ----------------------- + */ + private Texture2D MakeTex( int width, int height, Color col ) { + Color[] pix = new Color[width*height]; + + for ( int i = 0; i < pix.Length; i++ ) + pix[i] = col; + + Texture2D result = new Texture2D(width, height); + result.SetPixels( pix ); + result.Apply(); + + return result; + } + + /* + ----------------------- + DrawSoundEffects() + ----------------------- + */ + void DrawSoundEffects( Event e ) { + if ( ( selectedGroup < 0 ) || ( audioManager.soundGroupings.Length == 0 ) || ( selectedGroup >= audioManager.soundGroupings.Length ) ) { + return; + } + + if ( e.type == EventType.Repaint ) { + items.Clear(); + } else { + CheckStartDrag( e ); + } + + BeginContents(); + if ( DrawHeader( "Sound Effects", true ) ) { + GUILayout.Space(3f); + GUILayout.BeginVertical( GUI.skin.box ); + + SerializedProperty soundGroupsArray = serializedObject.FindProperty( "soundGroupings" ); + SerializedProperty soundGroup = soundGroupsArray.GetArrayElementAtIndex( selectedGroup ); + SerializedProperty soundList = soundGroup.FindPropertyRelative( "soundList" ); + + CreateStyles(); + + Rect prevRect = new Rect(); + if ( soundList.arraySize > 0 ) { + // show all the sounds + for ( int i = 0; i < soundList.arraySize; i++ ) { + EditorGUI.indentLevel = 1; + SerializedProperty soundFX = soundList.GetArrayElementAtIndex( i ); + SerializedProperty visToggle = soundFX.FindPropertyRelative( "visibilityToggle" ); + EditorGUILayout.BeginHorizontal( customDividerStyle ); + { + string soundFXName = soundFX.FindPropertyRelative( "name" ).stringValue; + // save the visibility state + visToggle.boolValue = EditorGUILayout.Foldout( visToggle.boolValue, soundFXName ); + + // play button + if ( GUILayout.Button( "\u25BA", GUILayout.Width( 17f ), GUILayout.Height( 16f ) ) ) { + if ( AudioManager.IsSoundPlaying( soundFXName ) ) { + AudioManager.StopSound( soundFXName ); + } else { + AudioManager.PlaySound( soundFXName ); + } + } + } + EditorGUILayout.EndHorizontal(); + if ( visToggle.boolValue ) { + EditorGUILayout.PropertyField( soundFX, true ); + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if ( GUILayout.Button( "Delete FX", GUILayout.Width( Screen.width / 3.0f ) ) ) { + if ( EditorUtility.DisplayDialog( "Delete " + soundFX.displayName, "Are you sure?", "Yes", "No!" ) ) { + deleteSoundIdx = i; + } + } + if ( GUILayout.Button( "Duplicate FX", GUILayout.Width( Screen.width / 3.0f ) ) ) { + dupeSoundIdx = i; + } + GUILayout.FlexibleSpace(); + EditorGUILayout.EndHorizontal(); + GUILayout.Space( 10.0f ); + } + if ( e.type == EventType.Repaint ) { + // GetLastRect() is now returning the last rect drawn in the property drawer, + // not the rect used for the entire SoundFX + Rect curRect = prevRect; + curRect.y = prevRect.y + EditorGUIUtility.singleLineHeight; + Rect lastRect = GUILayoutUtility.GetLastRect(); + curRect.height = ( lastRect.y + lastRect.height ) - curRect.y; + curRect.width = Screen.width; + items.Add( new ItemRect( i, curRect, soundFX ) ); + } + prevRect = GUILayoutUtility.GetLastRect(); + } + } else { + EditorGUILayout.LabelField( " " ); + } + GUILayout.EndVertical(); + GUILayout.Space(3f); + EditorGUILayout.BeginHorizontal(); + GUILayout.FlexibleSpace(); + if ( GUILayout.Button( "Add FX", GUILayout.Width( 70f ) ) ) { + //soundList.InsertArrayElementAtIndex( soundList.arraySize ); + //MarkDirty(); + addSound = true; + } + if ( GUILayout.Button( "Sort", GUILayout.Width( 70f ) ) ) { + sortSounds = true; + } + EditorGUILayout.EndHorizontal(); + + } + EndContents(); + + UpdateDrag( e ); + + } + + /* + ----------------------- + CheckStartDrag() + ----------------------- + */ + void CheckStartDrag( Event e ) { + + if ( ( e.type == EventType.MouseDrag ) && ( e.button == 0 ) ) { + for ( int i = 0; i < items.size; i++ ) { + if ( items[i].rect.Contains( e.mousePosition ) ) { + DragAndDrop.PrepareStartDrag();// reset data + + CustomDragData dragData = new CustomDragData(); + dragData.originalGroupIndex = selectedGroup; + dragData.originalIndex = items[i].index; + dragData.originalProperty = items[i].prop; + + DragAndDrop.SetGenericData( dragDropIdentifier, dragData ); + + DragAndDrop.objectReferences = new Object[0]; + + DragAndDrop.StartDrag( dragData.originalProperty.FindPropertyRelative( "name" ).stringValue ); + e.Use(); + } + } + } + } + + /* + ----------------------- + FindGroupIndex() + ----------------------- + */ + int FindGroupIndex( Event e ) { + for ( int i = 0; i < groups.size; i++ ) { + if ( groups[i].rect.Contains( e.mousePosition ) ) { + return i; + } + } + return -1; + } + + /* + ----------------------- + UpdateDrag() + ----------------------- + */ + void UpdateDrag( Event e ) { + + CustomDragData dragData = DragAndDrop.GetGenericData( dragDropIdentifier ) as CustomDragData; + if ( dragData == null ) { + return; + } + + int groupIndex = FindGroupIndex( e ); + + switch ( e.type ) { + case EventType.DragUpdated: + if ( ( groupIndex >= 0 ) && ( groupIndex != selectedGroup ) ) { + DragAndDrop.visualMode = DragAndDropVisualMode.Move; + } else { + DragAndDrop.visualMode = DragAndDropVisualMode.Rejected; + } + e.Use(); + break; + case EventType.Repaint: + if ( ( DragAndDrop.visualMode == DragAndDropVisualMode.None ) || + ( DragAndDrop.visualMode == DragAndDropVisualMode.Rejected ) ) { + break; + } + if ( groupIndex >= 0 && groupIndex < groups.size ) { + EditorGUI.DrawRect( groups[groupIndex].rect, new Color( 0f, 1f, 0f, 0.1f ) ); + } + break; + case EventType.DragPerform: + DragAndDrop.AcceptDrag(); + // queue the sound FX move + QueueSoundFXMove( dragData.originalGroupIndex, dragData.originalIndex, groupIndex ); + e.Use(); + break; + case EventType.MouseUp: + // in case MouseDrag never occurred: + DragAndDrop.PrepareStartDrag(); + break; + } + } + + /* + ----------------------- + QueueSoundFXMove() + ----------------------- + */ + void QueueSoundFXMove( int origGroupIndex, int origSoundIndex, int newGroupIndex ) { + moveQueued = true; + origGroup = origGroupIndex; + origIndex = origSoundIndex; + moveToGroup = newGroupIndex; + } + + /* + ----------------------- + DrawHeader() + ----------------------- + */ + static public bool DrawHeader (string text) { return DrawHeader(text, text, false); } + static public bool DrawHeader (string text, string key) { return DrawHeader(text, key, false); } + static public bool DrawHeader (string text, bool forceOn) { return DrawHeader(text, text, forceOn); } + static public bool DrawHeader( string text, string key, bool forceOn ) { + bool state = EditorPrefs.GetBool(key, true); + + GUILayout.Space(3f); + if (!forceOn && !state) GUI.backgroundColor = new Color(0.8f, 0.8f, 0.8f); + GUILayout.BeginHorizontal(); + GUILayout.Space(3f); + + GUI.changed = false; + text = "" + text + ""; + if (state) text = "\u25BC " + text; + else text = "\u25B6 " + text; + if (!GUILayout.Toggle(true, text, "dragtab", GUILayout.MinWidth(20f))) state = !state; + if (GUI.changed) EditorPrefs.SetBool(key, state); + + GUILayout.Space(2f); + GUILayout.EndHorizontal(); + GUI.backgroundColor = Color.white; + if (!forceOn && !state) GUILayout.Space(3f); + return state; + } + + /* + ----------------------- + BeginContents() + ----------------------- + */ + static public void BeginContents() { + GUILayout.BeginHorizontal(); + GUILayout.Space(4f); + EditorGUILayout.BeginHorizontal(GUILayout.MinHeight(10f)); + GUILayout.BeginVertical(); + GUILayout.Space(2f); + } + + /* + ----------------------- + EndContents() + ----------------------- + */ + static public void EndContents() { + GUILayout.Space(3f); + GUILayout.EndVertical(); + EditorGUILayout.EndHorizontal(); + GUILayout.Space(3f); + GUILayout.EndHorizontal(); + GUILayout.Space(3f); + } + +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioManagerInspector.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioManagerInspector.cs.meta new file mode 100644 index 0000000..df38b5f --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/AudioManagerInspector.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9f04a80514947486d9793cab0005447f +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MinMaxPropertyDrawer.cs b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MinMaxPropertyDrawer.cs new file mode 100644 index 0000000..9aa86a2 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MinMaxPropertyDrawer.cs @@ -0,0 +1,70 @@ +using UnityEditor; +using UnityEngine; + +namespace OVR +{ + +/* +----------------------- + + MinMaxPropertyDrawer + +----------------------- +*/ +[CustomPropertyDrawer (typeof (MinMaxAttribute))] +public class MinMaxPropertyDrawer : PropertyDrawer { + + // Provide easy access to the MinMaxAttribute for reading information from it. + MinMaxAttribute minMax { get { return ((MinMaxAttribute)attribute); } } + + /* + ----------------------- + GetPropertyHeight() + ----------------------- + */ + public override float GetPropertyHeight( SerializedProperty prop, GUIContent label ) { + return base.GetPropertyHeight( prop, label ) * 2f; + } + + /* + ----------------------- + OnGUI() + ----------------------- + */ + public override void OnGUI( Rect position, SerializedProperty property, GUIContent label ) { + Rect sliderPosition = EditorGUI.PrefixLabel( position, label ); + SerializedProperty min = property.FindPropertyRelative( "x" ); + SerializedProperty max = property.FindPropertyRelative( "y" ); + + // draw the range and the reset button first so that the slider doesn't grab all the input + Rect rangePosition = sliderPosition; + rangePosition.y += rangePosition.height * 0.5f; + rangePosition.height *= 0.5f; + Rect contentPosition = rangePosition; + EditorGUI.indentLevel = 0; + EditorGUIUtility.labelWidth = 30f; + contentPosition.width *= 0.3f; + EditorGUI.PropertyField(contentPosition, min, new GUIContent( "Min" ) ); + contentPosition.x += contentPosition.width + 20f; + EditorGUI.PropertyField( contentPosition, max, new GUIContent( "Max" ) ); + contentPosition.x += contentPosition.width + 20f; + contentPosition.width = 50.0f; + if ( GUI.Button( contentPosition, "Reset" ) ) { + min.floatValue = minMax.minDefaultVal; + max.floatValue = minMax.maxDefaultVal; + } + float minValue = min.floatValue; + float maxValue = max.floatValue; +#if UNITY_2017_1_OR_NEWER + EditorGUI.MinMaxSlider( sliderPosition, GUIContent.none, ref minValue, ref maxValue, minMax.min, minMax.max ); +#else + EditorGUI.MinMaxSlider( GUIContent.none, sliderPosition, ref minValue, ref maxValue, minMax.min, minMax.max ); +#endif + // round to readable values + min.floatValue = Mathf.Round( minValue / 0.01f ) * 0.01f; + max.floatValue = Mathf.Round( maxValue / 0.01f ) * 0.01f; + } + +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MinMaxPropertyDrawer.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MinMaxPropertyDrawer.cs.meta new file mode 100644 index 0000000..be80369 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MinMaxPropertyDrawer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 225aed143a64c4a6a93f3a07656ac5cd +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MixerSnapshotPropertyDrawer.cs b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MixerSnapshotPropertyDrawer.cs new file mode 100644 index 0000000..4b45e27 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MixerSnapshotPropertyDrawer.cs @@ -0,0 +1,50 @@ +using UnityEditor; +using UnityEngine; + +namespace OVR +{ + +/* +----------------------- + + MixerSnapshotPropertyDrawer + +----------------------- +*/ +[CustomPropertyDrawer( typeof( MixerSnapshot ) )] +public class MixerSnapshotPropertyDrawer : PropertyDrawer { + + // Draw the property inside the given rect + public override void OnGUI( Rect position, SerializedProperty property, GUIContent label ) { + // Using BeginProperty / EndProperty on the parent property means that + // prefab override logic works on the entire property. + EditorGUI.BeginProperty( position, label, property ); + + // Draw label + position = EditorGUI.PrefixLabel( position, GUIUtility.GetControlID( FocusType.Passive ), label ); + + // Don't make child fields be indented + var indent = EditorGUI.indentLevel; + EditorGUI.indentLevel = 0; + EditorGUIUtility.labelWidth = 65; + + float width = ( position.width - 15.0f ) / 2.0f; + + // Calculate rects + var srcRect = new Rect( position.x, position.y, width + 20, position.height ); position.x += width + 25.0f; + var destRect = new Rect( position.x, position.y, width - 60, position.height ); position.x += width - 60.0f; + var secsRect = new Rect( position.x, position.y, 40, position.height ); + + // Draw fields - pass GUIContent.none to each so they are drawn without labels + EditorGUI.PropertyField( srcRect, property.FindPropertyRelative( "snapshot" ), GUIContent.none ); + EditorGUI.PropertyField( destRect, property.FindPropertyRelative( "transitionTime" ), new GUIContent( "Transition" ) ); + EditorGUI.LabelField( secsRect, new GUIContent( "sec(s)" ) ); + + // Set indent back to what it was + EditorGUI.indentLevel = indent; + + EditorGUI.EndProperty(); + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MixerSnapshotPropertyDrawer.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MixerSnapshotPropertyDrawer.cs.meta new file mode 100644 index 0000000..9ab00d8 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/MixerSnapshotPropertyDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 82a91f30f2305c14dbfd2cc3c289dc59 +timeCreated: 1472247018 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/OSPPropsPropertyDrawer.cs b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/OSPPropsPropertyDrawer.cs new file mode 100644 index 0000000..3d2cd58 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/OSPPropsPropertyDrawer.cs @@ -0,0 +1,66 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; + +namespace OVR +{ + +/* +----------------------- + +OSPPropsPropertyDrawer + +----------------------- +*/ +[CustomPropertyDrawer(typeof(OSPProps))] +public class OSPPropsPropertyDrawer : PropertyDrawer { + + static float lineHeight = EditorGUIUtility.singleLineHeight + 2.0f; + static float indent = 32.0f; + // TODO - some day just enumerate these + static string[] props = new string[] { "useFastOverride", "gain", "enableInvSquare", "volumetric" , "invSquareFalloff" }; + static string[] names = new string[] { "Reflections Enabled", "Gain", "Enable Oculus Atten.", "Volumetric", "Range" }; + static int[] lines = new int[] { 1, 1, 1, 1, 2, 2 }; + /* + ----------------------- + OnGUI() + ----------------------- + */ + public override void OnGUI( Rect position, SerializedProperty prop, GUIContent label ) { + SerializedProperty playSpatializedProp = prop.FindPropertyRelative("enableSpatialization"); + position.height = lineHeight; + EditorGUI.PropertyField( position, playSpatializedProp ); + if ( playSpatializedProp.boolValue ) { + position.y += lineHeight + 4.0f; + Rect posLine = position; + posLine.x += indent; + posLine.width -= indent; + posLine.height = 1f; + GUI.Box( posLine, "" ); + position.y -= 10.0f; + for ( int i = 0; i < props.Length; i++ ) { + position.y += lineHeight; + position.height = ( lineHeight * lines[i] ); + SerializedProperty sibling = prop.FindPropertyRelative( props[i] ); + EditorGUI.PropertyField( position, sibling, new GUIContent( names[i] ) ); + } + } + } + + /* + ----------------------- + GetPropertyHeight() + ----------------------- + */ + public override float GetPropertyHeight (SerializedProperty prop, GUIContent label) { + SerializedProperty playSpatializedProp = prop.FindPropertyRelative("enableSpatialization"); + if ( !playSpatializedProp.boolValue ) { + return base.GetPropertyHeight( prop, label ); + } else { + return base.GetPropertyHeight( prop, label ) + ( lineHeight * ( props.Length + 1 ) ) + 16.0f; + } + } + +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/OSPPropsPropertyDrawer.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/OSPPropsPropertyDrawer.cs.meta new file mode 100644 index 0000000..ef2a739 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/OSPPropsPropertyDrawer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9fc79251b168140d68851f1e8c283514 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXPropertyDrawer.cs b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXPropertyDrawer.cs new file mode 100644 index 0000000..47283f4 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXPropertyDrawer.cs @@ -0,0 +1,67 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; + +namespace OVR +{ + +/* +----------------------- + +SoundFXPropertyDrawer + +----------------------- +*/ +[CustomPropertyDrawer(typeof(SoundFX))] +public class SoundFXPropertyDrawer : PropertyDrawer { + + static float lineHeight = EditorGUIUtility.singleLineHeight + 2.0f; + + static string[] props = new string[] { "name", "playback", "volume", "pitchVariance", "falloffDistance", "falloffCurve", "reverbZoneMix", "spread", "pctChanceToPlay", "priority", "delay", "looping", "ospProps", "soundClips" }; + + /* + ----------------------- + OnGUI() + ----------------------- + */ + public override void OnGUI( Rect position, SerializedProperty prop, GUIContent label ) { + + EditorGUILayout.BeginVertical(); + for ( int i = 0; i < props.Length; i++ ) { + EditorGUI.indentLevel = 2; + SerializedProperty property = prop.FindPropertyRelative( props[i] ); + if ( props[i] == "reverbZoneMix" ) { + EditorGUILayout.BeginHorizontal(); + SerializedProperty reverbCurve = prop.FindPropertyRelative( "reverbZoneMix" ); + EditorGUILayout.PropertyField( reverbCurve, true, GUILayout.Width( Screen.width - 130.0f ) ); + if ( GUILayout.Button( "Reset", GUILayout.Width( 50.0f ) ) ) { + reverbCurve.animationCurveValue = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } ); + } + EditorGUILayout.EndHorizontal(); + } else { + EditorGUILayout.PropertyField( property, true, GUILayout.Width( Screen.width - 80.0f ) ); + position.y += lineHeight + 4.0f; + if ( props[i] == "falloffCurve" ) { + if ( property.enumValueIndex == (int)AudioRolloffMode.Custom ) { + EditorGUILayout.PropertyField( prop.FindPropertyRelative( "volumeFalloffCurve" ), true, GUILayout.Width( Screen.width - 80.0f ) ); + position.y += lineHeight + 4.0f; + } + } + } + } + EditorGUILayout.EndVertical(); + GUILayout.Space( 5.0f ); + } + + /* + ----------------------- + GetPropertyHeight() + ----------------------- + */ + public override float GetPropertyHeight (SerializedProperty prop, GUIContent label) { + return base.GetPropertyHeight( prop, label ); + } + +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXPropertyDrawer.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXPropertyDrawer.cs.meta new file mode 100644 index 0000000..995e0c8 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXPropertyDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e791ce392b6937f47b1f7c90c6b402db +timeCreated: 1468857307 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXRefPropertyDrawer.cs b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXRefPropertyDrawer.cs new file mode 100644 index 0000000..5446a3a --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXRefPropertyDrawer.cs @@ -0,0 +1,62 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; + +namespace OVR +{ + +/* +----------------------- + +SoundFXRefPropertyDrawer + +----------------------- +*/ +[CustomPropertyDrawer(typeof(SoundFXRef))] +public class SoundFXRefPropertyDrawer : PropertyDrawer { + + static private GUIStyle disabledStyle = null; + + /* + ----------------------- + OnGUI() + ----------------------- + */ + public override void OnGUI( Rect position, SerializedProperty prop, GUIContent label ) { + int idx = 0; + Rect buttonPosition = position; + buttonPosition.x = position.x + position.width - 40f; + buttonPosition.width = 20f; + position.width = buttonPosition.x - position.x - 2f; + SerializedProperty nameProp = prop.FindPropertyRelative( "soundFXName" ); + if ( AudioManager.GetGameObject() == null ) { + if ( disabledStyle == null ) { + disabledStyle = new GUIStyle(); + disabledStyle.normal.textColor = Color.gray; + } + EditorGUI.LabelField(position, label.text, nameProp.stringValue, disabledStyle ); + } + else { + string[] soundFXNames = AudioManager.GetSoundFXNames( nameProp.stringValue, out idx ); + + idx = EditorGUI.Popup( position, label.text, idx, soundFXNames ); + nameProp.stringValue = AudioManager.NameMinusGroup( soundFXNames[idx] ); + // play button + if ( GUI.Button( buttonPosition, "\u25BA" ) ) { + if ( AudioManager.IsSoundPlaying( nameProp.stringValue ) ) { + AudioManager.StopSound( nameProp.stringValue ); + } else { + AudioManager.PlaySound( nameProp.stringValue ); + } + } + buttonPosition.x += 22.0f; + // select audio manager + if ( GUI.Button( buttonPosition, "\u2630" ) ) { + Selection.activeGameObject = AudioManager.GetGameObject(); + } + + } + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXRefPropertyDrawer.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXRefPropertyDrawer.cs.meta new file mode 100644 index 0000000..07b587f --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/Editor/SoundFXRefPropertyDrawer.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6204bcaba636340b48858c9f10ab9016 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/MinMaxAttribute.cs b/Assets/Oculus/AudioManager/Scripts/Audio/MinMaxAttribute.cs new file mode 100644 index 0000000..d56a825 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/MinMaxAttribute.cs @@ -0,0 +1,26 @@ +using UnityEngine; + +namespace OVR +{ + +/* +----------------------- + + MinMaxAttribute + +----------------------- +*/ +public class MinMaxAttribute : PropertyAttribute { + public float minDefaultVal = 1.0f; + public float maxDefaultVal = 1.0f; + public float min = 0.0f; + public float max = 1.0f; + public MinMaxAttribute( float minDefaultVal, float maxDefaultVal, float min, float max ) { + this.minDefaultVal = minDefaultVal; + this.maxDefaultVal = maxDefaultVal; + this.min = min; + this.max = max; + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/MinMaxAttribute.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/MinMaxAttribute.cs.meta new file mode 100644 index 0000000..a3a2ec1 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/MinMaxAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 15126f023faf44286a08bdb5bdbdb6e7 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/SoundEmitter.cs b/Assets/Oculus/AudioManager/Scripts/Audio/SoundEmitter.cs new file mode 100644 index 0000000..328e418 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/SoundEmitter.cs @@ -0,0 +1,433 @@ +using UnityEngine; +using UnityEngine.Audio; +using System.Collections; + +namespace OVR +{ + +/* +----------------------- + + SoundEmitter() + +----------------------- +*/ +public class SoundEmitter : MonoBehaviour { + public enum FadeState { + Null, + FadingIn, + FadingOut, + Ducking, + } + + // OPTIMIZE + + public float volume { get { return audioSource.volume; } set { audioSource.volume = value; } } + public float pitch { get { return audioSource.pitch; } set { audioSource.pitch = value; } } + public AudioClip clip { get { return audioSource.clip; } set { audioSource.clip = value; } } + public float time { get { return audioSource.time; } set { audioSource.time = value; } } + public float length { get { return ( audioSource.clip != null ) ? audioSource.clip.length : 0.0f; } } + public bool loop { get { return audioSource.loop; } set { audioSource.loop = value; } } + public bool mute { get { return audioSource.mute; } set { audioSource.mute = value; } } + public AudioVelocityUpdateMode velocityUpdateMode { get { return audioSource.velocityUpdateMode; } set { audioSource.velocityUpdateMode = value; } } + public bool isPlaying { get { return audioSource.isPlaying; } } + + public EmitterChannel channel = EmitterChannel.Reserved; + public bool disableSpatialization = false; + private FadeState state = FadeState.Null; + [System.NonSerialized] + [HideInInspector] + public AudioSource audioSource = null; + [System.NonSerialized] + [HideInInspector] + public SoundPriority priority = SoundPriority.Default; + [System.NonSerialized] + [HideInInspector] + public ONSPAudioSource osp = null; + [System.NonSerialized] + [HideInInspector] + public float endPlayTime = 0.0f; + private Transform lastParentTransform = null; + [System.NonSerialized] + [HideInInspector] + public float defaultVolume = 1.0f; + [System.NonSerialized] + [HideInInspector] + public Transform defaultParent = null; + [System.NonSerialized] + [HideInInspector] + public int originalIdx = -1; + [System.NonSerialized] + [HideInInspector] + public System.Action onFinished = null; + [System.NonSerialized] + [HideInInspector] + public System.Action onFinishedObject = null; + [System.NonSerialized] + [HideInInspector] + public object onFinishedParam; + [System.NonSerialized] + [HideInInspector] + public SoundGroup playingSoundGroup = null; + + /* + ----------------------- + Awake() + ----------------------- + */ + void Awake() { + // unity defaults to 'playOnAwake = true' + audioSource = GetComponent(); + if ( audioSource == null ) { + audioSource = gameObject.AddComponent(); + } + // is the spatialized audio enabled? + if ( AudioManager.enableSpatialization && !disableSpatialization ) { + osp = GetComponent(); + if ( osp == null ) { + osp = gameObject.AddComponent(); + } + } + audioSource.playOnAwake = false; + audioSource.Stop(); + } + + /* + ----------------------- + SetPlayingSoundGroup() + ----------------------- + */ + public void SetPlayingSoundGroup( SoundGroup soundGroup ) { + playingSoundGroup = soundGroup; + if ( soundGroup != null ) { + soundGroup.IncrementPlayCount(); + } + } + + /* + ----------------------- + SetOnFinished() + ----------------------- + */ + public void SetOnFinished( System.Action onFinished ) { + this.onFinished = onFinished; + } + + /* + ----------------------- + SetOnFinished() + ----------------------- + */ + public void SetOnFinished( System.Action onFinished, object obj ) { + onFinishedObject = onFinished; + onFinishedParam = obj; + } + + /* + ----------------------- + SetChannel() + ----------------------- + */ + public void SetChannel( int _channel ) { + channel = (EmitterChannel)_channel; + } + + /* + ----------------------- + SetDefaultParent() + ----------------------- + */ + public void SetDefaultParent( Transform parent ) { + defaultParent = parent; + } + + /* + ----------------------- + SetAudioMixer() + ----------------------- + */ + public void SetAudioMixer( AudioMixerGroup _mixer ) { + if ( audioSource != null ) { + audioSource.outputAudioMixerGroup = _mixer; + } + } + + /* + ----------------------- + IsPlaying() + ----------------------- + */ + public bool IsPlaying() { + if ( loop && audioSource.isPlaying ) { + return true; + } + return endPlayTime > Time.time; + } + + /* + ----------------------- + Play() + ----------------------- + */ + public void Play() { + // overrides everything + state = FadeState.Null; + endPlayTime = Time.time + length; + StopAllCoroutines(); + audioSource.Play(); + } + + /* + ----------------------- + Pause() + ----------------------- + */ + public void Pause() { + // overrides everything + state = FadeState.Null; + StopAllCoroutines(); + audioSource.Pause(); + } + + /* + ----------------------- + Stop() + ----------------------- + */ + public void Stop() { + // overrides everything + state = FadeState.Null; + StopAllCoroutines(); + if ( audioSource != null ) { + audioSource.Stop(); + } + if ( onFinished != null ) { + onFinished(); + onFinished = null; + } + if ( onFinishedObject != null ) { + onFinishedObject( onFinishedParam ); + onFinishedObject = null; + } + if ( playingSoundGroup != null ) { + playingSoundGroup.DecrementPlayCount(); + playingSoundGroup = null; + } + } + + /* + ----------------------- + GetSampleTime() + ----------------------- + */ + int GetSampleTime() { + return audioSource.clip.samples - audioSource.timeSamples; + } + + /* + ----------------------- + ParentTo() + ----------------------- + */ + public void ParentTo( Transform parent ) { + if ( lastParentTransform != null ) { + Debug.LogError( "[SoundEmitter] You must detach the sound emitter before parenting to another object!" ); + return; + } + lastParentTransform = transform.parent; + transform.parent = parent; + } + + /* + ----------------------- + DetachFromParent() + ----------------------- + */ + public void DetachFromParent() { + if ( lastParentTransform == null ) { + transform.parent = defaultParent; + return; + } + transform.parent = lastParentTransform; + lastParentTransform = null; + } + + /* + ----------------------- + ResetParent() + ----------------------- + */ + public void ResetParent( Transform parent ) { + transform.parent = parent; + lastParentTransform = null; + } + + /* + ----------------------- + SyncTo() + ----------------------- + */ + public void SyncTo( SoundEmitter other, float fadeTime, float toVolume ) { + StartCoroutine( DelayedSyncTo( other, fadeTime, toVolume ) ); + } + + /* + ----------------------- + DelayedSyncTo() + have to wait until the end of frame to do proper sync'ing + ----------------------- + */ + IEnumerator DelayedSyncTo( SoundEmitter other, float fadeTime, float toVolume ) { + yield return new WaitForEndOfFrame(); + //audio.timeSamples = other.GetSampleTime(); + //audio.time = Mathf.Min( Mathf.Max( 0.0f, other.time - other.length ), other.time ); + audioSource.time = other.time; + audioSource.Play(); + FadeTo( fadeTime, toVolume ); + } + + /* + ----------------------- + FadeTo() + ----------------------- + */ + public void FadeTo( float fadeTime, float toVolume ) { + //Log.Print( ">>> FADE TO: " + channel ); + + + // don't override a fade out + if ( state == FadeState.FadingOut ) { + //Log.Print( " ....ABORTED" ); + return; + } + state = FadeState.Ducking; + StopAllCoroutines(); + StartCoroutine( FadeSoundChannelTo( fadeTime, toVolume ) ); + } + + /* + ----------------------- + FadeIn() + ----------------------- + */ + public void FadeIn( float fadeTime, float defaultVolume ) { + + //Log.Print( ">>> FADE IN: " + channel ); + audioSource.volume = 0.0f; + state = FadeState.FadingIn; + StopAllCoroutines(); + StartCoroutine( FadeSoundChannel( 0.0f, fadeTime, Fade.In, defaultVolume ) ); + } + + /* + ----------------------- + FadeIn() + ----------------------- + */ + public void FadeIn( float fadeTime ) { + + //Log.Print( ">>> FADE IN: " + channel ); + audioSource.volume = 0.0f; + state = FadeState.FadingIn; + StopAllCoroutines(); + StartCoroutine( FadeSoundChannel( 0.0f, fadeTime, Fade.In, defaultVolume ) ); + } + + /* + ----------------------- + FadeOut() + ----------------------- + */ + public void FadeOut( float fadeTime ) { + //Log.Print( ">>> FADE OUT: " + channel ); + if ( !audioSource.isPlaying ) { + //Log.Print( " ... SKIPPING" ); + return; + } + state = FadeState.FadingOut; + StopAllCoroutines(); + StartCoroutine( FadeSoundChannel( 0.0f, fadeTime, Fade.Out, audioSource.volume ) ); + } + + /* + ----------------------- + FadeOutDelayed() + ----------------------- + */ + public void FadeOutDelayed( float delayedSecs, float fadeTime ) { + //Log.Print( ">>> FADE OUT DELAYED: " + channel ); + if ( !audioSource.isPlaying ) { + //Log.Print( " ... SKIPPING" ); + return; + } + state = FadeState.FadingOut; + StopAllCoroutines(); + StartCoroutine( FadeSoundChannel( delayedSecs, fadeTime, Fade.Out, audioSource.volume ) ); + } + + /* + ----------------------- + FadeSoundChannelTo() + ----------------------- + */ + IEnumerator FadeSoundChannelTo( float fadeTime, float toVolume ) { + float start = audioSource.volume; + float end = toVolume; + float startTime = Time.realtimeSinceStartup; + float elapsedTime = 0.0f; + + while ( elapsedTime < fadeTime ) { + elapsedTime = Time.realtimeSinceStartup - startTime; + float t = elapsedTime / fadeTime; + audioSource.volume = Mathf.Lerp( start, end, t ); + yield return 0; + } + state = FadeState.Null; + } + + /* + ----------------------- + FadeSoundChannel() + ----------------------- + */ + IEnumerator FadeSoundChannel( float delaySecs, float fadeTime, Fade fadeType, float defaultVolume ) { + if ( delaySecs > 0.0f ) { + yield return new WaitForSeconds( delaySecs ); + } + float start = ( fadeType == Fade.In ) ? 0.0f : defaultVolume; + float end = ( fadeType == Fade.In ) ? defaultVolume : 0.0f; + bool restartPlay = false; + + if ( fadeType == Fade.In ) { + if ( Time.time == 0.0f ) { + restartPlay = true; + } + audioSource.volume = 0.0f; + audioSource.Play(); + } + + float startTime = Time.realtimeSinceStartup; + float elapsedTime = 0.0f; + + while ( elapsedTime < fadeTime ) { + elapsedTime = Time.realtimeSinceStartup - startTime; + float t = elapsedTime / fadeTime; + audioSource.volume = Mathf.Lerp( start, end, t ); + yield return 0; + if ( restartPlay && ( Time.time > 0.0f ) ) { + audioSource.Play(); + restartPlay = false; + } + if ( !audioSource.isPlaying ) { + break; + } + } + + if ( fadeType == Fade.Out ) { + Stop(); + } + state = FadeState.Null; + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/SoundEmitter.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/SoundEmitter.cs.meta new file mode 100644 index 0000000..c4cc4f6 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/SoundEmitter.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ecd24e91b27c645fc95f6c42115c13cc +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/SoundFX.cs b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFX.cs new file mode 100644 index 0000000..f0f20d4 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFX.cs @@ -0,0 +1,311 @@ +using UnityEngine; +using UnityEngine.Audio; + +namespace OVR +{ + +public enum SoundFXNext { + Random = 0, + Sequential = 1, +} + +public enum FreqHint { + None = 0, + Wide = 1, + Narrow = 2, +} + +public enum SoundPriority { + VeryLow = -2, + Low = -1, + Default = 0, + High = 1, + VeryHigh = 2, +} + +[System.Serializable] +public class OSPProps { + public OSPProps() { + enableSpatialization = false; + useFastOverride = false; + gain = 0.0f; + enableInvSquare = false; + volumetric = 0.0f; + invSquareFalloff = new Vector2( 1.0f, 25.0f ); + } + + [Tooltip( "Set to true to play the sound FX spatialized with binaural HRTF, default = false")] + public bool enableSpatialization = false; + [Tooltip( "Play the sound FX with reflections, default = false")] + public bool useFastOverride = false; + [Tooltip( "Boost the gain on the spatialized sound FX, default = 0.0")] + [Range( 0.0f, 24.0f )] + public float gain = 0.0f; + [Tooltip("Enable Inverse Square attenuation curve, default = false")] + public bool enableInvSquare = false; + [Tooltip("Change the sound from point source (0.0f) to a spherical volume, default = 0.0")] + [Range(0.0f, 1000.0f)] + public float volumetric = 0.0f; + [Tooltip("Set the near and far falloff value for the OSP attenuation curve, default = 1.0")] + [MinMax ( 1.0f, 25.0f, 0.0f, 250.0f )] + public Vector2 invSquareFalloff = new Vector2( 1.0f, 25.0f ); +} + +/* +----------------------- + +SoundFX + +----------------------- +*/ +[System.Serializable] +public class SoundFX { + public SoundFX() { + playback = SoundFXNext.Random; + volume = 1.0f; + pitchVariance = Vector2.one; + falloffDistance = new Vector2( 1.0f, 25.0f ); + falloffCurve = AudioRolloffMode.Linear; + volumeFalloffCurve = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } ); + reverbZoneMix = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } ); + spread = 0.0f; + pctChanceToPlay = 1.0f; + priority = SoundPriority.Default; + delay = Vector2.zero; + looping = false; + ospProps = new OSPProps(); + } + + [Tooltip( "Each sound FX should have a unique name")] + public string name = string.Empty; + [Tooltip( "Sound diversity playback option when multiple audio clips are defined, default = Random")] + public SoundFXNext playback = SoundFXNext.Random; + [Tooltip( "Default volume for this sound FX, default = 1.0")] + [Range (0.0f, 1.0f)] + public float volume = 1.0f; + [Tooltip( "Random pitch variance each time a sound FX is played, default = 1.0 (none)")] + [MinMax ( 1.0f, 1.0f, 0.0f, 2.0f )] + public Vector2 pitchVariance = Vector2.one; + [Tooltip( "Falloff distance for the sound FX, default = 1m min to 25m max")] + [MinMax ( 1.0f, 25.0f, 0.0f, 250.0f )] + public Vector2 falloffDistance = new Vector2( 1.0f, 25.0f ); + [Tooltip( "Volume falloff curve - sets how the sound FX attenuates over distance, default = Linear")] + public AudioRolloffMode falloffCurve = AudioRolloffMode.Linear; + [Tooltip( "Defines the custom volume falloff curve")] + public AnimationCurve volumeFalloffCurve = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } ); + [Tooltip( "The amount by which the signal from the AudioSource will be mixed into the global reverb associated with the Reverb Zones | Valid range is 0.0 - 1.1, default = 1.0" )] + public AnimationCurve reverbZoneMix = new AnimationCurve( new Keyframe[2] { new Keyframe( 0f, 1.0f ), new Keyframe( 1f, 1f ) } ); + [Tooltip( "Sets the spread angle (in degrees) of a 3d stereo or multichannel sound in speaker space, default = 0")] + [Range (0.0f, 360.0f)] + public float spread = 0.0f; + [Tooltip( "The percentage chance that this sound FX will play | 0.0 = none, 1.0 = 100%, default = 1.0")] + [Range (0.0f, 1.0f)] + public float pctChanceToPlay = 1.0f; + [Tooltip( "Sets the priority for this sound to play and/or to override a currently playing sound FX, default = Default")] + public SoundPriority priority = SoundPriority.Default; + [Tooltip( "Specifies the default delay when this sound FX is played, default = 0.0 secs")] + [MinMax ( 0.0f, 0.0f, 0.0f, 2.0f )] + public Vector2 delay = Vector2.zero; // this overrides any delay passed into PlaySound() or PlaySoundAt() + [Tooltip( "Set to true for the sound to loop continuously, default = false")] + public bool looping = false; + public OSPProps ospProps = new OSPProps(); + [Tooltip( "List of the audio clips assigned to this sound FX")] + public AudioClip[] soundClips = new AudioClip[1]; + // editor only - unfortunately if we set it not to serialize, we can't query it from the editor + public bool visibilityToggle = false; + // runtime vars + [System.NonSerialized] + private SoundGroup soundGroup = null; + private int lastIdx = -1; + private int playingIdx = -1; + + public int Length { get { return soundClips.Length; } } + public bool IsValid { get { return ( ( soundClips.Length != 0 ) && ( soundClips[0] != null ) ); } } + public SoundGroup Group { get { return soundGroup; } set { soundGroup = value; } } + public float MaxFalloffDistSquared { get { return falloffDistance.y * falloffDistance.y; } } + public float GroupVolumeOverride { get { return ( soundGroup != null ) ? soundGroup.volumeOverride : 1.0f; } } + + /* + ----------------------- + GetClip() + ----------------------- + */ + public AudioClip GetClip() { + if ( soundClips.Length == 0 ) { + return null; + } else if ( soundClips.Length == 1 ) { + return soundClips[0]; + } + if ( playback == SoundFXNext.Random ) { + // random, but don't pick the last one + int idx = Random.Range( 0, soundClips.Length ); + while ( idx == lastIdx ) { + idx = Random.Range( 0, soundClips.Length ); + } + lastIdx = idx; + return soundClips[idx]; + } else { + // sequential + if ( ++lastIdx >= soundClips.Length ) { + lastIdx = 0; + } + return soundClips[lastIdx]; + } + } + + /* + ----------------------- + GetMixerGroup() + ----------------------- + */ + public AudioMixerGroup GetMixerGroup( AudioMixerGroup defaultMixerGroup ) { + if ( soundGroup != null ) { + return ( soundGroup.mixerGroup != null ) ? soundGroup.mixerGroup : defaultMixerGroup; + } + return defaultMixerGroup; + } + + /* + ----------------------- + ReachedGroupPlayLimit() + ----------------------- + */ + public bool ReachedGroupPlayLimit() { + if ( soundGroup != null ) { + return !soundGroup.CanPlaySound(); + } + return false; + } + + /* + ----------------------- + GetClipLength() + ----------------------- + */ + public float GetClipLength( int idx ) { + if ( ( idx == -1 ) || ( soundClips.Length == 0 ) || ( idx >= soundClips.Length ) || ( soundClips[idx] == null ) ) { + return 0.0f; + } else { + return soundClips[idx].length; + } + } + + /* + ----------------------- + GetPitch() + ----------------------- + */ + public float GetPitch() { + return Random.Range( pitchVariance.x, pitchVariance.y ); + } + + /* + ----------------------- + PlaySound() + ----------------------- + */ + public int PlaySound( float delaySecs = 0.0f ) { + playingIdx = -1; + + if ( !IsValid ) { + return playingIdx; + } + + // check the random chance to play here to save the function calls + if ( ( pctChanceToPlay > 0.99f ) || ( Random.value < pctChanceToPlay ) ) { + if ( delay.y > 0.0f ) { + delaySecs = Random.Range( delay.x, delay.y ); + } + playingIdx = AudioManager.PlaySound( this, EmitterChannel.Any, delaySecs ); + } + + return playingIdx; + } + + /* + ----------------------- + PlaySoundAt() + ----------------------- + */ + public int PlaySoundAt( Vector3 pos, float delaySecs = 0.0f, float volumeOverride = 1.0f, float pitchMultiplier = 1.0f ) { + playingIdx = -1; + + if ( !IsValid ) { + return playingIdx; + } + + // check the random chance to play here to save the function calls + if ( ( pctChanceToPlay > 0.99f ) || ( Random.value < pctChanceToPlay ) ) { + if ( delay.y > 0.0f ) { + delaySecs = Random.Range( delay.x, delay.y ); + } + playingIdx = AudioManager.PlaySoundAt( pos, this, EmitterChannel.Any, delaySecs, volumeOverride, pitchMultiplier ); + } + + return playingIdx; + } + + /* + ----------------------- + SetOnFinished() + get a callback when the sound is finished playing + ----------------------- + */ + public void SetOnFinished( System.Action onFinished ) { + if ( playingIdx > -1 ) { + AudioManager.SetOnFinished( playingIdx, onFinished ); + } + } + + /* + ----------------------- + SetOnFinished() + get a callback with an object parameter when the sound is finished playing + ----------------------- + */ + public void SetOnFinished( System.Action onFinished, object obj ) { + if ( playingIdx > -1 ) { + AudioManager.SetOnFinished( playingIdx, onFinished, obj ); + } + } + + /* + ----------------------- + StopSound() + ----------------------- + */ + public bool StopSound() { + bool stopped = false; + + if (playingIdx > -1){ + stopped = AudioManager.StopSound(playingIdx); + playingIdx = -1; + } + + return stopped; + } + + /* + ----------------------- + AttachToParent() + ----------------------- + */ + public void AttachToParent( Transform parent) { + if (playingIdx > -1) { + AudioManager.AttachSoundToParent(playingIdx, parent); + } + } + + /* + ----------------------- + DetachFromParent() + ----------------------- + */ + public void DetachFromParent() { + if (playingIdx > -1) { + AudioManager.DetachSoundFromParent(playingIdx); + } + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/SoundFX.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFX.cs.meta new file mode 100644 index 0000000..a521c30 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFX.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b0a1e5e7b5cff46a187b02100f0e4a3c +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/SoundFXRef.cs b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFXRef.cs new file mode 100644 index 0000000..a77f253 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFXRef.cs @@ -0,0 +1,144 @@ +using UnityEngine; +using System.Collections; + +namespace OVR +{ + +/* +----------------------- +SoundFXRef +just a references to a SoundFX.. all the SoundFX methods are called indirectly from here +----------------------- +*/ +[System.Serializable] +public class SoundFXRef { + + public string soundFXName = string.Empty; + + private bool initialized = false; + private SoundFX soundFXCached = null; + public SoundFX soundFX { + get { + if ( !initialized ) { + Init(); + } + return soundFXCached; + } + } + public string name { get { return soundFXName; } set { soundFXName = value; Init(); } } + + /* + ----------------------- + Init() + ----------------------- + */ + void Init() { + // look up the actual SoundFX object + soundFXCached = AudioManager.FindSoundFX( soundFXName ); + if ( soundFXCached == null ) { + soundFXCached = AudioManager.FindSoundFX( string.Empty ); + } + initialized = true; + } + + /* + ----------------------- + Length() + ----------------------- + */ + public int Length { get { return soundFX.Length; } } + + /* + ----------------------- + IsValid() + ----------------------- + */ + public bool IsValid { get { return soundFX.IsValid; } } + + /* + ----------------------- + GetClip() + ----------------------- + */ + public AudioClip GetClip() { + return soundFX.GetClip(); + } + + /* + ----------------------- + GetClipLength() + ----------------------- + */ + public float GetClipLength( int idx ) { + return soundFX.GetClipLength( idx ); + } + + /* + ----------------------- + PlaySound() + ----------------------- + */ + public int PlaySound( float delaySecs = 0.0f ) { + return soundFX.PlaySound( delaySecs ); + } + + /* + ----------------------- + PlaySoundAt() + ----------------------- + */ + public int PlaySoundAt( Vector3 pos, float delaySecs = 0.0f, float volume = 1.0f, float pitchMultiplier = 1.0f ) { + return soundFX.PlaySoundAt( pos, delaySecs, volume, pitchMultiplier ); + } + + /* + ----------------------- + SetOnFinished() + get a callback when the sound is finished playing + ----------------------- + */ + public void SetOnFinished( System.Action onFinished ) { + soundFX.SetOnFinished( onFinished ); + } + + /* + ----------------------- + SetOnFinished() + get a callback with an object parameter when the sound is finished playing + ----------------------- + */ + public void SetOnFinished( System.Action onFinished, object obj ) { + soundFX.SetOnFinished( onFinished, obj ); + } + + /* + ----------------------- + StopSound() + ----------------------- + */ + public bool StopSound() { + return soundFX.StopSound(); + } + + /* + ----------------------- + AttachToParent() + ----------------------- + */ + public void AttachToParent( Transform parent) + { + soundFX.AttachToParent( parent); + } + + /* + ----------------------- + DetachFromParent() + ----------------------- + */ + public void DetachFromParent() + { + soundFX.DetachFromParent(); + } +} + +} // namespace OVR diff --git a/Assets/Oculus/AudioManager/Scripts/Audio/SoundFXRef.cs.meta b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFXRef.cs.meta new file mode 100644 index 0000000..85306d1 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Audio/SoundFXRef.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48176edab546a48de9b146105d7c5f47 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Utils.meta b/Assets/Oculus/AudioManager/Scripts/Utils.meta new file mode 100644 index 0000000..2eeefae --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 02268a883a27b9c4abac4ee978caec4d +folderAsset: yes +timeCreated: 1468506022 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Utils/Editor.meta b/Assets/Oculus/AudioManager/Scripts/Utils/Editor.meta new file mode 100644 index 0000000..c0f334e --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b43e7f73d4ffc2545a17b938f63e6bc0 +folderAsset: yes +timeCreated: 1468507225 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Utils/Editor/DrawerInspectorNote.cs b/Assets/Oculus/AudioManager/Scripts/Utils/Editor/DrawerInspectorNote.cs new file mode 100644 index 0000000..f9b3b2a --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils/Editor/DrawerInspectorNote.cs @@ -0,0 +1,77 @@ +using UnityEngine; +using UnityEditor; +using System.Collections; +using System.Collections.Generic; + +[CustomPropertyDrawer(typeof(InspectorNoteAttribute))] +public class DrawerInspectorNote : DecoratorDrawer +{ + public override void OnGUI( Rect position ) + { + InspectorNoteAttribute note = attribute as InspectorNoteAttribute; + + // our header is always present + Rect posLabel = position; + posLabel.y += 13; + posLabel.x -= 2; + posLabel.height += 13; + EditorGUI.LabelField(posLabel, note.header, EditorStyles.whiteLargeLabel); + + // do we have a message too? + if (!string.IsNullOrEmpty(note.message)) + { + Color color = GUI.color; + Color faded = color; + faded.a = 0.6f; + + Rect posExplain = posLabel; + posExplain.y += 15; + GUI.color = faded; + EditorGUI.LabelField(posExplain, note.message, EditorStyles.whiteMiniLabel); + GUI.color = color; + } + + Rect posLine = position; + posLine.y += string.IsNullOrEmpty(note.message) ? 30 : 42; + posLine.height = 1f; + GUI.Box(posLine, ""); + } + + public override float GetHeight() { + InspectorNoteAttribute note = attribute as InspectorNoteAttribute; + return string.IsNullOrEmpty( note.message ) ? 38 : 50; + } +} + +[CustomPropertyDrawer( typeof( InspectorCommentAttribute ) )] +public class DrawerInspectorComment : DecoratorDrawer { + public override void OnGUI( Rect position ) { + InspectorCommentAttribute comment = attribute as InspectorCommentAttribute; + + // our header is always present + Rect posLabel = position; + //posLabel.y += 13; + //posLabel.x -= 2; + //posLabel.height += 13; + //EditorGUI.LabelField( posLabel, comment.header, EditorStyles.whiteLargeLabel ); + + // do we have a message too? + if ( !string.IsNullOrEmpty( comment.message ) ) { + Color color = GUI.color; + Color faded = color; + faded.a = 0.6f; + + Rect posExplain = posLabel; + posExplain.y += 15; + GUI.color = faded; + EditorGUI.LabelField( posExplain, comment.message, EditorStyles.whiteMiniLabel ); + GUI.color = color; + } + + } + + public override float GetHeight() { + InspectorNoteAttribute note = attribute as InspectorNoteAttribute; + return string.IsNullOrEmpty( note.message ) ? 38 : 50; + } +} diff --git a/Assets/Oculus/AudioManager/Scripts/Utils/Editor/DrawerInspectorNote.cs.meta b/Assets/Oculus/AudioManager/Scripts/Utils/Editor/DrawerInspectorNote.cs.meta new file mode 100644 index 0000000..10e7de1 --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils/Editor/DrawerInspectorNote.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f244e745a5bf8412d9d81d43dff35cf5 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/AudioManager/Scripts/Utils/FastList.cs b/Assets/Oculus/AudioManager/Scripts/Utils/FastList.cs new file mode 100644 index 0000000..1df741f --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils/FastList.cs @@ -0,0 +1,283 @@ +using UnityEngine; +using System; +using System.Collections; +using System.Collections.Generic; + +public class FastList { + + /// + /// Comparison function should return -1 if left is less than right, 1 if left is greater than right, and 0 if they match. + /// + public delegate int CompareFunc(T left, T right); + + + public T[] array = null; + public int size = 0; + + public FastList () { + } + + public FastList(int size) { + if (size > 0) { + this.size = 0; + array = new T[size]; + } + else { + this.size = 0; + } + } + + public int Count { + get { return size;} + set { } + } + + public T this[int i] { + get { return array[i];} + set { array[i] = value;} + } + + //Add item to end of list. + public void Add(T item) { + if (array == null || size == array.Length) { + Allocate(); + } + array[size] = item; + size++; + } + + //Add item to end of list if it is unique. + public void AddUnique( T item ) { + if ( array == null || size == array.Length ) { + Allocate(); + } + if ( !Contains( item ) ) { + array[size] = item; + size++; + } + } + + //Add items to the end of the list + public void AddRange( IEnumerable items ) { + foreach ( T item in items ) { + Add( item ); + } + } + + //Insert item at specified index + public void Insert(int index, T item) { + if (array == null || size == array.Length) { + Allocate(); + } + if (index < size) { + //move things back 1 + for (int i = size; i > index; i--) { + array[i] = array[i-1]; + } + array[index] = item; + size++; + } + else Add(item); + } + + //Removes specified item and keeps everything else in order + public bool Remove(T item) { + if (array != null) { + for (int i = 0; i < size; i++) { + if (item.Equals(array[i])) { //found it, push everything up + size--; + for (int j = i; j < size; j++) { + array[j] = array[j+1]; + } + array[size] = default(T); + return true; + } + } + } + return false; + } + + //Removes item at specified index while keeping everything else in order + //O(n) + public void RemoveAt(int index) { + if (array != null && size > 0 && index < size) { + size--; + for (int i = index; i < size; i++) { + array[i] = array[i+1]; + } + array[size] = default(T); + } + } + + //Removes the specified item from the list and replaces with last item. Return true if removed, false if not found. + public bool RemoveFast(T item) { + if (array != null) { + for (int i = 0; i < size; i++) { + if ( item.Equals( array[i] )) { //found + //Move last item here + if (i < (size - 1)) { + T lastItem = array[size-1]; + array[size-1] = default(T); + array[i] = lastItem; + } else { + array[i] = default(T); + } + size--; + return true; + } + } + } + return false; + } + + //Removes item at specified index and replace with last item. + public void RemoveAtFast(int index) { + if (array != null && index < size && index >= 0) { + //last element + if (index == size - 1) { + array[index] = default(T); + } + else { + T lastItem = array[size - 1]; + array[index] = lastItem; + array[size - 1] = default(T); + } + size--; + + } + } + + //Return whether an item is contained within the list + //O(n) + public bool Contains(T item) { + if (array == null || size <= 0 ) return false; + for (int i = 0; i < size; i++) { + if (array[i].Equals(item)) { return true;} + } + return false; + } + + //Returns index of specified item, or -1 if not found. + //O(n) + public int IndexOf(T item) { + if (size <= 0 || array == null) { return -1;} + for (int i = 0; i < size; i++) { + if (item.Equals(array[i])) { return i;} + } + return -1; + } + + public T Pop() { + if (array != null && size > 0) { + T lastItem = array[size-1]; + array[size-1] = default(T); + size--; + return lastItem; + } + + return default(T); + } + + public T[] ToArray() { + Trim(); + return array; + } + + public void Sort (CompareFunc comparer) { + int start = 0; + int end = size - 1; + bool changed = true; + + while (changed) { + changed = false; + + for (int i = start; i < end; i++) { + + if (comparer(array[i], array[i + 1]) > 0) { + T temp = array[i]; + array[i] = array[i+1]; + array[i+1] = temp; + changed = true; + } + else if (!changed) { + start = (i==0) ? 0 : i-1; + } + } + } + } + + public void InsertionSort(CompareFunc comparer) { + for (int i = 1; i < size; i++) { + T curr = array[i]; + int j = i; + while (j > 0 && comparer(array[j - 1], curr) > 0) { + array[j] = array[j-1]; + j--; + } + array[j] = curr; + } + } + + public IEnumerator GetEnumerator() { + if (array != null) { + for (int i = 0; i < size; i++) { + yield return array[i]; + } + } + } + + public T Find(Predicate match) { + if (match != null) { + if (array != null) { + for (int i = 0; i < size; i++) { + if (match(array[i])) { return array[i];} + } + } + } + return default(T); + } + + //Allocate more space to internal array. + void Allocate() { + T[] newArray; + if (array == null) { + newArray = new T[32]; + } + else { + newArray = new T[Mathf.Max(array.Length << 1, 32)]; + } + if (array != null && size > 0) { + array.CopyTo(newArray, 0); + } + + array = newArray; + } + + + void Trim() { + if (size > 0) { + T[] newArray = new T[size]; + for (int i = 0; i < size; i++) { + newArray[i] = array[i]; + } + array = newArray; + } + else { + array = null; + } + } + + //Set size to 0, does not delete array from memory + public void Clear() { + size = 0; + } + + //Delete array from memory + public void Release() { + Clear(); + array = null; + } + + + +} diff --git a/Assets/Oculus/AudioManager/Scripts/Utils/FastList.cs.meta b/Assets/Oculus/AudioManager/Scripts/Utils/FastList.cs.meta new file mode 100644 index 0000000..0d65e9b --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils/FastList.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 5ad95fb7eea735748bd34c963525ea21 +timeCreated: 1432749689 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/AudioManager/Scripts/Utils/InspectorNoteAttribute.cs b/Assets/Oculus/AudioManager/Scripts/Utils/InspectorNoteAttribute.cs new file mode 100644 index 0000000..b9dea3d --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils/InspectorNoteAttribute.cs @@ -0,0 +1,35 @@ +using UnityEngine; + +/* +----------------------- + + InspectorNoteAttribute() + +----------------------- +*/ +public class InspectorNoteAttribute : PropertyAttribute +{ + public readonly string header; + public readonly string message; + + public InspectorNoteAttribute(string header, string message = "") + { + this.header = header; + this.message = message; + } +} + +/* +----------------------- + + InspectorCommentAttribute() + +----------------------- +*/ +public class InspectorCommentAttribute : PropertyAttribute { + public readonly string message; + + public InspectorCommentAttribute( string message = "" ) { + this.message = message; + } +} diff --git a/Assets/Oculus/AudioManager/Scripts/Utils/InspectorNoteAttribute.cs.meta b/Assets/Oculus/AudioManager/Scripts/Utils/InspectorNoteAttribute.cs.meta new file mode 100644 index 0000000..3169ebb --- /dev/null +++ b/Assets/Oculus/AudioManager/Scripts/Utils/InspectorNoteAttribute.cs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4616bbe65d311471f8d71174295f4986 +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: diff --git a/Assets/Oculus/Avatar.meta b/Assets/Oculus/Avatar.meta new file mode 100644 index 0000000..c0bde7a --- /dev/null +++ b/Assets/Oculus/Avatar.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: da77b29a0418e4596b9a376850379241 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Content.meta b/Assets/Oculus/Avatar/Content.meta new file mode 100644 index 0000000..fdbc86b --- /dev/null +++ b/Assets/Oculus/Avatar/Content.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b7b5af4818686f84f844c1ae9df0f700 +folderAsset: yes +timeCreated: 1466716731 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Content/Prefabs.meta b/Assets/Oculus/Avatar/Content/Prefabs.meta new file mode 100644 index 0000000..99ff342 --- /dev/null +++ b/Assets/Oculus/Avatar/Content/Prefabs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e2c4ef7503877e647b22a4089384f04f +folderAsset: yes +timeCreated: 1466717433 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Content/Prefabs/LocalAvatar.prefab b/Assets/Oculus/Avatar/Content/Prefabs/LocalAvatar.prefab new file mode 100644 index 0000000..292918e --- /dev/null +++ b/Assets/Oculus/Avatar/Content/Prefabs/LocalAvatar.prefab @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &158226 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 463470} + - component: {fileID: 11437430} + - component: {fileID: 11441414} + m_Layer: 0 + m_Name: LocalAvatar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &463470 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 158226} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11437430 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 158226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 00f3402a2ea5bff4880c0313515240cd, type: 3} + m_Name: + m_EditorClassIdentifier: + oculusUserID: 0 + Driver: {fileID: 11441414} + EnableBody: 1 + EnableHands: 1 + EnableBase: 0 + EnableExpressive: 1 + RecordPackets: 1 + UseSDKPackets: 1 + PacketSettings: + UpdateRate: 0.033333335 + StartWithControllers: 0 + FirstPersonLayer: + layerIndex: 0 + ThirdPersonLayer: + layerIndex: 0 + ShowFirstPerson: 1 + ShowThirdPerson: 0 + LevelOfDetail: 5 + CombineMeshes: 1 + UseTransparentRenderQueue: 1 + Monochrome_SurfaceShader: {fileID: 4800000, guid: 73f67c4e7bf718b4385aa6b1f8a06591, + type: 3} + Monochrome_SurfaceShader_SelfOccluding: {fileID: 4800000, guid: 69f342b79d37541489919a19cfd8a924, + type: 3} + Monochrome_SurfaceShader_PBS: {fileID: 4800000, guid: 5e52aa58207bbf24d8eb8ec969e9ae88, + type: 3} + Skinshaded_SurfaceShader_SingleComponent: {fileID: 4800000, guid: 36b8b481cf607814a8cec318f0148d63, + type: 3} + Skinshaded_VertFrag_SingleComponent: {fileID: 4800000, guid: c26fc51e445dcfd4db09305d861dc11c, + type: 3} + Skinshaded_VertFrag_CombinedMesh: {fileID: 4800000, guid: 37d2b8298f61cd2469465fc36108675d, + type: 3} + Skinshaded_Expressive_SurfaceShader_SingleComponent: {fileID: 4800000, guid: 93b478e926e46654889c1c20f87f253f, + type: 3} + Skinshaded_Expressive_VertFrag_SingleComponent: {fileID: 4800000, guid: 2fe0ac0c2373ab143a6f21314b785d7d, + type: 3} + Skinshaded_Expressive_VertFrag_CombinedMesh: {fileID: 4800000, guid: 0600fe59b0c043344affd1d1368b9ef2, + type: 3} + Loader_VertFrag_CombinedMesh: {fileID: 4800000, guid: 822f5e641dc5dd54ca9555b727b3277f, + type: 3} + EyeLens: {fileID: 4800000, guid: 8392f54e79937ed4bb1b692a143dc02b, type: 3} + ControllerShader: {fileID: 4800000, guid: 28729c6ae5a33b04cb2f7956f3f3fc01, type: 3} + CanOwnMicrophone: 1 + MouthAnchor: {fileID: 0} + LeftHandCustomPose: {fileID: 0} + RightHandCustomPose: {fileID: 0} + VoiceAmplitude: 0 + EnableMouthVertexAnimation: 0 +--- !u!114 &11441414 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 158226} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: ac27124318cf8e84aa7350c2ac1cdb80, type: 3} + m_Name: + m_EditorClassIdentifier: + Mode: 0 +--- !u!114 &11477770 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 0} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 77e19ec58d4a9e844970103e5bd8946a, type: 3} + m_Name: + m_EditorClassIdentifier: + RenderParts: [] + isLeftHand: 1 +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 158226} + m_IsPrefabParent: 1 diff --git a/Assets/Oculus/Avatar/Content/Prefabs/LocalAvatar.prefab.meta b/Assets/Oculus/Avatar/Content/Prefabs/LocalAvatar.prefab.meta new file mode 100644 index 0000000..9a2bf1a --- /dev/null +++ b/Assets/Oculus/Avatar/Content/Prefabs/LocalAvatar.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 84c8b8609f9bb434eaf5248f17ff1293 +timeCreated: 1466806466 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Content/Prefabs/RemoteAvatar.prefab b/Assets/Oculus/Avatar/Content/Prefabs/RemoteAvatar.prefab new file mode 100644 index 0000000..c1190e2 --- /dev/null +++ b/Assets/Oculus/Avatar/Content/Prefabs/RemoteAvatar.prefab @@ -0,0 +1,114 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &143252 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 496618} + - component: {fileID: 11464902} + - component: {fileID: 11461908} + m_Layer: 0 + m_Name: RemoteAvatar + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &496618 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 143252} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &11461908 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 143252} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c198a42a3843ca04fa633b60f428ff51, type: 3} + m_Name: + m_EditorClassIdentifier: + Mode: 0 +--- !u!114 &11464902 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 143252} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 00f3402a2ea5bff4880c0313515240cd, type: 3} + m_Name: + m_EditorClassIdentifier: + oculusUserID: 0 + Driver: {fileID: 11461908} + EnableBody: 1 + EnableHands: 1 + EnableBase: 0 + EnableExpressive: 1 + RecordPackets: 0 + UseSDKPackets: 1 + PacketSettings: + UpdateRate: 0.033333335 + StartWithControllers: 0 + FirstPersonLayer: + layerIndex: 0 + ThirdPersonLayer: + layerIndex: 0 + ShowFirstPerson: 0 + ShowThirdPerson: 1 + LevelOfDetail: 3 + CombineMeshes: 1 + UseTransparentRenderQueue: 1 + Monochrome_SurfaceShader: {fileID: 4800000, guid: 73f67c4e7bf718b4385aa6b1f8a06591, + type: 3} + Monochrome_SurfaceShader_SelfOccluding: {fileID: 4800000, guid: 69f342b79d37541489919a19cfd8a924, + type: 3} + Monochrome_SurfaceShader_PBS: {fileID: 4800000, guid: 5e52aa58207bbf24d8eb8ec969e9ae88, + type: 3} + Skinshaded_SurfaceShader_SingleComponent: {fileID: 4800000, guid: 36b8b481cf607814a8cec318f0148d63, + type: 3} + Skinshaded_VertFrag_SingleComponent: {fileID: 4800000, guid: c26fc51e445dcfd4db09305d861dc11c, + type: 3} + Skinshaded_VertFrag_CombinedMesh: {fileID: 4800000, guid: 37d2b8298f61cd2469465fc36108675d, + type: 3} + Skinshaded_Expressive_SurfaceShader_SingleComponent: {fileID: 4800000, guid: 93b478e926e46654889c1c20f87f253f, + type: 3} + Skinshaded_Expressive_VertFrag_SingleComponent: {fileID: 4800000, guid: 2fe0ac0c2373ab143a6f21314b785d7d, + type: 3} + Skinshaded_Expressive_VertFrag_CombinedMesh: {fileID: 4800000, guid: 0600fe59b0c043344affd1d1368b9ef2, + type: 3} + Loader_VertFrag_CombinedMesh: {fileID: 4800000, guid: 822f5e641dc5dd54ca9555b727b3277f, + type: 3} + EyeLens: {fileID: 4800000, guid: 8392f54e79937ed4bb1b692a143dc02b, type: 3} + ControllerShader: {fileID: 4800000, guid: 28729c6ae5a33b04cb2f7956f3f3fc01, type: 3} + CanOwnMicrophone: 1 + MouthAnchor: {fileID: 0} + LeftHandCustomPose: {fileID: 0} + RightHandCustomPose: {fileID: 0} + VoiceAmplitude: 0 + EnableMouthVertexAnimation: 0 +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 143252} + m_IsPrefabParent: 1 diff --git a/Assets/Oculus/Avatar/Content/Prefabs/RemoteAvatar.prefab.meta b/Assets/Oculus/Avatar/Content/Prefabs/RemoteAvatar.prefab.meta new file mode 100644 index 0000000..5561d1e --- /dev/null +++ b/Assets/Oculus/Avatar/Content/Prefabs/RemoteAvatar.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 90bf33f968e6bb44ea0208fc82c90a44 +timeCreated: 1468001728 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Plugins.meta b/Assets/Oculus/Avatar/Plugins.meta new file mode 100644 index 0000000..0cd7491 --- /dev/null +++ b/Assets/Oculus/Avatar/Plugins.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 562797c69d851ed4ba23272425436ab6 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Plugins/Android32.meta b/Assets/Oculus/Avatar/Plugins/Android32.meta new file mode 100644 index 0000000..d6779d0 --- /dev/null +++ b/Assets/Oculus/Avatar/Plugins/Android32.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5efa82b7f37ef914c8e36b241d89eaf3 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Plugins/Android32/libovravatarloader.so b/Assets/Oculus/Avatar/Plugins/Android32/libovravatarloader.so new file mode 100644 index 0000000..a5cbd02 Binary files /dev/null and b/Assets/Oculus/Avatar/Plugins/Android32/libovravatarloader.so differ diff --git a/Assets/Oculus/Avatar/Plugins/Android32/libovravatarloader.so.meta b/Assets/Oculus/Avatar/Plugins/Android32/libovravatarloader.so.meta new file mode 100644 index 0000000..7a503ef --- /dev/null +++ b/Assets/Oculus/Avatar/Plugins/Android32/libovravatarloader.so.meta @@ -0,0 +1,25 @@ +fileFormatVersion: 2 +guid: 0dc1a28a4f6367642b859b703b901f30 +timeCreated: 1516392277 +licenseType: Free +PluginImporter: + serializedVersion: 1 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + Android: + enabled: 1 + settings: + CPU: ARMv7 + Any: + enabled: 0 + settings: {} + Editor: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Plugins/Android64.meta b/Assets/Oculus/Avatar/Plugins/Android64.meta new file mode 100644 index 0000000..a174221 --- /dev/null +++ b/Assets/Oculus/Avatar/Plugins/Android64.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7adeca2b5ccf4302a746d824ae866761 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Plugins/Android64/libovravatarloader.so b/Assets/Oculus/Avatar/Plugins/Android64/libovravatarloader.so new file mode 100644 index 0000000..8b5a7e3 Binary files /dev/null and b/Assets/Oculus/Avatar/Plugins/Android64/libovravatarloader.so differ diff --git a/Assets/Oculus/Avatar/Plugins/Android64/libovravatarloader.so.meta b/Assets/Oculus/Avatar/Plugins/Android64/libovravatarloader.so.meta new file mode 100644 index 0000000..84d2880 --- /dev/null +++ b/Assets/Oculus/Avatar/Plugins/Android64/libovravatarloader.so.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 6757695d745b8bc419fd41108ba2dec9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + defineConstraints: [] + isPreloaded: 0 + isOverridable: 0 + isExplicitlyReferenced: 0 + validateReferences: 1 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARM64 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources.meta b/Assets/Oculus/Avatar/Resources.meta new file mode 100644 index 0000000..43d9396 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7be352d6ab8b4db40b701e100dcc1000 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures.meta b/Assets/Oculus/Avatar/Resources/FallbackTextures.meta new file mode 100644 index 0000000..581a732 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e15cc54b32316d3448de9c9ef2bd7cc1 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_1024.png b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_1024.png new file mode 100644 index 0000000..12989c9 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_1024.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:88c65325f1105a73db2cdfd1187efec3b4d426876c6d2c6b03d2aa182776b2a7 +size 7159 diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_1024.png.meta b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_1024.png.meta new file mode 100644 index 0000000..2ff7045 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_1024.png.meta @@ -0,0 +1,121 @@ +fileFormatVersion: 2 +guid: 502d438d2584976448c3cdb146ed836d +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: 50 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_2048.png b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_2048.png new file mode 100644 index 0000000..7755781 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_2048.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:554c1fabc953425f3501f86894f73d6599c5c8ebfd1a59cd03ba98abd90f4093 +size 18737 diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_2048.png.meta b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_2048.png.meta new file mode 100644 index 0000000..bf343f0 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_2048.png.meta @@ -0,0 +1,121 @@ +fileFormatVersion: 2 +guid: b3e87b1024f5fa8408d004b398e7b0c0 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 50 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_256.png b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_256.png new file mode 100644 index 0000000..175e248 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_256.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fa2d0bce4fb49970abf0c9287c1ea3d3c193fce0eb8cff2aa514b4fccac5b04b +size 2707 diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_256.png.meta b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_256.png.meta new file mode 100644 index 0000000..b58f65f --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_diffuse_roughness_256.png.meta @@ -0,0 +1,121 @@ +fileFormatVersion: 2 +guid: 7d8da3d06466cc04da8c020819170a59 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: 50 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_1024.tif b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_1024.tif new file mode 100644 index 0000000..4730a9a Binary files /dev/null and b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_1024.tif differ diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_1024.tif.meta b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_1024.tif.meta new file mode 100644 index 0000000..47b2d72 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_1024.tif.meta @@ -0,0 +1,121 @@ +fileFormatVersion: 2 +guid: 9fb4a3be60417d043865e457a9d51e63 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 1 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: 50 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 1024 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_2048.png b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_2048.png new file mode 100644 index 0000000..e00b15c --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_2048.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7977a29b8766862f9a4784c0f74ee62c155f7b62891756bb4f65e8071e653789 +size 28319 diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_2048.png.meta b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_2048.png.meta new file mode 100644 index 0000000..eab3f5f --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_2048.png.meta @@ -0,0 +1,121 @@ +fileFormatVersion: 2 +guid: 22a046c12fc7f3c4d98a98add109fa96 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 1 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: 50 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_256.png b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_256.png new file mode 100644 index 0000000..d23b403 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_256.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:f0f79bb331c9573ff0521eb798bd7e9375afca53538af7e481f91acd71a8d7ae +size 5739 diff --git a/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_256.png.meta b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_256.png.meta new file mode 100644 index 0000000..ca406e4 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/FallbackTextures/fallback_normal_256.png.meta @@ -0,0 +1,121 @@ +fileFormatVersion: 2 +guid: 93a54b3b63bcc6d49b16f6bdb655b940 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 9 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 1 + streamingMipmaps: 0 + streamingMipmapsPriority: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -100 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 1 + textureShape: 1 + singleChannelComponent: 0 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - serializedVersion: 2 + buildTarget: DefaultTexturePlatform + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Standalone + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Android + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: 50 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 1 + androidETC2FallbackOverride: 0 + - serializedVersion: 2 + buildTarget: Windows Store Apps + maxTextureSize: 256 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + bones: [] + spriteID: + vertices: [] + indices: + edges: [] + weights: [] + spritePackingTag: + pSDRemoveMatte: 0 + pSDShowRemoveMatteOption: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials.meta b/Assets/Oculus/Avatar/Resources/Materials.meta new file mode 100644 index 0000000..34f0025 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a082ff1bb115495438c0dbd2a47e2b0f +folderAsset: yes +timeCreated: 1525971172 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc b/Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc new file mode 100644 index 0000000..2b0211e --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc @@ -0,0 +1,318 @@ +#ifndef AVATAR_UTIL_CG_INCLUDED +#define AVATAR_UTIL_CG_INCLUDED + +#include "UnityCG.cginc" + +#define SAMPLE_MODE_COLOR 0 +#define SAMPLE_MODE_TEXTURE 1 +#define SAMPLE_MODE_TEXTURE_SINGLE_CHANNEL 2 +#define SAMPLE_MODE_PARALLAX 3 +#define SAMPLE_MODE_RSRM 4 + +#define MASK_TYPE_NONE 0 +#define MASK_TYPE_POSITIONAL 1 +#define MASK_TYPE_REFLECTION 2 +#define MASK_TYPE_FRESNEL 3 +#define MASK_TYPE_PULSE 4 + +#define BLEND_MODE_ADD 0 +#define BLEND_MODE_MULTIPLY 1 + +#ifdef LAYERS_1 +#define LAYER_COUNT 1 +#elif LAYERS_2 +#define LAYER_COUNT 2 +#elif LAYERS_3 +#define LAYER_COUNT 3 +#elif LAYERS_4 +#define LAYER_COUNT 4 +#elif LAYERS_5 +#define LAYER_COUNT 5 +#elif LAYERS_6 +#define LAYER_COUNT 6 +#elif LAYERS_7 +#define LAYER_COUNT 7 +#elif LAYERS_8 +#define LAYER_COUNT 8 +#endif + +#define DECLARE_LAYER_UNIFORMS(index) \ + int _LayerSampleMode##index; \ + int _LayerBlendMode##index; \ + int _LayerMaskType##index; \ + fixed4 _LayerColor##index; \ + sampler2D _LayerSurface##index; \ + float4 _LayerSurface##index##_ST; \ + float4 _LayerSampleParameters##index; \ + float4 _LayerMaskParameters##index; \ + float4 _LayerMaskAxis##index; + +DECLARE_LAYER_UNIFORMS(0) +DECLARE_LAYER_UNIFORMS(1) +DECLARE_LAYER_UNIFORMS(2) +DECLARE_LAYER_UNIFORMS(3) +DECLARE_LAYER_UNIFORMS(4) +DECLARE_LAYER_UNIFORMS(5) +DECLARE_LAYER_UNIFORMS(6) +DECLARE_LAYER_UNIFORMS(7) + +struct VertexOutput +{ + float4 pos : SV_POSITION; + float2 texcoord : TEXCOORD0; + float3 worldPos : TEXCOORD1; + float3 worldNormal : TEXCOORD2; + float3 viewDir : TEXCOORD3; + float4 vertColor : COLOR; + +#if NORMAL_MAP_ON || PARALLAX_ON + float3 worldTangent : TANGENT; + float3 worldBitangent : TEXCOORD5; +#endif +}; + +float _Alpha; +int _BaseMaskType; +float4 _BaseMaskParameters; +float4 _BaseMaskAxis; +fixed4 _DarkMultiplier; +fixed4 _BaseColor; +sampler2D _AlphaMask; +float4 _AlphaMask_ST; +sampler2D _AlphaMask2; +float4 _AlphaMask2_ST; +sampler2D _NormalMap; +float4 _NormalMap_ST; +sampler2D _ParallaxMap; +float4 _ParallaxMap_ST; +sampler2D _RoughnessMap; +float4 _RoughnessMap_ST; +float4x4 _ProjectorWorldToLocal; + +VertexOutput vert(appdata_full v) +{ + VertexOutput o; + UNITY_INITIALIZE_OUTPUT(VertexOutput, o); + + o.texcoord = v.texcoord.xy; + o.worldPos = mul(unity_ObjectToWorld, v.vertex); + o.vertColor = v.color; + o.viewDir = normalize(_WorldSpaceCameraPos.xyz - o.worldPos); + o.worldNormal = normalize(mul(unity_ObjectToWorld, float4(v.normal, 0.0)).xyz); + +#if NORMAL_MAP_ON || PARALLAX_ON + o.worldTangent = normalize(mul(unity_ObjectToWorld, float4(v.tangent.xyz, 0.0)).xyz); + o.worldBitangent = normalize(cross(o.worldNormal, o.worldTangent) * v.tangent.w); +#endif + + o.pos = UnityObjectToClipPos(v.vertex); + return o; +} + +#ifndef NORMAL_MAP_ON +#define COMPUTE_NORMAL IN.worldNormal +#else +#define COMPUTE_NORMAL normalize(mul(lerp(float3(0, 0, 1), surfaceNormal, normalMapStrength), tangentTransform)) +#endif + +float3 ComputeColor( + VertexOutput IN, + float2 uv, +#if PARALLAX_ON || NORMAL_MAP_ON + float3x3 tangentTransform, +#endif +#ifdef NORMAL_MAP_ON + float3 surfaceNormal, +#endif + sampler2D surface, + float4 surface_ST, + fixed4 color, + int sampleMode, + float4 sampleParameters +) { + if (sampleMode == SAMPLE_MODE_TEXTURE) { + float2 panning = _Time.g * sampleParameters.xy; + return tex2D(surface, (uv + panning) * surface_ST.xy + surface_ST.zw).rgb * color.rgb; + } + else if (sampleMode == SAMPLE_MODE_TEXTURE_SINGLE_CHANNEL) { + float4 channelMask = sampleParameters; + float4 channels = tex2D(surface, uv * surface_ST.xy + surface_ST.zw); + return dot(channels, channelMask) * color.rgb; + } +#ifdef PARALLAX_ON + else if (sampleMode == SAMPLE_MODE_PARALLAX) { + float parallaxMinHeight = sampleParameters.x; + float parallaxMaxHeight = sampleParameters.y; + float parallaxValue = tex2D(_ParallaxMap, TRANSFORM_TEX(uv, _ParallaxMap)).r; + float scaledHeight = lerp(parallaxMinHeight, parallaxMaxHeight, parallaxValue); + float2 parallaxUV = mul(tangentTransform, IN.viewDir).xy * scaledHeight; + return tex2D(surface, (uv * surface_ST.xy + surface_ST.zw) + parallaxUV).rgb * color.rgb; + } +#endif + else if (sampleMode == SAMPLE_MODE_RSRM) { + float roughnessMin = sampleParameters.x; + float roughnessMax = sampleParameters.y; +#ifdef ROUGHNESS_ON + float roughnessValue = tex2D(_RoughnessMap, TRANSFORM_TEX(uv, _RoughnessMap)).r; + float scaledRoughness = lerp(roughnessMin, roughnessMax, roughnessValue); +#else + float scaledRoughness = roughnessMin; +#endif + +#ifdef NORMAL_MAP_ON + float normalMapStrength = sampleParameters.z; +#endif + float3 viewReflect = reflect(-IN.viewDir, COMPUTE_NORMAL); + float viewAngle = viewReflect.y * 0.5 + 0.5; + return tex2D(surface, float2(scaledRoughness, viewAngle)).rgb * color.rgb; + } + return color.rgb; +} + +float ComputeMask( + VertexOutput IN, +#ifdef NORMAL_MAP_ON + float3x3 tangentTransform, + float3 surfaceNormal, +#endif + int maskType, + float4 layerParameters, + float3 maskAxis +) { + if (maskType == MASK_TYPE_POSITIONAL) { + float centerDistance = layerParameters.x; + float fadeAbove = layerParameters.y; + float fadeBelow = layerParameters.z; + float3 objPos = mul(unity_WorldToObject, float4(IN.worldPos, 1.0)).xyz; + float d = dot(objPos, maskAxis); + if (d > centerDistance) { + return saturate(1.0 - (d - centerDistance) / fadeAbove); + } + else { + return saturate(1.0 - (centerDistance - d) / fadeBelow); + } + } + else if (maskType == MASK_TYPE_REFLECTION) { + float fadeStart = layerParameters.x; + float fadeEnd = layerParameters.y; +#ifdef NORMAL_MAP_ON + float normalMapStrength = layerParameters.z; +#endif + float power = layerParameters.w; + float3 viewReflect = reflect(-IN.viewDir, COMPUTE_NORMAL); + float d = max(0.0, dot(viewReflect, maskAxis)); + return saturate(1.0 - (d - fadeStart) / (fadeEnd - fadeStart)); + } + else if (maskType == MASK_TYPE_FRESNEL) { + float power = layerParameters.x; + float fadeStart = layerParameters.y; + float fadeEnd = layerParameters.z; +#ifdef NORMAL_MAP_ON + float normalMapStrength = layerParameters.w; +#endif + float d = saturate(1.0 - max(0.0, dot(IN.viewDir, COMPUTE_NORMAL))); + float p = pow(d, power); + return saturate(lerp(fadeStart, fadeEnd, p)); + } + else if (maskType == MASK_TYPE_PULSE) { + float distance = layerParameters.x; + float speed = layerParameters.y; + float power = layerParameters.z; + float3 objPos = mul(unity_WorldToObject, float4(IN.worldPos, 1.0)).xyz; + float d = dot(objPos, maskAxis); + float theta = 6.2831 * frac((d - _Time.g * speed) / distance); + return saturate(pow((sin(theta) * 0.5 + 0.5), power)); + } + else { + return 1.0; + } +} + +float3 ComputeBlend(float3 source, float3 blend, float mask, int blendMode) { + if (blendMode == BLEND_MODE_MULTIPLY) { + return source * (blend * mask); + } + else { + return source + (blend * mask); + } +} + +float4 ComputeSurface(VertexOutput IN) +{ +#if PROJECTOR_ON + float3 projectorPos = mul(_ProjectorWorldToLocal, float4(IN.worldPos, 1.0)).xyz; + if (abs(projectorPos.x) > 1.0 || abs(projectorPos.y) > 1.0 || abs(projectorPos.z) > 1.0) + { + discard; + } + float2 uv = projectorPos.xy * 0.5 + 0.5; +#else + float2 uv = IN.texcoord.xy; +#endif + + fixed4 c = _BaseColor; + IN.worldNormal = normalize(IN.worldNormal); + +#if PARALLAX_ON || NORMAL_MAP_ON + float3x3 tangentTransform = float3x3(IN.worldTangent, IN.worldBitangent, IN.worldNormal); +#endif + +#ifdef NORMAL_MAP_ON + float3 surfaceNormal = UnpackNormal(tex2D(_NormalMap, TRANSFORM_TEX(uv, _NormalMap))); +#endif + +#if PARALLAX_ON || NORMAL_MAP_ON +#ifndef NORMAL_MAP_ON +#define COLOR_INPUTS IN, uv, tangentTransform +#define MASK_INPUTS IN +#else +#define COLOR_INPUTS IN, uv, tangentTransform, surfaceNormal +#define MASK_INPUTS IN, tangentTransform, surfaceNormal +#endif +#else +#define COLOR_INPUTS IN, uv +#define MASK_INPUTS IN +#endif + +#define LAYER_COLOR(index) ComputeColor(COLOR_INPUTS, _LayerSurface##index, _LayerSurface##index##_ST, _LayerColor##index, _LayerSampleMode##index, _LayerSampleParameters##index) +#define LAYER_MASK(index) ComputeMask(MASK_INPUTS, _LayerMaskType##index, _LayerMaskParameters##index, _LayerMaskAxis##index##.xyz) +#define LAYER_BLEND(index, c) ComputeBlend(c, LAYER_COLOR(index), LAYER_MASK(index), _LayerBlendMode##index) + + c.rgb = LAYER_BLEND(0, c.rgb); +#if LAYER_COUNT > 1 + c.rgb = LAYER_BLEND(1, c.rgb); +#endif +#if LAYER_COUNT > 2 + c.rgb = LAYER_BLEND(2, c.rgb); +#endif +#if LAYER_COUNT > 3 + c.rgb = LAYER_BLEND(3, c.rgb); +#endif +#if LAYER_COUNT > 4 + c.rgb = LAYER_BLEND(4, c.rgb); +#endif +#if LAYER_COUNT > 5 + c.rgb = LAYER_BLEND(5, c.rgb); +#endif +#if LAYER_COUNT > 6 + c.rgb = LAYER_BLEND(6, c.rgb); +#endif +#if LAYER_COUNT > 7 + c.rgb = LAYER_BLEND(7, c.rgb); +#endif + +#ifdef VERTALPHA_ON + float scaledValue = IN.vertColor.a * 2.0; + float alpha0weight = max(0.0, 1.0 - scaledValue); + float alpha2weight = max(0.0, scaledValue - 1.0); + float alpha1weight = 1.0 - alpha0weight - alpha2weight; + c.a = _Alpha * c.a * (tex2D(_AlphaMask, TRANSFORM_TEX(uv, _AlphaMask)).r * alpha1weight + tex2D(_AlphaMask2, TRANSFORM_TEX(uv, _AlphaMask2)).r * alpha2weight + alpha0weight) * ComputeMask(MASK_INPUTS, _BaseMaskType, _BaseMaskParameters, _BaseMaskAxis); +#else + c.a = _Alpha * c.a * tex2D(_AlphaMask, TRANSFORM_TEX(uv, _AlphaMask)).r * IN.vertColor.a * ComputeMask(MASK_INPUTS, _BaseMaskType, _BaseMaskParameters, _BaseMaskAxis); +#endif + c.rgb = lerp(c.rgb, c.rgb * _DarkMultiplier, IN.vertColor.r); + + return c; +} + +#endif diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc.meta b/Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc.meta new file mode 100644 index 0000000..6a3728f --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 80b6b34e742970d4bb0cdef9c74b04ae +timeCreated: 1525971186 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarPBRV2Simple.shader b/Assets/Oculus/Avatar/Resources/Materials/AvatarPBRV2Simple.shader new file mode 100644 index 0000000..7524dc9 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarPBRV2Simple.shader @@ -0,0 +1,64 @@ +// +// OvrAvatar Simple Avatar Shader +// Uses the Avatar Material Model on the Standard Surface Shader +// + +Shader "OvrAvatar/AvatarPBRV2Simple" +{ + Properties + { + [NoScaleOffset] _MainTex("Color (RGB)", 2D) = "white" {} + [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {} + [NoScaleOffset] _RoughnessMap("Roughness Map", 2D) = "black" {} + } + + SubShader + { + Blend One Zero + Cull Back + CGPROGRAM +#pragma surface surf Standard keepalpha fullforwardshadows + +#pragma target 3.0 + +#pragma fragmentoption ARB_precision_hint_fastest + +#include "UnityCG.cginc" + + sampler2D _MainTex; + sampler2D _NormalMap; + sampler2D _RoughnessMap; + + struct Input + { + float2 uv_MainTex; + float2 uv_NormalMap; + float2 uv_RoughnessMap; + float3 viewDir; + float3 worldNormal; INTERNAL_DATA + }; + + void surf(Input IN, inout SurfaceOutputStandard o) + { + +#if (UNITY_VERSION >= 20171) + o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex)); +#else + o.Normal = tex2D(_NormalMap, IN.uv_MainTex) * 2.0 - 1.0; +#endif + half4 roughnessTex = tex2D(_RoughnessMap, IN.uv_MainTex); + + o.Albedo = tex2D(_MainTex, IN.uv_MainTex); + o.Smoothness = roughnessTex.a; + o.Metallic = roughnessTex.r; + +#if !defined(UNITY_COLORSPACE_GAMMA) + o.Albedo = GammaToLinearSpace(o.Albedo); +#endif + o.Albedo = saturate(o.Albedo); + o.Alpha = 1.0; + } + ENDCG + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarPBRV2Simple.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/AvatarPBRV2Simple.shader.meta new file mode 100644 index 0000000..0df9db8 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarPBRV2Simple.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 28729c6ae5a33b04cb2f7956f3f3fc01 +ShaderImporter: + externalObjects: {} + defaultTextures: [] + nonModifiableTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShader.shader b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShader.shader new file mode 100644 index 0000000..3d589dd --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShader.shader @@ -0,0 +1,141 @@ +Shader "OvrAvatar/AvatarSurfaceShader" { + Properties{ + // Global parameters + _Alpha("Alpha", Range(0.0, 1.0)) = 1.0 + _DarkMultiplier("Dark Multiplier", Color) = (0.6, 0.6, 0.6, 1.0) + _BaseColor("Base Color", Color) = (0.0, 0.0, 0.0, 0.0) + _BaseMaskType("Base Mask Type", Int) = 0 + _BaseMaskParameters("Base Mask Parameters", Vector) = (0, 0, 0, 0) + _BaseMaskAxis("Base Mask Axis", Vector) = (0, 1, 0, 0) + _AlphaMask("Alpha Mask", 2D) = "white" {} + _NormalMap("Normal Map", 2D) = "" {} + _ParallaxMap("Parallax Map", 2D) = "" {} + _RoughnessMap("Roughness Map", 2D) = "" {} + + // Layer 0 parameters + _LayerSampleMode0("Layer Sample Mode 0", Int) = 0 + _LayerBlendMode0("Layer Blend Mode 0", Int) = 0 + _LayerMaskType0("Layer Mask Type 0", Int) = 0 + _LayerColor0("Layer Color 0", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface0("Layer Surface 0", 2D) = "" {} + _LayerSampleParameters0("Layer Sample Parameters 0", Vector) = (0, 0, 0, 0) + _LayerMaskParameters0("Layer Mask Parameters 0", Vector) = (0, 0, 0, 0) + _LayerMaskAxis0("Layer Mask Axis 0", Vector) = (0, 1, 0, 0) + + // Layer 1 parameters + _LayerSampleMode1("Layer Sample Mode 1", Int) = 0 + _LayerBlendMode1("Layer Blend Mode 1", Int) = 0 + _LayerMaskType1("Layer Mask Type 1", Int) = 0 + _LayerColor1("Layer Color 1", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface1("Layer Surface 1", 2D) = "" {} + _LayerSampleParameters1("Layer Sample Parameters 1", Vector) = (0, 0, 0, 0) + _LayerMaskParameters1("Layer Mask Parameters 1", Vector) = (0, 0, 0, 0) + _LayerMaskAxis1("Layer Mask Axis 1", Vector) = (0, 1, 0, 0) + + // Layer 2 parameters + _LayerSampleMode2("Layer Sample Mode 2", Int) = 0 + _LayerBlendMode2("Layer Blend Mode 2", Int) = 0 + _LayerMaskType2("Layer Mask Type 2", Int) = 0 + _LayerColor2("Layer Color 2", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface2("Layer Surface 2", 2D) = "" {} + _LayerSampleParameters2("Layer Sample Parameters 2", Vector) = (0, 0, 0, 0) + _LayerMaskParameters2("Layer Mask Parameters 2", Vector) = (0, 0, 0, 0) + _LayerMaskAxis2("Layer Mask Axis 2", Vector) = (0, 1, 0, 0) + + // Layer 3 parameters + _LayerSampleMode3("Layer Sample Mode 3", Int) = 0 + _LayerBlendMode3("Layer Blend Mode 3", Int) = 0 + _LayerMaskType3("Layer Mask Type 3", Int) = 0 + _LayerColor3("Layer Color 3", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface3("Layer Surface 3", 2D) = "" {} + _LayerSampleParameters3("Layer Sample Parameters 3", Vector) = (0, 0, 0, 0) + _LayerMaskParameters3("Layer Mask Parameters 3", Vector) = (0, 0, 0, 0) + _LayerMaskAxis3("Layer Mask Axis 3", Vector) = (0, 1, 0, 0) + + // Layer 4 parameters + _LayerSampleMode4("Layer Sample Mode 4", Int) = 0 + _LayerBlendMode4("Layer Blend Mode 4", Int) = 0 + _LayerMaskType4("Layer Mask Type 4", Int) = 0 + _LayerColor4("Layer Color 4", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface4("Layer Surface 4", 2D) = "" {} + _LayerSampleParameters4("Layer Sample Parameters 4", Vector) = (0, 0, 0, 0) + _LayerMaskParameters4("Layer Mask Parameters 4", Vector) = (0, 0, 0, 0) + _LayerMaskAxis4("Layer Mask Axis 4", Vector) = (0, 1, 0, 0) + + // Layer 5 parameters + _LayerSampleMode5("Layer Sample Mode 5", Int) = 0 + _LayerBlendMode5("Layer Blend Mode 5", Int) = 0 + _LayerMaskType5("Layer Mask Type 5", Int) = 0 + _LayerColor5("Layer Color 5", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface5("Layer Surface 5", 2D) = "" {} + _LayerSampleParameters5("Layer Sample Parameters 5", Vector) = (0, 0, 0, 0) + _LayerMaskParameters5("Layer Mask Parameters 5", Vector) = (0, 0, 0, 0) + _LayerMaskAxis5("Layer Mask Axis 5", Vector) = (0, 1, 0, 0) + + // Layer 6 parameters + _LayerSampleMode6("Layer Sample Mode 6", Int) = 0 + _LayerBlendMode6("Layer Blend Mode 6", Int) = 0 + _LayerMaskType6("Layer Mask Type 6", Int) = 0 + _LayerColor6("Layer Color 6", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface6("Layer Surface 6", 2D) = "" {} + _LayerSampleParameters6("Layer Sample Parameters 6", Vector) = (0, 0, 0, 0) + _LayerMaskParameters6("Layer Mask Parameters 6", Vector) = (0, 0, 0, 0) + _LayerMaskAxis6("Layer Mask Axis 6", Vector) = (0, 1, 0, 0) + + // Layer 7 parameters + _LayerSampleMode7("Layer Sample Mode 7", Int) = 0 + _LayerBlendMode7("Layer Blend Mode 7", Int) = 0 + _LayerMaskType7("Layer Mask Type 7", Int) = 0 + _LayerColor7("Layer Color 7", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface7("Layer Surface 7", 2D) = "" {} + _LayerSampleParameters7("Layer Sample Parameters 7", Vector) = (0, 0, 0, 0) + _LayerMaskParameters7("Layer Mask Parameters 7", Vector) = (0, 0, 0, 0) + _LayerMaskAxis7("Layer Mask Axis 7", Vector) = (0, 1, 0, 0) + } + + SubShader + { + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + Blend SrcAlpha OneMinusSrcAlpha + ZWrite Off + LOD 200 + + Pass + { + Name "FORWARD" + Tags + { + "LightMode" = "ForwardBase" + } + + CGPROGRAM + #pragma only_renderers d3d11 gles3 gles + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma multi_compile PROJECTOR_OFF PROJECTOR_ON + #pragma multi_compile NORMAL_MAP_OFF NORMAL_MAP_ON + #pragma multi_compile PARALLAX_OFF PARALLAX_ON + #pragma multi_compile ROUGHNESS_OFF ROUGHNESS_ON + #pragma multi_compile VERTALPHA_OFF VERTALPHA_ON + #pragma multi_compile LAYERS_1 LAYERS_2 LAYERS_3 LAYERS_4 LAYERS_5 LAYERS_6 LAYERS_7 LAYERS_8 + + #include "Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc" + + float4 frag(VertexOutput IN) : COLOR + { + return ComputeSurface(IN); + } + + ENDCG + } + } + + FallBack "Diffuse" + CustomEditor "AvatarMaterialEditor" +} diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShader.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShader.shader.meta new file mode 100644 index 0000000..9c95091 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 73f67c4e7bf718b4385aa6b1f8a06591 +timeCreated: 1525971190 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBS.shader b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBS.shader new file mode 100644 index 0000000..5ba674a --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBS.shader @@ -0,0 +1,79 @@ +// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' + +Shader "OvrAvatar/AvatarSurfaceShaderPBS" { + Properties{ + // Global parameters + _Alpha("Alpha", Range(0.0, 1.0)) = 1.0 + _Albedo("Albedo (RGB)", 2D) = "" {} + _Surface("Metallic (R) Occlusion (G) and Smoothness (A)", 2D) = "" {} + } + SubShader{ + Tags { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + Pass { + ZWrite On + Cull Off + ColorMask 0 + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #include "UnityCG.cginc" + + struct v2f { + float4 position : SV_POSITION; + }; + v2f vert(appdata_full v) { + // Output + v2f output; + output.position = UnityObjectToClipPos(v.vertex); + return output; + } + + float4 frag(v2f input) : COLOR { + return 0; + } + ENDCG + } + + LOD 200 + + CGPROGRAM + +// Physically based Standard lighting model, and enable shadows on all light types +#pragma surface surf Standard vertex:vert nolightmap alpha noforwardadd + +float _Alpha; +sampler2D _Albedo; +float4 _Albedo_ST; +sampler2D _Surface; +float4 _Surface_ST; + +struct Input { + float2 texcoord; +}; + +void vert(inout appdata_full v, out Input o) { + UNITY_INITIALIZE_OUTPUT(Input, o); + o.texcoord = v.texcoord.xy; +} + +void surf (Input IN, inout SurfaceOutputStandard o) { + o.Albedo = tex2D(_Albedo, TRANSFORM_TEX(IN.texcoord, _Albedo)).rgb; + float4 surfaceParams = tex2D(_Surface, TRANSFORM_TEX(IN.texcoord, _Surface)); + o.Metallic = surfaceParams.r; + o.Occlusion = surfaceParams.g; + o.Smoothness = surfaceParams.a; + o.Alpha = _Alpha; +} + +#pragma only_renderers d3d11 gles3 gles + +ENDCG + } + FallBack "Diffuse" +} diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBS.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBS.shader.meta new file mode 100644 index 0000000..e55e87e --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBS.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 5e52aa58207bbf24d8eb8ec969e9ae88 +timeCreated: 1525971190 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBSV2.shader b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBSV2.shader new file mode 100644 index 0000000..1742a5e --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBSV2.shader @@ -0,0 +1,39 @@ +Shader "OvrAvatar/AvatarSurfaceShaderPBSV2" { + Properties { + _AlbedoMultiplier ("Albedo Multiplier", Color) = (1,1,1,1) + _Albedo ("Albedo (RGB)", 2D) = "white" {} + _Metallicness("Metallicness", 2D) = "grey" {} + _GlossinessScale ("Glossiness Scale", Range(0,1)) = 0.5 + } + SubShader { + Tags { "RenderType"="Opaque" } + LOD 200 + + CGPROGRAM + // Physically based Standard lighting model, and enable shadows on all light types + #pragma surface surf Standard fullforwardshadows + + // Use shader model 3.0 target, to get nicer looking lighting + #pragma target 3.0 + + sampler2D _Albedo; + sampler2D _Metallicness; + + struct Input { + float2 uv_Albedo; + }; + + float _GlossinessScale; + float4 _AlbedoMultiplier; + + void surf (Input IN, inout SurfaceOutputStandard o) { + fixed4 c = tex2D (_Albedo, IN.uv_Albedo) * _AlbedoMultiplier; + o.Albedo = c.rgb; + o.Metallic = tex2D (_Metallicness, IN.uv_Albedo).r; + o.Smoothness = _GlossinessScale; + o.Alpha = 1.0; + } + ENDCG + } + FallBack "Diffuse" +} \ No newline at end of file diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBSV2.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBSV2.shader.meta new file mode 100644 index 0000000..b0a14c3 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderPBSV2.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 176faebcc612eb147900defeda2149cb +timeCreated: 1525971187 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderSelfOccluding.shader b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderSelfOccluding.shader new file mode 100644 index 0000000..1a97029 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderSelfOccluding.shader @@ -0,0 +1,175 @@ +Shader "OvrAvatar/AvatarSurfaceShaderSelfOccluding" { + Properties{ + // Global parameters + _Alpha("Alpha", Range(0.0, 1.0)) = 1.0 + _DarkMultiplier("Dark Multiplier", Color) = (0.6, 0.6, 0.6, 1.0) + _BaseColor("Base Color", Color) = (0.0, 0.0, 0.0, 0.0) + _BaseMaskType("Base Mask Type", Int) = 0 + _BaseMaskParameters("Base Mask Parameters", Vector) = (0, 0, 0, 0) + _BaseMaskAxis("Base Mask Axis", Vector) = (0, 1, 0, 0) + _AlphaMask("Alpha Mask", 2D) = "white" {} + _NormalMap("Normal Map", 2D) = "" {} + _ParallaxMap("Parallax Map", 2D) = "" {} + _RoughnessMap("Roughness Map", 2D) = "" {} + + // Layer 0 parameters + _LayerSampleMode0("Layer Sample Mode 0", Int) = 0 + _LayerBlendMode0("Layer Blend Mode 0", Int) = 0 + _LayerMaskType0("Layer Mask Type 0", Int) = 0 + _LayerColor0("Layer Color 0", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface0("Layer Surface 0", 2D) = "" {} + _LayerSampleParameters0("Layer Sample Parameters 0", Vector) = (0, 0, 0, 0) + _LayerMaskParameters0("Layer Mask Parameters 0", Vector) = (0, 0, 0, 0) + _LayerMaskAxis0("Layer Mask Axis 0", Vector) = (0, 1, 0, 0) + + // Layer 1 parameters + _LayerSampleMode1("Layer Sample Mode 1", Int) = 0 + _LayerBlendMode1("Layer Blend Mode 1", Int) = 0 + _LayerMaskType1("Layer Mask Type 1", Int) = 0 + _LayerColor1("Layer Color 1", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface1("Layer Surface 1", 2D) = "" {} + _LayerSampleParameters1("Layer Sample Parameters 1", Vector) = (0, 0, 0, 0) + _LayerMaskParameters1("Layer Mask Parameters 1", Vector) = (0, 0, 0, 0) + _LayerMaskAxis1("Layer Mask Axis 1", Vector) = (0, 1, 0, 0) + + // Layer 2 parameters + _LayerSampleMode2("Layer Sample Mode 2", Int) = 0 + _LayerBlendMode2("Layer Blend Mode 2", Int) = 0 + _LayerMaskType2("Layer Mask Type 2", Int) = 0 + _LayerColor2("Layer Color 2", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface2("Layer Surface 2", 2D) = "" {} + _LayerSampleParameters2("Layer Sample Parameters 2", Vector) = (0, 0, 0, 0) + _LayerMaskParameters2("Layer Mask Parameters 2", Vector) = (0, 0, 0, 0) + _LayerMaskAxis2("Layer Mask Axis 2", Vector) = (0, 1, 0, 0) + + // Layer 3 parameters + _LayerSampleMode3("Layer Sample Mode 3", Int) = 0 + _LayerBlendMode3("Layer Blend Mode 3", Int) = 0 + _LayerMaskType3("Layer Mask Type 3", Int) = 0 + _LayerColor3("Layer Color 3", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface3("Layer Surface 3", 2D) = "" {} + _LayerSampleParameters3("Layer Sample Parameters 3", Vector) = (0, 0, 0, 0) + _LayerMaskParameters3("Layer Mask Parameters 3", Vector) = (0, 0, 0, 0) + _LayerMaskAxis3("Layer Mask Axis 3", Vector) = (0, 1, 0, 0) + + // Layer 4 parameters + _LayerSampleMode4("Layer Sample Mode 4", Int) = 0 + _LayerBlendMode4("Layer Blend Mode 4", Int) = 0 + _LayerMaskType4("Layer Mask Type 4", Int) = 0 + _LayerColor4("Layer Color 4", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface4("Layer Surface 4", 2D) = "" {} + _LayerSampleParameters4("Layer Sample Parameters 4", Vector) = (0, 0, 0, 0) + _LayerMaskParameters4("Layer Mask Parameters 4", Vector) = (0, 0, 0, 0) + _LayerMaskAxis4("Layer Mask Axis 4", Vector) = (0, 1, 0, 0) + + // Layer 5 parameters + _LayerSampleMode5("Layer Sample Mode 5", Int) = 0 + _LayerBlendMode5("Layer Blend Mode 5", Int) = 0 + _LayerMaskType5("Layer Mask Type 5", Int) = 0 + _LayerColor5("Layer Color 5", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface5("Layer Surface 5", 2D) = "" {} + _LayerSampleParameters5("Layer Sample Parameters 5", Vector) = (0, 0, 0, 0) + _LayerMaskParameters5("Layer Mask Parameters 5", Vector) = (0, 0, 0, 0) + _LayerMaskAxis5("Layer Mask Axis 5", Vector) = (0, 1, 0, 0) + + // Layer 6 parameters + _LayerSampleMode6("Layer Sample Mode 6", Int) = 0 + _LayerBlendMode6("Layer Blend Mode 6", Int) = 0 + _LayerMaskType6("Layer Mask Type 6", Int) = 0 + _LayerColor6("Layer Color 6", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface6("Layer Surface 6", 2D) = "" {} + _LayerSampleParameters6("Layer Sample Parameters 6", Vector) = (0, 0, 0, 0) + _LayerMaskParameters6("Layer Mask Parameters 6", Vector) = (0, 0, 0, 0) + _LayerMaskAxis6("Layer Mask Axis 6", Vector) = (0, 1, 0, 0) + + // Layer 7 parameters + _LayerSampleMode7("Layer Sample Mode 7", Int) = 0 + _LayerBlendMode7("Layer Blend Mode 7", Int) = 0 + _LayerMaskType7("Layer Mask Type 7", Int) = 0 + _LayerColor7("Layer Color 7", Color) = (1.0, 1.0, 1.0, 1.0) + _LayerSurface7("Layer Surface 7", 2D) = "" {} + _LayerSampleParameters7("Layer Sample Parameters 7", Vector) = (0, 0, 0, 0) + _LayerMaskParameters7("Layer Mask Parameters 7", Vector) = (0, 0, 0, 0) + _LayerMaskAxis7("Layer Mask Axis 7", Vector) = (0, 1, 0, 0) + } + + SubShader + { + Tags + { + "Queue" = "Transparent" + "RenderType" = "Transparent" + } + + Pass + { + ZWrite On + Cull Off + ColorMask 0 + Offset 1, 1 + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #include "UnityCG.cginc" + + struct v2f + { + float4 position : SV_POSITION; + }; + + v2f vert(appdata_full v) + { + // Output + v2f output; + output.position = UnityObjectToClipPos(v.vertex); + return output; + } + + float4 frag(v2f input) : COLOR + { + return 0; + } + + ENDCG + } + + Blend SrcAlpha OneMinusSrcAlpha + ZWrite Off + LOD 200 + + Pass + { + Name "FORWARD" + Tags + { + "LightMode" = "ForwardBase" + } + + CGPROGRAM + #pragma only_renderers d3d11 gles3 gles + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma multi_compile PROJECTOR_OFF PROJECTOR_ON + #pragma multi_compile NORMAL_MAP_OFF NORMAL_MAP_ON + #pragma multi_compile PARALLAX_OFF PARALLAX_ON + #pragma multi_compile ROUGHNESS_OFF ROUGHNESS_ON + #pragma multi_compile VERTALPHA_OFF VERTALPHA_ON + #pragma multi_compile LAYERS_1 LAYERS_2 LAYERS_3 LAYERS_4 LAYERS_5 LAYERS_6 LAYERS_7 LAYERS_8 + + #include "Assets/Oculus/Avatar/Resources/Materials/AvatarMaterialStateShader.cginc" + + float4 frag(VertexOutput IN) : SV_Target + { + return ComputeSurface(IN); + } + + ENDCG + } + } + + FallBack "Diffuse" + CustomEditor "AvatarMaterialEditor" +} diff --git a/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderSelfOccluding.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderSelfOccluding.shader.meta new file mode 100644 index 0000000..10e789e --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/AvatarSurfaceShaderSelfOccluding.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 69f342b79d37541489919a19cfd8a924 +timeCreated: 1525971190 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive.meta b/Assets/Oculus/Avatar/Resources/Materials/Expressive.meta new file mode 100644 index 0000000..f44e09b --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 08113db6bc6c49046beb604cc64556ba +folderAsset: yes +timeCreated: 1540579933 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/AvatarEyeLens.shader b/Assets/Oculus/Avatar/Resources/Materials/Expressive/AvatarEyeLens.shader new file mode 100644 index 0000000..522dca3 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/AvatarEyeLens.shader @@ -0,0 +1,86 @@ +// +// OvrAvatar eye lens shader +// +// Generates glint on the eye lens of expressive avatars +// + +Shader "OvrAvatar/Avatar_EyeLens" +{ + Properties + { + _Cube("Cubemap Reflection", CUBE) = "black" {} + _ReflectionIntensity("Reflection Intensity", Range(0.0,1.0)) = 0.2 + _GlintStrength("Glint Strength", Range(0, 10)) = 1.57 + _GlintSpead("Glint Spead", Range(32, 2048)) = 600 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + } + + SubShader + { + Tags { "LightMode" = "ForwardBase" "Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True" } + Pass + { + Blend SrcAlpha OneMinusSrcAlpha + + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma fragmentoption ARB_precision_hint_fastest + #pragma target 3.0 + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + #include "AutoLight.cginc" + + samplerCUBE _Cube; + half _ReflectionIntensity; + half _GlintStrength; + half _GlintSpead; + half _Alpha; + + struct VertexInput + { + float4 vertex : POSITION; + float3 normal : NORMAL; + }; + + struct VertexOutput + { + float4 pos : SV_POSITION; + float4 posWorld : TEXCOORD1; + float3 normalDir : TEXCOORD2; + }; + + VertexOutput vert(VertexInput v) + { + VertexOutput o = (VertexOutput)0; + o.normalDir = UnityObjectToWorldNormal(v.normal); + o.posWorld = mul(unity_ObjectToWorld, v.vertex); + o.pos = UnityObjectToClipPos(v.vertex); + return o; + } + + float4 frag(VertexOutput i) : COLOR + { + i.normalDir = normalize(i.normalDir); + half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); + half NdotLV = max(0, dot(i.normalDir, normalize(_WorldSpaceLightPos0.xyz + viewDirection))); + half3 spec = pow(NdotLV, _GlintSpead) * _GlintStrength; + + // Sample the default reflection cubemap using the reflection vector + half3 viewReflectDirection = reflect(-viewDirection, i.normalDir); + half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, viewReflectDirection); + // Decode cubemap data into actual color + half3 reflectionColor = DecodeHDR(skyData, unity_SpecCube0_HDR); + + half4 finalColor; + finalColor.rgb = reflectionColor.rgb * _ReflectionIntensity; + finalColor.rgb += spec; + finalColor.a = (finalColor.r + finalColor.g + finalColor.b) / 3; + + return finalColor; + } + ENDCG + } + } + FallBack "Diffuse" +} diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/AvatarEyeLens.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Expressive/AvatarEyeLens.shader.meta new file mode 100644 index 0000000..2111fca --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/AvatarEyeLens.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8392f54e79937ed4bb1b692a143dc02b +timeCreated: 1539383496 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_CombinedMeshExpressive.shader b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_CombinedMeshExpressive.shader new file mode 100644 index 0000000..2d95748 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_CombinedMeshExpressive.shader @@ -0,0 +1,280 @@ +// +// OvrAvatar Mobile combined mesh expressive shader +// For use on expressive face meshes +// Texture array approach for rendering a combined mesh avatar with blend shape expression +// Coupled with OvrAvatarMaterialManager to populate the texture arrays +// +// Unity vertex-fragnment implementation +// Simplified lighting model recommended for use on mobile supporting one directional light +// Surface shader recommended on PC +// +// Uses transparent queue for fade effects +// +// Color and appearance of the facial regions controlled via G&B channels in roughness texture +// Pupil size controlled by manipulating UV coordinates +// +// Shader keywords: +// - SECONDARY_LIGHT_ON SECONDARY_LIGHT_OFF +// Enable SECONDARY_LIGHT_ON for a second "light" comprised of _SecondaryLightDirection and +// _SecondaryLightColor This will influence the rim effect providing a lit contour to the avatar +// + + +Shader "OvrAvatar/Avatar_Mobile_CombinedMeshExpressive" +{ + Properties + { + [NoScaleOffset] _MainTex("Main Texture Array", 2DArray) = "white" {} + [NoScaleOffset] _NormalMap("Normal Map Array", 2DArray) = "bump" {} + [NoScaleOffset] _RoughnessMap("Roughness Map Array", 2DArray) = "black" {} + + _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + + // Index into the texture array needs an offset for precision + _Slices("Texture Array Slices", int) = 4.97 + + _PupilSize("Pupil Size", Range(-1, 2)) = 0 + _LipSmoothness("Lip Smoothness", Range(0, 1)) = 0 + + _MaskColorIris("Iris Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorLips("Lips Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorBrows("Brows Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorLashes("Lashes Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorSclera("Sclera Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorGums("Gums Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorTeeth("Teeth Color", Color) = (0.0,0.0,0.0,1.0) + + [HideInInspector] _SrcBlend("", Float) = 1 + [HideInInspector] _DstBlend("", Float) = 0 + } + + SubShader + { + Tags { "LightMode" = "ForwardBase" "IgnoreProjector" = "True"} + Pass + { + Blend [_SrcBlend] [_DstBlend] + Cull Back + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.5 + #pragma fragmentoption ARB_precision_hint_fastest + #pragma multi_compile SECONDARY_LIGHT_OFF SECONDARY_LIGHT_ON + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + + UNITY_DECLARE_TEX2DARRAY(_MainTex); + UNITY_DECLARE_TEX2DARRAY(_NormalMap); + float4 _NormalMap_ST; + UNITY_DECLARE_TEX2DARRAY(_RoughnessMap); + + int _Slices; + + half _Dimmer; + half _Alpha; + + half4 _BaseColor[5]; + half _DiffuseIntensity[5]; + half _RimIntensity[5]; + half _ReflectionIntensity[5]; + + half3 _SecondaryLightDirection; + half4 _SecondaryLightColor; + + half _PupilSize; + half _LipSmoothness; + + fixed4 _MaskColorIris; + fixed4 _MaskColorSclera; + fixed4 _MaskColorBrows; + fixed4 _MaskColorLashes; + fixed4 _MaskColorLashesEnd; + fixed4 _MaskColorLips; + fixed4 _MaskColorGums; + fixed4 _MaskColorTeeth; + + static const int ONE = 1; + static const fixed ALPHA_CLIP_THRESHOLD = 0.7; + static const int IRIS_BRIGHTNESS_MODIFIER = 2; + static const fixed SCLERA_BRIGHTNESS_MODIFIER = 1.2; + static const fixed LIP_SMOOTHNESS_MULTIPLIER = 0.5; + static const fixed LIP_SMOOTHNESS_MIN_NDOTL = 0.3; + static const fixed BROWS_LASHES_DIFFUSEINTENSITY = ONE - 0.25; + static const int COLOR_MULTIPLIER = 255; + static const half2 PUPIL_CENTER_UV = half2(0.127, 0.1175); + static const half DILATION_ENVELOPE = 0.024; + static const half2 EYE_REGION_UV = PUPIL_CENTER_UV + DILATION_ENVELOPE; + + static const int MASK_SLICE_SIZE = 17; + static const half MASK_SLICE_THRESHOLD = MASK_SLICE_SIZE * 0.5f; + static const int MASK_INDEX_IRIS = 255; + static const int MASK_INDEX_SCLERA = 238; + static const int MASK_INDEX_LASHES = 221; + static const int MASK_INDEX_LIPS = 204; + static const int MASK_INDEX_GUMS = 187; + static const int MASK_INDEX_TEETH = 170; + static const int MASK_INDEX_BROWS = 153; + + struct appdata + { + float4 vertex: POSITION; + float3 normal: NORMAL; + float4 tangent: TANGENT; + float2 texcoord: TEXCOORD0; + float4 vertexColor : COLOR0; + }; + + struct v2f + { + float4 pos : SV_POSITION; + float3 uv : TEXCOORD0; + float4 posWorld: TEXCOORD1; + float3 normalDir: TEXCOORD2; + float3 tangentDir: TEXCOORD3; + float3 bitangentDir: TEXCOORD4; + }; + + v2f vert(appdata v) + { + v2f o; + + // Calculate tangents for normal mapping + o.normalDir = normalize(UnityObjectToWorldNormal(v.normal)); + o.tangentDir = normalize(mul(unity_ObjectToWorld, half4(v.tangent.xyz, 0.0)).xyz); + o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); + + o.posWorld = mul(unity_ObjectToWorld, v.vertex); + o.pos = UnityObjectToClipPos(v.vertex); + o.uv.xy = v.texcoord; + o.uv.z = v.vertexColor.x * _Slices; + return o; + } + + fixed4 frag(v2f i) : COLOR + { + // Pupil size offsets uv coords + if (all(i.uv.xy < EYE_REGION_UV)) + { + i.uv.xy -= PUPIL_CENTER_UV; + half pupil = saturate(length(i.uv.xy) / DILATION_ENVELOPE); + i.uv.xy *= lerp(1.0, pupil, _PupilSize); + i.uv.xy += PUPIL_CENTER_UV; + } + + // Diffuse texture sample + float4 albedoColor = UNITY_SAMPLE_TEX2DARRAY(_MainTex, i.uv); + + // Process normal map + float3 transformedNormalUV = i.uv; + transformedNormalUV.xy = float2(TRANSFORM_TEX(i.uv.xy, _NormalMap)); + float3 normalMap = UNITY_SAMPLE_TEX2DARRAY(_NormalMap, transformedNormalUV) * 2.0 - ONE; + float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir); + float3 normalDirection = normalize(mul(normalMap.rgb, tangentTransform)); + + // Roughness contains metallic in r, smoothness in a, mask region in b and mask control in g + half4 roughnessTex = UNITY_SAMPLE_TEX2DARRAY(_RoughnessMap, i.uv); + + // Normal/Light/View calculations + half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); + half VdotN = saturate(dot(viewDirection, normalDirection)); + half NdotL = saturate(dot(normalDirection, normalize(_WorldSpaceLightPos0.xyz))); + + // Sample the default reflection cubemap using the reflection vector + float3 worldReflection = reflect(-viewDirection, normalDirection); + half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldReflection); + // Decode cubemap data into actual color + half3 reflectionColor = DecodeHDR(skyData, unity_SpecCube0_HDR); + + // Get index into texture array + int componentIndex = floor(i.uv.z + 0.5); + + // Base color from array + float4 baseColor = _BaseColor[componentIndex]; + + // Color space conversions if we are in linear +#ifndef UNITY_COLORSPACE_GAMMA + _MaskColorIris.rgb = LinearToGammaSpace(_MaskColorIris.rgb); + _MaskColorLips.rgb = LinearToGammaSpace(_MaskColorLips.rgb); + _MaskColorBrows.rgb = LinearToGammaSpace(_MaskColorBrows.rgb); + _MaskColorLashes.rgb = LinearToGammaSpace(_MaskColorLashes.rgb); + _MaskColorLashesEnd.rgb = LinearToGammaSpace(_MaskColorLashesEnd.rgb); + _MaskColorSclera.rgb = LinearToGammaSpace(_MaskColorSclera.rgb); + _MaskColorGums.rgb = LinearToGammaSpace(_MaskColorGums.rgb); + _MaskColorTeeth.rgb = LinearToGammaSpace(_MaskColorTeeth.rgb); +#endif + + // Calculate color masks + half irisScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_IRIS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half lipsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LIPS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half browsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_BROWS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + half lashesScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LASHES) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half scleraScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_SCLERA) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half teethScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_TEETH) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + half gumsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_GUMS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + + half3 maskIris = irisScalar * (_MaskColorIris * IRIS_BRIGHTNESS_MODIFIER - baseColor.rgb); + half3 maskBrows = browsScalar * (_MaskColorBrows - baseColor.rgb); + half3 maskLashes = lashesScalar * (_MaskColorLashes - baseColor.rgb); + half3 maskSclera = scleraScalar * (_MaskColorSclera * SCLERA_BRIGHTNESS_MODIFIER - baseColor.rgb); + half3 maskTeeth = teethScalar * (_MaskColorTeeth - baseColor.rgb); + half3 maskGums = gumsScalar * (_MaskColorGums - baseColor.rgb); + // Lip tint excluded from color mask as it lerps with texture color + half3 colorMask = maskIris + maskBrows + maskLashes + maskSclera + maskTeeth + maskGums; + + // Diffuse intensity from array + half diffuseIntensity = _DiffuseIntensity[componentIndex]; + + // Lerp diffuseIntensity with roughness map + diffuseIntensity = lerp(diffuseIntensity, ONE, roughnessTex.a); + + // Brows and lashes modify DiffuseIntensity + diffuseIntensity *= ONE - (saturate(browsScalar + lashesScalar) * BROWS_LASHES_DIFFUSEINTENSITY); + + // Add in diffuseIntensity and main lighting to base color + baseColor.rgb += diffuseIntensity * NdotL * _LightColor0; + + // Add in color mask to base color if this is the head component (index == 0) + baseColor.rgb += clamp(ONE - componentIndex, 0, ONE) * colorMask; + + // Multiply texture with base color with special case for lips + albedoColor.rgb = lerp(albedoColor.rgb * baseColor.rgb, _MaskColorLips.rgb, lipsScalar * _MaskColorLips.a); + + // Smoothness multiplier on lip region + albedoColor.rgb += lipsScalar * reflectionColor * (_LipSmoothness * LIP_SMOOTHNESS_MULTIPLIER) * + lerp(LIP_SMOOTHNESS_MIN_NDOTL, ONE, NdotL); + + // Reflection from cubemap + albedoColor.rgb += reflectionColor * (roughnessTex.a * _ReflectionIntensity[componentIndex]) * NdotL; + + // Rim term +#ifdef SECONDARY_LIGHT_ON + // Secondary light proxy (direction and color) passed into the rim term + NdotL = saturate(dot(normalDirection, _SecondaryLightDirection)); + albedoColor.rgb += pow(ONE - VdotN, _RimIntensity[componentIndex]) * NdotL * _SecondaryLightColor; +#else + albedoColor.rgb += pow(ONE - VdotN, _RimIntensity[componentIndex]) * NdotL; +#endif + + // Global dimmer + albedoColor.rgb *= _Dimmer; + +#if !defined(UNITY_COLORSPACE_GAMMA) + albedoColor.rgb = GammaToLinearSpace(albedoColor.rgb); +#endif + albedoColor.rgb = saturate(albedoColor.rgb); + + // Set alpha, with special case for lashes + albedoColor.a = saturate(albedoColor.a * lerp(ONE, _Alpha, ONE - lashesScalar) * _Alpha); + + // Clip fragments in the lash region for clean lash transparency + clip(albedoColor.a - lerp(0.0, ALPHA_CLIP_THRESHOLD, lashesScalar)); + + // Return clamped final color + return albedoColor; + } + ENDCG + } + } +} diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_CombinedMeshExpressive.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_CombinedMeshExpressive.shader.meta new file mode 100644 index 0000000..3a87e02 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_CombinedMeshExpressive.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 0600fe59b0c043344affd1d1368b9ef2 +timeCreated: 1539810396 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_SingleComponentExpressive.shader b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_SingleComponentExpressive.shader new file mode 100644 index 0000000..8160644 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_SingleComponentExpressive.shader @@ -0,0 +1,272 @@ +// +// OvrAvatar Mobile single component expressive face shader +// For use on expressive face meshes +// +// Unity vertex-fragnment implementation +// Simplified lighting model recommended for use on mobile supporting one directional light +// Surface shader recommended on PC +// +// Uses transparent queue for fade effects +// +// Color and appearance of the facial regions controlled via G&B channels in roughness texture +// Pupil size controlled by manipulating UV coordinates +// +// Shader keywords: +// - SECONDARY_LIGHT_ON SECONDARY_LIGHT_OFF +// Enable SECONDARY_LIGHT_ON for a second "light" comprised of _SecondaryLightDirection and +// _SecondaryLightColor This will influence the rim effect providing additional contour to the +// avatar +// + +Shader "OvrAvatar/Avatar_Mobile_SingleComponentExpressive" +{ + Properties + { + [NoScaleOffset] _MainTex("Main Texture", 2D) = "white" {} + [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {} + [NoScaleOffset] _RoughnessMap("Roughness Map", 2D) = "black" {} + + _BaseColor("Color Tint", Color) = (1.0,1.0,1.0,1.0) + _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + + _DiffuseIntensity("Diffuse Intensity", Range(0.0,1.0)) = 0.3 + _ReflectionIntensity("Reflection Intensity", Range(0.0,1.0)) = 0.0 + _RimIntensity("Rim Intensity", Range(0.0,10.0)) = 5.0 + + _PupilSize("Pupil Size", Range(-1, 2)) = 0 + _LipSmoothness("Lip Smoothness", Range(0, 1)) = 0 + + _MaskColorIris("Iris Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorLips("Lips Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorBrows("Brows Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorLashes("Lashes Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorSclera("Sclera Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorGums("Gums Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorTeeth("Teeth Color", Color) = (0.0,0.0,0.0,1.0) + + [HideInInspector] _SrcBlend("", Float) = 1 + [HideInInspector] _DstBlend("", Float) = 0 + } + + SubShader + { + Tags { "LightMode" = "ForwardBase" "IgnoreProjector" = "True"} + Pass + { + Blend [_SrcBlend] [_DstBlend] + Cull Back + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma fragmentoption ARB_precision_hint_fastest + #pragma multi_compile SECONDARY_LIGHT_OFF SECONDARY_LIGHT_ON + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + + sampler2D _MainTex; + sampler2D _NormalMap; + float4 _NormalMap_ST; + sampler2D _RoughnessMap; + + half4 _BaseColor; + half _Dimmer; + half _Alpha; + + half _DiffuseIntensity; + half _RimIntensity; + half _ReflectionIntensity; + + half3 _SecondaryLightDirection; + half4 _SecondaryLightColor; + + half _PupilSize; + half _LipSmoothness; + + fixed4 _MaskColorIris; + fixed4 _MaskColorSclera; + fixed4 _MaskColorBrows; + fixed4 _MaskColorLashes; + fixed4 _MaskColorLashesEnd; + fixed4 _MaskColorLips; + fixed4 _MaskColorGums; + fixed4 _MaskColorTeeth; + + static const int ONE = 1; + static const fixed ALPHA_CLIP_THRESHOLD = 0.7; + static const int IRIS_BRIGHTNESS_MODIFIER = 2; + static const fixed SCLERA_BRIGHTNESS_MODIFIER = 1.2; + static const fixed LIP_SMOOTHNESS_MULTIPLIER = 0.5; + static const fixed LIP_SMOOTHNESS_MIN_NDOTL = 0.3; + static const fixed BROWS_LASHES_DIFFUSEINTENSITY = ONE - 0.25; + static const int COLOR_MULTIPLIER = 255; + static const half2 PUPIL_CENTER_UV = half2(0.127, 0.1175); + static const half DILATION_ENVELOPE = 0.024; + static const half2 EYE_REGION_UV = PUPIL_CENTER_UV + DILATION_ENVELOPE; + + static const int MASK_SLICE_SIZE = 17; + static const half MASK_SLICE_THRESHOLD = MASK_SLICE_SIZE * 0.5f; + static const int MASK_INDEX_IRIS = 255; + static const int MASK_INDEX_SCLERA = 238; + static const int MASK_INDEX_LASHES = 221; + static const int MASK_INDEX_LIPS = 204; + static const int MASK_INDEX_GUMS = 187; + static const int MASK_INDEX_TEETH = 170; + static const int MASK_INDEX_BROWS = 153; + + struct appdata + { + float4 vertex: POSITION; + float3 normal: NORMAL; + float4 tangent: TANGENT; + float4 uv: TEXCOORD0; + }; + + struct v2f + { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float4 posWorld: TEXCOORD1; + float3 normalDir: TEXCOORD2; + float3 tangentDir: TEXCOORD3; + float3 bitangentDir: TEXCOORD4; + }; + + v2f vert(appdata v) + { + v2f o; + + // Calculate tangents for normal mapping + o.normalDir = normalize(UnityObjectToWorldNormal(v.normal)); + o.tangentDir = normalize(mul(unity_ObjectToWorld, half4(v.tangent.xyz, 0.0)).xyz); + o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); + + o.posWorld = mul(unity_ObjectToWorld, v.vertex); + o.pos = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + return o; + } + + fixed4 frag(v2f i) : COLOR + { + // Pupil size offsets uv coords + if (all(i.uv < EYE_REGION_UV)) + { + i.uv -= PUPIL_CENTER_UV; + half pupil = saturate(length(i.uv) / DILATION_ENVELOPE); + i.uv *= lerp(1.0, pupil, _PupilSize); + i.uv += PUPIL_CENTER_UV; + } + + // Diffuse texture sample + half4 albedoColor = tex2D(_MainTex, i.uv); + + // Process normal map +#if (UNITY_VERSION >= 20171) + float3 normalMap = UnpackNormal(tex2D(_NormalMap, i.uv)); +#else + float3 normalMap = tex2D(_NormalMap, i.uv) * 2.0 - ONE; +#endif + float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir); + float3 normalDirection = normalize(mul(normalMap.rgb, tangentTransform)); + + // Roughness contains metallic in r, smoothness in a, mask region in b and mask control in g + half4 roughnessTex = tex2D(_RoughnessMap, i.uv); + + // Normal/Light/View calculations + half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); + half VdotN = saturate(dot(viewDirection, normalDirection)); + half NdotL = saturate(dot(normalDirection, normalize(_WorldSpaceLightPos0.xyz))); + + // Sample the default reflection cubemap using the reflection vector + float3 worldReflection = reflect(-viewDirection, normalDirection); + half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldReflection); + // Decode cubemap data into actual color + half3 reflectionColor = DecodeHDR(skyData, unity_SpecCube0_HDR); + + // Color space conversions if we are in linear +#ifndef UNITY_COLORSPACE_GAMMA + _BaseColor.rgb = LinearToGammaSpace(_BaseColor.rgb); + _MaskColorIris.rgb = LinearToGammaSpace(_MaskColorIris); + _MaskColorLips.rgb = LinearToGammaSpace(_MaskColorLips.rgb); + _MaskColorBrows.rgb = LinearToGammaSpace(_MaskColorBrows.rgb); + _MaskColorLashes.rgb = LinearToGammaSpace(_MaskColorLashes.rgb); + _MaskColorLashesEnd.rgb = LinearToGammaSpace(_MaskColorLashesEnd.rgb); + _MaskColorSclera.rgb = LinearToGammaSpace(_MaskColorSclera.rgb); + _MaskColorGums.rgb = LinearToGammaSpace(_MaskColorGums.rgb); + _MaskColorTeeth.rgb = LinearToGammaSpace(_MaskColorTeeth.rgb); +#endif + + // Calculate color masks + half irisScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_IRIS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half lipsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LIPS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half browsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_BROWS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + half lashesScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LASHES) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half scleraScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_SCLERA) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half teethScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_TEETH) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + half gumsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_GUMS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + + half3 maskIris = irisScalar * (_MaskColorIris * IRIS_BRIGHTNESS_MODIFIER - _BaseColor.rgb); + half3 maskBrows = browsScalar * (_MaskColorBrows - _BaseColor.rgb); + half3 maskLashes = lashesScalar * (_MaskColorLashes - _BaseColor.rgb); + half3 maskSclera = scleraScalar * (_MaskColorSclera * SCLERA_BRIGHTNESS_MODIFIER - _BaseColor.rgb); + half3 maskTeeth = teethScalar * (_MaskColorTeeth - _BaseColor.rgb); + half3 maskGums = gumsScalar * (_MaskColorGums - _BaseColor.rgb); + // Lip tint excluded from color mask as it lerps with texture color + half3 colorMask = maskIris + maskBrows + maskLashes + maskSclera + maskTeeth + maskGums; + + // Lerp diffuseIntensity with roughness map + _DiffuseIntensity = lerp(_DiffuseIntensity, ONE, roughnessTex.a); + + // Brows and lashes modify DiffuseIntensity + _DiffuseIntensity *= ONE - (saturate(browsScalar + lashesScalar) * BROWS_LASHES_DIFFUSEINTENSITY); + + // Add in diffuseIntensity and main lighting to base color + _BaseColor.rgb += _DiffuseIntensity * NdotL * _LightColor0; + + // Add in color mask to base color + _BaseColor.rgb += colorMask; + + // Multiply texture with base color with special case for lips + albedoColor.rgb = lerp(albedoColor.rgb * _BaseColor.rgb, _MaskColorLips.rgb, lipsScalar * _MaskColorLips.a); + + // Smoothness multiplier on lip region + albedoColor.rgb += lipsScalar * reflectionColor * (_LipSmoothness * LIP_SMOOTHNESS_MULTIPLIER) * + lerp(LIP_SMOOTHNESS_MIN_NDOTL, ONE, NdotL); + + // Reflection from cubemap + albedoColor.rgb += reflectionColor * (roughnessTex.a * _ReflectionIntensity) * NdotL; + + // Rim term +#ifdef SECONDARY_LIGHT_ON + // Secondary light proxy (direction and color) passed into the rim term + NdotL = saturate(dot(normalDirection, _SecondaryLightDirection)); + albedoColor.rgb += pow(ONE - VdotN, _RimIntensity) * NdotL * _SecondaryLightColor; +#else + albedoColor.rgb += pow(ONE - VdotN, _RimIntensity) * NdotL; +#endif + + // Global dimmer + albedoColor.rgb *= _Dimmer; + + // Convert back to linear color space if we are in linear +#if !defined(UNITY_COLORSPACE_GAMMA) + albedoColor.rgb = GammaToLinearSpace(albedoColor.rgb); +#endif + albedoColor.rgb = saturate(albedoColor.rgb); + + // Set alpha, with special case for lashes + albedoColor.a = saturate(albedoColor.a * lerp(ONE, _Alpha, ONE - lashesScalar) * _Alpha); + + // Clip fragments in the lash region for clean lash transparency + clip(albedoColor.a - lerp(0.0, ALPHA_CLIP_THRESHOLD, lashesScalar)); + + // Return clamped final color + return albedoColor; + } + ENDCG + } + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_SingleComponentExpressive.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_SingleComponentExpressive.shader.meta new file mode 100644 index 0000000..62aa4e5 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_Mobile_SingleComponentExpressive.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2fe0ac0c2373ab143a6f21314b785d7d +timeCreated: 1544020283 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_PC_SingleComponentExpressive.shader b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_PC_SingleComponentExpressive.shader new file mode 100644 index 0000000..458ede6 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_PC_SingleComponentExpressive.shader @@ -0,0 +1,216 @@ +// +// OvrAvatar PC single component expressive face shader +// For use on expressive face meshes +// +// Unity Surface Shader implementation +// Mobile vertex/fragment shader is recommended for use on mobile platforms for performance. +// +// Uses transparent queue for fade effects +// +// Color and appearance of the facial regions controlled via G&B channels in roughness texture +// Pupil size controlled by manipulating UV coordinates +// + +Shader "OvrAvatar/Avatar_PC_SingleComponentExpressive" +{ + Properties + { + [NoScaleOffset] _MainTex("Color (RGB)", 2D) = "white" {} + [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {} + [NoScaleOffset] _RoughnessMap("Roughness Map", 2D) = "black" {} + + _BaseColor("Color Tint", Color) = (1.0,1.0,1.0,1.0) + _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + + _DiffuseIntensity("Diffuse Intensity", Range(0.0,1.0)) = 0.3 + _SmoothnessMultiplier("Smoothness Multiplier", Range(0.0,1.0)) = 1.0 + _MetallicMultiplier("Metallic Multiplier", Range(0.0,1.0)) = 0.3 + _RimIntensity("Rim Intensity", Range(0.0,10.0)) = 5.0 + + _PupilSize("Pupil Size", Range(-1, 2)) = 0 + _LipSmoothness("Lip Smoothness", Range(0, 1)) = 0 + + _MaskColorIris("Iris Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorLips("Lips Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorBrows("Brows Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorLashes("Lashes Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorSclera("Sclera Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorGums("Gums Color", Color) = (0.0,0.0,0.0,1.0) + _MaskColorTeeth("Teeth Color", Color) = (0.0,0.0,0.0,1.0) + + [HideInInspector] _SrcBlend("", Float) = 1 + [HideInInspector] _DstBlend("", Float) = 0 + } + + SubShader + { + Blend [_SrcBlend] [_DstBlend] + Cull Back + CGPROGRAM +#pragma surface surf Standard keepalpha fullforwardshadows +#pragma target 3.0 +#pragma fragmentoption ARB_precision_hint_fastest +#include "UnityCG.cginc" + + sampler2D _MainTex; + sampler2D _NormalMap; + sampler2D _RoughnessMap; + + half4 _BaseColor; + half _Dimmer; + half _Alpha; + + half _DiffuseIntensity; + half _SmoothnessMultiplier; + half _SmoothnessMultiplierLips; + half _MetallicMultiplier; + half _RimIntensity; + + half _PupilSize; + half _LipSmoothness; + + fixed4 _MaskColorIris; + fixed4 _MaskColorLips; + fixed4 _MaskColorBrows; + fixed4 _MaskColorLashes; + fixed4 _MaskColorLashesEnd; + fixed4 _MaskColorSclera; + fixed4 _MaskColorGums; + fixed4 _MaskColorTeeth; + + static const int ONE = 1; + static const fixed ALPHA_CLIP_THRESHOLD = 0.7; + static const int IRIS_BRIGHTNESS_MODIFIER = 2; + static const fixed SCLERA_BRIGHTNESS_MODIFIER = 1.2; + static const fixed LIP_SMOOTHNESS_MULTIPLIER = 0.5; + static const fixed LIP_SMOOTHNESS_MIN_NDOTL = 0.3; + static const fixed BROWS_LASHES_DIFFUSEINTENSITY = ONE - 0.25; + static const int COLOR_MULTIPLIER = 255; + static const half2 PUPIL_CENTER_UV = half2(0.127, 0.1175); + static const half DILATION_ENVELOPE = 0.024; + static const half2 EYE_REGION_UV = PUPIL_CENTER_UV + DILATION_ENVELOPE; + + static const int MASK_SLICE_SIZE = 17; + static const half MASK_SLICE_THRESHOLD = MASK_SLICE_SIZE * 0.5f; + static const int MASK_INDEX_IRIS = 255; + static const int MASK_INDEX_SCLERA = 238; + static const int MASK_INDEX_LASHES = 221; + static const int MASK_INDEX_LIPS = 204; + static const int MASK_INDEX_GUMS = 187; + static const int MASK_INDEX_TEETH = 170; + static const int MASK_INDEX_BROWS = 153; + + struct Input + { + float2 uv_MainTex; + float2 uv_NormalMap; + float2 uv_RoughnessMap; + float3 viewDir; + float3 worldNormal; INTERNAL_DATA + }; + + void surf(Input IN, inout SurfaceOutputStandard o) + { + // Pupil size offsets uv coords + if (all(IN.uv_MainTex < EYE_REGION_UV)) + { + IN.uv_MainTex -= PUPIL_CENTER_UV; + half pupil = saturate(length(IN.uv_MainTex) / DILATION_ENVELOPE); + IN.uv_MainTex *= lerp(ONE, pupil, _PupilSize); + IN.uv_MainTex += PUPIL_CENTER_UV; + } + + // Diffuse texture sample + half4 albedoColor = tex2D(_MainTex, IN.uv_MainTex); + + // Unpack normal map + #if (UNITY_VERSION >= 20171) + o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex)); + #else + o.Normal = tex2D(_NormalMap, IN.uv_MainTex) * 2.0 - ONE; + #endif + // Roughness contains metallic in r, smoothness in a, mask region in b and mask control in g + half4 roughnessTex = tex2D(_RoughnessMap, IN.uv_MainTex); + + // Normal/Light/View calculations + half NdotL = saturate(dot(WorldNormalVector(IN, o.Normal), _WorldSpaceLightPos0.xyz)); + half VdotN = saturate(dot(normalize(IN.viewDir), o.Normal)); + + // Color space conversions if we are in linear + #ifndef UNITY_COLORSPACE_GAMMA + _BaseColor.rgb = LinearToGammaSpace(_BaseColor.rgb); + _MaskColorIris.rgb = LinearToGammaSpace(_MaskColorIris.rgb); + _MaskColorLips.rgb = LinearToGammaSpace(_MaskColorLips.rgb); + _MaskColorBrows.rgb = LinearToGammaSpace(_MaskColorBrows.rgb); + _MaskColorLashes.rgb = LinearToGammaSpace(_MaskColorLashes.rgb); + _MaskColorLashesEnd.rgb = LinearToGammaSpace(_MaskColorLashesEnd.rgb); + _MaskColorSclera.rgb = LinearToGammaSpace(_MaskColorSclera.rgb); + _MaskColorGums.rgb = LinearToGammaSpace(_MaskColorGums.rgb); + _MaskColorTeeth.rgb = LinearToGammaSpace(_MaskColorTeeth.rgb); + #endif + + // Mask regions and colors + half irisScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_IRIS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half lipsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LIPS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half browsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_BROWS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + half lashesScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_LASHES) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half scleraScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_SCLERA) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + half teethScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_TEETH) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f;; + half gumsScalar = abs(roughnessTex.b * COLOR_MULTIPLIER - MASK_INDEX_GUMS) <= MASK_SLICE_THRESHOLD ? roughnessTex.g : 0.0f; + + half3 maskIris = irisScalar * (_MaskColorIris.rgb * IRIS_BRIGHTNESS_MODIFIER - _BaseColor.rgb); + half3 maskBrows = browsScalar * (_MaskColorBrows.rgb - _BaseColor.rgb); + half3 maskLashes = lashesScalar * (_MaskColorLashes.rgb - _BaseColor.rgb); + half3 maskSclera = scleraScalar * (_MaskColorSclera.rgb * SCLERA_BRIGHTNESS_MODIFIER - _BaseColor.rgb); + half3 maskTeeth = teethScalar * (_MaskColorTeeth.rgb - _BaseColor.rgb); + half3 maskGums = gumsScalar * (_MaskColorGums.rgb - _BaseColor.rgb); + // Lip tint excluded from color mask as it lerps with texture color + half3 colorMask = maskIris + maskBrows + maskLashes + maskSclera + maskTeeth + maskGums; + + // Set smoothness + o.Smoothness = roughnessTex.a * _SmoothnessMultiplier; + + // Force no smoothness on gums & teeth + o.Smoothness *= ONE - saturate(teethScalar + gumsScalar); + + // Use global smoothness or lip smoothness modifier + o.Smoothness += (_LipSmoothness * LIP_SMOOTHNESS_MULTIPLIER) * lipsScalar; + + // Set metallic with global modifier + o.Metallic = roughnessTex.r * _MetallicMultiplier; + + // Brows and lashes modify DiffuseIntensity + _DiffuseIntensity *= ONE - (saturate(browsScalar + lashesScalar) * BROWS_LASHES_DIFFUSEINTENSITY); + + // Modify base color with DiffuseIntensity * NdotL for lighting gradient + _BaseColor.rgb += _DiffuseIntensity * NdotL; + + // Add in color mask + _BaseColor.rgb += colorMask; + + // Multiply texture with base color with special case for lips + o.Albedo.rgb = lerp(albedoColor.rgb * _BaseColor.rgb, _MaskColorLips.rgb, lipsScalar * _MaskColorLips.a); + + // Rim term + o.Albedo += pow(ONE - VdotN, _RimIntensity) * NdotL; + + // Global dimmer + o.Albedo *= _Dimmer; + + // Convert back to linear color space if we are in linear + #if !defined(UNITY_COLORSPACE_GAMMA) + o.Albedo = GammaToLinearSpace(o.Albedo); + #endif + o.Albedo = saturate(o.Albedo); + + // Set alpha, with special case for lashes + o.Alpha = saturate(albedoColor.a * lerp(ONE, _Alpha, ONE - lashesScalar) * _Alpha); + + // Clip fragments in the lash region for clean lash transparency + clip(o.Alpha - lerp(0.0, ALPHA_CLIP_THRESHOLD, lashesScalar)); + } + ENDCG + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_PC_SingleComponentExpressive.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_PC_SingleComponentExpressive.shader.meta new file mode 100644 index 0000000..8db8f21 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Expressive/Avatar_PC_SingleComponentExpressive.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 93b478e926e46654889c1c20f87f253f +timeCreated: 1539382777 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5.meta b/Assets/Oculus/Avatar/Resources/Materials/Version1.5.meta new file mode 100644 index 0000000..7570a30 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: ced8ef067736a0b468cde573cc63e3ec +folderAsset: yes +timeCreated: 1525971173 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_CombinedMesh.shader b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_CombinedMesh.shader new file mode 100644 index 0000000..4419108 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_CombinedMesh.shader @@ -0,0 +1,207 @@ +// +// OvrAvatar Mobile combined mesh shader +// For use on non-expressive face meshes and other components +// Texture array approach for rendering a combined mesh avatar +// Coupled with OvrAvatarMaterialManager to populate the texture arrays +// +// Unity vertex-fragnment implementation +// Simplified lighting model recommended for use on mobile supporting one directional light +// Surface shader recommended on PC +// +// Uses transparent queue for fade effects +// +// Simple mouth animation with speech done with vertex perturbation +// +// Shader keywords: +// - SECONDARY_LIGHT_ON SECONDARY_LIGHT_OFF +// Enable SECONDARY_LIGHT_ON for a second "light" comprised of _SecondaryLightDirection and +// _SecondaryLightColor This will influence the rim effect providing a lit contour to the avatar +// + +Shader "OvrAvatar/Avatar_Mobile_CombinedMesh" +{ + Properties + { + [NoScaleOffset] _MainTex("Main Texture Array", 2DArray) = "white" {} + [NoScaleOffset] _NormalMap("Normal Map Array", 2DArray) = "bump" {} + [NoScaleOffset] _RoughnessMap("Roughness Map Array", 2DArray) = "black" {} + + _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + + // Index into the texture array needs an offset for precision + _Slices("Texture Array Slices", int) = 4.97 + + _Voice("Voice", Range(0.0,1.0)) = 0.0 + [HideInInspector] _MouthPosition("Mouth position", Vector) = (0,0,0,1) + [HideInInspector] _MouthDirection("Mouth direction", Vector) = (0,0,0,1) + [HideInInspector] _MouthEffectDistance("Mouth Effect Distance", Float) = 0.03 + [HideInInspector] _MouthEffectScale("Mouth Effect Scaler", Float) = 1 + + [HideInInspector] _SrcBlend("", Float) = 1 + [HideInInspector] _DstBlend("", Float) = 0 + } + + SubShader + { + Tags { "LightMode" = "ForwardBase" "IgnoreProjector" = "True"} + Pass + { + Blend [_SrcBlend] [_DstBlend] + Cull Back + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.5 + #pragma fragmentoption ARB_precision_hint_fastest + #pragma multi_compile SECONDARY_LIGHT_OFF SECONDARY_LIGHT_ON + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + + UNITY_DECLARE_TEX2DARRAY(_MainTex); + UNITY_DECLARE_TEX2DARRAY(_NormalMap); + float4 _NormalMap_ST; + UNITY_DECLARE_TEX2DARRAY(_RoughnessMap); + + int _Slices; + + half _Dimmer; + half _Alpha; + + half4 _BaseColor[5]; + half _DiffuseIntensity[5]; + half _RimIntensity[5]; + half _ReflectionIntensity[5]; + + half3 _SecondaryLightDirection; + half4 _SecondaryLightColor; + + half _Voice; + half4 _MouthPosition; + half4 _MouthDirection; + half _MouthEffectDistance; + half _MouthEffectScale; + + static const fixed MOUTH_ZSCALE = 0.5f; + static const fixed MOUTH_DROPOFF = 0.01f; + + struct appdata + { + float4 vertex: POSITION; + float3 normal: NORMAL; + float4 tangent: TANGENT; + float2 texcoord: TEXCOORD0; + float4 vertexColor : COLOR0; + }; + + struct v2f + { + float4 pos : SV_POSITION; + float3 uv : TEXCOORD0; + float4 posWorld: TEXCOORD1; + float3 normalDir: TEXCOORD2; + float3 tangentDir: TEXCOORD3; + float3 bitangentDir: TEXCOORD4; + }; + + v2f vert(appdata v) + { + v2f o; + + // Mouth vertex animation with voice + float4 worldVert = mul(unity_ObjectToWorld, v.vertex); + float3 delta = _MouthPosition - worldVert; + delta.z *= MOUTH_ZSCALE; + half dist = length(delta); + half scaledMouthDropoff = _MouthEffectScale * MOUTH_DROPOFF; + half scaledMouthEffect = _MouthEffectScale * _MouthEffectDistance; + half displacement = _Voice * smoothstep(scaledMouthEffect + scaledMouthDropoff, scaledMouthEffect, dist); + worldVert.xyz -= _MouthDirection * displacement; + v.vertex = mul(unity_WorldToObject, worldVert); + + // Calculate tangents for normal mapping + o.normalDir = normalize(UnityObjectToWorldNormal(v.normal)); + o.tangentDir = normalize(mul(unity_ObjectToWorld, half4(v.tangent.xyz, 0.0)).xyz); + o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); + + o.posWorld = worldVert; + o.pos = UnityObjectToClipPos(v.vertex); + o.uv.xy = v.texcoord; + o.uv.z = v.vertexColor.x * _Slices; + return o; + } + + fixed4 frag(v2f i) : COLOR + { + // Diffuse texture sample + float4 albedoColor = UNITY_SAMPLE_TEX2DARRAY(_MainTex, i.uv); + + // Process normal map + float3 transformedNormalUV = i.uv; + transformedNormalUV.xy = float2(TRANSFORM_TEX(i.uv.xy, _NormalMap)); + float3 normalMap = UNITY_SAMPLE_TEX2DARRAY(_NormalMap, transformedNormalUV) * 2.0 - 1.0; + float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir); + float3 normalDirection = normalize(mul(normalMap.rgb, tangentTransform)); + + // Roughness contains metallic in r, smoothness in a, mask region in b and mask control in g + half4 roughnessTex = UNITY_SAMPLE_TEX2DARRAY(_RoughnessMap, i.uv); + + // Normal/Light/View calculations + half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); + half VdotN = saturate(dot(viewDirection, normalDirection)); + half NdotL = saturate(dot(normalDirection, _WorldSpaceLightPos0.xyz)); + + // Sample the default reflection cubemap using the reflection vector + float3 worldReflection = reflect(-viewDirection, normalDirection); + half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldReflection); + // Decode cubemap data into actual color + half3 reflectionColor = DecodeHDR(skyData, unity_SpecCube0_HDR); + + // Get index into texture array + int componentIndex = floor(i.uv.z + 0.5); + + // Base color from array + float4 baseColor = _BaseColor[componentIndex]; + + // Diffuse intensity from array + half diffuseIntensity = _DiffuseIntensity[componentIndex]; + + // Multiply in base color + albedoColor.rgb *= baseColor.rgb; + + // Lerp diffuseIntensity with roughness map + diffuseIntensity = lerp(diffuseIntensity, 1.0, roughnessTex.a); + + // Apply main light with a lerp between DiffuseIntensity and 1 based on the roughness + albedoColor.rgb += diffuseIntensity * NdotL * _LightColor0; + + // Reflection from cubemap + albedoColor.rgb += reflectionColor * (roughnessTex.a * _ReflectionIntensity[componentIndex]) * NdotL; + + // Rim term +#ifdef SECONDARY_LIGHT_ON + // Secondary light proxy (direction and color) passed into the rim term + NdotL = saturate(dot(normalDirection, _SecondaryLightDirection)); + albedoColor.rgb += pow(1.0 - VdotN, _RimIntensity[componentIndex]) * NdotL * _SecondaryLightColor; +#else + albedoColor.rgb += pow(1.0 - VdotN, _RimIntensity[componentIndex]) * NdotL; +#endif + + // Global dimmer + albedoColor.rgb *= _Dimmer; + +#if !defined(UNITY_COLORSPACE_GAMMA) + albedoColor.rgb = GammaToLinearSpace(albedoColor.rgb); +#endif + albedoColor.rgb = saturate(albedoColor.rgb); + + // Set alpha, with special case for lashes + albedoColor.a *= _Alpha; + + // Return clamped final color + return albedoColor; + } + ENDCG + } + } +} diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_CombinedMesh.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_CombinedMesh.shader.meta new file mode 100644 index 0000000..db86ae4 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_CombinedMesh.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 37d2b8298f61cd2469465fc36108675d +timeCreated: 1526311739 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_Loader.shader b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_Loader.shader new file mode 100644 index 0000000..33e2625 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_Loader.shader @@ -0,0 +1,135 @@ +// +// OvrAvatar Mobile Single Component Loading shader +// +// Cut-down single component version of the avatar shader to be used during combined mesh loading +// +// See OvrAvatarMaterialManager implementation notes +// + +Shader "OvrAvatar/Avatar_Mobile_Loader" +{ + Properties + { + [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {} + + _BaseColor("Color Tint", Color) = (1.0,1.0,1.0,1.0) + _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0 + _LoadingDimmer("Loading Dimmer", Range(0.0,1.0)) = 1.0 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + + _DiffuseIntensity("Diffuse Intensity", Range(0.0,1.0)) = 0.3 + _RimIntensity("Rim Intensity", Range(0.0,10.0)) = 5.0 + } + + SubShader + { + Tags { "LightMode" = "ForwardBase" "IgnoreProjector" = "True"} + Pass + { + Blend One Zero + Cull Back + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma fragmentoption ARB_precision_hint_fastest + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + + sampler2D _NormalMap; + float4 _NormalMap_ST; + + float4 _BaseColor; + float _Dimmer; + float _LoadingDimmer; + float _Alpha; + + float _DiffuseIntensity; + float _RimIntensity; + + static const fixed MOUTH_ZSCALE = 0.5f; + static const fixed MOUTH_DROPOFF = 0.01f; + + struct appdata + { + float4 vertex: POSITION; + float3 normal: NORMAL; + float4 tangent: TANGENT; + float4 uv: TEXCOORD0; + }; + + struct v2f + { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float4 posWorld: TEXCOORD1; + float3 normalDir: TEXCOORD2; + float3 tangentDir: TEXCOORD3; + float3 bitangentDir: TEXCOORD4; + }; + + v2f vert(appdata v) + { + v2f o; + + // Calculate tangents for normal mapping + o.normalDir = normalize(UnityObjectToWorldNormal(v.normal)); + o.tangentDir = normalize(mul(unity_ObjectToWorld, half4(v.tangent.xyz, 0.0)).xyz); + o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); + + o.posWorld = mul(unity_ObjectToWorld, v.vertex); + o.pos = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + return o; + } + + fixed4 frag(v2f i) : COLOR + { + // Process normal map +#if (UNITY_VERSION >= 20171) + float3 normalMap = UnpackNormal(tex2D(_NormalMap, i.uv)); +#else + float3 normalMap = tex2D(_NormalMap, i.uv) * 2.0 - 1.0; +#endif + float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir); + float3 normalDirection = normalize(mul(normalMap.rgb, tangentTransform)); + + // Normal/Light/View calculations + half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); + half VdotN = saturate(dot(viewDirection, normalDirection)); + half NdotL = saturate(dot(normalDirection, _WorldSpaceLightPos0.xyz)); + + // Calculate color + float4 albedoColor; + +#if !defined(UNITY_COLORSPACE_GAMMA) + _BaseColor.rgb = LinearToGammaSpace(_BaseColor.rgb); +#endif + // Final base color including DiffuseIntensity and NdotL for lighting gradient + _BaseColor.rgb += _DiffuseIntensity * NdotL * _LightColor0; + + // No diffuse texture in the loader shader + albedoColor = _BaseColor; + + // Rim term + albedoColor.rgb += pow(1.0 - VdotN, _RimIntensity) * NdotL; + + // Global dimmer + albedoColor.rgb *= lerp(_Dimmer, _LoadingDimmer, step(_LoadingDimmer, _Dimmer)); + + // Convert back to linear color space if we are in linear +#if !defined(UNITY_COLORSPACE_GAMMA) + albedoColor.rgb = GammaToLinearSpace(albedoColor.rgb); +#endif + albedoColor.rgb = saturate(albedoColor.rgb); + + // Set alpha + albedoColor.a *= _Alpha; + + // Return clamped final color + return albedoColor; + } + ENDCG + } + } +} diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_Loader.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_Loader.shader.meta new file mode 100644 index 0000000..35cdaa0 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_Loader.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 822f5e641dc5dd54ca9555b727b3277f +timeCreated: 1526311739 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_SingleComponent.shader b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_SingleComponent.shader new file mode 100644 index 0000000..605c4bf --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_SingleComponent.shader @@ -0,0 +1,200 @@ +// +// OvrAvatar Mobile single component shader +// For use on non-expressive face meshes and other components +// +// Unity vertex-fragnment implementation +// Simplified lighting model recommended for use on mobile supporting one directional light +// Surface shader recommended on PC +// +// Uses transparent queue for fade effects +// +// Simple mouth animation with speech done with vertex perturbation +// +// Shader keywords: +// - SECONDARY_LIGHT_ON SECONDARY_LIGHT_OFF +// Enable SECONDARY_LIGHT_ON for a second "light" comprised of _SecondaryLightDirection and +// _SecondaryLightColor This will influence the rim effect providing a lit contour to the avatar +// + +Shader "OvrAvatar/Avatar_Mobile_SingleComponent" +{ + Properties + { + [NoScaleOffset] _MainTex("Main Texture", 2D) = "white" {} + [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {} + [NoScaleOffset] _RoughnessMap("Roughness Map", 2D) = "black" {} + + _BaseColor("Color Tint", Color) = (1.0,1.0,1.0,1.0) + _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + + _DiffuseIntensity("Diffuse Intensity", Range(0.0,1.0)) = 0.3 + _RimIntensity("Rim Intensity", Range(0.0,10.0)) = 5.0 + _ReflectionIntensity("Reflection Intensity", Range(0.0,1.0)) = 0.0 + + _Voice("Voice", Range(0.0,1.0)) = 0.0 + [HideInInspector] _MouthPosition("Mouth position", Vector) = (0,0,0,1) + [HideInInspector] _MouthDirection("Mouth direction", Vector) = (0,0,0,1) + [HideInInspector] _MouthEffectDistance("Mouth Effect Distance", Float) = 0.03 + [HideInInspector] _MouthEffectScale("Mouth Effect Scaler", Float) = 1 + + [HideInInspector] _SrcBlend("", Float) = 1 + [HideInInspector] _DstBlend("", Float) = 0 + } + + SubShader + { + Tags { "LightMode" = "ForwardBase" "IgnoreProjector" = "True"} + Pass + { + Blend [_SrcBlend] [_DstBlend] + Cull Back + CGPROGRAM + #pragma vertex vert + #pragma fragment frag + #pragma target 3.0 + #pragma fragmentoption ARB_precision_hint_fastest + #pragma multi_compile SECONDARY_LIGHT_OFF SECONDARY_LIGHT_ON + #include "UnityCG.cginc" + #include "UnityLightingCommon.cginc" + + sampler2D _MainTex; + sampler2D _NormalMap; + float4 _NormalMap_ST; + sampler2D _RoughnessMap; + + half4 _BaseColor; + half _Dimmer; + half _Alpha; + + half _DiffuseIntensity; + half _RimIntensity; + half _ReflectionIntensity; + + half3 _SecondaryLightDirection; + half4 _SecondaryLightColor; + + half _Voice; + half4 _MouthPosition; + half4 _MouthDirection; + half _MouthEffectDistance; + half _MouthEffectScale; + + static const fixed MOUTH_ZSCALE = 0.5f; + static const fixed MOUTH_DROPOFF = 0.01f; + + struct appdata + { + float4 vertex: POSITION; + float3 normal: NORMAL; + float4 tangent: TANGENT; + float4 uv: TEXCOORD0; + }; + + struct v2f + { + float4 pos : SV_POSITION; + float2 uv : TEXCOORD0; + float4 posWorld: TEXCOORD1; + float3 normalDir: TEXCOORD2; + float3 tangentDir: TEXCOORD3; + float3 bitangentDir: TEXCOORD4; + }; + + v2f vert(appdata v) + { + v2f o; + + // Mouth vertex animation with voice + float4 worldVert = mul(unity_ObjectToWorld, v.vertex); + float3 delta = _MouthPosition - worldVert; + delta.z *= MOUTH_ZSCALE; + half dist = length(delta); + half scaledMouthDropoff = _MouthEffectScale * MOUTH_DROPOFF; + half scaledMouthEffect = _MouthEffectScale * _MouthEffectDistance; + half displacement = _Voice * smoothstep(scaledMouthEffect + scaledMouthDropoff, scaledMouthEffect, dist); + worldVert.xyz -= _MouthDirection * displacement; + v.vertex = mul(unity_WorldToObject, worldVert); + + // Calculate tangents for normal mapping + o.normalDir = normalize(UnityObjectToWorldNormal(v.normal)); + o.tangentDir = normalize(mul(unity_ObjectToWorld, half4(v.tangent.xyz, 0.0)).xyz); + o.bitangentDir = normalize(cross(o.normalDir, o.tangentDir) * v.tangent.w); + + o.posWorld = worldVert; + o.pos = UnityObjectToClipPos(v.vertex); + o.uv = v.uv; + return o; + } + + fixed4 frag(v2f i) : COLOR + { + // Diffuse texture sample + half4 albedoColor = tex2D(_MainTex, i.uv); + + // Process normal map +#if (UNITY_VERSION >= 20171) + float3 normalMap = UnpackNormal(tex2D(_NormalMap, i.uv)); +#else + float3 normalMap = tex2D(_NormalMap, i.uv) * 2.0 - ONE; +#endif + float3x3 tangentTransform = float3x3(i.tangentDir, i.bitangentDir, i.normalDir); + float3 normalDirection = normalize(mul(normalMap.rgb, tangentTransform)); + + // Roughness contains metallic in r, smoothness in a, mask region in b and mask control in g + half4 roughnessTex = tex2D(_RoughnessMap, i.uv); + + // Normal/Light/View calculations + half3 viewDirection = normalize(_WorldSpaceCameraPos.xyz - i.posWorld.xyz); + half VdotN = saturate(dot(viewDirection, normalDirection)); + half NdotL = saturate(dot(normalDirection, _WorldSpaceLightPos0.xyz)); + + // Sample the default reflection cubemap using the reflection vector + float3 worldReflection = reflect(-viewDirection, normalDirection); + half4 skyData = UNITY_SAMPLE_TEXCUBE(unity_SpecCube0, worldReflection); + // Decode cubemap data into actual color + half3 reflectionColor = DecodeHDR(skyData, unity_SpecCube0_HDR); + +#ifndef UNITY_COLORSPACE_GAMMA + _BaseColor.rgb = LinearToGammaSpace(_BaseColor.rgb); +#endif + // Multiply in base color + albedoColor.rgb *= _BaseColor.rgb; + + // Lerp diffuseIntensity with roughness map + _DiffuseIntensity = lerp(_DiffuseIntensity, 1.0, roughnessTex.a); + + // Apply main light with a lerp between DiffuseIntensity and 1 based on the roughness + albedoColor.rgb += _DiffuseIntensity * NdotL * _LightColor0; + + // Rim term +#ifdef SECONDARY_LIGHT_ON + // Secondary light proxy (direction and color) passed into the rim term + NdotL = saturate(dot(normalDirection, _SecondaryLightDirection)); + albedoColor.rgb += pow(1.0 - VdotN, _RimIntensity) * NdotL * _SecondaryLightColor; +#else + albedoColor.rgb += pow(1.0 - VdotN, _RimIntensity) * NdotL; +#endif + // Reflection from cubemap + albedoColor.rgb += reflectionColor * (roughnessTex.a * _ReflectionIntensity) * NdotL; + + // Global dimmer + albedoColor.rgb *= _Dimmer; + + // Convert back to linear color space if we are in linear +#if !defined(UNITY_COLORSPACE_GAMMA) + albedoColor.rgb = GammaToLinearSpace(albedoColor.rgb); +#endif + albedoColor.rgb = saturate(albedoColor.rgb); + + // Set alpha + albedoColor.a *= _Alpha; + + // Return clamped final color + return albedoColor; + } + ENDCG + } + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_SingleComponent.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_SingleComponent.shader.meta new file mode 100644 index 0000000..19e0d41 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_Mobile_SingleComponent.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c26fc51e445dcfd4db09305d861dc11c +timeCreated: 1526311739 +licenseType: Pro +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_PC_SingleComponent.shader b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_PC_SingleComponent.shader new file mode 100644 index 0000000..a085439 --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_PC_SingleComponent.shader @@ -0,0 +1,114 @@ +// +// OvrAvatar PC single component shader +// For use on non-expressive face meshes and other components +// +// Unity Surface Shader implementation +// Mobile vertex/fragment shader is recommended for use on mobile platforms for performance +// +// Uses transparent queue for fade effects +// + +Shader "OvrAvatar/Avatar_PC_SingleComponent" +{ + Properties + { + [NoScaleOffset] _MainTex("Color (RGB)", 2D) = "white" {} + [NoScaleOffset] _NormalMap("Normal Map", 2D) = "bump" {} + [NoScaleOffset] _RoughnessMap("Roughness Map", 2D) = "black" {} + + _BaseColor("Color Tint", Color) = (1.0,1.0,1.0,1.0) + _Dimmer("Dimmer", Range(0.0,1.0)) = 1.0 + _Alpha("Alpha", Range(0.0,1.0)) = 1.0 + + _DiffuseIntensity("Diffuse Intensity", Range(0.0,1.0)) = 0.3 + _SmoothnessMultiplier("Smoothness Multiplier", Range(0.0,1.0)) = 1.0 + _MetallicMultiplier("Metallic Multiplier", Range(0.0,1.0)) = 1.0 + _RimIntensity("Rim Intensity", Range(0.0,10.0)) = 5.0 + + [HideInInspector] _SrcBlend("", Float) = 1 + [HideInInspector] _DstBlend("", Float) = 0 + } + + SubShader + { + Blend [_SrcBlend] [_DstBlend] + Cull Back + CGPROGRAM +#pragma surface surf Standard keepalpha fullforwardshadows +#pragma target 3.0 +#pragma fragmentoption ARB_precision_hint_fastest +#include "UnityCG.cginc" + + sampler2D _MainTex; + sampler2D _NormalMap; + sampler2D _RoughnessMap; + + half4 _BaseColor; + half _Dimmer; + half _Alpha; + + half _DiffuseIntensity; + half _SmoothnessMultiplier; + half _MetallicMultiplier; + half _RimIntensity; + + struct Input + { + float2 uv_MainTex; + float2 uv_NormalMap; + float2 uv_RoughnessMap; + float3 viewDir; + float3 worldNormal; INTERNAL_DATA + }; + + void surf(Input IN, inout SurfaceOutputStandard o) + { + // Diffuse texture sample + half4 albedoColor = tex2D(_MainTex, IN.uv_MainTex); + + // Unpack normal map +#if (UNITY_VERSION >= 20171) + o.Normal = UnpackNormal(tex2D(_NormalMap, IN.uv_MainTex)); +#else + o.Normal = tex2D(_NormalMap, IN.uv_MainTex) * 2.0 - 1.0; +#endif + // Roughness contains metallic in r, smoothness in a + half4 roughnessTex = tex2D(_RoughnessMap, IN.uv_MainTex); + + // Normal/Light/View calculations + half NdotL = saturate(dot(WorldNormalVector(IN, o.Normal), _WorldSpaceLightPos0.xyz)); + half VdotN = saturate(dot(normalize(IN.viewDir), o.Normal)); + + // Color space conversions if we are in linear +#ifndef UNITY_COLORSPACE_GAMMA + _BaseColor.rgb = LinearToGammaSpace(_BaseColor.rgb); +#endif + // Set smoothness and metallic + o.Smoothness = roughnessTex.a * _SmoothnessMultiplier; + o.Metallic = roughnessTex.r * _MetallicMultiplier; + + // Final base color including DiffuseIntensity and NdotL for lighting gradient + _BaseColor.rgb += _DiffuseIntensity * NdotL; + + // Multiply texture with base color + o.Albedo = albedoColor.rgb * _BaseColor; + + // Rim term + o.Albedo += pow(1.0 - VdotN, _RimIntensity) * NdotL; + + // Global dimmer + o.Albedo *= _Dimmer; + + // Convert back to linear color space if we are in linear +#if !defined(UNITY_COLORSPACE_GAMMA) + o.Albedo = GammaToLinearSpace(o.Albedo); +#endif + o.Albedo = saturate(o.Albedo); + + // Global alpha + o.Alpha = albedoColor.a * _Alpha; + } + ENDCG + } + Fallback "Diffuse" +} \ No newline at end of file diff --git a/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_PC_SingleComponent.shader.meta b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_PC_SingleComponent.shader.meta new file mode 100644 index 0000000..e3a8f3a --- /dev/null +++ b/Assets/Oculus/Avatar/Resources/Materials/Version1.5/Avatar_PC_SingleComponent.shader.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 36b8b481cf607814a8cec318f0148d63 +timeCreated: 1525971189 +licenseType: Free +ShaderImporter: + defaultTextures: [] + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples.meta b/Assets/Oculus/Avatar/Samples.meta new file mode 100644 index 0000000..d40b793 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b18c7ae976868a4499e2dbd7f60e92a4 +folderAsset: yes +timeCreated: 1467313717 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/AvatarGallery.meta b/Assets/Oculus/Avatar/Samples/AvatarGallery.meta new file mode 100644 index 0000000..df3d649 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/AvatarGallery.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 35f0ba21582517e45900137034e130af +folderAsset: yes +timeCreated: 1532639215 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/AvatarGallery/AvatarGallery.unity b/Assets/Oculus/Avatar/Samples/AvatarGallery/AvatarGallery.unity new file mode 100644 index 0000000..2cc0179 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/AvatarGallery/AvatarGallery.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a3f3b312e3a3b4beb62f53380385e0244369af1b8b3e9ed5a17c6221a2841a8f +size 45044 diff --git a/Assets/Oculus/Avatar/Samples/AvatarGallery/AvatarGallery.unity.meta b/Assets/Oculus/Avatar/Samples/AvatarGallery/AvatarGallery.unity.meta new file mode 100644 index 0000000..3ad0e35 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/AvatarGallery/AvatarGallery.unity.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7090d8e061d50cf459005277eef3e505 +timeCreated: 1532639215 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts.meta b/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts.meta new file mode 100644 index 0000000..949b3ae --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts.meta @@ -0,0 +1,10 @@ +fileFormatVersion: 2 +guid: 401f2fc661aa6af4da8c35c4f60718f8 +folderAsset: yes +timeCreated: 1532729557 +licenseType: Pro +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts/OvrAvatarTestDriver.cs b/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts/OvrAvatarTestDriver.cs new file mode 100644 index 0000000..018cec3 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts/OvrAvatarTestDriver.cs @@ -0,0 +1,96 @@ +using UnityEngine; +using System.Collections; +using System; +using System.Collections.Generic; +using Oculus.Avatar; + +public class OvrAvatarTestDriver : OvrAvatarDriver { + + private Vector3 headPos = new Vector3(0f, 1.6f, 0f); + private Quaternion headRot = Quaternion.identity; + + ControllerPose GetMalibuControllerPose(OVRInput.Controller controller) + { + ovrAvatarButton buttons = 0; + if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, controller)) buttons |= ovrAvatarButton.One; + + return new ControllerPose + { + buttons = buttons, + touches = OVRInput.Get(OVRInput.Touch.PrimaryTouchpad) ? ovrAvatarTouch.One : 0, + joystickPosition = OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad, controller), + indexTrigger = 0f, + handTrigger = 0f, + isActive = (OVRInput.GetActiveController() & controller) != 0, + }; + } + + float voiceAmplitude = 0.0f; + ControllerPose GetControllerPose(OVRInput.Controller controller) + { + ovrAvatarButton buttons = 0; + if (OVRInput.Get(OVRInput.Button.One, controller)) buttons |= ovrAvatarButton.One; + if (OVRInput.Get(OVRInput.Button.Two, controller)) buttons |= ovrAvatarButton.Two; + if (OVRInput.Get(OVRInput.Button.Start, controller)) buttons |= ovrAvatarButton.Three; + if (OVRInput.Get(OVRInput.Button.PrimaryThumbstick, controller)) buttons |= ovrAvatarButton.Joystick; + + ovrAvatarTouch touches = 0; + if (OVRInput.Get(OVRInput.Touch.One, controller)) touches |= ovrAvatarTouch.One; + if (OVRInput.Get(OVRInput.Touch.Two, controller)) touches |= ovrAvatarTouch.Two; + if (OVRInput.Get(OVRInput.Touch.PrimaryThumbstick, controller)) touches |= ovrAvatarTouch.Joystick; + if (OVRInput.Get(OVRInput.Touch.PrimaryThumbRest, controller)) touches |= ovrAvatarTouch.ThumbRest; + if (OVRInput.Get(OVRInput.Touch.PrimaryIndexTrigger, controller)) touches |= ovrAvatarTouch.Index; + if (!OVRInput.Get(OVRInput.NearTouch.PrimaryIndexTrigger, controller)) touches |= ovrAvatarTouch.Pointing; + if (!OVRInput.Get(OVRInput.NearTouch.PrimaryThumbButtons, controller)) touches |= ovrAvatarTouch.ThumbUp; + + return new ControllerPose + { + buttons = buttons, + touches = touches, + joystickPosition = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick, controller), + indexTrigger = OVRInput.Get(OVRInput.Axis1D.PrimaryIndexTrigger, controller), + handTrigger = OVRInput.Get(OVRInput.Axis1D.PrimaryHandTrigger, controller), + isActive = (OVRInput.GetActiveController() & controller) != 0, + }; + } + + private void CalculateCurrentPose() + { + if (GetIsTrackedRemote()) + { + CurrentPose = new PoseFrame + { + voiceAmplitude = voiceAmplitude, + headPosition = headPos, + headRotation = headRot, + handLeftPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTrackedRemote), + handLeftRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTrackedRemote), + handRightPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTrackedRemote), + handRightRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTrackedRemote), + controllerLeftPose = GetMalibuControllerPose(OVRInput.Controller.LTrackedRemote), + controllerRightPose = GetMalibuControllerPose(OVRInput.Controller.RTrackedRemote), + }; + } + else + { + CurrentPose = new PoseFrame + { + voiceAmplitude = voiceAmplitude, + headPosition = headPos, + headRotation = headRot, + handLeftPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch), + handLeftRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch), + handRightPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTouch), + handRightRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTouch), + controllerLeftPose = GetControllerPose(OVRInput.Controller.LTouch), + controllerRightPose = GetControllerPose(OVRInput.Controller.RTouch), + }; + } + } + + public override void UpdateTransforms(IntPtr sdkAvatar) + { + CalculateCurrentPose(); + UpdateTransformsFromPose(sdkAvatar); + } +} diff --git a/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts/OvrAvatarTestDriver.cs.meta b/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts/OvrAvatarTestDriver.cs.meta new file mode 100644 index 0000000..6b452c8 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/AvatarGallery/Scripts/OvrAvatarTestDriver.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 151f6ca5e4e605c4ca65b3199bfc3377 +timeCreated: 1532699599 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/Controllers.meta b/Assets/Oculus/Avatar/Samples/Controllers.meta new file mode 100644 index 0000000..a129b47 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/Controllers.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2856d681f3672e641a2e57df9676108c +folderAsset: yes +timeCreated: 1468456735 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/Controllers/Controllers.unity b/Assets/Oculus/Avatar/Samples/Controllers/Controllers.unity new file mode 100644 index 0000000..7776c9f --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/Controllers/Controllers.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4350ae6869080a5a317b5cd17f073aecbc454f010412a3cc969aa6f242bf041d +size 35300 diff --git a/Assets/Oculus/Avatar/Samples/Controllers/Controllers.unity.meta b/Assets/Oculus/Avatar/Samples/Controllers/Controllers.unity.meta new file mode 100644 index 0000000..8f14c97 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/Controllers/Controllers.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2a83dd010542d2744bf59af99b4bc47c +timeCreated: 1468457372 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/CrossPlatform.meta b/Assets/Oculus/Avatar/Samples/CrossPlatform.meta new file mode 100644 index 0000000..beeca2b --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/CrossPlatform.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: ad3077b9e8d4c4b4ea6177561faccbd2 +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/CrossPlatform/CrossPlatform.unity b/Assets/Oculus/Avatar/Samples/CrossPlatform/CrossPlatform.unity new file mode 100644 index 0000000..ba08f4c --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/CrossPlatform/CrossPlatform.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:dd803bf5eabfa5d7c380161c91c0d0ea8fb1e6146beb2ed96415399e5ee441ee +size 43463 diff --git a/Assets/Oculus/Avatar/Samples/CrossPlatform/CrossPlatform.unity.meta b/Assets/Oculus/Avatar/Samples/CrossPlatform/CrossPlatform.unity.meta new file mode 100644 index 0000000..1148031 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/CrossPlatform/CrossPlatform.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a95993f3779c6f842830a1f7ad81a478 +timeCreated: 1539938343 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/CrossPlatform/Readme.txt b/Assets/Oculus/Avatar/Samples/CrossPlatform/Readme.txt new file mode 100644 index 0000000..ba32dbd --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/CrossPlatform/Readme.txt @@ -0,0 +1,20 @@ +This CrossPlatform sample scene demonstrates how Oculus Avatars can now be used on non-Oculus devices. + +For more detailed information on this sample and cross-platform Avatar functionality, including details on customization and redistribution requirements, see the topic on this sample at: https://developer.oculus.com/documentation/avatarsdk/latest/concepts/avatars-unity-crossplat-sample/ + +Setup instructions: +1 - Install Steam and SteamVR +2 - Create a new Unity Project +3 - Import the Oculus Integration from the Unity Asset Store. +4 - Open the CrossPlatform scene (in Assets/Oculus/Avatar/Samples/CrossPlatform) +5 - Use the Oculus Dashboard (https://dashboard.oculus.com/) to create a placeholder Rift app and copy the App ID +6 - Paste the App ID in Unity under Oculus Avatars > Edit Configuration > Oculus Rift App Id +7 - Enable OpenVR: + Open PlayerSettings in the Inspector tab (from menu bar, Edit > Project Settings > Player) + Under Virtual Reality SDKs, add OpenVR if it's not there already + Remove Oculus (or drag it below OpenVR) so that OpenVR is used when the scene is played. +8 - Click Play + +The scene should play using SteamVR rather than the Oculus platform, and you'll see 12 different Oculus Avatars in front of you. + + diff --git a/Assets/Oculus/Avatar/Samples/CrossPlatform/Readme.txt.meta b/Assets/Oculus/Avatar/Samples/CrossPlatform/Readme.txt.meta new file mode 100644 index 0000000..2d2ba09 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/CrossPlatform/Readme.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5ec1b7b12e3fb3e4b99590edb47d298f +timeCreated: 1539938373 +licenseType: Pro +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/GripPoses.meta b/Assets/Oculus/Avatar/Samples/GripPoses.meta new file mode 100644 index 0000000..cb265df --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/GripPoses.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: b8c4b9475079cf040953bf344ff4e44f +folderAsset: yes +timeCreated: 1477955918 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/GripPoses/GripPoses.unity b/Assets/Oculus/Avatar/Samples/GripPoses/GripPoses.unity new file mode 100644 index 0000000..07857ed --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/GripPoses/GripPoses.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:63d17e77d6b34caf2406b23b1b72062a19433d30354f72dc0b699b7cd08b6a3a +size 84418 diff --git a/Assets/Oculus/Avatar/Samples/GripPoses/GripPoses.unity.meta b/Assets/Oculus/Avatar/Samples/GripPoses/GripPoses.unity.meta new file mode 100644 index 0000000..bacecaf --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/GripPoses/GripPoses.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 697c6df5e1eddad40b634d311b0bb2e5 +timeCreated: 1477966491 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/GripPoses/Scripts.meta b/Assets/Oculus/Avatar/Samples/GripPoses/Scripts.meta new file mode 100644 index 0000000..3271407 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/GripPoses/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 85678699140c6c3429a87f4d679b1a17 +folderAsset: yes +timeCreated: 1477957292 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/GripPoses/Scripts/PoseEditHelper.cs b/Assets/Oculus/Avatar/Samples/GripPoses/Scripts/PoseEditHelper.cs new file mode 100644 index 0000000..9e2af7e --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/GripPoses/Scripts/PoseEditHelper.cs @@ -0,0 +1,31 @@ +using UnityEngine; +using System.Collections; +using System; + +public class PoseEditHelper : MonoBehaviour { + + public Transform poseRoot; + + void OnDrawGizmos() + { + if (poseRoot != null) + { + DrawJoints(poseRoot); + } + } + + private void DrawJoints(Transform joint) + { + Gizmos.DrawWireSphere(joint.position, 0.005f); + for (int i = 0; i < joint.childCount; ++i) + { + Transform child = joint.GetChild(i); + if (child.name.EndsWith("_grip") || child.name.EndsWith("hand_ignore")) + { + continue; + } + Gizmos.DrawLine(joint.position, child.position); + DrawJoints(child); + } + } +} diff --git a/Assets/Oculus/Avatar/Samples/GripPoses/Scripts/PoseEditHelper.cs.meta b/Assets/Oculus/Avatar/Samples/GripPoses/Scripts/PoseEditHelper.cs.meta new file mode 100644 index 0000000..9d6cd77 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/GripPoses/Scripts/PoseEditHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6bc5b4ba964e02b4ea773b2aaca7dc67 +timeCreated: 1477957304 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar.meta b/Assets/Oculus/Avatar/Samples/LocalAvatar.meta new file mode 100644 index 0000000..e72b93c --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 2883b756c033a864ca988b3f522f3339 +folderAsset: yes +timeCreated: 1467313725 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/LocalAvatar.unity b/Assets/Oculus/Avatar/Samples/LocalAvatar/LocalAvatar.unity new file mode 100644 index 0000000..15e657e --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/LocalAvatar.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7e9ad6270b9e1d773fe19fbbb9c4f82c0951125800dbec827034f346c6edd667 +size 20799 diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/LocalAvatar.unity.meta b/Assets/Oculus/Avatar/Samples/LocalAvatar/LocalAvatar.unity.meta new file mode 100644 index 0000000..e078837 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/LocalAvatar.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c65ef87480e70eb43931036c9c66d08d +timeCreated: 1466730185 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs.meta b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs.meta new file mode 100644 index 0000000..22645b9 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6ab4fae765a78ff4891d22240708e124 +folderAsset: yes +timeCreated: 1543419231 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTarget.prefab b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTarget.prefab new file mode 100644 index 0000000..19b5649 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTarget.prefab @@ -0,0 +1,97 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1862311091348296} + m_IsPrefabParent: 1 +--- !u!1 &1862311091348296 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4698346712314376} + - component: {fileID: 33311121837070838} + - component: {fileID: 23625037719976976} + - component: {fileID: 114267226149696678} + m_Layer: 0 + m_Name: GazeTarget + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4698346712314376 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1862311091348296} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.05, y: 0.05, z: 0.05} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &23625037719976976 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1862311091348296} + m_Enabled: 0 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33311121837070838 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1862311091348296} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &114267226149696678 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1862311091348296} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 5bfcd054df64e334ba2f191666f3fe92, type: 3} + m_Name: + m_EditorClassIdentifier: + Type: 2 diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTarget.prefab.meta b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTarget.prefab.meta new file mode 100644 index 0000000..c58eb5e --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTarget.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 38d5bb078fd83c9428125e487bef4a1a +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTargetSpawner.prefab b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTargetSpawner.prefab new file mode 100644 index 0000000..109defd --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTargetSpawner.prefab @@ -0,0 +1,58 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1886941009443022} + m_IsPrefabParent: 1 +--- !u!1 &1886941009443022 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4372900245187776} + - component: {fileID: 114195579247105032} + m_Layer: 0 + m_Name: GazeTargetSpawner + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4372900245187776 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1886941009443022} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &114195579247105032 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1886941009443022} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 3864ef0c62744294899fddc93640130f, type: 3} + m_Name: + m_EditorClassIdentifier: + GazeTargetPrefab: {fileID: 1862311091348296, guid: 38d5bb078fd83c9428125e487bef4a1a, + type: 2} + NumberOfDummyTargets: 100 + RadiusMultiplier: 3 + isVisible: 0 diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTargetSpawner.prefab.meta b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTargetSpawner.prefab.meta new file mode 100644 index 0000000..4161bff --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Prefabs/GazeTargetSpawner.prefab.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 93c8b27ca530be741a2ea419a122d453 +timeCreated: 1543419517 +licenseType: Pro +NativeFormatImporter: + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts.meta b/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts.meta new file mode 100644 index 0000000..fc5906a --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 1391b4a6e544aab4bb1d8cf41ef93d8e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts/GazeTargetSpawner.cs b/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts/GazeTargetSpawner.cs new file mode 100644 index 0000000..e82db7d --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts/GazeTargetSpawner.cs @@ -0,0 +1,48 @@ +using UnityEngine; + +public class GazeTargetSpawner : MonoBehaviour +{ + public GameObject GazeTargetPrefab; + public int NumberOfDummyTargets = 100; + public int RadiusMultiplier = 3; + [SerializeField] + private bool isVisible; + public bool IsVisible + { + get + { + return isVisible; + } + set + { + isVisible = value; + GazeTarget[] dummyGazeTargets = gameObject.GetComponentsInChildren(); + for (int i = 0; i < dummyGazeTargets.Length; ++i) + { + MeshRenderer dummyMesh = dummyGazeTargets[i].GetComponent(); + if (dummyMesh != null) + { + dummyMesh.enabled = isVisible; + } + } + } + } + + void Start () + { + for (int i = 0; i < NumberOfDummyTargets; ++i) + { + GameObject target = Instantiate(GazeTargetPrefab, transform); + target.name += "_" + i; + target.transform.localPosition = Random.insideUnitSphere * RadiusMultiplier; + target.transform.rotation = Quaternion.identity; + target.GetComponent().enabled = IsVisible; + } + } + + void OnValidate() + { + // Run through OnValidate to pick up changes from inspector + IsVisible = isVisible; + } +} diff --git a/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts/GazeTargetSpawner.cs.meta b/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts/GazeTargetSpawner.cs.meta new file mode 100644 index 0000000..f25b58c --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/LocalAvatar/Scripts/GazeTargetSpawner.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3864ef0c62744294899fddc93640130f +timeCreated: 1543418975 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/RemoteLoopback.meta b/Assets/Oculus/Avatar/Samples/RemoteLoopback.meta new file mode 100644 index 0000000..6746d42 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/RemoteLoopback.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f26892c9951b6f54c82a5f1bf34e8d8a +folderAsset: yes +timeCreated: 1468000039 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/RemoteLoopback/RemoteLoopback.unity b/Assets/Oculus/Avatar/Samples/RemoteLoopback/RemoteLoopback.unity new file mode 100644 index 0000000..e513295 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/RemoteLoopback/RemoteLoopback.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:90437a3351ed01002c98037d22146994d40d677f4ceca2c66b61c9d8fb608cad +size 16410 diff --git a/Assets/Oculus/Avatar/Samples/RemoteLoopback/RemoteLoopback.unity.meta b/Assets/Oculus/Avatar/Samples/RemoteLoopback/RemoteLoopback.unity.meta new file mode 100644 index 0000000..131caa3 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/RemoteLoopback/RemoteLoopback.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: aa35ff5ba76fb384d839383c84209da9 +timeCreated: 1468000130 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts.meta b/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts.meta new file mode 100644 index 0000000..d808d70 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: edf34aa3892fd9f4eb0795663f7e3ffc +folderAsset: yes +timeCreated: 1468000607 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts/RemoteLoopbackManager.cs b/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts/RemoteLoopbackManager.cs new file mode 100644 index 0000000..354e791 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts/RemoteLoopbackManager.cs @@ -0,0 +1,155 @@ +using UnityEngine; +using System.Collections; +using System; +using System.IO; +using Oculus.Avatar; +using System.Runtime.InteropServices; +using System.Collections.Generic; + +public class RemoteLoopbackManager : MonoBehaviour +{ + class PacketLatencyPair + { + public byte[] PacketData; + public float FakeLatency; + }; + + public OvrAvatar LocalAvatar; + public OvrAvatar LoopbackAvatar; + + [System.Serializable] + public class SimulatedLatencySettings + { + [Range(0.0f, 0.5f)] + public float FakeLatencyMax = 0.25f; //250 ms max latency + + [Range(0.0f, 0.5f)] + public float FakeLatencyMin = 0.002f; //2ms min latency + + [Range(0.0f, 1.0f)] + public float LatencyWeight = 0.25f; // How much the latest sample impacts the current latency + + [Range(0,10)] + public int MaxSamples = 4; //How many samples in our window + + internal float AverageWindow = 0f; + internal float LatencySum = 0f; + internal LinkedList LatencyValues = new LinkedList(); + + public float NextValue() + { + AverageWindow = LatencySum / (float)LatencyValues.Count; + float RandomLatency = UnityEngine.Random.Range(FakeLatencyMin, FakeLatencyMax); + float FakeLatency = AverageWindow * (1f - LatencyWeight) + LatencyWeight * RandomLatency; + + if (LatencyValues.Count >= MaxSamples) + { + LatencySum -= LatencyValues.First.Value; + LatencyValues.RemoveFirst(); + } + + LatencySum += FakeLatency; + LatencyValues.AddLast(FakeLatency); + + return FakeLatency; + } + }; + + public SimulatedLatencySettings LatencySettings = new SimulatedLatencySettings(); + + private int PacketSequence = 0; + + LinkedList packetQueue = new LinkedList(); + + void Start() + { + LocalAvatar.RecordPackets = true; + LocalAvatar.PacketRecorded += OnLocalAvatarPacketRecorded; + float FirstValue = UnityEngine.Random.Range(LatencySettings.FakeLatencyMin, LatencySettings.FakeLatencyMax); + LatencySettings.LatencyValues.AddFirst(FirstValue); + LatencySettings.LatencySum += FirstValue; + } + + void OnLocalAvatarPacketRecorded(object sender, OvrAvatar.PacketEventArgs args) + { + using (MemoryStream outputStream = new MemoryStream()) + { + BinaryWriter writer = new BinaryWriter(outputStream); + + if (LocalAvatar.UseSDKPackets) + { + var size = CAPI.ovrAvatarPacket_GetSize(args.Packet.ovrNativePacket); + byte[] data = new byte[size]; + CAPI.ovrAvatarPacket_Write(args.Packet.ovrNativePacket, size, data); + + writer.Write(PacketSequence++); + writer.Write(size); + writer.Write(data); + } + else + { + writer.Write(PacketSequence++); + args.Packet.Write(outputStream); + } + + SendPacketData(outputStream.ToArray()); + } + } + + void Update() + { + if (packetQueue.Count > 0) + { + List deadList = new List(); + foreach (var packet in packetQueue) + { + packet.FakeLatency -= Time.deltaTime; + + if (packet.FakeLatency < 0f) + { + ReceivePacketData(packet.PacketData); + deadList.Add(packet); + } + } + + foreach (var packet in deadList) + { + packetQueue.Remove(packet); + } + } + } + + void SendPacketData(byte[] data) + { + PacketLatencyPair PacketPair = new PacketLatencyPair(); + PacketPair.PacketData = data; + PacketPair.FakeLatency = LatencySettings.NextValue(); + + packetQueue.AddLast(PacketPair); + } + + void ReceivePacketData(byte[] data) + { + using (MemoryStream inputStream = new MemoryStream(data)) + { + BinaryReader reader = new BinaryReader(inputStream); + int sequence = reader.ReadInt32(); + + OvrAvatarPacket avatarPacket; + if (LoopbackAvatar.UseSDKPackets) + { + int size = reader.ReadInt32(); + byte[] sdkData = reader.ReadBytes(size); + + IntPtr packet = CAPI.ovrAvatarPacket_Read((UInt32)data.Length, sdkData); + avatarPacket = new OvrAvatarPacket { ovrNativePacket = packet }; + } + else + { + avatarPacket = OvrAvatarPacket.Read(inputStream); + } + + LoopbackAvatar.GetComponent().QueuePacket(sequence, avatarPacket); + } + } +} diff --git a/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts/RemoteLoopbackManager.cs.meta b/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts/RemoteLoopbackManager.cs.meta new file mode 100644 index 0000000..53843bd --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/RemoteLoopback/Scripts/RemoteLoopbackManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1675d6690178fd0459887aed66409f70 +timeCreated: 1468000639 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter.meta b/Assets/Oculus/Avatar/Samples/SocialStarter.meta new file mode 100644 index 0000000..b2c7c5a --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f853d92f5be267947bcbbc142982b463 +folderAsset: yes +timeCreated: 1517509658 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets.meta new file mode 100644 index 0000000..76300ed --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 95e9e8192781ad94bad26b153c265787 +folderAsset: yes +timeCreated: 1517509663 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/MainScene.unity b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/MainScene.unity new file mode 100644 index 0000000..cbe800b --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/MainScene.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ecd0a3cbe238b58bdf145dfbd4b1ed8222b0e659bb4f6e980388dea515975df4 +size 21652 diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/MainScene.unity.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/MainScene.unity.meta new file mode 100644 index 0000000..a9255b4 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/MainScene.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 236a5f96528802e47a70d6e47ebd3c16 +timeCreated: 1496779803 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials.meta new file mode 100644 index 0000000..2d83e77 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 777b874d432a52044991fe1a0210200c +folderAsset: yes +timeCreated: 1496779985 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/GearHelp.mat b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/GearHelp.mat new file mode 100644 index 0000000..99b55f7 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/GearHelp.mat @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: GearHelp + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + - first: + name: _BumpMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailAlbedoMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailMask + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailNormalMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _EmissionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MainTex + second: + m_Texture: {fileID: 2800000, guid: 0453138effcc80349b11371805f72f5b, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MetallicGlossMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _OcclusionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _ParallaxMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - first: + name: _BumpScale + second: 1 + - first: + name: _Cutoff + second: 0.5 + - first: + name: _DetailNormalMapScale + second: 1 + - first: + name: _DstBlend + second: 0 + - first: + name: _GlossMapScale + second: 1 + - first: + name: _Glossiness + second: 0.5 + - first: + name: _GlossyReflections + second: 1 + - first: + name: _Metallic + second: 0 + - first: + name: _Mode + second: 0 + - first: + name: _OcclusionStrength + second: 1 + - first: + name: _Parallax + second: 0.02 + - first: + name: _SmoothnessTextureChannel + second: 0 + - first: + name: _SpecularHighlights + second: 1 + - first: + name: _SrcBlend + second: 1 + - first: + name: _UVSec + second: 0 + - first: + name: _ZWrite + second: 1 + m_Colors: + - first: + name: _Color + second: {r: 1, g: 1, b: 1, a: 1} + - first: + name: _EmissionColor + second: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/GearHelp.mat.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/GearHelp.mat.meta new file mode 100644 index 0000000..7d8cbc5 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/GearHelp.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 09c03a3c5049d234590b91bbc6e84462 +timeCreated: 1497549036 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Help.mat b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Help.mat new file mode 100644 index 0000000..8e48f7b --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Help.mat @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Help + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 5 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + - first: + name: _BumpMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailAlbedoMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailMask + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailNormalMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _EmissionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MainTex + second: + m_Texture: {fileID: 2800000, guid: c8f5462cc092d0c40ad71773132863e0, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MetallicGlossMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _OcclusionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _ParallaxMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - first: + name: _BumpScale + second: 1 + - first: + name: _Cutoff + second: 0.5 + - first: + name: _DetailNormalMapScale + second: 1 + - first: + name: _DstBlend + second: 0 + - first: + name: _GlossMapScale + second: 1 + - first: + name: _Glossiness + second: 0.5 + - first: + name: _GlossyReflections + second: 1 + - first: + name: _Metallic + second: 0 + - first: + name: _Mode + second: 0 + - first: + name: _OcclusionStrength + second: 1 + - first: + name: _Parallax + second: 0.02 + - first: + name: _SmoothnessTextureChannel + second: 0 + - first: + name: _SpecularHighlights + second: 1 + - first: + name: _SrcBlend + second: 1 + - first: + name: _UVSec + second: 0 + - first: + name: _ZWrite + second: 1 + m_Colors: + - first: + name: _Color + second: {r: 1, g: 1, b: 1, a: 1} + - first: + name: _EmissionColor + second: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Help.mat.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Help.mat.meta new file mode 100644 index 0000000..b604021 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Help.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4c18da23435024b43a2b78449cbb6ed0 +timeCreated: 1496780065 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Offline_Mat.mat b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Offline_Mat.mat new file mode 100644 index 0000000..4c68bcc --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Offline_Mat.mat @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Offline_Mat + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION + m_LightmapFlags: 1 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + - first: + name: _BumpMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailAlbedoMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailMask + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailNormalMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _EmissionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MainTex + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MetallicGlossMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _OcclusionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _ParallaxMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - first: + name: _BumpScale + second: 1 + - first: + name: _Cutoff + second: 0.5 + - first: + name: _DetailNormalMapScale + second: 1 + - first: + name: _DstBlend + second: 0 + - first: + name: _GlossMapScale + second: 1 + - first: + name: _Glossiness + second: 0.5 + - first: + name: _GlossyReflections + second: 1 + - first: + name: _Metallic + second: 0 + - first: + name: _Mode + second: 0 + - first: + name: _OcclusionStrength + second: 1 + - first: + name: _Parallax + second: 0.02 + - first: + name: _SmoothnessTextureChannel + second: 0 + - first: + name: _SpecularHighlights + second: 1 + - first: + name: _SrcBlend + second: 1 + - first: + name: _UVSec + second: 0 + - first: + name: _ZWrite + second: 1 + m_Colors: + - first: + name: _Color + second: {r: 0, g: 0, b: 0, a: 1} + - first: + name: _EmissionColor + second: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Offline_Mat.mat.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Offline_Mat.mat.meta new file mode 100644 index 0000000..715d9cd --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Offline_Mat.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 296de5be1228bf34380061dd6e6b0f49 +timeCreated: 1496780100 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Plane_Mat.mat b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Plane_Mat.mat new file mode 100644 index 0000000..95d36c2 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Plane_Mat.mat @@ -0,0 +1,127 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Plane_Mat + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION + m_LightmapFlags: 1 + m_CustomRenderQueue: -1 + stringTagMap: {} + m_SavedProperties: + serializedVersion: 2 + m_TexEnvs: + - first: + name: _BumpMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailAlbedoMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailMask + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _DetailNormalMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _EmissionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MainTex + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _MetallicGlossMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _OcclusionMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - first: + name: _ParallaxMap + second: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - first: + name: _BumpScale + second: 1 + - first: + name: _Cutoff + second: 0.5 + - first: + name: _DetailNormalMapScale + second: 1 + - first: + name: _DstBlend + second: 0 + - first: + name: _GlossMapScale + second: 1 + - first: + name: _Glossiness + second: 0.5 + - first: + name: _GlossyReflections + second: 1 + - first: + name: _Metallic + second: 0 + - first: + name: _Mode + second: 0 + - first: + name: _OcclusionStrength + second: 1 + - first: + name: _Parallax + second: 0.02 + - first: + name: _SmoothnessTextureChannel + second: 0 + - first: + name: _SpecularHighlights + second: 1 + - first: + name: _SrcBlend + second: 1 + - first: + name: _UVSec + second: 0 + - first: + name: _ZWrite + second: 1 + m_Colors: + - first: + name: _Color + second: {r: 0, g: 0.25517225, b: 1, a: 1} + - first: + name: _EmissionColor + second: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Plane_Mat.mat.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Plane_Mat.mat.meta new file mode 100644 index 0000000..df072c2 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials/Plane_Mat.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c466b89bb972b8a42bd266c102f8f2cb +timeCreated: 1496780131 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts.meta new file mode 100644 index 0000000..112dcf9 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: f05e47c366870a44ab2b3b5a8a64e107 +folderAsset: yes +timeCreated: 1496780004 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/P2PManager.cs b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/P2PManager.cs new file mode 100644 index 0000000..e2ade5b --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/P2PManager.cs @@ -0,0 +1,232 @@ +using UnityEngine; +using System; +using Oculus.Platform; +using Oculus.Platform.Models; + +// Helper class to manage a Peer-to-Peer connection to the other user. +// The connection is used to send and received the Transforms for the +// Avatars. The Transforms are sent via unreliable UDP at a fixed +// frequency. +public class P2PManager +{ + // packet header is a message type byte + private enum MessageType : byte + { + Update = 1, + }; + + public P2PManager() + { + Net.SetPeerConnectRequestCallback(PeerConnectRequestCallback); + Net.SetConnectionStateChangedCallback(ConnectionStateChangedCallback); + } + + #region Connection Management + + public void ConnectTo(ulong userID) + { + // ID comparison is used to decide who calls Connect and who calls Accept + if (SocialPlatformManager.MyID < userID) + { + Net.Connect(userID); + SocialPlatformManager.LogOutput("P2P connect to " + userID); + } + } + + public void Disconnect(ulong userID) + { + if (userID != 0) + { + Net.Close(userID); + + RemotePlayer remote = SocialPlatformManager.GetRemoteUser(userID); + if (remote != null) + { + remote.p2pConnectionState = PeerConnectionState.Unknown; + } + } + } + + void PeerConnectRequestCallback(Message msg) + { + SocialPlatformManager.LogOutput("P2P request from " + msg.Data.ID); + + RemotePlayer remote = SocialPlatformManager.GetRemoteUser(msg.Data.ID); + if (remote != null) + { + SocialPlatformManager.LogOutput("P2P request accepted from " + msg.Data.ID); + Net.Accept(msg.Data.ID); + } + } + + void ConnectionStateChangedCallback(Message msg) + { + SocialPlatformManager.LogOutput("P2P state to " + msg.Data.ID + " changed to " + msg.Data.State); + + RemotePlayer remote = SocialPlatformManager.GetRemoteUser(msg.Data.ID); + if (remote != null) + { + remote.p2pConnectionState = msg.Data.State; + + if (msg.Data.State == PeerConnectionState.Timeout && + // ID comparison is used to decide who calls Connect and who calls Accept + SocialPlatformManager.MyID < msg.Data.ID) + { + // keep trying until hangup! + Net.Connect(msg.Data.ID); + SocialPlatformManager.LogOutput("P2P re-connect to " + msg.Data.ID); + } + } + } + + #endregion + + #region Message Sending + + public void SendAvatarUpdate(ulong userID, Transform rootTransform, UInt32 sequence, byte[] avatarPacket) + { + const int UPDATE_DATA_LENGTH = 41; + byte[] sendBuffer = new byte[avatarPacket.Length + UPDATE_DATA_LENGTH]; + + int offset = 0; + PackByte((byte)MessageType.Update, sendBuffer, ref offset); + + PackULong(SocialPlatformManager.MyID, sendBuffer, ref offset); + + PackFloat(rootTransform.position.x, sendBuffer, ref offset); + // Lock to floor height + PackFloat(0f, sendBuffer, ref offset); + PackFloat(rootTransform.position.z, sendBuffer, ref offset); + PackFloat(rootTransform.rotation.x, sendBuffer, ref offset); + PackFloat(rootTransform.rotation.y, sendBuffer, ref offset); + PackFloat(rootTransform.rotation.z, sendBuffer, ref offset); + PackFloat(rootTransform.rotation.w, sendBuffer, ref offset); + + PackUInt32(sequence, sendBuffer, ref offset); + + Debug.Assert(offset == UPDATE_DATA_LENGTH); + + Buffer.BlockCopy(avatarPacket, 0, sendBuffer, offset, avatarPacket.Length); + Net.SendPacket(userID, sendBuffer, SendPolicy.Unreliable); + } + #endregion + + #region Message Receiving + + public void GetRemotePackets() + { + Packet packet; + + while ((packet = Net.ReadPacket()) != null) + { + byte[] receiveBuffer = new byte[packet.Size]; + packet.ReadBytes(receiveBuffer); + + int offset = 0; + MessageType messageType = (MessageType)ReadByte(receiveBuffer, ref offset); + + ulong remoteUserID = ReadULong(receiveBuffer, ref offset); + RemotePlayer remote = SocialPlatformManager.GetRemoteUser(remoteUserID); + if (remote == null) + { + SocialPlatformManager.LogOutput("Unknown remote player: " + remoteUserID); + continue; + } + + if (messageType == MessageType.Update) + { + processAvatarPacket(remote, ref receiveBuffer, ref offset); + } + else + { + SocialPlatformManager.LogOutput("Invalid packet type: " + packet.Size); + continue; + } + + } + } + + public void processAvatarPacket(RemotePlayer remote, ref byte[] packet, ref int offset) + { + if (remote == null) + return; + + remote.receivedRootPositionPrior = remote.receivedRootPosition; + remote.receivedRootPosition.x = ReadFloat(packet, ref offset); + remote.receivedRootPosition.y = ReadFloat(packet, ref offset); + remote.receivedRootPosition.z = ReadFloat(packet, ref offset); + + remote.receivedRootRotationPrior = remote.receivedRootRotation; + remote.receivedRootRotation.x = ReadFloat(packet, ref offset); + remote.receivedRootRotation.y = ReadFloat(packet, ref offset); + remote.receivedRootRotation.z = ReadFloat(packet, ref offset); + remote.receivedRootRotation.w = ReadFloat(packet, ref offset); + + remote.RemoteAvatar.transform.position = remote.receivedRootPosition; + remote.RemoteAvatar.transform.rotation = remote.receivedRootRotation; + + // forward the remaining data to the avatar system + int sequence = (int)ReadUInt32(packet, ref offset); + + byte[] remainingAvatarBuffer = new byte[packet.Length - offset]; + Buffer.BlockCopy(packet, offset, remainingAvatarBuffer, 0, remainingAvatarBuffer.Length); + + IntPtr avatarPacket = Oculus.Avatar.CAPI.ovrAvatarPacket_Read((UInt32)remainingAvatarBuffer.Length, remainingAvatarBuffer); + + var ovravatarPacket = new OvrAvatarPacket { ovrNativePacket = avatarPacket }; + remote.RemoteAvatar.GetComponent().QueuePacket(sequence, ovravatarPacket); + } + #endregion + + #region Serialization + + void PackByte(byte b, byte[] buf, ref int offset) + { + buf[offset] = b; + offset += sizeof(byte); + } + byte ReadByte(byte[] buf, ref int offset) + { + byte val = buf[offset]; + offset += sizeof(byte); + return val; + } + + void PackFloat(float f, byte[] buf, ref int offset) + { + Buffer.BlockCopy(BitConverter.GetBytes(f), 0, buf, offset, sizeof(float)); + offset += sizeof(float); + } + float ReadFloat(byte[] buf, ref int offset) + { + float val = BitConverter.ToSingle(buf, offset); + offset += sizeof(float); + return val; + } + + void PackULong(ulong u, byte[] buf, ref int offset) + { + Buffer.BlockCopy(BitConverter.GetBytes(u), 0, buf, offset, sizeof(ulong)); + offset += sizeof(ulong); + } + ulong ReadULong(byte[] buf, ref int offset) + { + ulong val = BitConverter.ToUInt64(buf, offset); + offset += sizeof(ulong); + return val; + } + + void PackUInt32(UInt32 u, byte[] buf, ref int offset) + { + Buffer.BlockCopy(BitConverter.GetBytes(u), 0, buf, offset, sizeof(UInt32)); + offset += sizeof(UInt32); + } + UInt32 ReadUInt32(byte[] buf, ref int offset) + { + UInt32 val = BitConverter.ToUInt32(buf, offset); + offset += sizeof(UInt32); + return val; + } + + #endregion +} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/P2PManager.cs.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/P2PManager.cs.meta new file mode 100644 index 0000000..6903446 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/P2PManager.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e5d77a60e86b5bd4a999ef6c83f9e651 +timeCreated: 1521151723 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/PlayerController.cs b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/PlayerController.cs new file mode 100644 index 0000000..332d0cb --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/PlayerController.cs @@ -0,0 +1,101 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +using Oculus.Platform; +using Oculus.Platform.Models; + +public class PlayerController : SocialPlatformManager +{ + + // Secondary camera to debug and view the whole scene from above + public Camera spyCamera; + + // The OVRCameraRig for the main player so we can disable it + private GameObject cameraRig; + + private bool showUI = true; + + public override void Awake() + { + base.Awake(); + cameraRig = localPlayerHead.gameObject; + } + + // Use this for initialization + public override void Start() + { + base.Start(); + spyCamera.enabled = false; + } + + // Update is called once per frame + public override void Update() + { + base.Update(); + checkInput(); + } + + // Check for input from the touch controllers + void checkInput() + { + if (UnityEngine.Application.platform == RuntimePlatform.Android) + { + // GearVR Controller + + // Bring up friend invite list + if (OVRInput.GetDown(OVRInput.Button.Back)) + { + Rooms.LaunchInvitableUserFlow(roomManager.roomID); + } + + // Toggle Camera + if (OVRInput.GetDown(OVRInput.Button.PrimaryTouchpad)) + { + ToggleCamera(); + } + + // Toggle Help UI + if (OVRInput.GetDown(OVRInput.Button.PrimaryIndexTrigger)) + { + ToggleUI(); + } + } + else + { + // PC Touch + + // Bring up friend invite list + if (OVRInput.GetDown(OVRInput.Button.Three)) + { + Rooms.LaunchInvitableUserFlow (roomManager.roomID); + } + + // Toggle Camera + if (OVRInput.GetDown(OVRInput.Button.Four)) + { + ToggleCamera(); + } + + // Toggle Help UI + if (OVRInput.GetDown(OVRInput.Button.PrimaryThumbstick)) + { + ToggleUI(); + } + } + } + + void ToggleCamera() + { + spyCamera.enabled = !spyCamera.enabled; + localAvatar.ShowThirdPerson = !localAvatar.ShowThirdPerson; + cameraRig.SetActive(!cameraRig.activeSelf); + } + + void ToggleUI() + { + showUI = !showUI; + helpPanel.SetActive(showUI); + localAvatar.ShowLeftController(showUI); + } +} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/PlayerController.cs.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/PlayerController.cs.meta new file mode 100644 index 0000000..74a852b --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/PlayerController.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 043fbfd0ae7027742bace7a3691feb13 +timeCreated: 1521151723 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RemotePlayer.cs b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RemotePlayer.cs new file mode 100644 index 0000000..639e1de --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RemotePlayer.cs @@ -0,0 +1,32 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using Oculus.Platform; + +public class RemotePlayer +{ + public ulong remoteUserID; + public bool stillInRoom; + + // the result of the last connection state update message + public PeerConnectionState p2pConnectionState; + // the last reported state of the VOIP connection + public PeerConnectionState voipConnectionState; + + public OvrAvatar RemoteAvatar; + + // the last received root transform position updates, equivalent to local tracking space transform + public Vector3 receivedRootPosition; + + // the previous received positions to interpolate from + public Vector3 receivedRootPositionPrior; + + // the last received root transform rotation updates, equivalent to local tracking space transform + public Quaternion receivedRootRotation; + + // the previous received rotations to interpolate from + public Quaternion receivedRootRotationPrior; + + // the voip tracker for the player + public VoipAudioSourceHiLevel voipSource; +} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RemotePlayer.cs.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RemotePlayer.cs.meta new file mode 100644 index 0000000..9ae6e75 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RemotePlayer.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: e5bc955e8176ef1478360f25ef5ccc8a +timeCreated: 1521151723 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RoomManager.cs b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RoomManager.cs new file mode 100644 index 0000000..924429b --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RoomManager.cs @@ -0,0 +1,225 @@ +using UnityEngine; +using System; +using System.Collections.Generic; +using Oculus.Platform; +using Oculus.Platform.Models; + +// Helper class to manage Room creation, membership and invites. +// Rooms are a mechanism to help Oculus users create a shared experience. +// Users can only be in one Room at a time. If the Owner of a room +// leaves, then ownership is transferred to some other member. +// Here we use rooms to create the notion of a 'call' to help us +// invite a Friend and establish a VOIP and P2P connection. +public class RoomManager +{ + // the ID of the Room that I'm in + public ulong roomID; + + // the ID of the Room that I'm invited to + private ulong invitedRoomID; + + // Am I the server? + private bool amIServer; + + // Have we already gone through the startup? + private bool startupDone; + + public RoomManager() + { + amIServer = false; + startupDone = false; + Rooms.SetRoomInviteAcceptedNotificationCallback(AcceptingInviteCallback); + Rooms.SetUpdateNotificationCallback(RoomUpdateCallback); + } + + #region Launched Application from Accepting Invite + + // Callback to check whether the User accepted an invite + void AcceptingInviteCallback(Message msg) + { + if (msg.IsError) + { + SocialPlatformManager.TerminateWithError(msg); + return; + } + + SocialPlatformManager.LogOutput("Launched Invite to join Room: " + msg.Data); + + invitedRoomID = Convert.ToUInt64(msg.GetString()); + + if (startupDone) + { + CheckForInvite(); + } + } + + // Check to see if the App was launched by accepting the Notication from the main Oculus app. + // If so, we can directly join that room. (If it's still available.) + public bool CheckForInvite() + { + startupDone = true; + + if (invitedRoomID != 0) + { + JoinExistingRoom(invitedRoomID); + return true; + } + else + { + return false; + } + } + + #endregion + + #region Create a Room and Invite Friend(s) from the Oculus Universal Menu + + public void CreateRoom() + { + Rooms.CreateAndJoinPrivate(RoomJoinPolicy.FriendsOfOwner, 4, true) + .OnComplete(CreateAndJoinPrivateRoomCallback); + } + + void CreateAndJoinPrivateRoomCallback(Message msg) + { + if (msg.IsError) + { + SocialPlatformManager.TerminateWithError(msg); + return; + } + + roomID = msg.Data.ID; + + if (msg.Data.OwnerOptional != null && msg.Data.OwnerOptional.ID == SocialPlatformManager.MyID) + { + amIServer = true; + } + else + { + amIServer = false; + } + + SocialPlatformManager.TransitionToState(SocialPlatformManager.State.WAITING_IN_A_ROOM); + SocialPlatformManager.SetFloorColorForState(amIServer); + } + + void OnLaunchInviteWorkflowComplete(Message msg) + { + if (msg.IsError) + { + SocialPlatformManager.TerminateWithError(msg); + return; + } + } + + #endregion + + #region Accept Invite + + public void JoinExistingRoom(ulong roomID) + { + SocialPlatformManager.TransitionToState(SocialPlatformManager.State.JOINING_A_ROOM); + Rooms.Join(roomID, true).OnComplete(JoinRoomCallback); + } + + void JoinRoomCallback(Message msg) + { + if (msg.IsError) + { + // is reasonable if caller called more than 1 person, and I didn't answer first + return; + } + + var ownerOculusId = msg.Data.OwnerOptional != null ? msg.Data.OwnerOptional.OculusID : "null"; + var userCount = msg.Data.UsersOptional != null ? msg.Data.UsersOptional.Count : 0; + + SocialPlatformManager.LogOutput("Joined Room " + msg.Data.ID + " owner: " + ownerOculusId + " count: " + userCount); + roomID = msg.Data.ID; + ProcessRoomData(msg); + } + + #endregion + + #region Room Updates + + void RoomUpdateCallback(Message msg) + { + if (msg.IsError) + { + SocialPlatformManager.TerminateWithError(msg); + return; + } + + var ownerOculusId = msg.Data.OwnerOptional != null ? msg.Data.OwnerOptional.OculusID : "null"; + var userCount = msg.Data.UsersOptional != null ? msg.Data.UsersOptional.Count : 0; + + SocialPlatformManager.LogOutput("Room Update " + msg.Data.ID + " owner: " + ownerOculusId + " count: " + userCount); + ProcessRoomData(msg); + } + + #endregion + + #region Room Exit + + public void LeaveCurrentRoom() + { + if (roomID != 0) + { + Rooms.Leave(roomID); + roomID = 0; + } + SocialPlatformManager.TransitionToState(SocialPlatformManager.State.LEAVING_A_ROOM); + } + + #endregion + + #region Process Room Data + + void ProcessRoomData(Message msg) + { + if (msg.Data.OwnerOptional != null && msg.Data.OwnerOptional.ID == SocialPlatformManager.MyID) + { + amIServer = true; + } + else + { + amIServer = false; + } + + // if the caller left while I was in the process of joining, just use that as our new room + if (msg.Data.UsersOptional != null && msg.Data.UsersOptional.Count == 1) + { + SocialPlatformManager.TransitionToState(SocialPlatformManager.State.WAITING_IN_A_ROOM); + } + else + { + SocialPlatformManager.TransitionToState(SocialPlatformManager.State.CONNECTED_IN_A_ROOM); + } + + // Look for users that left + SocialPlatformManager.MarkAllRemoteUsersAsNotInRoom(); + + if (msg.Data.UsersOptional != null) + { + foreach (User user in msg.Data.UsersOptional) + { + if (user.ID != SocialPlatformManager.MyID) + { + if (!SocialPlatformManager.IsUserInRoom(user.ID)) + { + SocialPlatformManager.AddRemoteUser(user.ID); + } + else + { + SocialPlatformManager.MarkRemoteUserInRoom(user.ID); + } + } + } + } + + SocialPlatformManager.ForgetRemoteUsersNotInRoom(); + SocialPlatformManager.SetFloorColorForState(amIServer); + } + + #endregion +} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RoomManager.cs.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RoomManager.cs.meta new file mode 100644 index 0000000..aa04741 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/RoomManager.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 923f57b3cf1990047b2e448680c8d5b8 +timeCreated: 1521151723 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/SocialPlatformManager.cs b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/SocialPlatformManager.cs new file mode 100644 index 0000000..901de2d --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/SocialPlatformManager.cs @@ -0,0 +1,587 @@ +using UnityEngine; +using AOT; +using System; +using System.IO; +using System.Collections.Generic; +using Oculus.Avatar; +using Oculus.Platform; +using Oculus.Platform.Models; + + +// This class coordinates communication with the Oculus Platform +// Service running in your device. +public class SocialPlatformManager : MonoBehaviour +{ + private static readonly Vector3 START_ROTATION_ONE = new Vector3(0, 180, 0); + private static readonly Vector3 START_POSITION_ONE = new Vector3(0, 4, 5); + + private static readonly Vector3 START_ROTATION_TWO = new Vector3(0, 0, 0); + private static readonly Vector3 START_POSITION_TWO = new Vector3(0, 4, -5); + + private static readonly Vector3 START_ROTATION_THREE = new Vector3(0, 270, 0); + private static readonly Vector3 START_POSITION_THREE = new Vector3(5, 4, 0); + + private static readonly Vector3 START_ROTATION_FOUR = new Vector3(0, 90, 0); + private static readonly Vector3 START_POSITION_FOUR = new Vector3(-5, 4, 0); + + private static readonly Color BLACK = new Color(0.0f, 0.0f, 0.0f); + private static readonly Color WHITE = new Color(1.0f, 1.0f, 1.0f); + private static readonly Color CYAN = new Color(0.0f, 1.0f, 1.0f); + private static readonly Color BLUE = new Color(0.0f, 0.0f, 1.0f); + private static readonly Color GREEN = new Color(0.0f, 1.0f, 0.0f); + + private float voiceCurrent = 0.0f; + + // Local player + private UInt32 packetSequence = 0; + + public OvrAvatar localAvatarPrefab; + public OvrAvatar remoteAvatarPrefab; + + public GameObject helpPanel; + protected MeshRenderer helpMesh; + public Material riftMaterial; + public Material gearMaterial; + + protected OvrAvatar localAvatar; + protected GameObject localTrackingSpace; + protected GameObject localPlayerHead; + + // Remote players + protected Dictionary remoteUsers = new Dictionary(); + + // GameObject that represents the center sphere as a visual status indicator of the room + public GameObject roomSphere; + protected MeshRenderer sphereMesh; + public GameObject roomFloor; + protected MeshRenderer floorMesh; + + protected State currentState; + + protected static SocialPlatformManager s_instance = null; + protected RoomManager roomManager; + protected P2PManager p2pManager; + protected VoipManager voipManager; + + // my Application-scoped Oculus ID + protected ulong myID; + + // my Oculus user name + protected string myOculusID; + + + // animating the mouth for voip + public static readonly float VOIP_SCALE = 2f; + + public virtual void Update() + { + // Look for updates from remote users + p2pManager.GetRemotePackets(); + + // update avatar mouths to match voip volume + foreach (KeyValuePair kvp in remoteUsers) + { + if (kvp.Value.voipSource == null) + { + if (kvp.Value.RemoteAvatar.MouthAnchor != null) + { + kvp.Value.voipSource = kvp.Value.RemoteAvatar.MouthAnchor.AddComponent(); + kvp.Value.voipSource.senderID = kvp.Value.remoteUserID; + } + } + + if (kvp.Value.voipSource != null) + { + float remoteVoiceCurrent = Mathf.Clamp(kvp.Value.voipSource.peakAmplitude * VOIP_SCALE, 0f, 1f); + kvp.Value.RemoteAvatar.VoiceAmplitude = remoteVoiceCurrent; + } + } + + if (localAvatar != null) + { + localAvatar.VoiceAmplitude = Mathf.Clamp(voiceCurrent * VOIP_SCALE, 0f, 1f); + } + + Oculus.Platform.Request.RunCallbacks(); + } + + #region Initialization and Shutdown + + public virtual void Awake() + { + LogOutputLine("Start Log."); + + // Grab the MeshRenderers. We'll be using the material colour to visually show status + helpMesh = helpPanel.GetComponent(); + sphereMesh = roomSphere.GetComponent(); + floorMesh = roomFloor.GetComponent(); + + // Set up the local player + localTrackingSpace = this.transform.Find("OVRCameraRig/TrackingSpace").gameObject; + localPlayerHead = this.transform.Find("OVRCameraRig/TrackingSpace/CenterEyeAnchor").gameObject; + + // make sure only one instance of this manager ever exists + if (s_instance != null) + { + Destroy(gameObject); + return; + } + + s_instance = this; + DontDestroyOnLoad(gameObject); + + TransitionToState(State.INITIALIZING); + + Core.AsyncInitialize().OnComplete(InitCallback); + + roomManager = new RoomManager(); + p2pManager = new P2PManager(); + voipManager = new VoipManager(); + } + + void InitCallback(Message msg) + { + if (msg.IsError) + { + TerminateWithError(msg); + return; + } + + LaunchDetails launchDetails = ApplicationLifecycle.GetLaunchDetails(); + SocialPlatformManager.LogOutput("App launched with LaunchType " + launchDetails.LaunchType); + + // First thing we should do is perform an entitlement check to make sure + // we successfully connected to the Oculus Platform Service. + Entitlements.IsUserEntitledToApplication().OnComplete(IsEntitledCallback); + } + + public virtual void Start() + { + // noop here, but is being overridden in PlayerController + } + + void IsEntitledCallback(Message msg) + { + if (msg.IsError) + { + TerminateWithError(msg); + return; + } + + // Next get the identity of the user that launched the Application. + Users.GetLoggedInUser().OnComplete(GetLoggedInUserCallback); + } + + void GetLoggedInUserCallback(Message msg) + { + if (msg.IsError) + { + TerminateWithError(msg); + return; + } + + myID = msg.Data.ID; + myOculusID = msg.Data.OculusID; + + localAvatar = Instantiate(localAvatarPrefab); + localAvatar.CanOwnMicrophone = false; + localTrackingSpace = this.transform.Find("OVRCameraRig/TrackingSpace").gameObject; + + localAvatar.transform.SetParent(localTrackingSpace.transform, false); + localAvatar.transform.localPosition = new Vector3(0, 0, 0); + localAvatar.transform.localRotation = Quaternion.identity; + + if (UnityEngine.Application.platform == RuntimePlatform.Android) + { + helpPanel.transform.SetParent(localAvatar.transform.Find("body"), false); + helpPanel.transform.localPosition = new Vector3(0, 1.0f, 1.0f); + helpMesh.material = gearMaterial; + } + else + { + helpPanel.transform.SetParent(localAvatar.transform.Find("hand_left"), false); + helpPanel.transform.localPosition = new Vector3(0, 0.2f, 0.2f); + helpMesh.material = riftMaterial; + } + + localAvatar.oculusUserID = myID.ToString(); + localAvatar.RecordPackets = true; + localAvatar.PacketRecorded += OnLocalAvatarPacketRecorded; + localAvatar.EnableMouthVertexAnimation = true; + + Quaternion rotation = Quaternion.identity; + + switch (UnityEngine.Random.Range(0, 4)) + { + case 0: + rotation.eulerAngles = START_ROTATION_ONE; + this.transform.localPosition = START_POSITION_ONE; + this.transform.localRotation = rotation; + break; + + case 1: + rotation.eulerAngles = START_ROTATION_TWO; + this.transform.localPosition = START_POSITION_TWO; + this.transform.localRotation = rotation; + break; + + case 2: + rotation.eulerAngles = START_ROTATION_THREE; + this.transform.localPosition = START_POSITION_THREE; + this.transform.localRotation = rotation; + break; + + case 3: + default: + rotation.eulerAngles = START_ROTATION_FOUR; + this.transform.localPosition = START_POSITION_FOUR; + this.transform.localRotation = rotation; + break; + } + + TransitionToState(State.CHECKING_LAUNCH_STATE); + + // If the user launched the app by accepting the notification, then we want to + // join that room. If not, try to find a friend's room to join + if (!roomManager.CheckForInvite()) + { + SocialPlatformManager.LogOutput("No invite on launch, looking for a friend to join."); + Users.GetLoggedInUserFriendsAndRooms() + .OnComplete(GetLoggedInUserFriendsAndRoomsCallback); + } + Voip.SetMicrophoneFilterCallback(MicFilter); + } + + void GetLoggedInUserFriendsAndRoomsCallback(Message msg) + { + if (msg.IsError) + { + return; + } + + foreach (UserAndRoom el in msg.Data) + { + // see if any friends are in a joinable room + if (el.User == null) continue; + if (el.RoomOptional == null) continue; + if (el.RoomOptional.IsMembershipLocked == true) continue; + if (el.RoomOptional.Joinability != RoomJoinability.CanJoin) continue; + if (el.RoomOptional.JoinPolicy == RoomJoinPolicy.None) continue; + + SocialPlatformManager.LogOutput("Trying to join room " + el.RoomOptional.ID + ", friend " + el.User.OculusID); + roomManager.JoinExistingRoom(el.RoomOptional.ID); + return; + } + + SocialPlatformManager.LogOutput("No friend to join. Creating my own room."); + // didn't find any open rooms, start a new room + roomManager.CreateRoom(); + TransitionToState(State.CREATING_A_ROOM); + } + + public void OnLocalAvatarPacketRecorded(object sender, OvrAvatar.PacketEventArgs args) + { + var size = Oculus.Avatar.CAPI.ovrAvatarPacket_GetSize(args.Packet.ovrNativePacket); + byte[] toSend = new byte[size]; + + Oculus.Avatar.CAPI.ovrAvatarPacket_Write(args.Packet.ovrNativePacket, size, toSend); + + foreach (KeyValuePair kvp in remoteUsers) + { + //LogOutputLine("Sending avatar Packet to " + kvp.Key); + // Root is local tracking space transform + p2pManager.SendAvatarUpdate(kvp.Key, localTrackingSpace.transform, packetSequence, toSend); + } + + packetSequence++; + } + + public void OnApplicationQuit() + { + roomManager.LeaveCurrentRoom(); + + foreach (KeyValuePair kvp in remoteUsers) + { + p2pManager.Disconnect(kvp.Key); + voipManager.Disconnect(kvp.Key); + } + LogOutputLine("End Log."); + } + + public void AddUser(ulong userID, ref RemotePlayer remoteUser) + { + remoteUsers.Add(userID, remoteUser); + } + + public void LogOutputLine(string line) + { + Debug.Log(Time.time + ": " + line); + } + + // For most errors we terminate the Application since this example doesn't make + // sense if the user is disconnected. + public static void TerminateWithError(Message msg) + { + s_instance.LogOutputLine("Error: " + msg.GetError().Message); + UnityEngine.Application.Quit(); + } + + #endregion + + #region Properties + + public static State CurrentState + { + get + { + return s_instance.currentState; + } + } + + public static ulong MyID + { + get + { + if (s_instance != null) + { + return s_instance.myID; + } + else + { + return 0; + } + } + } + + public static string MyOculusID + { + get + { + if (s_instance != null && s_instance.myOculusID != null) + { + return s_instance.myOculusID; + } + else + { + return string.Empty; + } + } + } + + #endregion + + #region State Management + + public enum State + { + // loading platform library, checking application entitlement, + // getting the local user info + INITIALIZING, + + // Checking to see if we were launched from an invite + CHECKING_LAUNCH_STATE, + + // Creating a room to join + CREATING_A_ROOM, + + // in this state we've create a room, and hopefully + // sent some invites, and we're waiting people to join + WAITING_IN_A_ROOM, + + // in this state we're attempting to join a room from an invite + JOINING_A_ROOM, + + // we're in a room with others + CONNECTED_IN_A_ROOM, + + // Leaving a room + LEAVING_A_ROOM, + + // shutdown any connections and leave the current room + SHUTDOWN, + }; + + public static void TransitionToState(State newState) + { + if (s_instance) + { + s_instance.LogOutputLine("State " + s_instance.currentState + " -> " + newState); + } + + if (s_instance && s_instance.currentState != newState) + { + s_instance.currentState = newState; + + // state transition logic + switch (newState) + { + case State.SHUTDOWN: + s_instance.OnApplicationQuit(); + break; + + default: + break; + } + } + + SetSphereColorForState(); + } + + private static void SetSphereColorForState() + { + switch (s_instance.currentState) + { + case State.INITIALIZING: + case State.SHUTDOWN: + s_instance.sphereMesh.material.color = BLACK; + break; + + case State.WAITING_IN_A_ROOM: + s_instance.sphereMesh.material.color = WHITE; + break; + + case State.CONNECTED_IN_A_ROOM: + s_instance.sphereMesh.material.color = CYAN; + break; + + default: + break; + } + } + + public static void SetFloorColorForState(bool host) + { + if (host) + { + s_instance.floorMesh.material.color = BLUE; + } + else + { + s_instance.floorMesh.material.color = GREEN; + } + } + + public static void MarkAllRemoteUsersAsNotInRoom() + { + foreach (KeyValuePair kvp in s_instance.remoteUsers) + { + kvp.Value.stillInRoom = false; + } + } + + public static void MarkRemoteUserInRoom(ulong userID) + { + RemotePlayer remoteUser = new RemotePlayer(); + + if (s_instance.remoteUsers.TryGetValue(userID, out remoteUser)) + { + remoteUser.stillInRoom = true; + } + } + + public static void ForgetRemoteUsersNotInRoom() + { + List toPurge = new List(); + + foreach (KeyValuePair kvp in s_instance.remoteUsers) + { + if (kvp.Value.stillInRoom == false) + { + toPurge.Add(kvp.Key); + } + } + + foreach (ulong key in toPurge) + { + RemoveRemoteUser(key); + } + } + + public static void LogOutput(string line) + { + s_instance.LogOutputLine(Time.time + ": " + line); + } + + public static bool IsUserInRoom(ulong userID) + { + return s_instance.remoteUsers.ContainsKey(userID); + } + + public static void AddRemoteUser(ulong userID) + { + RemotePlayer remoteUser = new RemotePlayer(); + + remoteUser.RemoteAvatar = Instantiate(s_instance.remoteAvatarPrefab); + remoteUser.RemoteAvatar.oculusUserID = userID.ToString(); + remoteUser.RemoteAvatar.ShowThirdPerson = true; + remoteUser.RemoteAvatar.EnableMouthVertexAnimation = true; + remoteUser.p2pConnectionState = PeerConnectionState.Unknown; + remoteUser.voipConnectionState = PeerConnectionState.Unknown; + remoteUser.stillInRoom = true; + remoteUser.remoteUserID = userID; + + s_instance.AddUser(userID, ref remoteUser); + s_instance.p2pManager.ConnectTo(userID); + s_instance.voipManager.ConnectTo(userID); + + s_instance.LogOutputLine("Adding User " + userID); + } + + public static void RemoveRemoteUser(ulong userID) + { + RemotePlayer remoteUser = new RemotePlayer(); + + if (s_instance.remoteUsers.TryGetValue(userID, out remoteUser)) + { + Destroy(remoteUser.RemoteAvatar.MouthAnchor.GetComponent(), 0); + Destroy(remoteUser.RemoteAvatar.gameObject, 0); + s_instance.remoteUsers.Remove(userID); + + s_instance.LogOutputLine("Removing User " + userID); + } + } + + public void UpdateVoiceData(short[] pcmData, int numChannels) + { + if (localAvatar != null) + { + localAvatar.UpdateVoiceData(pcmData, numChannels); + } + + float voiceMax = 0.0f; + float[] floats = new float[pcmData.Length]; + for (int n = 0; n < pcmData.Length; n++) + { + float cur = floats[n] = (float)pcmData[n] / (float)short.MaxValue; + if (cur > voiceMax) + { + voiceMax = cur; + } + } + voiceCurrent = voiceMax; + } + + [MonoPInvokeCallback(typeof(Oculus.Platform.CAPI.FilterCallback))] + public static void MicFilter(short[] pcmData, System.UIntPtr pcmDataLength, int frequency, int numChannels) + { + s_instance.UpdateVoiceData(pcmData, numChannels); + } + + + public static RemotePlayer GetRemoteUser(ulong userID) + { + RemotePlayer remoteUser = new RemotePlayer(); + + if (s_instance.remoteUsers.TryGetValue(userID, out remoteUser)) + { + return remoteUser; + } + else + { + return null; + } + } + + #endregion + +} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/SocialPlatformManager.cs.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/SocialPlatformManager.cs.meta new file mode 100644 index 0000000..02e3d5f --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/SocialPlatformManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a14858202ffbfc041afe4e5c282240d9 +timeCreated: 1539938349 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/VoipManager.cs b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/VoipManager.cs new file mode 100644 index 0000000..33a229b --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/VoipManager.cs @@ -0,0 +1,72 @@ +using UnityEngine; +using System.Collections; + +using Oculus.Platform; +using Oculus.Platform.Models; + +// Helper class to manage the Voice-over-IP connection to the +// remote users +public class VoipManager +{ + public VoipManager() + { + Voip.SetVoipConnectRequestCallback(VoipConnectRequestCallback); + Voip.SetVoipStateChangeCallback(VoipStateChangedCallback); + } + + public void ConnectTo(ulong userID) + { + // ID comparison is used to decide who initiates and who gets the Callback + if (SocialPlatformManager.MyID < userID) + { + Voip.Start(userID); + SocialPlatformManager.LogOutput("Voip connect to " + userID); + } + } + + + public void Disconnect(ulong userID) + { + if (userID != 0) + { + Voip.Stop(userID); + + RemotePlayer remote = SocialPlatformManager.GetRemoteUser(userID); + if (remote != null) + { + remote.voipConnectionState = PeerConnectionState.Unknown; + } + } + } + + void VoipConnectRequestCallback(Message msg) + { + SocialPlatformManager.LogOutput("Voip request from " + msg.Data.ID); + + RemotePlayer remote = SocialPlatformManager.GetRemoteUser(msg.Data.ID); + if (remote != null) + { + SocialPlatformManager.LogOutput("Voip request accepted from " + msg.Data.ID); + Voip.Accept(msg.Data.ID); + } + } + + void VoipStateChangedCallback(Message msg) + { + SocialPlatformManager.LogOutput("Voip state to " + msg.Data.ID + " changed to " + msg.Data.State); + + RemotePlayer remote = SocialPlatformManager.GetRemoteUser(msg.Data.ID); + if (remote != null) + { + remote.voipConnectionState = msg.Data.State; + + // ID comparison is used to decide who initiates and who gets the Callback + if (msg.Data.State == PeerConnectionState.Timeout && SocialPlatformManager.MyID < msg.Data.ID) + { + // keep trying until hangup! + Voip.Start(msg.Data.ID); + SocialPlatformManager.LogOutput("Voip re-connect to " + msg.Data.ID); + } + } + } +} diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/VoipManager.cs.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/VoipManager.cs.meta new file mode 100644 index 0000000..0e02285 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Scripts/VoipManager.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: d22b9da5532b0224f82207825f9f6a65 +timeCreated: 1521151723 +licenseType: Free +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures.meta new file mode 100644 index 0000000..9538277 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fc164fe2aad000b40a6f426b477793aa +folderAsset: yes +timeCreated: 1496779994 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/GearHelp.png b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/GearHelp.png new file mode 100644 index 0000000..8c95af1 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/GearHelp.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8b3049362ded30647bd4bc1ba7100da46d9df22146e1896e232ba8a350b1df59 +size 17859 diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/GearHelp.png.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/GearHelp.png.meta new file mode 100644 index 0000000..8b67a9a --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/GearHelp.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: 0453138effcc80349b11371805f72f5b +timeCreated: 1497548991 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/Help.png b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/Help.png new file mode 100644 index 0000000..8337147 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/Help.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:484564407aae1c0faa35cb4b37d59bcbc84fea76e71eb30b63417859e78b2b96 +size 20360 diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/Help.png.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/Help.png.meta new file mode 100644 index 0000000..00f80b8 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Textures/Help.png.meta @@ -0,0 +1,58 @@ +fileFormatVersion: 2 +guid: c8f5462cc092d0c40ad71773132863e0 +timeCreated: 1496780052 +licenseType: Free +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 7 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/README.txt b/Assets/Oculus/Avatar/Samples/SocialStarter/README.txt new file mode 100644 index 0000000..1c6d8b5 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/README.txt @@ -0,0 +1,41 @@ +The SocialStarter sample shows how to leverage Oculus Avatar and Oculus Platform features to make a very basic networked social experience. + +For full functionality, this sample requires the following: +1. An App ID from the Oculus Dashboard (https://dashboard.oculus.com/). +2. A build associated with the App ID must be uploaded to a release channel on the Dashboard. +3. The email associated with your Oculus account must be added to the Users for the release channel of the build. + + +Setup instructions: +1. Create a new Unity project. +2. Import the Oculus Integration from the Unity Asset Store. The Oculus Integration contains everything you need to use Oculus Avatar and Oculus Platforms. +3. From the Oculus Dashboard, create an Oculus Rift app and copy the App ID. An App ID is required to use Avatar and Platform features. There must be a build associated with the App ID uploaded to a release channel on the Dashboard for full functionality. The email address associated with your Oculus account must be added to the Users list of the release channel. +4. From the Unity Editor menu bar, select Oculus Avatars > Edit Configuration and place your App ID in the two fields for Oculus Rift App Id and Gear VR App Id. +5. From the Unity Editor menu bar, select Oculus Platform > Edit Settings and place your App ID in the two fields for Oculus Rift App Id and Gear VR App Id. +6. Make sure the prefabs are set correctly. Select the OVRPlayerController object in the scene: +a) Local Avatar Prefab should be set to the LocalAvatar (OvrAvatar) prefab found at Assets > Oculus > Avatar > Content > Prefabs. +b) Remote Avatar Prefab should be set to the RemoteAvatar (OvrAvatar) prefab found at Assets > Oculus > Avatar > Content > Prefabs. +c) From Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials, drag Help to the OVRPlayerController’s Rift Material property. +d) From Assets/Oculus/Avatar/Samples/SocialStarter/Assets/Materials, drag GearHelp to the OVRPlayerController’s Gear Material property. + + +How to use: +1. When you first start up the sample you are placed in a virtual room. In the virtual room, the color of the floor and sphere are used as indicators. +a) The floor color indicates whether you are the owner of the room. Blue means you are the owner of the room. Green means you are a member of the room that joined via an invitation from the owner. +b) The sphere color indicates whether you are in an online room. White means you are in an online room. Black means that either online room creation or an invite attempt failed for some reason. +2. Your left hand should be holding the instructions UI. If you do not see the instructions, please make sure you followed steps 6c and 6d above. The instructions are as follows: + +Rift +Click left stick: Toggle showing the instructions. +Button Y: Toggle the sky camera. This allows you to view the scene from a static third-person camera. +Button X: Room invites. This will bring up the invite UI, which will show a list of your friends that you can invite to the room. This may take a second or two to pop up. Note that this functionality only works if you have uploaded a build to the Dashboard for the App ID you used. +Left stick: Move around. +Right stick: Rotate direction. + +Oculus Go and Gear VR +Trigger: Toggle showing the instructions. +Touchpad click: Toggle the sky camera. +Back button: Room invites. +Touchpad: Move around. + +3. When a user joins your room, a VoIP connection and a P2P connection will be set up. The P2P connection is used to send Avatar and positional updates. Note that this functionality only works if you have uploaded a build to the Dashboard for the App ID you used. diff --git a/Assets/Oculus/Avatar/Samples/SocialStarter/README.txt.meta b/Assets/Oculus/Avatar/Samples/SocialStarter/README.txt.meta new file mode 100644 index 0000000..d7adf50 --- /dev/null +++ b/Assets/Oculus/Avatar/Samples/SocialStarter/README.txt.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a7a78d98ba50c73429cf004f1635d521 +timeCreated: 1517510514 +licenseType: Free +TextScriptImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts.meta b/Assets/Oculus/Avatar/Scripts.meta new file mode 100644 index 0000000..f14c173 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1eb18b8db6c77f04c96874806a37143d +folderAsset: yes +timeCreated: 1466714102 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/GazeTarget.cs b/Assets/Oculus/Avatar/Scripts/GazeTarget.cs new file mode 100644 index 0000000..76b1246 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/GazeTarget.cs @@ -0,0 +1,56 @@ +using System; +using UnityEngine; +using Oculus.Avatar; + +public class GazeTarget : MonoBehaviour +{ + public ovrAvatarGazeTargetType Type; + private static ovrAvatarGazeTargets RuntimeTargetList; + + static GazeTarget() + { + // This size has to match the 'MarshalAs' attribute in the ovrAvatarGazeTargets declaration. + RuntimeTargetList.targets = new ovrAvatarGazeTarget[128]; + RuntimeTargetList.targetCount = 1; + } + + void Start() + { + UpdateGazeTarget(); + transform.hasChanged = false; + } + + void Update() + { + if (transform.hasChanged) + { + transform.hasChanged = false; + UpdateGazeTarget(); + } + } + + void OnDestroy() + { + UInt32[] targetIds = new UInt32[1]; + targetIds[0] = (UInt32) transform.GetInstanceID(); + CAPI.ovrAvatar_RemoveGazeTargets(1, targetIds); + } + + private void UpdateGazeTarget() + { + ovrAvatarGazeTarget target = CreateOvrGazeTarget((UInt32) transform.GetInstanceID(), transform.position, Type); + RuntimeTargetList.targets[0] = target; + CAPI.ovrAvatar_UpdateGazeTargets(RuntimeTargetList); + } + + private ovrAvatarGazeTarget CreateOvrGazeTarget(UInt32 targetId, Vector3 targetPosition, ovrAvatarGazeTargetType targetType) + { + return new ovrAvatarGazeTarget + { + id = targetId, + // Do coordinate system switch. + worldPosition = new Vector3(targetPosition.x, targetPosition.y, -targetPosition.z), + type = targetType + }; + } +} diff --git a/Assets/Oculus/Avatar/Scripts/GazeTarget.cs.meta b/Assets/Oculus/Avatar/Scripts/GazeTarget.cs.meta new file mode 100644 index 0000000..d2b2082 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/GazeTarget.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 5bfcd054df64e334ba2f191666f3fe92 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatar.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatar.cs new file mode 100644 index 0000000..9bc02eb --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatar.cs @@ -0,0 +1,1344 @@ +using UnityEngine; +using System.Collections; +using System; +using Oculus.Avatar; +using System.Runtime.InteropServices; +using System.Collections.Generic; +#if UNITY_EDITOR +using UnityEditor; +#endif + +#if AVATAR_INTERNAL +using UnityEngine.Events; +#endif + +[System.Serializable] +public class AvatarLayer +{ + public int layerIndex; +} + +#if UNITY_EDITOR +[CustomPropertyDrawer(typeof(AvatarLayer))] +public class AvatarLayerPropertyDrawer : PropertyDrawer +{ + public override void OnGUI(Rect position, SerializedProperty property, GUIContent label) + { + EditorGUI.BeginProperty(position, GUIContent.none, property); + SerializedProperty layerIndex = property.FindPropertyRelative("layerIndex"); + position = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label); + layerIndex.intValue = EditorGUI.LayerField(position, layerIndex.intValue); + EditorGUI.EndProperty(); + } +} +#endif + +[System.Serializable] +public class PacketRecordSettings +{ + internal bool RecordingFrames = false; + public float UpdateRate = 1f / 30f; // 30 hz update of packets + internal float AccumulatedTime; +}; + +public class OvrAvatar : MonoBehaviour +{ + [Header("Avatar")] + public IntPtr sdkAvatar = IntPtr.Zero; + public string oculusUserID; + public OvrAvatarDriver Driver; + + [Header("Capabilities")] + public bool EnableBody = true; + public bool EnableHands = true; + public bool EnableBase = true; + public bool EnableExpressive = false; + + [Header("Network")] + public bool RecordPackets; + public bool UseSDKPackets = true; + public PacketRecordSettings PacketSettings = new PacketRecordSettings(); + + [Header("Visibility")] + public bool StartWithControllers; + public AvatarLayer FirstPersonLayer; + public AvatarLayer ThirdPersonLayer; + public bool ShowFirstPerson = true; + public bool ShowThirdPerson; + internal ovrAvatarCapabilities Capabilities = ovrAvatarCapabilities.Body; + + [Header("Performance")] +#if UNITY_ANDROID + [Tooltip( + "LOD mesh complexity and texture resolution. Highest LOD recommended on PC and simple mobile apps." + + " Medium LOD recommended on mobile devices or for background characters on PC." + + " Lowest LOD recommended for background characters on mobile.")] + [SerializeField] + internal ovrAvatarAssetLevelOfDetail LevelOfDetail = ovrAvatarAssetLevelOfDetail.Medium; +#else + [SerializeField] + internal ovrAvatarAssetLevelOfDetail LevelOfDetail = ovrAvatarAssetLevelOfDetail.Highest; +#endif +#if UNITY_ANDROID && UNITY_5_5_OR_NEWER + [Tooltip( + "Enable to use combined meshes to reduce draw calls. Currently only available on mobile devices. " + + "Will be forced to false on PC.")] + private bool CombineMeshes = true; +#else + private bool CombineMeshes = false; +#endif + [Tooltip( + "Enable to use transparent queue, disable to use geometry queue. Requires restart to take effect.")] + public bool UseTransparentRenderQueue = true; + + [Header("Shaders")] + public Shader Monochrome_SurfaceShader; + public Shader Monochrome_SurfaceShader_SelfOccluding; + public Shader Monochrome_SurfaceShader_PBS; + public Shader Skinshaded_SurfaceShader_SingleComponent; + public Shader Skinshaded_VertFrag_SingleComponent; + public Shader Skinshaded_VertFrag_CombinedMesh; + public Shader Skinshaded_Expressive_SurfaceShader_SingleComponent; + public Shader Skinshaded_Expressive_VertFrag_SingleComponent; + public Shader Skinshaded_Expressive_VertFrag_CombinedMesh; + public Shader Loader_VertFrag_CombinedMesh; + public Shader EyeLens; + public Shader ControllerShader; + + [Header("Other")] + public bool CanOwnMicrophone = true; + [Tooltip( + "Enable laughter detection and animation as part of OVRLipSync.")] + public bool EnableLaughter = true; + public GameObject MouthAnchor; + public Transform LeftHandCustomPose; + public Transform RightHandCustomPose; + + // Avatar asset + private HashSet assetLoadingIds = new HashSet(); + private bool assetsFinishedLoading = false; + + // Material manager + private OvrAvatarMaterialManager materialManager; + private bool waitingForCombinedMesh = false; + + // Global expressive system initialization + private static bool doneExpressiveGlobalInit = false; + + // Clothing offsets + private Vector4 clothingAlphaOffset = new Vector4(0f, 0f, 0f, 1f); + private UInt64 clothingAlphaTexture = 0; + + // Lipsync + private OVRLipSyncMicInput micInput = null; + private OVRLipSyncContext lipsyncContext = null; + private OVRLipSync.Frame currentFrame = new OVRLipSync.Frame(); + private float[] visemes = new float[VISEME_COUNT]; + private AudioSource audioSource; + private ONSPAudioSource spatializedSource; + private List voiceUpdates = new List(); + private static ovrAvatarVisemes RuntimeVisemes; + + // Custom hand poses + private Transform cachedLeftHandCustomPose; + private Transform[] cachedCustomLeftHandJoints; + private ovrAvatarTransform[] cachedLeftHandTransforms; + private Transform cachedRightHandCustomPose; + private Transform[] cachedCustomRightHandJoints; + private ovrAvatarTransform[] cachedRightHandTransforms; + private bool showLeftController; + private bool showRightController; + + // Consts +#if UNITY_ANDROID + private const bool USE_MOBILE_TEXTURE_FORMAT = true; +#else + private const bool USE_MOBILE_TEXTURE_FORMAT = false; +#endif + private static readonly Vector3 MOUTH_HEAD_OFFSET = new Vector3(0, -0.085f, 0.09f); + private const string MOUTH_HELPER_NAME = "MouthAnchor"; + // Initial 'silence' score, 14 viseme scores and 1 laughter score as last element + private const int VISEME_COUNT = 16; + // Lipsync animation speeds + private const float ACTION_UNIT_ONSET_SPEED = 30f; + private const float ACTION_UNIT_FALLOFF_SPEED = 20f; + private const float VISEME_LEVEL_MULTIPLIER = 1.5f; + + // Internals + internal UInt64 oculusUserIDInternal; + internal OvrAvatarBase Base = null; + internal OvrAvatarTouchController ControllerLeft = null; + internal OvrAvatarTouchController ControllerRight = null; + internal OvrAvatarBody Body = null; + internal OvrAvatarHand HandLeft = null; + internal OvrAvatarHand HandRight = null; + internal ovrAvatarLookAndFeelVersion LookAndFeelVersion = ovrAvatarLookAndFeelVersion.Two; + internal ovrAvatarLookAndFeelVersion FallbackLookAndFeelVersion = ovrAvatarLookAndFeelVersion.Two; +#if AVATAR_INTERNAL + public AvatarControllerBlend BlendController; + public UnityEvent AssetsDoneLoading = new UnityEvent(); +#endif + + // Avatar packets + public class PacketEventArgs : EventArgs + { + public readonly OvrAvatarPacket Packet; + public PacketEventArgs(OvrAvatarPacket packet) + { + Packet = packet; + } + } + private OvrAvatarPacket CurrentUnityPacket; + public EventHandler PacketRecorded; + + public enum HandType + { + Right, + Left, + + Max + }; + + public enum HandJoint + { + HandBase, + IndexBase, + IndexTip, + ThumbBase, + ThumbTip, + + Max, + } + + private static string[,] HandJoints = new string[(int)HandType.Max, (int)HandJoint.Max] + { + { + "hands:r_hand_world", + "hands:r_hand_world/hands:b_r_hand/hands:b_r_index1", + "hands:r_hand_world/hands:b_r_hand/hands:b_r_index1/hands:b_r_index2/hands:b_r_index3/hands:b_r_index_ignore", + "hands:r_hand_world/hands:b_r_hand/hands:b_r_thumb1/hands:b_r_thumb2", + "hands:r_hand_world/hands:b_r_hand/hands:b_r_thumb1/hands:b_r_thumb2/hands:b_r_thumb3/hands:b_r_thumb_ignore" + }, + { + "hands:l_hand_world", + "hands:l_hand_world/hands:b_l_hand/hands:b_l_index1", + "hands:l_hand_world/hands:b_l_hand/hands:b_l_index1/hands:b_l_index2/hands:b_l_index3/hands:b_l_index_ignore", + "hands:l_hand_world/hands:b_l_hand/hands:b_l_thumb1/hands:b_l_thumb2", + "hands:l_hand_world/hands:b_l_hand/hands:b_l_thumb1/hands:b_l_thumb2/hands:b_l_thumb3/hands:b_l_thumb_ignore" + } + }; + + static OvrAvatar() + { + // This size has to match the 'MarshalAs' attribute in the ovrAvatarVisemes declaration. + RuntimeVisemes.visemeParams = new float[32]; + RuntimeVisemes.visemeParamCount = VISEME_COUNT; + } + + void OnDestroy() + { + if (sdkAvatar != IntPtr.Zero) + { + CAPI.ovrAvatar_Destroy(sdkAvatar); + } + } + + public void AssetLoadedCallback(OvrAvatarAsset asset) + { + assetLoadingIds.Remove(asset.assetID); + } + + public void CombinedMeshLoadedCallback(IntPtr assetPtr) + { + if (!waitingForCombinedMesh) + { + return; + } + + var meshIDs = CAPI.ovrAvatarAsset_GetCombinedMeshIDs(assetPtr); + foreach (var id in meshIDs) + { + assetLoadingIds.Remove(id); + } + + CAPI.ovrAvatar_GetCombinedMeshAlphaData(sdkAvatar, ref clothingAlphaTexture, ref clothingAlphaOffset); + + waitingForCombinedMesh = false; + } + + private OvrAvatarSkinnedMeshRenderComponent AddSkinnedMeshRenderComponent(GameObject gameObject, ovrAvatarRenderPart_SkinnedMeshRender skinnedMeshRender) + { + OvrAvatarSkinnedMeshRenderComponent skinnedMeshRenderer = gameObject.AddComponent(); + skinnedMeshRenderer.Initialize(skinnedMeshRender, Monochrome_SurfaceShader, Monochrome_SurfaceShader_SelfOccluding, ThirdPersonLayer.layerIndex, FirstPersonLayer.layerIndex); + return skinnedMeshRenderer; + } + + private OvrAvatarSkinnedMeshRenderPBSComponent AddSkinnedMeshRenderPBSComponent(GameObject gameObject, ovrAvatarRenderPart_SkinnedMeshRenderPBS skinnedMeshRenderPBS) + { + OvrAvatarSkinnedMeshRenderPBSComponent skinnedMeshRenderer = gameObject.AddComponent(); + skinnedMeshRenderer.Initialize(skinnedMeshRenderPBS, Monochrome_SurfaceShader_PBS, ThirdPersonLayer.layerIndex, FirstPersonLayer.layerIndex); + return skinnedMeshRenderer; + } + + private OvrAvatarSkinnedMeshPBSV2RenderComponent AddSkinnedMeshRenderPBSV2Component( + IntPtr renderPart, + GameObject go, + ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 skinnedMeshRenderPBSV2, + bool isBodyPartZero, + bool isControllerModel) + { + OvrAvatarSkinnedMeshPBSV2RenderComponent skinnedMeshRenderer = go.AddComponent(); + skinnedMeshRenderer.Initialize( + renderPart, + skinnedMeshRenderPBSV2, + materialManager, + ThirdPersonLayer.layerIndex, + FirstPersonLayer.layerIndex, + isBodyPartZero && CombineMeshes, + LevelOfDetail, + isBodyPartZero && EnableExpressive, + this, + isControllerModel); + + return skinnedMeshRenderer; + } + + static public IntPtr GetRenderPart(ovrAvatarComponent component, UInt32 renderPartIndex) + { + return Marshal.ReadIntPtr(component.renderParts, Marshal.SizeOf(typeof(IntPtr)) * (int)renderPartIndex); + } + + private static string GetRenderPartName(ovrAvatarComponent component, uint renderPartIndex) + { + return component.name + "_renderPart_" + (int)renderPartIndex; + } + + internal static void ConvertTransform(float[] transform, ref ovrAvatarTransform target) + { + target.position.x = transform[0]; + target.position.y = transform[1]; + target.position.z = transform[2]; + + target.orientation.x = transform[3]; + target.orientation.y = transform[4]; + target.orientation.z = transform[5]; + target.orientation.w = transform[6]; + + target.scale.x = transform[7]; + target.scale.y = transform[8]; + target.scale.z = transform[9]; + } + + internal static void ConvertTransform(ovrAvatarTransform transform, Transform target) + { + Vector3 position = transform.position; + position.z = -position.z; + Quaternion orientation = transform.orientation; + orientation.x = -orientation.x; + orientation.y = -orientation.y; + target.localPosition = position; + target.localRotation = orientation; + target.localScale = transform.scale; + } + + public static ovrAvatarTransform CreateOvrAvatarTransform(Vector3 position, Quaternion orientation) + { + return new ovrAvatarTransform + { + position = new Vector3(position.x, position.y, -position.z), + orientation = new Quaternion(-orientation.x, -orientation.y, orientation.z, orientation.w), + scale = Vector3.one + }; + } + + private static ovrAvatarGazeTarget CreateOvrGazeTarget(uint targetId, Vector3 targetPosition, ovrAvatarGazeTargetType targetType) + { + return new ovrAvatarGazeTarget + { + id = targetId, + // Do coordinate system switch. + worldPosition = new Vector3(targetPosition.x, targetPosition.y, -targetPosition.z), + type = targetType + }; + } + + private void BuildRenderComponents() + { + ovrAvatarBaseComponent baseComponnet = new ovrAvatarBaseComponent(); + ovrAvatarHandComponent leftHandComponnet = new ovrAvatarHandComponent(); + ovrAvatarHandComponent rightHandComponnet = new ovrAvatarHandComponent(); + ovrAvatarControllerComponent leftControllerComponent = new ovrAvatarControllerComponent(); + ovrAvatarControllerComponent rightControllerComponent = new ovrAvatarControllerComponent(); + ovrAvatarBodyComponent bodyComponent = new ovrAvatarBodyComponent(); + + ovrAvatarComponent dummyComponent = new ovrAvatarComponent(); + + const bool FetchName = true; + + if (CAPI.ovrAvatarPose_GetLeftHandComponent(sdkAvatar, ref leftHandComponnet)) + { + CAPI.ovrAvatarComponent_Get(leftHandComponnet.renderComponent, FetchName, ref dummyComponent); + AddAvatarComponent(ref HandLeft, dummyComponent); + HandLeft.isLeftHand = true; + } + + if (CAPI.ovrAvatarPose_GetRightHandComponent(sdkAvatar, ref rightHandComponnet)) + { + CAPI.ovrAvatarComponent_Get(rightHandComponnet.renderComponent, FetchName, ref dummyComponent); + AddAvatarComponent(ref HandRight, dummyComponent); + HandRight.isLeftHand = false; + } + + if (CAPI.ovrAvatarPose_GetBodyComponent(sdkAvatar, ref bodyComponent)) + { + CAPI.ovrAvatarComponent_Get(bodyComponent.renderComponent, FetchName, ref dummyComponent); + AddAvatarComponent(ref Body, dummyComponent); + } + + if (CAPI.ovrAvatarPose_GetLeftControllerComponent(sdkAvatar, ref leftControllerComponent)) + { + CAPI.ovrAvatarComponent_Get(leftControllerComponent.renderComponent, FetchName, ref dummyComponent); + AddAvatarComponent(ref ControllerLeft, dummyComponent); + ControllerLeft.isLeftHand = true; + } + + if (CAPI.ovrAvatarPose_GetRightControllerComponent(sdkAvatar, ref rightControllerComponent)) + { + CAPI.ovrAvatarComponent_Get(rightControllerComponent.renderComponent, FetchName, ref dummyComponent); + AddAvatarComponent(ref ControllerRight, dummyComponent); + ControllerRight.isLeftHand = false; + } + + if (CAPI.ovrAvatarPose_GetBaseComponent(sdkAvatar, ref baseComponnet)) + { + CAPI.ovrAvatarComponent_Get(baseComponnet.renderComponent, FetchName, ref dummyComponent); + AddAvatarComponent(ref Base, dummyComponent); + } + } + + private void AddAvatarComponent(ref T root, ovrAvatarComponent nativeComponent) where T : OvrAvatarComponent + { + GameObject componentObject = new GameObject(); + componentObject.name = nativeComponent.name; + componentObject.transform.SetParent(transform); + root = componentObject.AddComponent(); + root.SetOvrAvatarOwner(this); + AddRenderParts(root, nativeComponent, componentObject.transform); + } + + void UpdateCustomPoses() + { + // Check to see if the pose roots changed + if (UpdatePoseRoot(LeftHandCustomPose, ref cachedLeftHandCustomPose, ref cachedCustomLeftHandJoints, ref cachedLeftHandTransforms)) + { + if (cachedLeftHandCustomPose == null && sdkAvatar != IntPtr.Zero) + { + CAPI.ovrAvatar_SetLeftHandGesture(sdkAvatar, ovrAvatarHandGesture.Default); + } + } + if (UpdatePoseRoot(RightHandCustomPose, ref cachedRightHandCustomPose, ref cachedCustomRightHandJoints, ref cachedRightHandTransforms)) + { + if (cachedRightHandCustomPose == null && sdkAvatar != IntPtr.Zero) + { + CAPI.ovrAvatar_SetRightHandGesture(sdkAvatar, ovrAvatarHandGesture.Default); + } + } + + // Check to see if the custom gestures need to be updated + if (sdkAvatar != IntPtr.Zero) + { + if (cachedLeftHandCustomPose != null && UpdateTransforms(cachedCustomLeftHandJoints, cachedLeftHandTransforms)) + { + CAPI.ovrAvatar_SetLeftHandCustomGesture(sdkAvatar, (uint)cachedLeftHandTransforms.Length, cachedLeftHandTransforms); + } + if (cachedRightHandCustomPose != null && UpdateTransforms(cachedCustomRightHandJoints, cachedRightHandTransforms)) + { + CAPI.ovrAvatar_SetRightHandCustomGesture(sdkAvatar, (uint)cachedRightHandTransforms.Length, cachedRightHandTransforms); + } + } + } + + static bool UpdatePoseRoot(Transform poseRoot, ref Transform cachedPoseRoot, ref Transform[] cachedPoseJoints, ref ovrAvatarTransform[] transforms) + { + if (poseRoot == cachedPoseRoot) + { + return false; + } + + if (!poseRoot) + { + cachedPoseRoot = null; + cachedPoseJoints = null; + transforms = null; + } + else + { + List joints = new List(); + OrderJoints(poseRoot, joints); + cachedPoseRoot = poseRoot; + cachedPoseJoints = joints.ToArray(); + transforms = new ovrAvatarTransform[joints.Count]; + } + return true; + } + + static bool UpdateTransforms(Transform[] joints, ovrAvatarTransform[] transforms) + { + bool updated = false; + for (int i = 0; i < joints.Length; ++i) + { + Transform joint = joints[i]; + ovrAvatarTransform transform = CreateOvrAvatarTransform(joint.localPosition, joint.localRotation); + if (transform.position != transforms[i].position || transform.orientation != transforms[i].orientation) + { + transforms[i] = transform; + updated = true; + } + } + return updated; + } + + + private static void OrderJoints(Transform transform, List joints) + { + joints.Add(transform); + for (int i = 0; i < transform.childCount; ++i) + { + Transform child = transform.GetChild(i); + OrderJoints(child, joints); + } + } + + void AvatarSpecificationCallback(IntPtr avatarSpecification) + { + sdkAvatar = CAPI.ovrAvatar_Create(avatarSpecification, Capabilities); + ShowLeftController(showLeftController); + ShowRightController(showRightController); + + // Pump the Remote driver once to push the controller type through + if (Driver != null) + { + Driver.UpdateTransformsFromPose(sdkAvatar); + } + + //Fetch all the assets that this avatar uses. + UInt32 assetCount = CAPI.ovrAvatar_GetReferencedAssetCount(sdkAvatar); + for (UInt32 i = 0; i < assetCount; ++i) + { + UInt64 id = CAPI.ovrAvatar_GetReferencedAsset(sdkAvatar, i); + if (OvrAvatarSDKManager.Instance.GetAsset(id) == null) + { + OvrAvatarSDKManager.Instance.BeginLoadingAsset( + id, + LevelOfDetail, + AssetLoadedCallback); + + assetLoadingIds.Add(id); + } + } + + if (CombineMeshes) + { + OvrAvatarSDKManager.Instance.RegisterCombinedMeshCallback( + sdkAvatar, + CombinedMeshLoadedCallback); + } + } + + void Start() + { + if (OvrAvatarSDKManager.Instance == null) + { + return; + } +#if !UNITY_ANDROID + if (CombineMeshes) + { + CombineMeshes = false; + AvatarLogger.Log("Combined Meshes currently only supported on mobile"); + } +#endif +#if !UNITY_5_5_OR_NEWER + if (CombineMeshes) + { + CombineMeshes = false; + AvatarLogger.LogWarning("Combined Meshes requires Unity 5.5.0+"); + } +#endif + materialManager = gameObject.AddComponent(); + + try + { + oculusUserIDInternal = UInt64.Parse(oculusUserID); + } + catch (Exception) + { + oculusUserIDInternal = 0; + AvatarLogger.LogWarning("Invalid Oculus User ID Format"); + } + + // If no oculus ID is supplied then turn off combine meshes to prevent the texture arrays + // being populated by invalid textures. + if (oculusUserIDInternal == 0) + { + AvatarLogger.LogWarning("Oculus User ID set to 0. Provide actual user ID: " + gameObject.name); + CombineMeshes = false; + } + + AvatarLogger.Log("Starting OvrAvatar " + gameObject.name); + AvatarLogger.Log(AvatarLogger.Tab + "LOD: " + LevelOfDetail.ToString()); + AvatarLogger.Log(AvatarLogger.Tab + "Combine Meshes: " + CombineMeshes); + AvatarLogger.Log(AvatarLogger.Tab + "Force Mobile Textures: " + USE_MOBILE_TEXTURE_FORMAT); + AvatarLogger.Log(AvatarLogger.Tab + "Oculus User ID: " + oculusUserIDInternal); + + Capabilities = 0; + + bool is3Dof = false; + var headsetType = OVRPlugin.GetSystemHeadsetType(); + switch (headsetType) + { + case OVRPlugin.SystemHeadset.GearVR_R320: + case OVRPlugin.SystemHeadset.GearVR_R321: + case OVRPlugin.SystemHeadset.GearVR_R322: + case OVRPlugin.SystemHeadset.GearVR_R323: + case OVRPlugin.SystemHeadset.GearVR_R324: + case OVRPlugin.SystemHeadset.GearVR_R325: + case OVRPlugin.SystemHeadset.Oculus_Go: + is3Dof = true; + break; + case OVRPlugin.SystemHeadset.Oculus_Quest: + case OVRPlugin.SystemHeadset.Rift_S: + case OVRPlugin.SystemHeadset.Rift_DK1: + case OVRPlugin.SystemHeadset.Rift_DK2: + case OVRPlugin.SystemHeadset.Rift_CV1: + default: + break; + } + + // The SDK 3 DOF Arm Model requires the body skeleton to pose itself. It will crash without it + // The likely use case here is trying to have an invisible body. + // T45010595 + if (is3Dof && !EnableBody) + { + AvatarLogger.Log("Forcing the Body component for 3Dof hand tracking, and setting the visibility to 1st person"); + EnableBody = true; + ShowFirstPerson = true; + ShowThirdPerson = false; + } + + if (EnableBody) Capabilities |= ovrAvatarCapabilities.Body; + if (EnableHands) Capabilities |= ovrAvatarCapabilities.Hands; + if (EnableBase && EnableBody) Capabilities |= ovrAvatarCapabilities.Base; + if (EnableExpressive) Capabilities |= ovrAvatarCapabilities.Expressive; + + // Enable body tilt on 6dof devices + if(OVRPlugin.positionSupported) + { + Capabilities |= ovrAvatarCapabilities.BodyTilt; + } + + ShowLeftController(StartWithControllers); + ShowRightController(StartWithControllers); + + OvrAvatarSDKManager.AvatarSpecRequestParams avatarSpecRequest = new OvrAvatarSDKManager.AvatarSpecRequestParams( + oculusUserIDInternal, + this.AvatarSpecificationCallback, + CombineMeshes, + LevelOfDetail, + USE_MOBILE_TEXTURE_FORMAT, + LookAndFeelVersion, + FallbackLookAndFeelVersion, + EnableExpressive); + + OvrAvatarSDKManager.Instance.RequestAvatarSpecification(avatarSpecRequest); + OvrAvatarSDKManager.Instance.AddLoadingAvatar(GetInstanceID()); + + waitingForCombinedMesh = CombineMeshes; + if (Driver != null) + { + Driver.Mode = UseSDKPackets ? OvrAvatarDriver.PacketMode.SDK : OvrAvatarDriver.PacketMode.Unity; + } + } + + void Update() + { + if (!OvrAvatarSDKManager.Instance || sdkAvatar == IntPtr.Zero || materialManager == null) + { + return; + } + + if (Driver != null) + { + Driver.UpdateTransforms(sdkAvatar); + + foreach (float[] voiceUpdate in voiceUpdates) + { + CAPI.ovrAvatarPose_UpdateVoiceVisualization(sdkAvatar, voiceUpdate); + } + + voiceUpdates.Clear(); +#if AVATAR_INTERNAL + if (BlendController != null) + { + BlendController.UpdateBlend(sdkAvatar); + } +#endif + CAPI.ovrAvatarPose_Finalize(sdkAvatar, Time.deltaTime); + } + + if (RecordPackets) + { + RecordFrame(); + } + + if (assetLoadingIds.Count == 0) + { + if (!assetsFinishedLoading) + { + try + { + BuildRenderComponents(); + } + catch (Exception e) + { + assetsFinishedLoading = true; + throw e; // rethrow the original exception to preserve callstack + } +#if AVATAR_INTERNAL + AssetsDoneLoading.Invoke(); +#endif + InitPostLoad(); + assetsFinishedLoading = true; + OvrAvatarSDKManager.Instance.RemoveLoadingAvatar(GetInstanceID()); + } + + UpdateVoiceBehavior(); + UpdateCustomPoses(); + if (EnableExpressive) + { + UpdateExpressive(); + } + } + } + + public static ovrAvatarHandInputState CreateInputState(ovrAvatarTransform transform, OvrAvatarDriver.ControllerPose pose) + { + ovrAvatarHandInputState inputState = new ovrAvatarHandInputState(); + inputState.transform = transform; + inputState.buttonMask = pose.buttons; + inputState.touchMask = pose.touches; + inputState.joystickX = pose.joystickPosition.x; + inputState.joystickY = pose.joystickPosition.y; + inputState.indexTrigger = pose.indexTrigger; + inputState.handTrigger = pose.handTrigger; + inputState.isActive = pose.isActive; + return inputState; + } + + public void ShowControllers(bool show) + { + ShowLeftController(show); + ShowRightController(show); + } + + public void ShowLeftController(bool show) + { + if (sdkAvatar != IntPtr.Zero) + { + CAPI.ovrAvatar_SetLeftControllerVisibility(sdkAvatar, show); + } + showLeftController = show; + } + + public void ShowRightController(bool show) + { + if (sdkAvatar != IntPtr.Zero) + { + CAPI.ovrAvatar_SetRightControllerVisibility(sdkAvatar, show); + } + showRightController = show; + } + + public void UpdateVoiceVisualization(float[] voiceSamples) + { + voiceUpdates.Add(voiceSamples); + } + + void RecordFrame() + { + if(UseSDKPackets) + { + RecordSDKFrame(); + } + else + { + RecordUnityFrame(); + } + } + + // Meant to be used mutually exclusively with RecordSDKFrame to give user more options to optimize or tweak packet data + private void RecordUnityFrame() + { + var deltaSeconds = Time.deltaTime; + var frame = Driver.GetCurrentPose(); + // If this is our first packet, store the pose as the initial frame + if (CurrentUnityPacket == null) + { + CurrentUnityPacket = new OvrAvatarPacket(frame); + deltaSeconds = 0; + } + + float recordedSeconds = 0; + while (recordedSeconds < deltaSeconds) + { + float remainingSeconds = deltaSeconds - recordedSeconds; + float remainingPacketSeconds = PacketSettings.UpdateRate - CurrentUnityPacket.Duration; + + // If we're not going to fill the packet, just add the frame + if (remainingSeconds < remainingPacketSeconds) + { + CurrentUnityPacket.AddFrame(frame, remainingSeconds); + recordedSeconds += remainingSeconds; + } + + // If we're going to fill the packet, interpolate the pose, send the packet, + // and open a new one + else + { + // Interpolate between the packet's last frame and our target pose + // to compute a pose at the end of the packet time. + OvrAvatarDriver.PoseFrame a = CurrentUnityPacket.FinalFrame; + OvrAvatarDriver.PoseFrame b = frame; + float t = remainingPacketSeconds / remainingSeconds; + OvrAvatarDriver.PoseFrame intermediatePose = OvrAvatarDriver.PoseFrame.Interpolate(a, b, t); + CurrentUnityPacket.AddFrame(intermediatePose, remainingPacketSeconds); + recordedSeconds += remainingPacketSeconds; + + // Broadcast the recorded packet + if (PacketRecorded != null) + { + PacketRecorded(this, new PacketEventArgs(CurrentUnityPacket)); + } + + // Open a new packet + CurrentUnityPacket = new OvrAvatarPacket(intermediatePose); + } + } + } + + private void RecordSDKFrame() + { + if (sdkAvatar == IntPtr.Zero) + { + return; + } + + if (!PacketSettings.RecordingFrames) + { + CAPI.ovrAvatarPacket_BeginRecording(sdkAvatar); + PacketSettings.AccumulatedTime = 0.0f; + PacketSettings.RecordingFrames = true; + } + + PacketSettings.AccumulatedTime += Time.deltaTime; + + if (PacketSettings.AccumulatedTime >= PacketSettings.UpdateRate) + { + PacketSettings.AccumulatedTime = 0.0f; + var packet = CAPI.ovrAvatarPacket_EndRecording(sdkAvatar); + CAPI.ovrAvatarPacket_BeginRecording(sdkAvatar); + + if (PacketRecorded != null) + { + PacketRecorded(this, new PacketEventArgs(new OvrAvatarPacket { ovrNativePacket = packet })); + } + + CAPI.ovrAvatarPacket_Free(packet); + } + } + + private void AddRenderParts( + OvrAvatarComponent ovrComponent, + ovrAvatarComponent component, + Transform parent) + { + bool isBody = ovrComponent.name == "body"; + bool isLeftController = ovrComponent.name == "controller_left"; + bool isReftController = ovrComponent.name == "controller_right"; + + for (UInt32 renderPartIndex = 0; renderPartIndex < component.renderPartCount; renderPartIndex++) + { + GameObject renderPartObject = new GameObject(); + renderPartObject.name = GetRenderPartName(component, renderPartIndex); + renderPartObject.transform.SetParent(parent); + IntPtr renderPart = GetRenderPart(component, renderPartIndex); + ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart); + OvrAvatarRenderComponent ovrRenderPart = null; + switch (type) + { + case ovrAvatarRenderPartType.SkinnedMeshRender: + ovrRenderPart = AddSkinnedMeshRenderComponent(renderPartObject, CAPI.ovrAvatarRenderPart_GetSkinnedMeshRender(renderPart)); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS: + ovrRenderPart = AddSkinnedMeshRenderPBSComponent(renderPartObject, CAPI.ovrAvatarRenderPart_GetSkinnedMeshRenderPBS(renderPart)); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2: + { + ovrRenderPart = AddSkinnedMeshRenderPBSV2Component( + renderPart, + renderPartObject, + CAPI.ovrAvatarRenderPart_GetSkinnedMeshRenderPBSV2(renderPart), + isBody && renderPartIndex == 0, + isLeftController || isReftController); + } + break; + default: + break; + } + + if (ovrRenderPart != null) + { + ovrComponent.RenderParts.Add(ovrRenderPart); + } + } + } + + public void RefreshBodyParts() + { + if (Body != null) + { + foreach (var part in Body.RenderParts) + { + Destroy(part.gameObject); + } + + Body.RenderParts.Clear(); + + var nativeAvatarComponent = Body.GetNativeAvatarComponent(); + if (nativeAvatarComponent.HasValue) + { + AddRenderParts(Body, nativeAvatarComponent.Value, Body.gameObject.transform); + } + } + } + + public ovrAvatarBodyComponent? GetBodyComponent() + { + if (Body != null) + { + CAPI.ovrAvatarPose_GetBodyComponent(sdkAvatar, ref Body.component); + return Body.component; + } + + return null; + } + + public Transform GetHandTransform(HandType hand, HandJoint joint) + { + if (hand >= HandType.Max || joint >= HandJoint.Max) + { + return null; + } + + var HandObject = hand == HandType.Left ? HandLeft : HandRight; + + if (HandObject != null) + { + var AvatarComponent = HandObject.GetComponent(); + if (AvatarComponent != null && AvatarComponent.RenderParts.Count > 0) + { + var SkinnedMesh = AvatarComponent.RenderParts[0]; + return SkinnedMesh.transform.Find(HandJoints[(int)hand, (int)joint]); + } + } + + return null; + } + + public void GetPointingDirection(HandType hand, ref Vector3 forward, ref Vector3 up) + { + Transform handBase = GetHandTransform(hand, HandJoint.HandBase); + + if (handBase != null) + { + forward = handBase.forward; + up = handBase.up; + } + } + + static Vector3 MOUTH_POSITION_OFFSET = new Vector3(0, -0.018f, 0.1051f); + static string VOICE_PROPERTY = "_Voice"; + static string MOUTH_POSITION_PROPERTY = "_MouthPosition"; + static string MOUTH_DIRECTION_PROPERTY = "_MouthDirection"; + static string MOUTH_SCALE_PROPERTY = "_MouthEffectScale"; + + static float MOUTH_SCALE_GLOBAL = 0.007f; + static float MOUTH_MAX_GLOBAL = 0.007f; + static string NECK_JONT = "root_JNT/body_JNT/chest_JNT/neckBase_JNT/neck_JNT"; + + public float VoiceAmplitude = 0f; + public bool EnableMouthVertexAnimation = false; + + private void UpdateVoiceBehavior() + { + if (!EnableMouthVertexAnimation) + { + return; + } + + if (Body != null) + { + OvrAvatarComponent component = Body.GetComponent(); + + VoiceAmplitude = Mathf.Clamp(VoiceAmplitude, 0f, 1f); + + if (component.RenderParts.Count > 0) + { + var material = component.RenderParts[0].mesh.sharedMaterial; + var neckJoint = component.RenderParts[0].mesh.transform.Find(NECK_JONT); + var scaleDiff = neckJoint.TransformPoint(Vector3.up) - neckJoint.position; + + material.SetFloat(MOUTH_SCALE_PROPERTY, scaleDiff.magnitude); + + material.SetFloat( + VOICE_PROPERTY, + Mathf.Min(scaleDiff.magnitude * MOUTH_MAX_GLOBAL, scaleDiff.magnitude * VoiceAmplitude * MOUTH_SCALE_GLOBAL)); + + material.SetVector( + MOUTH_POSITION_PROPERTY, + neckJoint.TransformPoint(MOUTH_POSITION_OFFSET)); + + material.SetVector(MOUTH_DIRECTION_PROPERTY, neckJoint.up); + } + } + } + + bool IsValidMic() + { + string[] devices = Microphone.devices; + + if (devices.Length < 1) + { + return false; + } + + int selectedDeviceIndex = 0; +#if UNITY_STANDALONE_WIN + for (int i = 1; i < devices.Length; i++) + { + if (devices[i].ToUpper().Contains("RIFT")) + { + selectedDeviceIndex = i; + break; + } + } +#endif + + string selectedDevice = devices[selectedDeviceIndex]; + + int minFreq; + int maxFreq; + Microphone.GetDeviceCaps(selectedDevice, out minFreq, out maxFreq); + + if (maxFreq == 0) + { + maxFreq = 44100; + } + + AudioClip clip = Microphone.Start(selectedDevice, true, 1, maxFreq); + if (clip == null) + { + return false; + } + + Microphone.End(selectedDevice); + return true; + } + + void InitPostLoad() + { + ExpressiveGlobalInit(); + + ConfigureHelpers(); + + if (GetComponent() != null) + { + // Use mic. + lipsyncContext.audioLoopback = false; + if (CanOwnMicrophone && IsValidMic()) + { + micInput = MouthAnchor.gameObject.AddComponent(); + micInput.enableMicSelectionGUI = false; + micInput.MicFrequency = 44100; + micInput.micControl = OVRLipSyncMicInput.micActivation.ConstantSpeak; + } + + // Set lipsync animation parameters in SDK + CAPI.ovrAvatar_SetActionUnitOnsetSpeed(sdkAvatar, ACTION_UNIT_ONSET_SPEED); + CAPI.ovrAvatar_SetActionUnitFalloffSpeed(sdkAvatar, ACTION_UNIT_FALLOFF_SPEED); + CAPI.ovrAvatar_SetVisemeMultiplier(sdkAvatar, VISEME_LEVEL_MULTIPLIER); + } + } + + static ovrAvatarLights ovrLights = new ovrAvatarLights(); + static void ExpressiveGlobalInit() + { + if (doneExpressiveGlobalInit) + { + return; + } + + doneExpressiveGlobalInit = true; + + // This array size has to match the 'MarshalAs' attribute in the ovrAvatarLights declaration. + const int MAXSIZE = 16; + ovrLights.lights = new ovrAvatarLight[MAXSIZE]; + + InitializeLights(); + } + + static void InitializeLights() + { + // Set light info. Lights are shared across all avatar instances. + ovrLights.ambientIntensity = RenderSettings.ambientLight.grayscale * 0.5f; + + Light[] sceneLights = FindObjectsOfType(typeof(Light)) as Light[]; + int i = 0; + for (i = 0; i < sceneLights.Length && i < ovrLights.lights.Length; ++i) + { + Light sceneLight = sceneLights[i]; + if (sceneLight && sceneLight.enabled) + { + uint instanceID = (uint)sceneLight.transform.GetInstanceID(); + switch (sceneLight.type) + { + case LightType.Directional: + { + CreateLightDirectional(instanceID, sceneLight.transform.forward, sceneLight.intensity, ref ovrLights.lights[i]); + break; + } + case LightType.Point: + { + CreateLightPoint(instanceID, sceneLight.transform.position, sceneLight.range, sceneLight.intensity, ref ovrLights.lights[i]); + break; + } + case LightType.Spot: + { + CreateLightSpot(instanceID, sceneLight.transform.position, sceneLight.transform.forward, sceneLight.spotAngle, sceneLight.range, sceneLight.intensity, ref ovrLights.lights[i]); + break; + } + } + } + } + + ovrLights.lightCount = (uint)i; + + CAPI.ovrAvatar_UpdateLights(ovrLights); + } + + static ovrAvatarLight CreateLightDirectional(uint id, Vector3 direction, float intensity, ref ovrAvatarLight light) + { + light.id = id; + light.type = ovrAvatarLightType.Direction; + light.worldDirection = new Vector3(direction.x, direction.y, -direction.z); + light.intensity = intensity; + return light; + } + + static ovrAvatarLight CreateLightPoint(uint id, Vector3 position, float range, float intensity, ref ovrAvatarLight light) + { + light.id = id; + light.type = ovrAvatarLightType.Point; + light.worldPosition = new Vector3(position.x, position.y, -position.z); + light.range = range; + light.intensity = intensity; + return light; + } + + static ovrAvatarLight CreateLightSpot(uint id, Vector3 position, Vector3 direction, float spotAngleDeg, float range, float intensity, ref ovrAvatarLight light) + { + light.id = id; + light.type = ovrAvatarLightType.Spot; + light.worldPosition = new Vector3(position.x, position.y, -position.z); + light.worldDirection = new Vector3(direction.x, direction.y, -direction.z); + light.spotAngleDeg = spotAngleDeg; + light.range = range; + light.intensity = intensity; + return light; + } + + void UpdateExpressive() + { + ovrAvatarTransform baseTransform = OvrAvatar.CreateOvrAvatarTransform(transform.position, transform.rotation); + CAPI.ovrAvatar_UpdateWorldTransform(sdkAvatar, baseTransform); + + UpdateFacewave(); + } + + private void ConfigureHelpers() + { + Transform head = + transform.Find("body/body_renderPart_0/root_JNT/body_JNT/chest_JNT/neckBase_JNT/neck_JNT/head_JNT"); + if (head == null) + { + AvatarLogger.LogError("Avatar helper config failed. Cannot find head transform. All helpers spawning on root avatar transform"); + head = transform; + } + + if (MouthAnchor == null) + { + MouthAnchor = CreateHelperObject(head, MOUTH_HEAD_OFFSET, MOUTH_HELPER_NAME); + } + + if (GetComponent() != null) + { + if (audioSource == null) + { + audioSource = MouthAnchor.gameObject.AddComponent(); + } + spatializedSource = MouthAnchor.GetComponent(); + + if (spatializedSource == null) + { + spatializedSource = MouthAnchor.gameObject.AddComponent(); + } + + spatializedSource.UseInvSqr = true; + spatializedSource.EnableRfl = false; + spatializedSource.EnableSpatialization = true; + spatializedSource.Far = 100f; + spatializedSource.Near = 0.1f; + + // Add phoneme context to the mouth anchor + lipsyncContext = MouthAnchor.GetComponent(); + if (lipsyncContext == null) + { + lipsyncContext = MouthAnchor.gameObject.AddComponent(); + } + + lipsyncContext.provider = EnableLaughter + ? OVRLipSync.ContextProviders.Enhanced_with_Laughter + : OVRLipSync.ContextProviders.Enhanced; + + // Ignore audio callback if microphone is owned by VoIP + lipsyncContext.skipAudioSource = !CanOwnMicrophone; + + StartCoroutine(WaitForMouthAudioSource()); + } + + if (GetComponent() != null) + { + GazeTarget headTarget = head.gameObject.AddComponent(); + headTarget.Type = ovrAvatarGazeTargetType.AvatarHead; + AvatarLogger.Log("Added head as gaze target"); + + Transform hand = transform.Find("hand_left"); + if (hand == null) + { + AvatarLogger.LogWarning("Gaze target helper config failed: Cannot find left hand transform"); + } + else + { + GazeTarget handTarget = hand.gameObject.AddComponent(); + handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; + AvatarLogger.Log("Added left hand as gaze target"); + } + + hand = transform.Find("hand_right"); + if (hand == null) + { + AvatarLogger.Log("Gaze target helper config failed: Cannot find right hand transform"); + } + else + { + GazeTarget handTarget = hand.gameObject.AddComponent(); + handTarget.Type = ovrAvatarGazeTargetType.AvatarHand; + AvatarLogger.Log("Added right hand as gaze target"); + } + } + } + + private IEnumerator WaitForMouthAudioSource() + { + while (MouthAnchor.GetComponent() == null) + { + yield return new WaitForSeconds(0.1f); + } + AudioSource AS = MouthAnchor.GetComponent(); + AS.minDistance = 0.3f; + AS.maxDistance = 4f; + AS.rolloffMode = AudioRolloffMode.Logarithmic; + AS.loop = true; + AS.playOnAwake = true; + AS.spatialBlend = 1.0f; + AS.spatialize = true; + AS.spatializePostEffects = true; + } + + public void DestroyHelperObjects() + { + if (MouthAnchor) + { + DestroyImmediate(MouthAnchor.gameObject); + } + } + + public GameObject CreateHelperObject(Transform parent, Vector3 localPositionOffset, string helperName, + string helperTag = "") + { + GameObject helper = new GameObject(); + helper.name = helperName; + if (helperTag != "") + { + helper.tag = helperTag; + } + helper.transform.SetParent(parent); + helper.transform.localRotation = Quaternion.identity; + helper.transform.localPosition = localPositionOffset; + return helper; + } + + public void UpdateVoiceData(short[] pcmData, int numChannels) + { + if (lipsyncContext != null && micInput == null) + { + lipsyncContext.ProcessAudioSamplesRaw(pcmData, numChannels); + } + } + public void UpdateVoiceData(float[] pcmData, int numChannels) + { + if (lipsyncContext != null && micInput == null) + { + lipsyncContext.ProcessAudioSamplesRaw(pcmData, numChannels); + } + } + + + private void UpdateFacewave() + { + if (lipsyncContext != null && (micInput != null || CanOwnMicrophone == false)) + { + // Get the current viseme frame + currentFrame = lipsyncContext.GetCurrentPhonemeFrame(); + + // Verify length (-1 for laughter) + if (currentFrame.Visemes.Length != (VISEME_COUNT - 1)) + { + Debug.LogError("Unexpected number of visemes " + currentFrame.Visemes); + return; + } + + // Copy to viseme array + currentFrame.Visemes.CopyTo(visemes, 0); + // Copy laughter as final element + visemes[VISEME_COUNT - 1] = EnableLaughter ? currentFrame.laughterScore : 0.0f; + + // Send visemes to native implementation. + for (int i = 0; i < VISEME_COUNT; i++) + { + RuntimeVisemes.visemeParams[i] = visemes[i]; + } + CAPI.ovrAvatar_SetVisemes(sdkAvatar, RuntimeVisemes); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatar.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatar.cs.meta new file mode 100644 index 0000000..7e568fa --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatar.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 00f3402a2ea5bff4880c0313515240cd +timeCreated: 1464046614 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs new file mode 100644 index 0000000..9d3b785 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs @@ -0,0 +1,5 @@ +using System; + +public class OvrAvatarAsset { + public UInt64 assetID; +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs.meta new file mode 100644 index 0000000..8d4604c --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarAsset.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a7045bb39115f484a89ecaa778a2a60f +timeCreated: 1475521356 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs new file mode 100644 index 0000000..05516ad --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs @@ -0,0 +1,279 @@ +using System; +using Oculus.Avatar; +using UnityEngine; +using System.Runtime.InteropServices; + +public class OvrAvatarAssetMesh : OvrAvatarAsset +{ + public Mesh mesh; + private ovrAvatarSkinnedMeshPose skinnedBindPose; + public string[] jointNames; + + public OvrAvatarAssetMesh(UInt64 _assetId, IntPtr asset, ovrAvatarAssetType meshType) + { + assetID = _assetId; + mesh = new Mesh(); + mesh.name = "Procedural Geometry for asset " + _assetId; + + SetSkinnedBindPose(asset, meshType); + + long vertexCount = 0; + IntPtr vertexBuffer = IntPtr.Zero; + uint indexCount = 0; + IntPtr indexBuffer = IntPtr.Zero; + + GetVertexAndIndexData(asset, meshType, out vertexCount, out vertexBuffer, out indexCount, out indexBuffer); + + AvatarLogger.Log("OvrAvatarAssetMesh: " + _assetId + " " + meshType.ToString() + " VertexCount:" + vertexCount); + + Vector3[] vertices = new Vector3[vertexCount]; + Vector3[] normals = new Vector3[vertexCount]; + Vector4[] tangents = new Vector4[vertexCount]; + Vector2[] uv = new Vector2[vertexCount]; + Color[] colors = new Color[vertexCount]; + BoneWeight[] boneWeights = new BoneWeight[vertexCount]; + + long vertexBufferStart = vertexBuffer.ToInt64(); + + // We have different underlying vertex types to unpack, so switch on mesh type. + switch (meshType) + { + case ovrAvatarAssetType.Mesh: + { + long vertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarMeshVertex)); + + for (long i = 0; i < vertexCount; i++) + { + long offset = vertexSize * i; + + ovrAvatarMeshVertex vertex = (ovrAvatarMeshVertex)Marshal.PtrToStructure(new IntPtr(vertexBufferStart + offset), typeof(ovrAvatarMeshVertex)); + vertices[i] = new Vector3(vertex.x, vertex.y, -vertex.z); + normals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); + tangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz, vertex.tw); + uv[i] = new Vector2(vertex.u, vertex.v); + colors[i] = new Color(0, 0, 0, 1); + + boneWeights[i].boneIndex0 = vertex.blendIndices[0]; + boneWeights[i].boneIndex1 = vertex.blendIndices[1]; + boneWeights[i].boneIndex2 = vertex.blendIndices[2]; + boneWeights[i].boneIndex3 = vertex.blendIndices[3]; + boneWeights[i].weight0 = vertex.blendWeights[0]; + boneWeights[i].weight1 = vertex.blendWeights[1]; + boneWeights[i].weight2 = vertex.blendWeights[2]; + boneWeights[i].weight3 = vertex.blendWeights[3]; + } + } + break; + + case ovrAvatarAssetType.CombinedMesh: + { + long vertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarMeshVertexV2)); + + for (long i = 0; i < vertexCount; i++) + { + long offset = vertexSize * i; + + ovrAvatarMeshVertexV2 vertex = (ovrAvatarMeshVertexV2)Marshal.PtrToStructure(new IntPtr(vertexBufferStart + offset), typeof(ovrAvatarMeshVertexV2)); + vertices[i] = new Vector3(vertex.x, vertex.y, -vertex.z); + normals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); + tangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz, vertex.tw); + uv[i] = new Vector2(vertex.u, vertex.v); + colors[i] = new Color(vertex.r, vertex.g, vertex.b, vertex.a); + + boneWeights[i].boneIndex0 = vertex.blendIndices[0]; + boneWeights[i].boneIndex1 = vertex.blendIndices[1]; + boneWeights[i].boneIndex2 = vertex.blendIndices[2]; + boneWeights[i].boneIndex3 = vertex.blendIndices[3]; + boneWeights[i].weight0 = vertex.blendWeights[0]; + boneWeights[i].weight1 = vertex.blendWeights[1]; + boneWeights[i].weight2 = vertex.blendWeights[2]; + boneWeights[i].weight3 = vertex.blendWeights[3]; + } + } + break; + default: + throw new Exception("Bad Mesh Asset Type"); + } + + mesh.vertices = vertices; + mesh.normals = normals; + mesh.uv = uv; + mesh.tangents = tangents; + mesh.boneWeights = boneWeights; + mesh.colors = colors; + + LoadBlendShapes(asset, vertexCount); + LoadSubmeshes(asset, indexBuffer, indexCount); + + UInt32 jointCount = skinnedBindPose.jointCount; + jointNames = new string[jointCount]; + for (UInt32 i = 0; i < jointCount; i++) + { + jointNames[i] = Marshal.PtrToStringAnsi(skinnedBindPose.jointNames[i]); + } + } + + private void LoadSubmeshes(IntPtr asset, IntPtr indexBufferPtr, ulong indexCount) + { + UInt32 subMeshCount = CAPI.ovrAvatarAsset_GetSubmeshCount(asset); + + AvatarLogger.Log("LoadSubmeshes: " + subMeshCount); + + Int16[] indices = new Int16[indexCount]; + Marshal.Copy(indexBufferPtr, indices, 0, (int)indexCount); + + mesh.subMeshCount = (int)subMeshCount; + uint accumedOffset = 0; + for (UInt32 index = 0; index < subMeshCount; index++) + { + var submeshIndexCount = CAPI.ovrAvatarAsset_GetSubmeshLastIndex(asset, index); + var currSpan = submeshIndexCount - accumedOffset; + + Int32[] triangles = new Int32[currSpan]; + + int triangleOffset = 0; + for (ulong i = accumedOffset; i < submeshIndexCount; i += 3) + { + // NOTE: We are changing the order of each triangle to match unity expectations vs pipeline. + triangles[triangleOffset + 2] = (Int32)indices[i]; + triangles[triangleOffset + 1] = (Int32)indices[i + 1]; + triangles[triangleOffset] = (Int32)indices[i + 2]; + + triangleOffset += 3; + } + + accumedOffset += currSpan; + + mesh.SetIndices(triangles, MeshTopology.Triangles, (int)index); + } + } + + private void LoadBlendShapes(IntPtr asset, long vertexCount) + { + UInt32 blendShapeCount = CAPI.ovrAvatarAsset_GetMeshBlendShapeCount(asset); + IntPtr blendShapeVerts = CAPI.ovrAvatarAsset_GetMeshBlendShapeVertices(asset); + + AvatarLogger.Log("LoadBlendShapes: " + blendShapeCount); + + if (blendShapeVerts != IntPtr.Zero) + { + long offset = 0; + long blendVertexSize = (long)Marshal.SizeOf(typeof(ovrAvatarBlendVertex)); + long blendVertexBufferStart = blendShapeVerts.ToInt64(); + + for (UInt32 blendIndex = 0; blendIndex < blendShapeCount; blendIndex++) + { + Vector3[] blendVerts = new Vector3[vertexCount]; + Vector3[] blendNormals = new Vector3[vertexCount]; + Vector3[] blendTangents = new Vector3[vertexCount]; + + for (long i = 0; i < vertexCount; i++) + { + ovrAvatarBlendVertex vertex = (ovrAvatarBlendVertex)Marshal.PtrToStructure(new IntPtr(blendVertexBufferStart + offset), typeof(ovrAvatarBlendVertex)); + blendVerts[i] = new Vector3(vertex.x, vertex.y, -vertex.z); + blendNormals[i] = new Vector3(vertex.nx, vertex.ny, -vertex.nz); + blendTangents[i] = new Vector4(vertex.tx, vertex.ty, -vertex.tz); + + offset += blendVertexSize; + } + + IntPtr namePtr = CAPI.ovrAvatarAsset_GetMeshBlendShapeName(asset, blendIndex); + string name = Marshal.PtrToStringAnsi(namePtr); + const float frameWeight = 100f; + mesh.AddBlendShapeFrame(name, frameWeight, blendVerts, blendNormals, blendTangents); + } + } + } + + private void SetSkinnedBindPose(IntPtr asset, ovrAvatarAssetType meshType) + { + switch (meshType) + { + case ovrAvatarAssetType.Mesh: + skinnedBindPose = CAPI.ovrAvatarAsset_GetMeshData(asset).skinnedBindPose; + break; + case ovrAvatarAssetType.CombinedMesh: + skinnedBindPose = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).skinnedBindPose; + break; + default: + break; + + } + } + + private void GetVertexAndIndexData( + IntPtr asset, + ovrAvatarAssetType meshType, + out long vertexCount, + out IntPtr vertexBuffer, + out uint indexCount, + out IntPtr indexBuffer) + { + vertexCount = 0; + vertexBuffer = IntPtr.Zero; + indexCount = 0; + indexBuffer = IntPtr.Zero; + + switch (meshType) + { + case ovrAvatarAssetType.Mesh: + vertexCount = CAPI.ovrAvatarAsset_GetMeshData(asset).vertexCount; + vertexBuffer = CAPI.ovrAvatarAsset_GetMeshData(asset).vertexBuffer; + indexCount = CAPI.ovrAvatarAsset_GetMeshData(asset).indexCount; + indexBuffer = CAPI.ovrAvatarAsset_GetMeshData(asset).indexBuffer; + break; + case ovrAvatarAssetType.CombinedMesh: + vertexCount = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).vertexCount; + vertexBuffer = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).vertexBuffer; + indexCount = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).indexCount; + indexBuffer = CAPI.ovrAvatarAsset_GetCombinedMeshData(asset).indexBuffer; + break; + default: + break; + } + } + + public SkinnedMeshRenderer CreateSkinnedMeshRendererOnObject(GameObject target) + { + SkinnedMeshRenderer skinnedMeshRenderer = target.AddComponent(); + skinnedMeshRenderer.sharedMesh = mesh; + mesh.name = "AvatarMesh_" + assetID; + UInt32 jointCount = skinnedBindPose.jointCount; + GameObject[] bones = new GameObject[jointCount]; + Transform[] boneTransforms = new Transform[jointCount]; + Matrix4x4[] bindPoses = new Matrix4x4[jointCount]; + for (UInt32 i = 0; i < jointCount; i++) + { + bones[i] = new GameObject(); + boneTransforms[i] = bones[i].transform; + bones[i].name = jointNames[i]; + int parentIndex = skinnedBindPose.jointParents[i]; + if (parentIndex == -1) + { + bones[i].transform.parent = skinnedMeshRenderer.transform; + skinnedMeshRenderer.rootBone = bones[i].transform; + } + else + { + bones[i].transform.parent = bones[parentIndex].transform; + } + + // Set the position relative to the parent + Vector3 position = skinnedBindPose.jointTransform[i].position; + position.z = -position.z; + bones[i].transform.localPosition = position; + + Quaternion orientation = skinnedBindPose.jointTransform[i].orientation; + orientation.x = -orientation.x; + orientation.y = -orientation.y; + bones[i].transform.localRotation = orientation; + + bones[i].transform.localScale = skinnedBindPose.jointTransform[i].scale; + + bindPoses[i] = bones[i].transform.worldToLocalMatrix * skinnedMeshRenderer.transform.localToWorldMatrix; + } + skinnedMeshRenderer.bones = boneTransforms; + mesh.bindposes = bindPoses; + return skinnedMeshRenderer; + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs.meta new file mode 100644 index 0000000..6a244d6 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetMesh.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 80be643e69fa4a4478a5cb27a190bbd2 +timeCreated: 1475522461 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs new file mode 100644 index 0000000..e98e278 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs @@ -0,0 +1,62 @@ +using System; +using Oculus.Avatar; +using UnityEngine; + +public class OvrAvatarAssetTexture : OvrAvatarAsset +{ + public Texture2D texture; + private const int ASTCHeaderSize = 16; + + public OvrAvatarAssetTexture(UInt64 _assetId, IntPtr asset) { + assetID = _assetId; + ovrAvatarTextureAssetData textureAssetData = CAPI.ovrAvatarAsset_GetTextureData(asset); + TextureFormat format; + IntPtr textureData = textureAssetData.textureData; + int textureDataSize = (int)textureAssetData.textureDataSize; + + AvatarLogger.Log( + "OvrAvatarAssetTexture - " + + _assetId + + ": " + + textureAssetData.format.ToString() + + " " + + textureAssetData.sizeX + + "x" + + textureAssetData.sizeY); + + switch (textureAssetData.format) + { + case ovrAvatarTextureFormat.RGB24: + format = TextureFormat.RGB24; + break; + case ovrAvatarTextureFormat.DXT1: + format = TextureFormat.DXT1; + break; + case ovrAvatarTextureFormat.DXT5: + format = TextureFormat.DXT5; + break; + case ovrAvatarTextureFormat.ASTC_RGB_6x6: + format = TextureFormat.ASTC_RGB_6x6; + textureData = new IntPtr(textureData.ToInt64() + ASTCHeaderSize); + textureDataSize -= ASTCHeaderSize; + break; + case ovrAvatarTextureFormat.ASTC_RGB_6x6_MIPMAPS: + format = TextureFormat.ASTC_RGB_6x6; + break; + default: + throw new NotImplementedException( + string.Format("Unsupported texture format {0}", + textureAssetData.format.ToString())); + } + texture = new Texture2D( + (int)textureAssetData.sizeX, (int)textureAssetData.sizeY, + format, textureAssetData.mipCount > 1, + QualitySettings.activeColorSpace == ColorSpace.Gamma ? false : true) + { + filterMode = FilterMode.Trilinear, + anisoLevel = 4, + }; + texture.LoadRawTextureData(textureData, textureDataSize); + texture.Apply(true, false); + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs.meta new file mode 100644 index 0000000..147ed2b --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarAssetTexture.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8a3167eed50e56346be5b1cc65ad7226 +timeCreated: 1475522480 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs new file mode 100644 index 0000000..544eddc --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs @@ -0,0 +1,24 @@ +using Oculus.Avatar; + +public class OvrAvatarBase : OvrAvatarComponent +{ + ovrAvatarBaseComponent component = new ovrAvatarBaseComponent(); + + void Update() + { + if (owner == null) + { + return; + } + + if (CAPI.ovrAvatarPose_GetBaseComponent(owner.sdkAvatar, ref component)) + { + UpdateAvatar(component.renderComponent); + } + else + { + owner.Base = null; + Destroy(this); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs.meta new file mode 100644 index 0000000..7f390f5 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarBase.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a0e33623ec5372748b5703f61a4df82d +timeCreated: 1477606822 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs new file mode 100644 index 0000000..d0ecc54 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs @@ -0,0 +1,43 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System; +using Oculus.Avatar; +public class OvrAvatarBody : OvrAvatarComponent +{ + public ovrAvatarBodyComponent component = new ovrAvatarBodyComponent(); + + public ovrAvatarComponent? GetNativeAvatarComponent() + { + if (owner == null) + { + return null; + } + + if (CAPI.ovrAvatarPose_GetBodyComponent(owner.sdkAvatar, ref component)) + { + CAPI.ovrAvatarComponent_Get(component.renderComponent, true, ref nativeAvatarComponent); + return nativeAvatarComponent; + } + + return null; + } + + void Update() + { + if (owner == null) + { + return; + } + + if (CAPI.ovrAvatarPose_GetBodyComponent(owner.sdkAvatar, ref component)) + { + UpdateAvatar(component.renderComponent); + } + else + { + owner.Body = null; + Destroy(this); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs.meta new file mode 100644 index 0000000..f6b666b --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarBody.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: eb7a6650b6cb46545967d3b380b7396c +timeCreated: 1466814542 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs new file mode 100644 index 0000000..70f58f3 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs @@ -0,0 +1,145 @@ +using System; +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using Oculus.Avatar; +using System.Threading; + +public class OvrAvatarComponent : MonoBehaviour +{ + public static readonly string[] LayerKeywords = new[] { "LAYERS_0", "LAYERS_1", "LAYERS_2", "LAYERS_3", "LAYERS_4", "LAYERS_5", "LAYERS_6", "LAYERS_7", "LAYERS_8", }; + public static readonly string[] LayerSampleModeParameters = new[] { "_LayerSampleMode0", "_LayerSampleMode1", "_LayerSampleMode2", "_LayerSampleMode3", "_LayerSampleMode4", "_LayerSampleMode5", "_LayerSampleMode6", "_LayerSampleMode7", }; + public static readonly string[] LayerBlendModeParameters = new[] { "_LayerBlendMode0", "_LayerBlendMode1", "_LayerBlendMode2", "_LayerBlendMode3", "_LayerBlendMode4", "_LayerBlendMode5", "_LayerBlendMode6", "_LayerBlendMode7", }; + public static readonly string[] LayerMaskTypeParameters = new[] { "_LayerMaskType0", "_LayerMaskType1", "_LayerMaskType2", "_LayerMaskType3", "_LayerMaskType4", "_LayerMaskType5", "_LayerMaskType6", "_LayerMaskType7", }; + public static readonly string[] LayerColorParameters = new[] { "_LayerColor0", "_LayerColor1", "_LayerColor2", "_LayerColor3", "_LayerColor4", "_LayerColor5", "_LayerColor6", "_LayerColor7", }; + public static readonly string[] LayerSurfaceParameters = new[] { "_LayerSurface0", "_LayerSurface1", "_LayerSurface2", "_LayerSurface3", "_LayerSurface4", "_LayerSurface5", "_LayerSurface6", "_LayerSurface7", }; + public static readonly string[] LayerSampleParametersParameters = new[] { "_LayerSampleParameters0", "_LayerSampleParameters1", "_LayerSampleParameters2", "_LayerSampleParameters3", "_LayerSampleParameters4", "_LayerSampleParameters5", "_LayerSampleParameters6", "_LayerSampleParameters7", }; + public static readonly string[] LayerMaskParametersParameters = new[] { "_LayerMaskParameters0", "_LayerMaskParameters1", "_LayerMaskParameters2", "_LayerMaskParameters3", "_LayerMaskParameters4", "_LayerMaskParameters5", "_LayerMaskParameters6", "_LayerMaskParameters7", }; + public static readonly string[] LayerMaskAxisParameters = new[] { "_LayerMaskAxis0", "_LayerMaskAxis1", "_LayerMaskAxis2", "_LayerMaskAxis3", "_LayerMaskAxis4", "_LayerMaskAxis5", "_LayerMaskAxis6", "_LayerMaskAxis7", }; + + private Dictionary materialStates = new Dictionary(); + public List RenderParts = new List(); + + protected OvrAvatar owner = null; + protected ovrAvatarComponent nativeAvatarComponent = new ovrAvatarComponent(); + + public void SetOvrAvatarOwner(OvrAvatar ovrAvatarOwner) + { + owner = ovrAvatarOwner; + } + + public void UpdateAvatar(IntPtr nativeComponent) + { + CAPI.ovrAvatarComponent_Get(nativeComponent, false, ref nativeAvatarComponent); + + OvrAvatar.ConvertTransform(nativeAvatarComponent.transform, transform); + + for (UInt32 renderPartIndex = 0; renderPartIndex < nativeAvatarComponent.renderPartCount; renderPartIndex++) + { + if (RenderParts.Count <= renderPartIndex) + { + break; + } + + OvrAvatarRenderComponent renderComponent = RenderParts[(int)renderPartIndex]; + IntPtr renderPart = OvrAvatar.GetRenderPart(nativeAvatarComponent, renderPartIndex); + ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart); + switch (type) + { + case ovrAvatarRenderPartType.SkinnedMeshRender: + ((OvrAvatarSkinnedMeshRenderComponent)renderComponent).UpdateSkinnedMeshRender(this, owner, renderPart); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS: + ((OvrAvatarSkinnedMeshRenderPBSComponent)renderComponent).UpdateSkinnedMeshRenderPBS(owner, renderPart, renderComponent.mesh.sharedMaterial); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2: + ((OvrAvatarSkinnedMeshPBSV2RenderComponent)renderComponent).UpdateSkinnedMeshRender(this, owner, renderPart); + break; + default: + break; + } + } + } + + protected void UpdateActive(OvrAvatar avatar, ovrAvatarVisibilityFlags mask) + { + bool active = avatar.ShowFirstPerson && (mask & ovrAvatarVisibilityFlags.FirstPerson) != 0; + active |= avatar.ShowThirdPerson && (mask & ovrAvatarVisibilityFlags.ThirdPerson) != 0; + this.gameObject.SetActive(active); + } + + public void UpdateAvatarMaterial(Material mat, ovrAvatarMaterialState matState) + { + mat.SetColor("_BaseColor", matState.baseColor); + mat.SetInt("_BaseMaskType", (int)matState.baseMaskType); + mat.SetVector("_BaseMaskParameters", matState.baseMaskParameters); + mat.SetVector("_BaseMaskAxis", matState.baseMaskAxis); + + if (matState.alphaMaskTextureID != 0) + { + mat.SetTexture("_AlphaMask", GetLoadedTexture(matState.alphaMaskTextureID)); + mat.SetTextureScale("_AlphaMask", new Vector2(matState.alphaMaskScaleOffset.x, matState.alphaMaskScaleOffset.y)); + mat.SetTextureOffset("_AlphaMask", new Vector2(matState.alphaMaskScaleOffset.z, matState.alphaMaskScaleOffset.w)); + } + + if (matState.normalMapTextureID != 0) + { + mat.EnableKeyword("NORMAL_MAP_ON"); + mat.SetTexture("_NormalMap", GetLoadedTexture(matState.normalMapTextureID)); + mat.SetTextureScale("_NormalMap", new Vector2(matState.normalMapScaleOffset.x, matState.normalMapScaleOffset.y)); + mat.SetTextureOffset("_NormalMap", new Vector2(matState.normalMapScaleOffset.z, matState.normalMapScaleOffset.w)); + } + if (matState.parallaxMapTextureID != 0) + { + mat.SetTexture("_ParallaxMap", GetLoadedTexture(matState.parallaxMapTextureID)); + mat.SetTextureScale("_ParallaxMap", new Vector2(matState.parallaxMapScaleOffset.x, matState.parallaxMapScaleOffset.y)); + mat.SetTextureOffset("_ParallaxMap", new Vector2(matState.parallaxMapScaleOffset.z, matState.parallaxMapScaleOffset.w)); + } + if (matState.roughnessMapTextureID != 0) + { + mat.EnableKeyword("ROUGHNESS_ON"); + mat.SetTexture("_RoughnessMap", GetLoadedTexture(matState.roughnessMapTextureID)); + mat.SetTextureScale("_RoughnessMap", new Vector2(matState.roughnessMapScaleOffset.x, matState.roughnessMapScaleOffset.y)); + mat.SetTextureOffset("_RoughnessMap", new Vector2(matState.roughnessMapScaleOffset.z, matState.roughnessMapScaleOffset.w)); + } + mat.EnableKeyword(LayerKeywords[matState.layerCount]); + for (ulong layerIndex = 0; layerIndex < matState.layerCount; layerIndex++) + { + ovrAvatarMaterialLayerState layer = matState.layers[layerIndex]; + + mat.SetInt(LayerSampleModeParameters[layerIndex], (int)layer.sampleMode); + mat.SetInt(LayerBlendModeParameters[layerIndex], (int)layer.blendMode); + mat.SetInt(LayerMaskTypeParameters[layerIndex], (int)layer.maskType); + mat.SetColor(LayerColorParameters[layerIndex], layer.layerColor); + if (layer.sampleMode != ovrAvatarMaterialLayerSampleMode.Color) + { + string surfaceProperty = LayerSurfaceParameters[layerIndex]; + mat.SetTexture(surfaceProperty, GetLoadedTexture(layer.sampleTexture)); + mat.SetTextureScale(surfaceProperty, new Vector2(layer.sampleScaleOffset.x, layer.sampleScaleOffset.y)); + mat.SetTextureOffset(surfaceProperty, new Vector2(layer.sampleScaleOffset.z, layer.sampleScaleOffset.w)); + } + + if (layer.sampleMode == ovrAvatarMaterialLayerSampleMode.Parallax) + { + mat.EnableKeyword("PARALLAX_ON"); + } + + mat.SetColor(LayerSampleParametersParameters[layerIndex], layer.sampleParameters); + mat.SetColor(LayerMaskParametersParameters[layerIndex], layer.maskParameters); + mat.SetColor(LayerMaskAxisParameters[layerIndex], layer.maskAxis); + } + + materialStates[mat] = matState; + } + + public static Texture2D GetLoadedTexture(UInt64 assetId) + { + OvrAvatarAssetTexture tex = (OvrAvatarAssetTexture)OvrAvatarSDKManager.Instance.GetAsset(assetId); + if (tex == null) + { + return null; + } + + return tex.texture; + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs.meta new file mode 100644 index 0000000..e5973d7 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarComponent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4d8af585c6ed18849905454f83194043 +timeCreated: 1479155378 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs new file mode 100644 index 0000000..3ac54dd --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs @@ -0,0 +1,119 @@ +using UnityEngine; +using System.Collections; +using System; +using Oculus.Avatar; + +public abstract class OvrAvatarDriver : MonoBehaviour { + + public enum PacketMode + { + SDK, + Unity + }; + + public PacketMode Mode; + protected PoseFrame CurrentPose; + public PoseFrame GetCurrentPose() { return CurrentPose; } + public abstract void UpdateTransforms(IntPtr sdkAvatar); + + private ovrAvatarControllerType ControllerType = ovrAvatarControllerType.Quest; + public struct ControllerPose + { + public ovrAvatarButton buttons; + public ovrAvatarTouch touches; + public Vector2 joystickPosition; + public float indexTrigger; + public float handTrigger; + public bool isActive; + + public static ControllerPose Interpolate(ControllerPose a, ControllerPose b, float t) + { + return new ControllerPose + { + buttons = t < 0.5f ? a.buttons : b.buttons, + touches = t < 0.5f ? a.touches : b.touches, + joystickPosition = Vector2.Lerp(a.joystickPosition, b.joystickPosition, t), + indexTrigger = Mathf.Lerp(a.indexTrigger, b.indexTrigger, t), + handTrigger = Mathf.Lerp(a.handTrigger, b.handTrigger, t), + isActive = t < 0.5f ? a.isActive : b.isActive, + }; + } + } + + public struct PoseFrame + { + public Vector3 headPosition; + public Quaternion headRotation; + public Vector3 handLeftPosition; + public Quaternion handLeftRotation; + public Vector3 handRightPosition; + public Quaternion handRightRotation; + public float voiceAmplitude; + + public ControllerPose controllerLeftPose; + public ControllerPose controllerRightPose; + + public static PoseFrame Interpolate(PoseFrame a, PoseFrame b, float t) + { + return new PoseFrame + { + headPosition = Vector3.Lerp(a.headPosition, b.headPosition, t), + headRotation = Quaternion.Slerp(a.headRotation, b.headRotation, t), + handLeftPosition = Vector3.Lerp(a.handLeftPosition, b.handLeftPosition, t), + handLeftRotation = Quaternion.Slerp(a.handLeftRotation, b.handLeftRotation, t), + handRightPosition = Vector3.Lerp(a.handRightPosition, b.handRightPosition, t), + handRightRotation = Quaternion.Slerp(a.handRightRotation, b.handRightRotation, t), + voiceAmplitude = Mathf.Lerp(a.voiceAmplitude, b.voiceAmplitude, t), + controllerLeftPose = ControllerPose.Interpolate(a.controllerLeftPose, b.controllerLeftPose, t), + controllerRightPose = ControllerPose.Interpolate(a.controllerRightPose, b.controllerRightPose, t), + }; + } + }; + + void Start() + { + var headsetType = OVRPlugin.GetSystemHeadsetType(); + switch (headsetType) + { + case OVRPlugin.SystemHeadset.GearVR_R320: + case OVRPlugin.SystemHeadset.GearVR_R321: + case OVRPlugin.SystemHeadset.GearVR_R322: + case OVRPlugin.SystemHeadset.GearVR_R323: + case OVRPlugin.SystemHeadset.GearVR_R324: + case OVRPlugin.SystemHeadset.GearVR_R325: + ControllerType = ovrAvatarControllerType.Malibu; + break; + case OVRPlugin.SystemHeadset.Oculus_Go: + ControllerType = ovrAvatarControllerType.Go; + break; + case OVRPlugin.SystemHeadset.Oculus_Quest: + case OVRPlugin.SystemHeadset.Rift_S: + ControllerType = ovrAvatarControllerType.Quest; + break; + case OVRPlugin.SystemHeadset.Rift_DK1: + case OVRPlugin.SystemHeadset.Rift_DK2: + case OVRPlugin.SystemHeadset.Rift_CV1: + default: + ControllerType = ovrAvatarControllerType.Touch; + break; + } + } + + public void UpdateTransformsFromPose(IntPtr sdkAvatar) + { + if (sdkAvatar != IntPtr.Zero) + { + ovrAvatarTransform bodyTransform = OvrAvatar.CreateOvrAvatarTransform(CurrentPose.headPosition, CurrentPose.headRotation); + ovrAvatarHandInputState inputStateLeft = OvrAvatar.CreateInputState(OvrAvatar.CreateOvrAvatarTransform(CurrentPose.handLeftPosition, CurrentPose.handLeftRotation), CurrentPose.controllerLeftPose); + ovrAvatarHandInputState inputStateRight = OvrAvatar.CreateInputState(OvrAvatar.CreateOvrAvatarTransform(CurrentPose.handRightPosition, CurrentPose.handRightRotation), CurrentPose.controllerRightPose); + + CAPI.ovrAvatarPose_UpdateBody(sdkAvatar, bodyTransform); + CAPI.ovrAvatarPose_UpdateHandsWithType(sdkAvatar, inputStateLeft, inputStateRight, ControllerType); + } + } + + public static bool GetIsTrackedRemote() + { + return OVRInput.IsControllerConnected(OVRInput.Controller.RTrackedRemote) || OVRInput.IsControllerConnected(OVRInput.Controller.LTrackedRemote); + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs.meta new file mode 100644 index 0000000..8208090 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarDriver.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b0bda905d6cc47640bc17f99e364a1b9 +timeCreated: 1464049373 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs new file mode 100644 index 0000000..d4886b4 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs @@ -0,0 +1,48 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System; +using Oculus.Avatar; + +public class OvrAvatarHand : OvrAvatarComponent +{ + public bool isLeftHand = true; + ovrAvatarHandComponent component = new ovrAvatarHandComponent(); + + void Update() + { + if (owner == null) + { + return; + } + + bool hasComponent = false; + if (isLeftHand) + { + hasComponent = CAPI.ovrAvatarPose_GetLeftHandComponent(owner.sdkAvatar, ref component); + } + else + { + hasComponent = CAPI.ovrAvatarPose_GetRightHandComponent(owner.sdkAvatar, ref component); + } + + if (hasComponent) + { + UpdateAvatar(component.renderComponent); + } + else + { + if (isLeftHand) + { + owner.HandLeft = null; + + } + else + { + owner.HandRight = null; + } + + Destroy(this); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs.meta new file mode 100644 index 0000000..0e9d912 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarHand.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e53b07ad62d980a4da9fffff0b05fd2e +timeCreated: 1464054646 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs new file mode 100644 index 0000000..2de5156 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs @@ -0,0 +1,102 @@ +using UnityEngine; +using System.Collections; +using System; +using System.Collections.Generic; +using Oculus.Avatar; + +public class OvrAvatarLocalDriver : OvrAvatarDriver { + + Vector3 centerEyePosition = Vector3.zero; + Quaternion centerEyeRotation = Quaternion.identity; + + ControllerPose GetMalibuControllerPose(OVRInput.Controller controller) + { + ovrAvatarButton buttons = 0; + if (OVRInput.Get(OVRInput.Button.PrimaryIndexTrigger, controller)) buttons |= ovrAvatarButton.One; + + return new ControllerPose + { + buttons = buttons, + touches = OVRInput.Get(OVRInput.Touch.PrimaryTouchpad) ? ovrAvatarTouch.One : 0, + joystickPosition = OVRInput.Get(OVRInput.Axis2D.PrimaryTouchpad, controller), + indexTrigger = 0f, + handTrigger = 0f, + isActive = (OVRInput.GetActiveController() & controller) != 0, + }; + } + + float voiceAmplitude = 0.0f; + ControllerPose GetControllerPose(OVRInput.Controller controller) + { + ovrAvatarButton buttons = 0; + if (OVRInput.Get(OVRInput.Button.One, controller)) buttons |= ovrAvatarButton.One; + if (OVRInput.Get(OVRInput.Button.Two, controller)) buttons |= ovrAvatarButton.Two; + if (OVRInput.Get(OVRInput.Button.Start, controller)) buttons |= ovrAvatarButton.Three; + if (OVRInput.Get(OVRInput.Button.PrimaryThumbstick, controller)) buttons |= ovrAvatarButton.Joystick; + + ovrAvatarTouch touches = 0; + if (OVRInput.Get(OVRInput.Touch.One, controller)) touches |= ovrAvatarTouch.One; + if (OVRInput.Get(OVRInput.Touch.Two, controller)) touches |= ovrAvatarTouch.Two; + if (OVRInput.Get(OVRInput.Touch.PrimaryThumbstick, controller)) touches |= ovrAvatarTouch.Joystick; + if (OVRInput.Get(OVRInput.Touch.PrimaryThumbRest, controller)) touches |= ovrAvatarTouch.ThumbRest; + if (OVRInput.Get(OVRInput.Touch.PrimaryIndexTrigger, controller)) touches |= ovrAvatarTouch.Index; + if (!OVRInput.Get(OVRInput.NearTouch.PrimaryIndexTrigger, controller)) touches |= ovrAvatarTouch.Pointing; + if (!OVRInput.Get(OVRInput.NearTouch.PrimaryThumbButtons, controller)) touches |= ovrAvatarTouch.ThumbUp; + + return new ControllerPose + { + buttons = buttons, + touches = touches, + joystickPosition = OVRInput.Get(OVRInput.Axis2D.PrimaryThumbstick, controller), + indexTrigger = OVRInput.Get(OVRInput.Axis1D.PrimaryIndexTrigger, controller), + handTrigger = OVRInput.Get(OVRInput.Axis1D.PrimaryHandTrigger, controller), + isActive = (OVRInput.GetActiveController() & controller) != 0, + }; + } + + private void CalculateCurrentPose() + { + // Platform and device agnostic calls to return center eye pose, used to pass in head pose to sdk + OVRNodeStateProperties.GetNodeStatePropertyVector3(UnityEngine.XR.XRNode.CenterEye, NodeStatePropertyType.Position, + OVRPlugin.Node.EyeCenter, OVRPlugin.Step.Render, out centerEyePosition); + OVRNodeStateProperties.GetNodeStatePropertyQuaternion(UnityEngine.XR.XRNode.CenterEye, NodeStatePropertyType.Orientation, + OVRPlugin.Node.EyeCenter, OVRPlugin.Step.Render, out centerEyeRotation); + + if (GetIsTrackedRemote()) + { + CurrentPose = new PoseFrame + { + voiceAmplitude = voiceAmplitude, + headPosition = centerEyePosition, + headRotation = centerEyeRotation, + handLeftPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTrackedRemote), + handLeftRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTrackedRemote), + handRightPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTrackedRemote), + handRightRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTrackedRemote), + controllerLeftPose = GetMalibuControllerPose(OVRInput.Controller.LTrackedRemote), + controllerRightPose = GetMalibuControllerPose(OVRInput.Controller.RTrackedRemote), + }; + } + else + { + CurrentPose = new PoseFrame + { + voiceAmplitude = voiceAmplitude, + headPosition = centerEyePosition, + headRotation = centerEyeRotation, + handLeftPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.LTouch), + handLeftRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.LTouch), + handRightPosition = OVRInput.GetLocalControllerPosition(OVRInput.Controller.RTouch), + handRightRotation = OVRInput.GetLocalControllerRotation(OVRInput.Controller.RTouch), + controllerLeftPose = GetControllerPose(OVRInput.Controller.LTouch), + controllerRightPose = GetControllerPose(OVRInput.Controller.RTouch), + }; + } + } + + public override void UpdateTransforms(IntPtr sdkAvatar) + { + CalculateCurrentPose(); + UpdateTransformsFromPose(sdkAvatar); + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs.meta new file mode 100644 index 0000000..2183c86 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarLocalDriver.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: ac27124318cf8e84aa7350c2ac1cdb80 +timeCreated: 1464049705 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs new file mode 100644 index 0000000..033e6a6 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs @@ -0,0 +1,45 @@ +using UnityEngine; + +namespace Oculus.Avatar +{ + public static class AvatarLogger + { + public const string LogAvatar = "[Avatars] - "; + public const string Tab = " "; + + [System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"), + System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_BASIC")] + public static void Log(string logMsg) + { + Debug.Log(LogAvatar + logMsg); + } + + [System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"), + System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_BASIC")] + public static void Log(string logMsg, Object context) + { + Debug.Log(LogAvatar + logMsg , context); + } + + [System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"), + System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_WARNING")] + public static void LogWarning(string logMsg) + { + Debug.LogWarning(LogAvatar + logMsg); + } + + [System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"), + System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_ERROR")] + public static void LogError(string logMsg) + { + Debug.LogError(LogAvatar + logMsg); + } + + [System.Diagnostics.Conditional("ENABLE_AVATAR_LOGS"), + System.Diagnostics.Conditional("ENABLE_AVATAR_LOG_ERROR")] + public static void LogError(string logMsg, Object context) + { + Debug.LogError(LogAvatar + logMsg, context); + } + }; +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs.meta new file mode 100644 index 0000000..e2799c6 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarLogger.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6d391500bc1e8da42a41ef796dd22ed0 +timeCreated: 1519433181 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs new file mode 100644 index 0000000..4c49aa9 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs @@ -0,0 +1,430 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.Rendering; + +public class OvrAvatarMaterialManager : MonoBehaviour +{ + private Renderer TargetRenderer; + private AvatarTextureArrayProperties[] TextureArrays; + + public enum TextureType + { + DiffuseTextures = 0, + NormalMaps, + RoughnessMaps, + + Count + } + + // Material properties required to render a single component + public struct AvatarComponentMaterialProperties + { + public ovrAvatarBodyPartType TypeIndex; + public Color Color; + public Texture2D[] Textures; + public float DiffuseIntensity; + public float RimIntensity; + public float ReflectionIntensity; + } + + // Texture arrays + public struct AvatarTextureArrayProperties + { + public Texture2D[] Textures; + public Texture2DArray TextureArray; + } + + // Material property arrays that are pushed to the shader + public struct AvatarMaterialPropertyBlock + { + public Vector4[] Colors; + public float[] DiffuseIntensities; + public float[] RimIntensities; + public float[] ReflectionIntensities; + } + + private readonly string[] TextureTypeToShaderProperties = + { + "_MainTex", // TextureType.DiffuseTextures = 0 + "_NormalMap", // TextureType.NormalMaps + "_RoughnessMap" // TextureType.RoughnessMaps + }; + + // Container class for all the data relating to an avatar material description + [System.Serializable] + public class AvatarMaterialConfig + { + public AvatarComponentMaterialProperties[] ComponentMaterialProperties; + public AvatarMaterialPropertyBlock MaterialPropertyBlock; + } + + // Local config that this manager instance will render + public AvatarMaterialConfig LocalAvatarConfig = new AvatarMaterialConfig(); + + public List ReflectionProbes = new List(); + + // Cache the previous shader when swapping in the loading shader. + private Shader CombinedShader; + // Shader properties + public static string AVATAR_SHADER_LOADER = "OvrAvatar/Avatar_Mobile_Loader"; + public static string AVATAR_SHADER_MAINTEX = "_MainTex"; + public static string AVATAR_SHADER_NORMALMAP = "_NormalMap"; + public static string AVATAR_SHADER_ROUGHNESSMAP = "_RoughnessMap"; + public static string AVATAR_SHADER_COLOR = "_BaseColor"; + public static string AVATAR_SHADER_DIFFUSEINTENSITY = "_DiffuseIntensity"; + public static string AVATAR_SHADER_RIMINTENSITY = "_RimIntensity"; + public static string AVATAR_SHADER_REFLECTIONINTENSITY = "_ReflectionIntensity"; + public static string AVATAR_SHADER_CUBEMAP = "_Cubemap"; + public static string AVATAR_SHADER_ALPHA = "_Alpha"; + public static string AVATAR_SHADER_LOADING_DIMMER = "_LoadingDimmer"; + + public static string AVATAR_SHADER_IRIS_COLOR = "_MaskColorIris"; + public static string AVATAR_SHADER_LIP_COLOR = "_MaskColorLips"; + public static string AVATAR_SHADER_BROW_COLOR = "_MaskColorBrows"; + public static string AVATAR_SHADER_LASH_COLOR = "_MaskColorLashes"; + public static string AVATAR_SHADER_SCLERA_COLOR = "_MaskColorSclera"; + public static string AVATAR_SHADER_GUM_COLOR = "_MaskColorGums"; + public static string AVATAR_SHADER_TEETH_COLOR = "_MaskColorTeeth"; + public static string AVATAR_SHADER_LIP_SMOOTHNESS = "_LipSmoothness"; + + // Diffuse Intensity constants: body, clothes, eyewear, hair, beard + public static float[] DiffuseIntensities = new[] {0.3f, 0.1f, 0f, 0.15f, 0.15f}; + // Rim Intensity constants: body, clothes, eyewear, hair, beard + public static float[] RimIntensities = new[] {5f, 2f, 2.84f, 4f, 4f}; + // Reflection Intensity constants: body, clothes, eyewear, hair, beard + public static float[] ReflectionIntensities = new[] {0f, 0.3f, 0.4f, 0f, 0f}; + + // Loading animation + private const float LOADING_ANIMATION_AMPLITUDE = 0.5f; + private const float LOADING_ANIMATION_PERIOD = 0.35f; + private const float LOADING_ANIMATION_CURVE_SCALE = 0.25f; + private const float LOADING_ANIMATION_DIMMER_MIN = 0.3f; + + public void CreateTextureArrays() + { + const int componentCount = (int)ovrAvatarBodyPartType.Count; + const int textureTypeCount = (int)TextureType.Count; + + LocalAvatarConfig.ComponentMaterialProperties = new AvatarComponentMaterialProperties[componentCount]; + LocalAvatarConfig.MaterialPropertyBlock.Colors = new Vector4[componentCount]; + LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities = new float[componentCount]; + LocalAvatarConfig.MaterialPropertyBlock.RimIntensities = new float[componentCount]; + LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities = new float[componentCount]; + + for (int i = 0; i < LocalAvatarConfig.ComponentMaterialProperties.Length; ++i) + { + LocalAvatarConfig.ComponentMaterialProperties[i].Textures = new Texture2D[textureTypeCount]; + } + + TextureArrays = new AvatarTextureArrayProperties[textureTypeCount]; + } + + public void SetRenderer(Renderer renderer) + { + TargetRenderer = renderer; + TargetRenderer.GetClosestReflectionProbes(ReflectionProbes); + } + + public void OnCombinedMeshReady() + { + InitTextureArrays(); + SetMaterialPropertyBlock(); + // Callback to delete texture set once the avatar is fully loaded + StartCoroutine(RunLoadingAnimation(DeleteTextureSet)); + } + + // Add a texture ID so that it's managed for deletion + public void AddTextureIDToTextureManager(ulong assetID, bool isSingleComponent) + { + OvrAvatarSDKManager.Instance.GetTextureCopyManager().AddTextureIDToTextureSet( + GetInstanceID(), assetID, isSingleComponent); + } + + // Once avatar loading is completed trigger the texture set for deletion + private void DeleteTextureSet() + { + OvrAvatarSDKManager.Instance.GetTextureCopyManager().DeleteTextureSet(GetInstanceID()); + } + + // Prepare texture arrays and copy to GPU + public void InitTextureArrays() + { + var localProps = LocalAvatarConfig.ComponentMaterialProperties[0]; + + for (int i = 0; i < TextureArrays.Length && i < localProps.Textures.Length; i++) + { + TextureArrays[i].TextureArray = new Texture2DArray( + localProps.Textures[0].height, localProps.Textures[0].width, + LocalAvatarConfig.ComponentMaterialProperties.Length, + localProps.Textures[0].format, + true, + QualitySettings.activeColorSpace == ColorSpace.Gamma ? false : true + ) { filterMode = FilterMode.Trilinear, + //Can probably get away with 4 for roughness maps as well, once we switch + //to BC7/ASTC4x4 texture compression. + anisoLevel = (TextureType)i == TextureType.RoughnessMaps ? 16 : 4 }; + //So a name shows up in Renderdoc + TextureArrays[i].TextureArray.name = string.Format("Texture Array Type: {0}", (TextureType)i); + + TextureArrays[i].Textures + = new Texture2D[LocalAvatarConfig.ComponentMaterialProperties.Length]; + + for (int j = 0; j < LocalAvatarConfig.ComponentMaterialProperties.Length; j++) + { + TextureArrays[i].Textures[j] + = LocalAvatarConfig.ComponentMaterialProperties[j].Textures[i]; + //So a name shows up in Renderdoc + TextureArrays[i].Textures[j].name = string.Format("Texture Type: {0} Component: {1}", (TextureType)i, j); + } + + ProcessTexturesWithMips( + TextureArrays[i].Textures, + localProps.Textures[i].height, + TextureArrays[i].TextureArray); + } + } + + private void ProcessTexturesWithMips( + Texture2D[] textures, + int texArrayResolution, + Texture2DArray texArray) + { + for (int i = 0; i < textures.Length; i++) + { + int currentMipSize = texArrayResolution; + int correctNumberOfMips = textures[i].mipmapCount - 1; + + // Add mips to copyTexture queue in low-high order from correctNumberOfMips..0 + for (int mipLevel = correctNumberOfMips; mipLevel >= 0; mipLevel--) + { + int mipSize = texArrayResolution / currentMipSize; + OvrAvatarSDKManager.Instance.GetTextureCopyManager().CopyTexture( + textures[i], + texArray, + mipLevel, + mipSize, + i, + false); + + currentMipSize /= 2; + } + } + } + + private void SetMaterialPropertyBlock() + { + if (TargetRenderer != null) + { + for (int i = 0; i < LocalAvatarConfig.ComponentMaterialProperties.Length; i++) + { + LocalAvatarConfig.MaterialPropertyBlock.Colors[i] + = LocalAvatarConfig.ComponentMaterialProperties[i].Color; + LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities[i] = DiffuseIntensities[i]; + LocalAvatarConfig.MaterialPropertyBlock.RimIntensities[i] = RimIntensities[i]; + LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities[i] = ReflectionIntensities[i]; + } + } + } + + private void ApplyMaterialPropertyBlock() + { + MaterialPropertyBlock materialPropertyBlock = new MaterialPropertyBlock(); + materialPropertyBlock.SetVectorArray(AVATAR_SHADER_COLOR, + LocalAvatarConfig.MaterialPropertyBlock.Colors); + materialPropertyBlock.SetFloatArray(AVATAR_SHADER_DIFFUSEINTENSITY, + LocalAvatarConfig.MaterialPropertyBlock.DiffuseIntensities); + materialPropertyBlock.SetFloatArray(AVATAR_SHADER_RIMINTENSITY, + LocalAvatarConfig.MaterialPropertyBlock.RimIntensities); + materialPropertyBlock.SetFloatArray(AVATAR_SHADER_REFLECTIONINTENSITY, + LocalAvatarConfig.MaterialPropertyBlock.ReflectionIntensities); + TargetRenderer.GetClosestReflectionProbes(ReflectionProbes); + + if (ReflectionProbes != null && ReflectionProbes.Count > 0 && ReflectionProbes[0].probe.texture != null) + { + materialPropertyBlock.SetTexture(AVATAR_SHADER_CUBEMAP, ReflectionProbes[0].probe.texture); + } + + for (int i = 0; i < TextureArrays.Length; i++) + { + materialPropertyBlock.SetTexture(TextureTypeToShaderProperties[i], + TextureArrays[(int)(TextureType)i].TextureArray); + } + + TargetRenderer.SetPropertyBlock(materialPropertyBlock); + } + + // Return a component type based on name + public static ovrAvatarBodyPartType GetComponentType(string objectName) + { + if (objectName.Contains("0")) + { + return ovrAvatarBodyPartType.Body; + } + else if (objectName.Contains("1")) + { + return ovrAvatarBodyPartType.Clothing; + } + else if (objectName.Contains("2")) + { + return ovrAvatarBodyPartType.Eyewear; + } + else if (objectName.Contains("3")) + { + return ovrAvatarBodyPartType.Hair; + } + else if (objectName.Contains("4")) + { + return ovrAvatarBodyPartType.Beard; + } + + return ovrAvatarBodyPartType.Count; + } + + UInt64 GetTextureIDForType(ovrAvatarPBSMaterialState materialState, TextureType type) + { + if (type == TextureType.DiffuseTextures) + { + return materialState.albedoTextureID; + } + else if (type == TextureType.NormalMaps) + { + return materialState.normalTextureID; + } + else if (type == TextureType.RoughnessMaps) + { + return materialState.metallicnessTextureID; + } + + return 0; + } + + public void ValidateTextures(ovrAvatarPBSMaterialState[] materialStates) + { + var props = LocalAvatarConfig.ComponentMaterialProperties; + + int[] heights = new int[(int)TextureType.Count]; + TextureFormat[] formats = new TextureFormat[(int)TextureType.Count]; + + for (var propIndex = 0; propIndex < props.Length; propIndex++) + { + for (var index = 0; index < props[propIndex].Textures.Length; index++) + { + if (props[propIndex].Textures[index] == null) + { + throw new System.Exception( + props[propIndex].TypeIndex.ToString() + + "Invalid: " + + ((TextureType)index).ToString()); + } + + heights[index] = props[propIndex].Textures[index].height; + formats[index] = props[propIndex].Textures[index].format; + } + } + + for (int textureIndex = 0; textureIndex < (int)TextureType.Count; textureIndex++) + { + for (var propIndex = 1; propIndex < props.Length; propIndex++) + { + if (props[propIndex - 1].Textures[textureIndex].height + != props[propIndex].Textures[textureIndex].height) + { + throw new System.Exception( + props[propIndex].TypeIndex.ToString() + + " Mismatching Resolutions: " + + ((TextureType)textureIndex).ToString() + + " " + + props[propIndex - 1].Textures[textureIndex].height + + " (ID: " + + GetTextureIDForType(materialStates[propIndex - 1], (TextureType)textureIndex) + + ") vs " + + props[propIndex].Textures[textureIndex].height + + " (ID: " + + GetTextureIDForType(materialStates[propIndex], (TextureType)textureIndex) + + ") Ensure you are using ASTC texture compression on Android or turn off CombineMeshes"); + } + + if (props[propIndex - 1].Textures[textureIndex].format + != props[propIndex].Textures[textureIndex].format) + { + throw new System.Exception( + props[propIndex].TypeIndex.ToString() + + " Mismatching Formats: " + + ((TextureType)textureIndex).ToString() + + " " + + props[propIndex - 1].Textures[textureIndex].format + + " (ID: " + + GetTextureIDForType(materialStates[propIndex - 1], (TextureType)textureIndex) + + ") vs " + + props[propIndex].Textures[textureIndex].format + + " (ID: " + + GetTextureIDForType(materialStates[propIndex], (TextureType)textureIndex) + + ") Ensure you are using ASTC texture compression on Android or turn off CombineMeshes"); + } + } + } + } + + // Loading animation on the Dimmer properyt + // Smooth sine lerp every 0.3 seconds between 0.25 and 0.5 + private IEnumerator RunLoadingAnimation(Action callBack) + { + // Set the material to single component while the avatar loads + CombinedShader = TargetRenderer.sharedMaterial.shader; + + // Save shader properties + int srcBlend = TargetRenderer.sharedMaterial.GetInt("_SrcBlend"); + int dstBlend = TargetRenderer.sharedMaterial.GetInt("_DstBlend"); + string lightModeTag = TargetRenderer.sharedMaterial.GetTag("LightMode", false); + string renderTypeTag = TargetRenderer.sharedMaterial.GetTag("RenderType", false); + string renderQueueTag = TargetRenderer.sharedMaterial.GetTag("Queue", false); + string ignoreProjectorTag = TargetRenderer.sharedMaterial.GetTag("IgnoreProjector", false); + int renderQueue = TargetRenderer.sharedMaterial.renderQueue; + bool transparentQueue = TargetRenderer.sharedMaterial.IsKeywordEnabled("_ALPHATEST_ON"); + + // Swap in loading shader + TargetRenderer.sharedMaterial.shader = Shader.Find(AVATAR_SHADER_LOADER); + TargetRenderer.sharedMaterial.SetColor(AVATAR_SHADER_COLOR, Color.white); + + while (OvrAvatarSDKManager.Instance.GetTextureCopyManager().GetTextureCount() > 0) + { + float distance = (LOADING_ANIMATION_AMPLITUDE * Mathf.Sin(Time.timeSinceLevelLoad / LOADING_ANIMATION_PERIOD) + + LOADING_ANIMATION_AMPLITUDE) * (LOADING_ANIMATION_CURVE_SCALE) + LOADING_ANIMATION_DIMMER_MIN; + TargetRenderer.sharedMaterial.SetFloat(AVATAR_SHADER_LOADING_DIMMER, distance); + yield return null; + } + // Swap back main shader + TargetRenderer.sharedMaterial.SetFloat(AVATAR_SHADER_LOADING_DIMMER, 1f); + TargetRenderer.sharedMaterial.shader = CombinedShader; + + // Restore shader properties + TargetRenderer.sharedMaterial.SetInt("_SrcBlend", srcBlend); + TargetRenderer.sharedMaterial.SetInt("_DstBlend", dstBlend); + TargetRenderer.sharedMaterial.SetOverrideTag("LightMode", lightModeTag); + TargetRenderer.sharedMaterial.SetOverrideTag("RenderType", renderTypeTag); + TargetRenderer.sharedMaterial.SetOverrideTag("Queue", renderQueueTag); + TargetRenderer.sharedMaterial.SetOverrideTag("IgnoreProjector", ignoreProjectorTag); + if (transparentQueue) + { + TargetRenderer.sharedMaterial.EnableKeyword("_ALPHATEST_ON"); + TargetRenderer.sharedMaterial.EnableKeyword("_ALPHABLEND_ON"); + TargetRenderer.sharedMaterial.EnableKeyword("_ALPHAPREMULTIPLY_ON"); + } + else + { + TargetRenderer.sharedMaterial.DisableKeyword("_ALPHATEST_ON"); + TargetRenderer.sharedMaterial.DisableKeyword("_ALPHABLEND_ON"); + TargetRenderer.sharedMaterial.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + } + TargetRenderer.sharedMaterial.renderQueue = renderQueue; + + ApplyMaterialPropertyBlock(); + + if (callBack != null) + { + callBack(); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs.meta new file mode 100644 index 0000000..14d13c1 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarMaterialManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: a139d83bf6796734db220df8a5bfacbd +timeCreated: 1518209612 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs new file mode 100644 index 0000000..7a3c641 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs @@ -0,0 +1,231 @@ +using UnityEngine; +using System.Collections; +using System.IO; +using System.Collections.Generic; +using System; + +public class OvrAvatarPacket +{ + // Used with SDK driven packet flow + public IntPtr ovrNativePacket = IntPtr.Zero; + + // =============================================================== + // All code below used for unity only pose blending option. + // =============================================================== + List frameTimes = new List(); + List frames = new List(); + List encodedAudioPackets = new List(); + + public float Duration { get { return frameTimes[frameTimes.Count - 1]; } } + public OvrAvatarDriver.PoseFrame FinalFrame { get { return frames[frames.Count - 1]; } } + + public OvrAvatarPacket() + { + } + + public OvrAvatarPacket(OvrAvatarDriver.PoseFrame initialPose) + { + frameTimes.Add(0.0f); + frames.Add(initialPose); + } + + OvrAvatarPacket(List frameTimes, List frames, List audioPackets) + { + this.frameTimes = frameTimes; + this.frames = frames; + } + + public void AddFrame(OvrAvatarDriver.PoseFrame frame, float deltaSeconds) + { + frameTimes.Add(Duration + deltaSeconds); + frames.Add(frame); + } + + public OvrAvatarDriver.PoseFrame GetPoseFrame(float seconds) + { + if (frames.Count == 1) + { + return frames[0]; + } + + // This can be replaced with a more efficient binary search + int tailIndex = 1; + while (tailIndex < frameTimes.Count && frameTimes[tailIndex] < seconds) + { + ++tailIndex; + } + OvrAvatarDriver.PoseFrame a = frames[tailIndex - 1]; + OvrAvatarDriver.PoseFrame b = frames[tailIndex]; + float aTime = frameTimes[tailIndex - 1]; + float bTime = frameTimes[tailIndex]; + float t = (seconds - aTime) / (bTime - aTime); + return OvrAvatarDriver.PoseFrame.Interpolate(a, b, t); + } + + public static OvrAvatarPacket Read(Stream stream) + { + BinaryReader reader = new BinaryReader(stream); + + // Todo: bounds check frame count + int frameCount = reader.ReadInt32(); + List frameTimes = new List(frameCount); + for (int i = 0; i < frameCount; ++i) + { + frameTimes.Add(reader.ReadSingle()); + } + List frames = new List(frameCount); + for (int i = 0; i < frameCount; ++i) + { + frames.Add(reader.ReadPoseFrame()); + } + + // Todo: bounds check audio packet count + int audioPacketCount = reader.ReadInt32(); + List audioPackets = new List(audioPacketCount); + for (int i = 0; i < audioPacketCount; ++i) + { + int audioPacketSize = reader.ReadInt32(); + byte[] audioPacket = reader.ReadBytes(audioPacketSize); + audioPackets.Add(audioPacket); + } + + return new OvrAvatarPacket(frameTimes, frames, audioPackets); + } + + public void Write(Stream stream) + { + BinaryWriter writer = new BinaryWriter(stream); + + // Write all of the frames + int frameCount = frameTimes.Count; + writer.Write(frameCount); + for (int i = 0; i < frameCount; ++i) + { + writer.Write(frameTimes[i]); + } + for (int i = 0; i < frameCount; ++i) + { + OvrAvatarDriver.PoseFrame frame = frames[i]; + writer.Write(frame); + } + + // Write all of the encoded audio packets + int audioPacketCount = encodedAudioPackets.Count; + writer.Write(audioPacketCount); + for (int i = 0; i < audioPacketCount; ++i) + { + byte[] packet = encodedAudioPackets[i]; + writer.Write(packet.Length); + writer.Write(packet); + } + } +} + +static class BinaryWriterExtensions +{ + public static void Write(this BinaryWriter writer, OvrAvatarDriver.PoseFrame frame) + { + writer.Write(frame.headPosition); + writer.Write(frame.headRotation); + writer.Write(frame.handLeftPosition); + writer.Write(frame.handLeftRotation); + writer.Write(frame.handRightPosition); + writer.Write(frame.handRightRotation); + writer.Write(frame.voiceAmplitude); + + writer.Write(frame.controllerLeftPose); + writer.Write(frame.controllerRightPose); + } + + public static void Write(this BinaryWriter writer, Vector3 vec3) + { + writer.Write(vec3.x); + writer.Write(vec3.y); + writer.Write(vec3.z); + } + + public static void Write(this BinaryWriter writer, Vector2 vec2) + { + writer.Write(vec2.x); + writer.Write(vec2.y); + } + + public static void Write(this BinaryWriter writer, Quaternion quat) + { + writer.Write(quat.x); + writer.Write(quat.y); + writer.Write(quat.z); + writer.Write(quat.w); + } + public static void Write(this BinaryWriter writer, OvrAvatarDriver.ControllerPose pose) + { + writer.Write((uint)pose.buttons); + writer.Write((uint)pose.touches); + writer.Write(pose.joystickPosition); + writer.Write(pose.indexTrigger); + writer.Write(pose.handTrigger); + writer.Write(pose.isActive); + } +} + +static class BinaryReaderExtensions +{ + public static OvrAvatarDriver.PoseFrame ReadPoseFrame(this BinaryReader reader) + { + return new OvrAvatarDriver.PoseFrame + { + headPosition = reader.ReadVector3(), + headRotation = reader.ReadQuaternion(), + handLeftPosition = reader.ReadVector3(), + handLeftRotation = reader.ReadQuaternion(), + handRightPosition = reader.ReadVector3(), + handRightRotation = reader.ReadQuaternion(), + voiceAmplitude = reader.ReadSingle(), + + controllerLeftPose = reader.ReadControllerPose(), + controllerRightPose = reader.ReadControllerPose(), + }; + } + + public static Vector2 ReadVector2(this BinaryReader reader) + { + return new Vector2 + { + x = reader.ReadSingle(), + y = reader.ReadSingle() + }; + } + + public static Vector3 ReadVector3(this BinaryReader reader) + { + return new Vector3 + { + x = reader.ReadSingle(), + y = reader.ReadSingle(), + z = reader.ReadSingle() + }; + } + + public static Quaternion ReadQuaternion(this BinaryReader reader) + { + return new Quaternion + { + x = reader.ReadSingle(), + y = reader.ReadSingle(), + z = reader.ReadSingle(), + w = reader.ReadSingle(), + }; + } + public static OvrAvatarDriver.ControllerPose ReadControllerPose(this BinaryReader reader) + { + return new OvrAvatarDriver.ControllerPose + { + buttons = (ovrAvatarButton)reader.ReadUInt32(), + touches = (ovrAvatarTouch)reader.ReadUInt32(), + joystickPosition = reader.ReadVector2(), + indexTrigger = reader.ReadSingle(), + handTrigger = reader.ReadSingle(), + isActive = reader.ReadBoolean(), + }; + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs.meta new file mode 100644 index 0000000..9c74783 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarPacket.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 3b7dd866fbed2654e838d772129dc70c +timeCreated: 1464197799 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs new file mode 100644 index 0000000..0681632 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs @@ -0,0 +1,121 @@ +using UnityEngine; +using System.Collections; +using System; +using System.Collections.Generic; +using Oculus.Avatar; + +public class OvrAvatarRemoteDriver : OvrAvatarDriver +{ + Queue packetQueue = new Queue(); + + IntPtr CurrentSDKPacket = IntPtr.Zero; + float CurrentPacketTime = 0f; + + const int MinPacketQueue = 1; + const int MaxPacketQueue = 4; + + int CurrentSequence = -1; + + // Used for legacy Unity only packet blending + bool isStreaming = false; + OvrAvatarPacket currentPacket = null; + + public void QueuePacket(int sequence, OvrAvatarPacket packet) + { + if (sequence > CurrentSequence) + { + CurrentSequence = sequence; + packetQueue.Enqueue(packet); + } + } + + public override void UpdateTransforms(IntPtr sdkAvatar) + { + switch(Mode) + { + case PacketMode.SDK: + UpdateFromSDKPacket(sdkAvatar); + break; + case PacketMode.Unity: + UpdateFromUnityPacket(sdkAvatar); + break; + default: + break; + } + } + + private void UpdateFromSDKPacket(IntPtr sdkAvatar) + { + + if (CurrentSDKPacket == IntPtr.Zero && packetQueue.Count >= MinPacketQueue) + { + CurrentSDKPacket = packetQueue.Dequeue().ovrNativePacket; + } + + if (CurrentSDKPacket != IntPtr.Zero) + { + float PacketDuration = CAPI.ovrAvatarPacket_GetDurationSeconds(CurrentSDKPacket); + CAPI.ovrAvatar_UpdatePoseFromPacket(sdkAvatar, CurrentSDKPacket, Mathf.Min(PacketDuration, CurrentPacketTime)); + CurrentPacketTime += Time.deltaTime; + + if (CurrentPacketTime > PacketDuration) + { + CAPI.ovrAvatarPacket_Free(CurrentSDKPacket); + CurrentSDKPacket = IntPtr.Zero; + CurrentPacketTime = CurrentPacketTime - PacketDuration; + + //Throw away packets deemed too old. + while (packetQueue.Count > MaxPacketQueue) + { + packetQueue.Dequeue(); + } + } + } + } + + private void UpdateFromUnityPacket(IntPtr sdkAvatar) + { + // If we're not currently streaming, check to see if we've buffered enough + if (!isStreaming && packetQueue.Count > MinPacketQueue) + { + currentPacket = packetQueue.Dequeue(); + isStreaming = true; + } + + // If we are streaming, update our pose + if (isStreaming) + { + CurrentPacketTime += Time.deltaTime; + + // If we've elapsed past our current packet, advance + while (CurrentPacketTime > currentPacket.Duration) + { + + // If we're out of packets, stop streaming and + // lock to the final frame + if (packetQueue.Count == 0) + { + CurrentPose = currentPacket.FinalFrame; + CurrentPacketTime = 0.0f; + currentPacket = null; + isStreaming = false; + return; + } + + while (packetQueue.Count > MaxPacketQueue) + { + packetQueue.Dequeue(); + } + + // Otherwise, dequeue the next packet + CurrentPacketTime -= currentPacket.Duration; + currentPacket = packetQueue.Dequeue(); + } + + // Compute the pose based on our current time offset in the packet + CurrentPose = currentPacket.GetPoseFrame(CurrentPacketTime); + + UpdateTransformsFromPose(sdkAvatar); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs.meta new file mode 100644 index 0000000..cc18854 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarRemoteDriver.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c198a42a3843ca04fa633b60f428ff51 +timeCreated: 1464302604 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs new file mode 100644 index 0000000..0f0edf8 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs @@ -0,0 +1,135 @@ +using UnityEngine; +using System.Collections; +using System.Collections.Generic; +using System; +using Oculus.Avatar; + +public class OvrAvatarRenderComponent : MonoBehaviour { + + private bool firstSkinnedUpdate = true; + public SkinnedMeshRenderer mesh; + public Transform[] bones; + bool isBodyComponent = false; + + protected void UpdateActive(OvrAvatar avatar, ovrAvatarVisibilityFlags mask) + { + bool doActiveHack = isBodyComponent && avatar.EnableExpressive && avatar.ShowFirstPerson && !avatar.ShowThirdPerson; + if (doActiveHack) + { + bool showFirstPerson = (mask & ovrAvatarVisibilityFlags.FirstPerson) != 0; + bool showThirdPerson = (mask & ovrAvatarVisibilityFlags.ThirdPerson) != 0; + gameObject.SetActive(showThirdPerson || showThirdPerson); + + if (!showFirstPerson) + { + mesh.enabled = false; + } + } + else + { + bool active = avatar.ShowFirstPerson && (mask & ovrAvatarVisibilityFlags.FirstPerson) != 0; + active |= avatar.ShowThirdPerson && (mask & ovrAvatarVisibilityFlags.ThirdPerson) != 0; + this.gameObject.SetActive(active); + mesh.enabled = active; + } + } + + protected SkinnedMeshRenderer CreateSkinnedMesh(ulong assetID, ovrAvatarVisibilityFlags visibilityMask, int thirdPersonLayer, int firstPersonLayer) + { + isBodyComponent = name.Contains("body"); + + OvrAvatarAssetMesh meshAsset = (OvrAvatarAssetMesh)OvrAvatarSDKManager.Instance.GetAsset(assetID); + if (meshAsset == null) + { + throw new Exception("Couldn't find mesh for asset " + assetID); + } + if ((visibilityMask & ovrAvatarVisibilityFlags.ThirdPerson) != 0) + { + this.gameObject.layer = thirdPersonLayer; + } + else + { + this.gameObject.layer = firstPersonLayer; + } + SkinnedMeshRenderer renderer = meshAsset.CreateSkinnedMeshRendererOnObject(gameObject); +#if UNITY_ANDROID + renderer.quality = SkinQuality.Bone2; +#else + renderer.quality = SkinQuality.Bone4; +#endif + renderer.updateWhenOffscreen = true; + if ((visibilityMask & ovrAvatarVisibilityFlags.SelfOccluding) == 0) + { + renderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; + } + + gameObject.SetActive(false); + + return renderer; + } + + protected void UpdateSkinnedMesh(OvrAvatar avatar, Transform[] bones, ovrAvatarTransform localTransform, ovrAvatarVisibilityFlags visibilityMask, IntPtr renderPart) + { + UpdateActive(avatar, visibilityMask); + OvrAvatar.ConvertTransform(localTransform, this.transform); + ovrAvatarRenderPartType type = CAPI.ovrAvatarRenderPart_GetType(renderPart); + UInt64 dirtyJoints; + switch (type) + { + case ovrAvatarRenderPartType.SkinnedMeshRender: + dirtyJoints = CAPI.ovrAvatarSkinnedMeshRender_GetDirtyJoints(renderPart); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS: + dirtyJoints = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetDirtyJoints(renderPart); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2: + dirtyJoints = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetDirtyJoints(renderPart); + break; + default: + throw new Exception("Unhandled render part type: " + type); + } + for (UInt32 i = 0; i < 64; i++) + { + UInt64 dirtyMask = (ulong)1 << (int)i; + // We need to make sure that we fully update the initial position of + // Skinned mesh renderers, then, thereafter, we can only update dirty joints + if ((firstSkinnedUpdate && i < bones.Length) || + (dirtyMask & dirtyJoints) != 0) + { + //This joint is dirty and needs to be updated + Transform targetBone = bones[i]; + ovrAvatarTransform transform; + switch (type) + { + case ovrAvatarRenderPartType.SkinnedMeshRender: + transform = CAPI.ovrAvatarSkinnedMeshRender_GetJointTransform(renderPart, i); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS: + transform = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetJointTransform(renderPart, i); + break; + case ovrAvatarRenderPartType.SkinnedMeshRenderPBS_V2: + transform = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetJointTransform(renderPart, i); + break; + default: + throw new Exception("Unhandled render part type: " + type); + } + OvrAvatar.ConvertTransform(transform, targetBone); + } + } + + firstSkinnedUpdate = false; + } + + protected Material CreateAvatarMaterial(string name, Shader shader) + { + if (shader == null) + { + throw new Exception("No shader provided for avatar material."); + } + Material mat = new Material(shader); + mat.name = name; + return mat; + } + + +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs.meta new file mode 100644 index 0000000..5957b5e --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarRenderComponent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 6a9e8691abb99884880df5ecada5e4d8 +timeCreated: 1479155394 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs new file mode 100644 index 0000000..3e8e3c1 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs @@ -0,0 +1,1663 @@ +using UnityEngine; +using System; +using System.Runtime.InteropServices; +using AOT; +using Oculus.Avatar; + +//This needs to be the csharp equivalent of ovrAvatarCapabilities in OVR_Avatar.h +[Flags] +public enum ovrAvatarCapabilities +{ + Body = 1 << 0, + Hands = 1 << 1, + Base = 1 << 2, + BodyTilt = 1 << 4, + Expressive = 1 << 5, + All = -1 +}; + +// This needs to be the csharp equivalent of ovrAvatarMessageType in OVR_Avatar.h +public enum ovrAvatarMessageType { + AvatarSpecification, + AssetLoaded, + Count +}; + +// This needs to be the csharp equivalent of ovrAvatarMessage_AvatarSpecification in OVR_Avatar.h +public struct ovrAvatarMessage_AvatarSpecification { + public IntPtr avatarSpec; //ovrAvatarSpecification*, opaque pointer + public UInt64 oculusUserID; +}; + +// This needs to be the csharp equivalent of ovrAvatarMessage_AssetLoaded in OVR_Avatar.h +public struct ovrAvatarMessage_AssetLoaded { + public UInt64 assetID; + public IntPtr asset; //ovrAvatarAsset*, opaque pointer +}; + +// This needs to be the csharp equivalent of ovrAvatarAssetType in OVR_Avatar.h +public enum ovrAvatarAssetType { + Mesh, + Texture, + Pose, + Material, + CombinedMesh, + PBSMaterial, + FailedLoad, + Count +}; + +// This needs to be the csharp equivalent of ovrAvatarMeshVertex in OVR_Avatar.h +public struct ovrAvatarMeshVertex +{ + public float x; + public float y; + public float z; + public float nx; + public float ny; + public float nz; + public float tx; + public float ty; + public float tz; + public float tw; + public float u; + public float v; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] blendIndices; ///< Indices into the bind pose + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public float[] blendWeights; ///< Blend weights for each component in the bind pose +}; + +// This needs to be the csharp equivalent of ovrAvatarMeshVertex in OVR_Avatar.h +public struct ovrAvatarMeshVertexV2 +{ + public float x; + public float y; + public float z; + public float nx; + public float ny; + public float nz; + public float tx; + public float ty; + public float tz; + public float tw; + public float u; + public float v; + public float r; + public float g; + public float b; + public float a; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public byte[] blendIndices; ///< Indices into the bind pose + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] + public float[] blendWeights; ///< Blend weights for each component in the bind pose +}; + +// This needs to be the csharp equivalent of ovrAvatarMeshVertex in OVR_Avatar.h +public struct ovrAvatarBlendVertex +{ + public float x; + public float y; + public float z; + public float nx; + public float ny; + public float nz; + public float tx; + public float ty; + public float tz; +}; + +// This needs to be the csharp equivalent of ovrAvatarMeshAssetData in OVR_Avatar.h +public struct ovrAvatarMeshAssetData +{ + public UInt32 vertexCount; + public IntPtr vertexBuffer; //const ovrAvatarMeshVertex* + public UInt32 indexCount; + public IntPtr indexBuffer; //const uint16t* + public ovrAvatarSkinnedMeshPose skinnedBindPose; +}; + +/// Mesh Asset Data V2 +/// +public struct ovrAvatarMeshAssetDataV2 +{ + public UInt32 vertexCount; + public IntPtr vertexBuffer; //const ovrAvatarMeshVertexV2* + public UInt32 indexCount; + public IntPtr indexBuffer; //const uint16t* + public ovrAvatarSkinnedMeshPose skinnedBindPose; +}; + +// This needs to be the csharp equivalent of ovrAvatarTextureFormat in OVR_Avatar.h +public enum ovrAvatarTextureFormat { + RGB24, + DXT1, + DXT5, + ASTC_RGB_6x6, + ASTC_RGB_6x6_MIPMAPS, + Count +}; + +// This needs to be the csharp equivalent of ovrAvatarTextureAssetData in OVR_Avatar.h +public struct ovrAvatarTextureAssetData { + public ovrAvatarTextureFormat format; + public UInt32 sizeX; + public UInt32 sizeY; + public UInt32 mipCount; + public UInt64 textureDataSize; + public IntPtr textureData; // const uint8_t* +}; + +// This needs to be the csharp equivalent of ovrAvatarRenderPartType in OVR_Avatar.h +public enum ovrAvatarRenderPartType +{ + SkinnedMeshRender, + SkinnedMeshRenderPBS, + ProjectorRender, + SkinnedMeshRenderPBS_V2, + Count +}; + +/// Avatar Logging Level +/// Matches the Android Log Levels +public enum ovrAvatarLogLevel +{ + Unknown, + Default, + Verbose, + Debug, + Info, + Warn, + Error, + Fatal, + Silent +}; + +// This needs to be the csharp equivalent of ovrAvatarTransform in OVR_Avatar.h +public struct ovrAvatarTransform +{ + public Vector3 position; + public Quaternion orientation; + public Vector3 scale; +}; + +// This needs to be the csharp equivalent of ovrAvatarButton in OVR_Avatar.h +[Flags] +public enum ovrAvatarButton +{ + One = 0x0001, + Two = 0x0002, + Three = 0x0004, + Joystick = 0x0008, +} + +// This needs to be the csharp equivalent of ovrAvatarTouch in OVR_Avatar.h +[Flags] +public enum ovrAvatarTouch +{ + One = 0x0001, + Two = 0x0002, + Joystick = 0x0004, + ThumbRest = 0x0008, + Index = 0x0010, + Pointing = 0x0040, + ThumbUp = 0x0080, +} + +// This needs to be the csharp equivalent of ovrAvatarHandInputState in OVR_Avatar.h +public struct ovrAvatarHandInputState +{ + public ovrAvatarTransform transform; + public ovrAvatarButton buttonMask; + public ovrAvatarTouch touchMask; + public float joystickX; + public float joystickY; + public float indexTrigger; + public float handTrigger; + [MarshalAs(UnmanagedType.I1)] + public bool isActive; +}; + +// This needs to be the csharp equivalent of ovrAvatarComponent in OVR_Avatar.h +public struct ovrAvatarComponent +{ + public ovrAvatarTransform transform; + public UInt32 renderPartCount; + public IntPtr renderParts; //const ovrAvatarRenderPart* const* + + [MarshalAs(UnmanagedType.LPStr)] + public string name; +}; + +struct ovrAvatarComponent_Offsets +{ + public static long transform = Marshal.OffsetOf(typeof(ovrAvatarComponent), "transform").ToInt64(); + public static Int32 renderPartCount = Marshal.OffsetOf(typeof(ovrAvatarComponent), "renderPartCount").ToInt32(); + public static Int32 renderParts = Marshal.OffsetOf(typeof(ovrAvatarComponent), "renderParts").ToInt32(); + public static Int32 name = Marshal.OffsetOf(typeof(ovrAvatarComponent), "name").ToInt32(); +}; + +// This needs to be the csharp equivalent of ovrAvatarBodyComponent in OVR_Avatar.h +public struct ovrAvatarBaseComponent +{ + public Vector3 basePosition; + public IntPtr renderComponent; //const ovrAvatarComponent* +}; + +// This needs to be the csharp equivalent of ovrAvatarBodyComponent in OVR_Avatar.h +public struct ovrAvatarBodyComponent { + public ovrAvatarTransform leftEyeTransform; + public ovrAvatarTransform rightEyeTransform; + public ovrAvatarTransform centerEyeTransform; + public IntPtr renderComponent; //const ovrAvatarComponent* +}; + +public struct ovrAvatarBodyComponent_Offsets +{ + public static long leftEyeTransform = Marshal.OffsetOf(typeof(ovrAvatarBodyComponent), "leftEyeTransform").ToInt64(); + public static long rightEyeTransform = Marshal.OffsetOf(typeof(ovrAvatarBodyComponent), "rightEyeTransform").ToInt64(); + public static long centerEyeTransform = Marshal.OffsetOf(typeof(ovrAvatarBodyComponent), "centerEyeTransform").ToInt64(); + public static long renderComponent = Marshal.OffsetOf(typeof(ovrAvatarBodyComponent), "renderComponent").ToInt64(); +}; + +// This needs to be the csharp equivalent of ovrAvatarControllerComponent in OVR_Avatar.h +public struct ovrAvatarControllerComponent +{ + public ovrAvatarHandInputState inputState; + public IntPtr renderComponent; //const ovrAvatarComponent* +}; + +// This needs to be the csharp equivalent of ovrAvatarHandComponent in OVR_Avatar.h +public struct ovrAvatarHandComponent { + public ovrAvatarHandInputState inputState; + public IntPtr renderComponent; //const ovrAvatarComponent* +}; + +// This needs to be the csharp equivalent of ovrAvatarMaterialLayerBlendMode in OVR_Avatar.h +public enum ovrAvatarMaterialLayerBlendMode{ + Add, + Multiply, + Count +}; + +// This needs to be the csharp equivalent of ovrAvatarMaterialLayerSampleMode in OVR_Avatar.h +public enum ovrAvatarMaterialLayerSampleMode{ + Color, + Texture, + TextureSingleChannel, + Parallax, + Count +}; + +// This needs to be the csharp equivalent of ovrAvatarMaterialLayerMaskType in OVR_Avatar.h +public enum ovrAvatarMaterialMaskType{ + None, + Positional, + ViewReflection, + Fresnel, + Pulse, + Count +}; + +// This needs to be the csharp equivalent of Controller Types from OVR_Avatar.h +public enum ovrAvatarControllerType +{ + Touch, + Malibu, + Go, + Quest, + + Count, +}; + +public enum ovrAvatarAssetLevelOfDetail +{ + Lowest = 1, + Medium = 3, + Highest = 5, +}; + +public enum ovrAvatarLookAndFeelVersion +{ + Unknown = -1, + One = 0, + Two = 1, +}; + +// This needs to be the csharp equivalent of ovrAvatarMaterialLayerState in OVR_Avatar.h +public struct ovrAvatarMaterialLayerState{ + public ovrAvatarMaterialLayerBlendMode blendMode; + public ovrAvatarMaterialLayerSampleMode sampleMode; + public ovrAvatarMaterialMaskType maskType; + public Vector4 layerColor; + public Vector4 sampleParameters; + public UInt64 sampleTexture; + public Vector4 sampleScaleOffset; + public Vector4 maskParameters; + public Vector4 maskAxis; + + static bool VectorEquals(Vector4 a, Vector4 b) + { + return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; + } + + public override bool Equals(object obj) + { + if (!(obj is ovrAvatarMaterialLayerState)) + { + return false; + } + ovrAvatarMaterialLayerState other = (ovrAvatarMaterialLayerState)obj; + if (blendMode != other.blendMode) return false; + if (sampleMode != other.sampleMode) return false; + if (maskType != other.maskType) return false; + if (!VectorEquals(layerColor, other.layerColor)) return false; + if (!VectorEquals(sampleParameters, other.sampleParameters)) return false; + if (sampleTexture != other.sampleTexture) return false; + if (!VectorEquals(sampleScaleOffset, other.sampleScaleOffset)) return false; + if (!VectorEquals(maskParameters, other.maskParameters)) return false; + if (!VectorEquals(maskAxis, other.maskAxis)) return false; + return true; + } + public override int GetHashCode() + { + return blendMode.GetHashCode() ^ + sampleMode.GetHashCode() ^ + maskType.GetHashCode() ^ + layerColor.GetHashCode() ^ + sampleParameters.GetHashCode() ^ + sampleTexture.GetHashCode() ^ + sampleScaleOffset.GetHashCode() ^ + maskParameters.GetHashCode() ^ + maskAxis.GetHashCode(); + } +}; + +// This needs to be the csharp equivalent of ovrAvatarMaterialState in OVR_Avatar.h +public struct ovrAvatarMaterialState +{ + public Vector4 baseColor; + public ovrAvatarMaterialMaskType baseMaskType; + public Vector4 baseMaskParameters; + public Vector4 baseMaskAxis; + public ovrAvatarMaterialLayerSampleMode sampleMode; + public UInt64 alphaMaskTextureID; + public Vector4 alphaMaskScaleOffset; + public UInt64 normalMapTextureID; + public Vector4 normalMapScaleOffset; + public UInt64 parallaxMapTextureID; + public Vector4 parallaxMapScaleOffset; + public UInt64 roughnessMapTextureID; + public Vector4 roughnessMapScaleOffset; + public UInt32 layerCount; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] + public ovrAvatarMaterialLayerState[] layers; + + static bool VectorEquals(Vector4 a, Vector4 b) + { + return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; + } + + public override bool Equals(object obj) + { + if (!(obj is ovrAvatarMaterialState)) + { + return false; + } + ovrAvatarMaterialState other = (ovrAvatarMaterialState)obj; + if (!VectorEquals(baseColor, other.baseColor)) return false; + if (baseMaskType != other.baseMaskType) return false; + if (!VectorEquals(baseMaskParameters, other.baseMaskParameters)) return false; + if (!VectorEquals(baseMaskAxis, other.baseMaskAxis)) return false; + if (sampleMode != other.sampleMode) return false; + if (alphaMaskTextureID != other.alphaMaskTextureID) return false; + if (!VectorEquals(alphaMaskScaleOffset, other.alphaMaskScaleOffset)) return false; + if (normalMapTextureID != other.normalMapTextureID) return false; + if (!VectorEquals(normalMapScaleOffset, other.normalMapScaleOffset)) return false; + if (parallaxMapTextureID != other.parallaxMapTextureID) return false; + if (!VectorEquals(parallaxMapScaleOffset, other.parallaxMapScaleOffset)) return false; + if (roughnessMapTextureID != other.roughnessMapTextureID) return false; + if (!VectorEquals(roughnessMapScaleOffset, other.roughnessMapScaleOffset)) return false; + if (layerCount != other.layerCount) return false; + for (int i = 0; i < layerCount; ++i) + { + if (!layers[i].Equals(other.layers[i])) return false; + } + return true; + } + + public override int GetHashCode() + { + int hash = 0; + hash ^= baseColor.GetHashCode(); + hash ^= baseMaskType.GetHashCode(); + hash ^= baseMaskParameters.GetHashCode(); + hash ^= baseMaskAxis.GetHashCode(); + hash ^= sampleMode.GetHashCode(); + hash ^= alphaMaskTextureID.GetHashCode(); + hash ^= alphaMaskScaleOffset.GetHashCode(); + hash ^= normalMapTextureID.GetHashCode(); + hash ^= normalMapScaleOffset.GetHashCode(); + hash ^= parallaxMapTextureID.GetHashCode(); + hash ^= parallaxMapScaleOffset.GetHashCode(); + hash ^= roughnessMapTextureID.GetHashCode(); + hash ^= roughnessMapScaleOffset.GetHashCode(); + hash ^= layerCount.GetHashCode(); + for (int i = 0; i < layerCount; ++i) + { + hash ^= layers[i].GetHashCode(); + } + return hash; + } +}; + +public struct ovrAvatarExpressiveParameters +{ + public Vector4 irisColor; + public Vector4 scleraColor; + public Vector4 lashColor; + public Vector4 browColor; + public Vector4 lipColor; + public Vector4 teethColor; + public Vector4 gumColor; + public float browLashIntensity; + public float lipSmoothness; + + static bool VectorEquals(Vector4 a, Vector4 b) + { + return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; + } + public override bool Equals(object obj) + { + if (!(obj is ovrAvatarExpressiveParameters)) + { + return false; + } + ovrAvatarExpressiveParameters other = (ovrAvatarExpressiveParameters)obj; + if (!VectorEquals(irisColor, other.irisColor)) return false; + if (!VectorEquals(scleraColor, other.scleraColor)) return false; + if (!VectorEquals(lashColor, other.lashColor)) return false; + if (!VectorEquals(browColor, other.browColor)) return false; + if (!VectorEquals(lipColor, other.lipColor)) return false; + if (!VectorEquals(teethColor, other.teethColor)) return false; + if (!VectorEquals(gumColor, other.gumColor)) return false; + if (browLashIntensity != other.browLashIntensity) return false; + if (lipSmoothness != other.lipSmoothness) return false; + + return true; + } + public override int GetHashCode() + { + return irisColor.GetHashCode() ^ + scleraColor.GetHashCode() ^ + lashColor.GetHashCode() ^ + browColor.GetHashCode() ^ + lipColor.GetHashCode() ^ + teethColor.GetHashCode() ^ + gumColor.GetHashCode() ^ + browLashIntensity.GetHashCode() ^ + lipSmoothness.GetHashCode(); + } +} + +public struct ovrAvatarPBSMaterialState +{ + public Vector4 baseColor; ///< Underlying base color for the material + public UInt64 albedoTextureID; ///< Texture id for the albedo map + public Vector4 albedoMultiplier; ///< Multiplier for albedo texture sample + public UInt64 metallicnessTextureID; ///< Texture id for the metal map + public float glossinessScale; ///< Glossiness factor + public UInt64 normalTextureID; ///< Texture id for the normal map + public UInt64 heightTextureID; ///< Texture id for the height map + public UInt64 occlusionTextureID; ///< Texture id for the occlusion map + public UInt64 emissionTextureID; ///< Texture id for the emission map + public Vector4 emissionMultiplier; ///< Multiplier for emission texture sample + public UInt64 detailMaskTextureID; ///< Texture id for the detail mask map + public UInt64 detailAlbedoTextureID; ///< Texture id for the detail albedo map + public UInt64 detailNormalTextureID; ///< Texture id for the detail normal map + static bool VectorEquals(Vector4 a, Vector4 b) + { + return a.x == b.x && a.y == b.y && a.z == b.z && a.w == b.w; + } + + public override bool Equals(object obj) + { + if (!(obj is ovrAvatarPBSMaterialState)) + { + return false; + } + ovrAvatarPBSMaterialState other = (ovrAvatarPBSMaterialState)obj; + if (!VectorEquals(baseColor, other.baseColor)) return false; + if (albedoTextureID != other.albedoTextureID) return false; + if (!VectorEquals(albedoMultiplier, other.albedoMultiplier)) return false; + if (metallicnessTextureID != other.metallicnessTextureID) return false; + if (glossinessScale != other.glossinessScale) return false; + if (normalTextureID != other.normalTextureID) return false; + if (heightTextureID != other.heightTextureID) return false; + if (occlusionTextureID != other.occlusionTextureID) return false; + if (emissionTextureID != other.emissionTextureID) return false; + if (!VectorEquals(emissionMultiplier, other.emissionMultiplier)) return false; + if (detailMaskTextureID != other.detailMaskTextureID) return false; + if (detailAlbedoTextureID != other.detailAlbedoTextureID) return false; + if (detailNormalTextureID != other.detailNormalTextureID) return false; + return true; + } + public override int GetHashCode() + { + return baseColor.GetHashCode() ^ + albedoTextureID.GetHashCode() ^ + albedoMultiplier.GetHashCode() ^ + metallicnessTextureID.GetHashCode() ^ + glossinessScale.GetHashCode() ^ + normalTextureID.GetHashCode() ^ + heightTextureID.GetHashCode() ^ + occlusionTextureID.GetHashCode() ^ + emissionTextureID.GetHashCode() ^ + emissionMultiplier.GetHashCode() ^ + detailMaskTextureID.GetHashCode() ^ + detailAlbedoTextureID.GetHashCode() ^ + detailNormalTextureID.GetHashCode(); + } +}; + +public class OvrAvatarAssetMaterial : OvrAvatarAsset +{ + public OvrAvatarAssetMaterial(UInt64 id, IntPtr mat) + { + assetID = id; + material = CAPI.ovrAvatarAsset_GetMaterialState(mat); + } + + public ovrAvatarMaterialState material; +} +// This needs to be the csharp equivalent of ovrAvatarSkinnedMeshPose in OVR_Avatar.h +public struct ovrAvatarSkinnedMeshPose +{ + public UInt32 jointCount; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public ovrAvatarTransform[] jointTransform; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public int[] jointParents; + + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public IntPtr[] jointNames; //const char * jointNames[64]; +}; + + +[Flags] +public enum ovrAvatarVisibilityFlags +{ + FirstPerson = 1 << 0, + ThirdPerson = 1 << 1, + SelfOccluding = 1 << 2, +}; + +// This needs to be the csharp equivalent of ovrAvatarRenderPart_SkinnedMeshRender in OVR_Avatar.h +public struct ovrAvatarRenderPart_SkinnedMeshRender +{ + public ovrAvatarTransform localTransform; + public ovrAvatarVisibilityFlags visibilityMask; + public UInt64 meshAssetID; + public ovrAvatarMaterialState materialState; + public ovrAvatarSkinnedMeshPose skinnedPose; +}; + +// This needs to be the csharp equivalent of ovrAvatarRenderPart_SkinnedMeshRenderPBS in OVR_Avatar.h +public struct ovrAvatarRenderPart_SkinnedMeshRenderPBS +{ + public ovrAvatarTransform localTransform; + public ovrAvatarVisibilityFlags visibilityMask; + public UInt64 meshAssetID; + public UInt64 albedoTextureAssetID; + public UInt64 surfaceTextureAssetID; + public ovrAvatarSkinnedMeshPose skinnedPose; +}; + +// This needs to be the csharp equivalent of ovrAvatarRenderPart_ProjectorRender in OVR_Avatar.h +public struct ovrAvatarRenderPart_ProjectorRender +{ + public ovrAvatarTransform localTransform; + public UInt32 componentIndex; + public UInt32 renderPartIndex; + public ovrAvatarMaterialState materialState; +}; + +// This needs to be the csharp equivalent of ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 in OVR_Avatar.h +public struct ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 +{ + public ovrAvatarTransform localTransform; + public ovrAvatarVisibilityFlags visibilityMask; + public UInt64 meshAssetID; + public ovrAvatarPBSMaterialState materialState; + public ovrAvatarSkinnedMeshPose skinnedPose; +}; + +// This needs to be the csharp equivalent of ovrAvatarHandGesture in OVR_Avatar.h +public enum ovrAvatarHandGesture { + Default, + GripSphere, + GripCube, + Count +}; + +public enum ovrAvatarBodyPartType +{ + Body, + Clothing, + Eyewear, + Hair, + Beard, + Count +}; + +// This needs to be the csharp equivalent of ovrAvatarBlendShapeParams in OVR_Avatar.h +public struct ovrAvatarBlendShapeParams +{ + public UInt32 blendShapeParamCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 64)] + public float[] blendShapeParams; +}; + +struct ovrAvatarBlendShapeParams_Offsets +{ + public static Int32 blendShapeParamCount = Marshal.OffsetOf(typeof(ovrAvatarBlendShapeParams), "blendShapeParamCount").ToInt32(); + // Bug with Marshal.OffsetOf is returning an incorrect offset, causing an off by 1 float issue in the blendShapeParams + //public static long blendShapeParams = Marshal.OffsetOf(typeof(ovrAvatarBlendShapeParams), "blendShapeParams").ToInt64(); + public static long blendShapeParams = Marshal.SizeOf(typeof(UInt32)); +}; + +// This needs to be the csharp equivalent of ovrAvatarVisemes in OVR_Avatar.h +public struct ovrAvatarVisemes +{ + public UInt32 visemeParamCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 32)] + public float[] visemeParams; +}; + +struct ovrAvatarVisemes_Offsets +{ + public static Int32 visemeParamCount = Marshal.OffsetOf(typeof(ovrAvatarVisemes), "visemeParamCount").ToInt32(); + // Bug with Marshal.OffsetOf is returning an incorrect offset, causing an off by 1 float issue in the visemeParams + //public static long visemeParams = Marshal.OffsetOf(typeof(ovrAvatarVisemes), "visemeParams").ToInt64(); + public static long visemeParams = Marshal.SizeOf(typeof(UInt32)); +}; + +// This needs to be the csharp equivalent of ovrAvatarGazeTargetType in OVR_AvatarInternal.h +public enum ovrAvatarGazeTargetType { + AvatarHead = 0, + AvatarHand, + Object, + ObjectStatic, + Count, +}; + +// This needs to be the csharp equivalent of ovrAvatarGazeTarget in OVR_AvatarInternal.h +public struct ovrAvatarGazeTarget +{ + public UInt32 id; + public Vector3 worldPosition; + public ovrAvatarGazeTargetType type; +}; + +struct ovrAvatarGazeTarget_Offsets +{ + public static Int32 id = 0; + public static Int32 worldPosition = Marshal.SizeOf(typeof(UInt32)); + public static Int32 type = worldPosition + Marshal.SizeOf(typeof(Vector3)); +}; + +public struct ovrAvatarGazeTargets +{ + public UInt32 targetCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)] + public ovrAvatarGazeTarget[] targets; +}; + +struct ovrAvatarGazeTargets_Offsets +{ + public static Int32 targetCount = Marshal.OffsetOf(typeof(ovrAvatarGazeTargets), "targetCount").ToInt32(); + // Bug with Marshal.OffsetOf is returning an incorrect offset, causing an off by 1 float issue in the targets + //public static long targets = Marshal.OffsetOf(typeof(ovrAvatarGazeTargets), "targets").ToInt64(); + public static long targets = Marshal.SizeOf(typeof(UInt32)); +}; + +// This needs to be the csharp equivalent of ovrAvatarLightType in OVR_AvatarInternal.h +public enum ovrAvatarLightType { + Point = 0, + Direction, + Spot, + Count, +}; + +// This needs to be the csharp equivalent of ovrAvatarLight in OVR_AvatarInternal.h +public struct ovrAvatarLight +{ + public UInt32 id; + public ovrAvatarLightType type; + public float intensity; + public Vector3 worldDirection; + public Vector3 worldPosition; + public float range; + public float spotAngleDeg; +}; + +struct ovrAvatarLight_Offsets +{ + public static long id = Marshal.OffsetOf(typeof(ovrAvatarLight), "id").ToInt64(); + public static long type = Marshal.OffsetOf(typeof(ovrAvatarLight), "type").ToInt64(); + public static long intensity = Marshal.OffsetOf(typeof(ovrAvatarLight), "intensity").ToInt64(); + public static long worldDirection = Marshal.OffsetOf(typeof(ovrAvatarLight), "worldDirection").ToInt64(); + public static long worldPosition = Marshal.OffsetOf(typeof(ovrAvatarLight), "worldPosition").ToInt64(); + public static long range = Marshal.OffsetOf(typeof(ovrAvatarLight), "range").ToInt64(); + public static long spotAngleDeg = Marshal.OffsetOf(typeof(ovrAvatarLight), "spotAngleDeg").ToInt64(); +}; + +public struct ovrAvatarLights +{ + public float ambientIntensity; + public UInt32 lightCount; + [MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] + public ovrAvatarLight[] lights; +}; + +struct ovrAvatarLights_Offsets +{ + public static long ambientIntensity = Marshal.OffsetOf(typeof(ovrAvatarLights), "ambientIntensity").ToInt64(); + public static long lightCount = Marshal.OffsetOf(typeof(ovrAvatarLights), "lightCount").ToInt64(); + public static long lights = Marshal.OffsetOf(typeof(ovrAvatarLights), "lights").ToInt64(); +}; + +// Debug Render +[Flags] +public enum ovrAvatarDebugContext : uint +{ + None = 0, + GazeTarget = 0x01, + Any = 0xffffffff +}; + +public struct ovrAvatarDebugLine +{ + public Vector3 startPoint; + public Vector3 endPoint; + public Vector3 color; + public ovrAvatarDebugContext context; + public IntPtr text; +}; +public struct ovrAvatarDebugTransform +{ + public ovrAvatarTransform transform; + public ovrAvatarDebugContext context; + public IntPtr text; +}; + +namespace Oculus.Avatar +{ + public class CAPI + { +#if UNITY_ANDROID && !UNITY_EDITOR +#if AVATAR_XPLAT + private const string LibFile = "ovravatar"; + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_Initialize(string appID); +#else + private const string LibFile = "ovravatarloader"; + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_InitializeAndroidUnity(string appID); +#endif +#else + private const string LibFile = "libovravatar"; + + public static readonly System.Version AvatarSDKVersion = new System.Version(1, 36, 0); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_Initialize(string appID); +#endif + + static IntPtr nativeVisemeData = IntPtr.Zero; + static IntPtr nativeGazeTargetsData = IntPtr.Zero; + static IntPtr nativeAvatarLightsData = IntPtr.Zero; + static IntPtr DebugLineCountData = IntPtr.Zero; + static float[] scratchBufferFloat = new float[16]; + static GameObject debugLineGo; + public static void Initialize() + { + nativeVisemeData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ovrAvatarVisemes))); + nativeGazeTargetsData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ovrAvatarGazeTargets))); + nativeAvatarLightsData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ovrAvatarLights))); + DebugLineCountData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(uint))); + + debugLineGo = new GameObject(); + debugLineGo.name = "AvatarSDKDebugDrawHelper"; + } + + public static void Shutdown() + { + Marshal.FreeHGlobal(nativeVisemeData); + Marshal.FreeHGlobal(nativeGazeTargetsData); + Marshal.FreeHGlobal(nativeAvatarLightsData); + Marshal.FreeHGlobal(DebugLineCountData); + + debugLineGo = null; + } + + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_Shutdown(); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatarMessage_Pop(); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarMessageType ovrAvatarMessage_GetType(IntPtr msg); + + public static ovrAvatarMessage_AvatarSpecification ovrAvatarMessage_GetAvatarSpecification( + IntPtr msg) + { + IntPtr ptr = ovrAvatarMessage_GetAvatarSpecification_Native(msg); + return (ovrAvatarMessage_AvatarSpecification)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarMessage_AvatarSpecification)); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarMessage_GetAvatarSpecification")] + private static extern IntPtr ovrAvatarMessage_GetAvatarSpecification_Native(IntPtr msg); + + public static ovrAvatarMessage_AssetLoaded ovrAvatarMessage_GetAssetLoaded( + IntPtr msg) + { + IntPtr ptr = ovrAvatarMessage_GetAssetLoaded_Native(msg); + return (ovrAvatarMessage_AssetLoaded)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarMessage_AssetLoaded)); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarMessage_GetAssetLoaded")] + private static extern IntPtr ovrAvatarMessage_GetAssetLoaded_Native(IntPtr msg); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarMessage_Free(IntPtr msg); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatarSpecificationRequest_Create(UInt64 userID); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarSpecificationRequest_Destroy(IntPtr specificationRequest); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarSpecificationRequest_SetCombineMeshes(IntPtr specificationRequest, bool useCombinedMesh); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarSpecificationRequest_SetLookAndFeelVersion(IntPtr specificationRequest, ovrAvatarLookAndFeelVersion version); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarSpecificationRequest_SetLevelOfDetail(IntPtr specificationRequest, ovrAvatarAssetLevelOfDetail lod); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_RequestAvatarSpecification(UInt64 userID); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_RequestAvatarSpecificationFromSpecRequest(IntPtr specificationRequest); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarSpecificationRequest_SetFallbackLookAndFeelVersion(IntPtr specificationRequest, ovrAvatarLookAndFeelVersion version); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarSpecificationRequest_SetExpressiveFlag(IntPtr specificationRequest, bool enable); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatar_Create(IntPtr avatarSpecification, + ovrAvatarCapabilities capabilities); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_Destroy(IntPtr avatar); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarPose_UpdateBody( + IntPtr avatar, ovrAvatarTransform headPose); + + public static void ovrAvatarPose_UpdateVoiceVisualization( + IntPtr avatar, float[] pcmData) + { + ovrAvatarPose_UpdateVoiceVisualization_Native( + avatar, (UInt32)pcmData.Length, pcmData); + } + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarPose_UpdateVoiceVisualization")] + private static extern void ovrAvatarPose_UpdateVoiceVisualization_Native( + IntPtr avatar, UInt32 pcmDataSize, [In] float[] pcmData); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarPose_UpdateHands( + IntPtr avatar, + ovrAvatarHandInputState inputStateLeft, + ovrAvatarHandInputState inputStateRight); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarPose_UpdateHandsWithType( + IntPtr avatar, + ovrAvatarHandInputState inputStateLeft, + ovrAvatarHandInputState inputStateRight, + ovrAvatarControllerType type); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarPose_Finalize(IntPtr avatar, float elapsedSeconds); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetLeftControllerVisibility(IntPtr avatar, bool show); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetRightControllerVisibility(IntPtr avatar, bool show); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetLeftHandVisibility(IntPtr avatar, bool show); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetRightHandVisibility(IntPtr avatar, bool show); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 ovrAvatarComponent_Count(IntPtr avatar); + + public static void ovrAvatarComponent_Get(IntPtr avatar, UInt32 index, bool includeName, ref ovrAvatarComponent component) + { + IntPtr ptr = ovrAvatarComponent_Get_Native(avatar, index); + ovrAvatarComponent_Get(ptr, includeName, ref component); + } + + public static void ovrAvatarComponent_Get(IntPtr componentPtr, bool includeName, ref ovrAvatarComponent component) + { + Marshal.Copy(new IntPtr(componentPtr.ToInt64() + ovrAvatarComponent_Offsets.transform), scratchBufferFloat, 0, 10); + OvrAvatar.ConvertTransform(scratchBufferFloat, ref component.transform); + + component.renderPartCount = (UInt32)Marshal.ReadInt32(componentPtr, ovrAvatarComponent_Offsets.renderPartCount); + component.renderParts = Marshal.ReadIntPtr(componentPtr, ovrAvatarComponent_Offsets.renderParts); + + if (includeName) + { + IntPtr namePtr = Marshal.ReadIntPtr(componentPtr, ovrAvatarComponent_Offsets.name); + component.name = Marshal.PtrToStringAnsi(namePtr); + } + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarComponent_Get")] + public static extern IntPtr ovrAvatarComponent_Get_Native(IntPtr avatar, UInt32 index); + + public static bool ovrAvatarPose_GetBaseComponent(IntPtr avatar, ref ovrAvatarBaseComponent component) + { + IntPtr ptr = ovrAvatarPose_GetBaseComponent_Native(avatar); + if (ptr == IntPtr.Zero) + { + return false; + } + + int renderComponentOffset = Marshal.SizeOf(typeof(ovrAvatarBaseComponent)) - Marshal.SizeOf(typeof(IntPtr)); + component.renderComponent = Marshal.ReadIntPtr(ptr, renderComponentOffset); + return true; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint ="ovrAvatarPose_GetBaseComponent")] + private static extern IntPtr ovrAvatarPose_GetBaseComponent_Native(IntPtr avatar); + + public static IntPtr MarshalRenderComponent(IntPtr ptr) where T : struct + { + return Marshal.ReadIntPtr(new IntPtr(ptr.ToInt64() + Marshal.OffsetOf(typeof(T), "renderComponent").ToInt64())); + } + public static bool ovrAvatarPose_GetBodyComponent(IntPtr avatar, ref ovrAvatarBodyComponent component) + { + IntPtr ptr = ovrAvatarPose_GetBodyComponent_Native(avatar); + + if (ptr == IntPtr.Zero) + { + return false; + } + + Marshal.Copy(new IntPtr(ptr.ToInt64() + ovrAvatarBodyComponent_Offsets.leftEyeTransform), scratchBufferFloat, 0, 10); + OvrAvatar.ConvertTransform(scratchBufferFloat, ref component.leftEyeTransform); + + Marshal.Copy(new IntPtr(ptr.ToInt64() + ovrAvatarBodyComponent_Offsets.rightEyeTransform), scratchBufferFloat, 0, 10); + OvrAvatar.ConvertTransform(scratchBufferFloat, ref component.rightEyeTransform); + + Marshal.Copy(new IntPtr(ptr.ToInt64() + ovrAvatarBodyComponent_Offsets.centerEyeTransform), scratchBufferFloat, 0, 10); + OvrAvatar.ConvertTransform(scratchBufferFloat, ref component.centerEyeTransform); + + component.renderComponent = MarshalRenderComponent(ptr); + return true; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint ="ovrAvatarPose_GetBodyComponent")] + private static extern IntPtr ovrAvatarPose_GetBodyComponent_Native(IntPtr avatar); + + public static bool ovrAvatarPose_GetLeftControllerComponent(IntPtr avatar, ref ovrAvatarControllerComponent component) + { + IntPtr ptr = ovrAvatarPose_GetLeftControllerComponent_Native(avatar); + if (ptr == IntPtr.Zero) + { + return false; + } + + int renderComponentOffset = Marshal.SizeOf(typeof(ovrAvatarControllerComponent)) - Marshal.SizeOf(typeof(IntPtr)); + component.renderComponent = Marshal.ReadIntPtr(ptr, renderComponentOffset); + return true; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarPose_GetLeftControllerComponent")] + private static extern IntPtr ovrAvatarPose_GetLeftControllerComponent_Native(IntPtr avatar); + + public static bool ovrAvatarPose_GetRightControllerComponent(IntPtr avatar, ref ovrAvatarControllerComponent component) + { + IntPtr ptr = ovrAvatarPose_GetRightControllerComponent_Native(avatar); + + if (ptr == IntPtr.Zero) + { + return false; + } + + int renderComponentOffset = Marshal.SizeOf(typeof(ovrAvatarControllerComponent)) - Marshal.SizeOf(typeof(IntPtr)); + component.renderComponent = Marshal.ReadIntPtr(ptr, renderComponentOffset); + return true; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarPose_GetRightControllerComponent")] + private static extern IntPtr ovrAvatarPose_GetRightControllerComponent_Native(IntPtr avatar); + + public static bool ovrAvatarPose_GetLeftHandComponent(IntPtr avatar, ref ovrAvatarHandComponent component) + { + IntPtr ptr = ovrAvatarPose_GetLeftHandComponent_Native(avatar); + if (ptr == IntPtr.Zero) + { + return false; + } + + int renderComponentOffset = Marshal.SizeOf(typeof(ovrAvatarHandComponent)) - Marshal.SizeOf(typeof(IntPtr)); + component.renderComponent = Marshal.ReadIntPtr(ptr, renderComponentOffset); + return true; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarPose_GetLeftHandComponent")] + private static extern IntPtr ovrAvatarPose_GetLeftHandComponent_Native(IntPtr avatar); + + public static bool ovrAvatarPose_GetRightHandComponent(IntPtr avatar, ref ovrAvatarHandComponent component) + { + IntPtr ptr = ovrAvatarPose_GetRightHandComponent_Native(avatar); + if (ptr == IntPtr.Zero) + { + return false; + } + + int renderComponentOffset = Marshal.SizeOf(typeof(ovrAvatarHandComponent)) - Marshal.SizeOf(typeof(IntPtr)); + component.renderComponent = Marshal.ReadIntPtr(ptr, renderComponentOffset); + return true; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarPose_GetRightHandComponent")] + private static extern IntPtr ovrAvatarPose_GetRightHandComponent_Native(IntPtr avatar); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarAsset_BeginLoading(UInt64 assetID); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern bool ovrAvatarAsset_BeginLoadingLOD(UInt64 assetId, ovrAvatarAssetLevelOfDetail lod); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarAssetType ovrAvatarAsset_GetType(IntPtr assetHandle); + + public static ovrAvatarMeshAssetData ovrAvatarAsset_GetMeshData( + IntPtr assetPtr) + { + IntPtr ptr = ovrAvatarAsset_GetMeshData_Native(assetPtr); + return (ovrAvatarMeshAssetData)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarMeshAssetData)); + } + + public static ovrAvatarMeshAssetDataV2 ovrAvatarAsset_GetCombinedMeshData( + IntPtr assetPtr) + { + IntPtr ptr = ovrAvatarAsset_GetCombinedMeshData_Native(assetPtr); + return (ovrAvatarMeshAssetDataV2)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarMeshAssetDataV2)); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarAsset_GetCombinedMeshData")] + private static extern IntPtr ovrAvatarAsset_GetCombinedMeshData_Native(IntPtr assetPtr); + + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarAsset_GetMeshData")] + private static extern IntPtr ovrAvatarAsset_GetMeshData_Native(IntPtr assetPtr); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 ovrAvatarAsset_GetMeshBlendShapeCount(IntPtr assetPtr); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatarAsset_GetMeshBlendShapeName(IntPtr assetPtr, UInt32 index); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 ovrAvatarAsset_GetSubmeshCount(IntPtr assetPtr); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 ovrAvatarAsset_GetSubmeshLastIndex(IntPtr assetPtr, UInt32 index); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatarAsset_GetMeshBlendShapeVertices(IntPtr assetPtr); + + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatarAsset_GetAvatar(IntPtr assetHandle); + + public static UInt64[] ovrAvatarAsset_GetCombinedMeshIDs(IntPtr assetHandle) + { + UInt32 count = 0; + System.IntPtr countPtr = Marshal.AllocHGlobal(Marshal.SizeOf(count)); + IntPtr idBuffer = ovrAvatarAsset_GetCombinedMeshIDs_Native(assetHandle, countPtr); + count = (UInt32)Marshal.PtrToStructure(countPtr, typeof(UInt32)); + UInt64[] meshIDs = new UInt64[count]; + + for (int i = 0; i < count; i++) + { + meshIDs[i] = (UInt64)Marshal.ReadInt64(idBuffer, i * Marshal.SizeOf(typeof(UInt64))); + } + + Marshal.FreeHGlobal(countPtr); + + return meshIDs; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarAsset_GetCombinedMeshIDs")] + public static extern IntPtr ovrAvatarAsset_GetCombinedMeshIDs_Native(IntPtr assetHandle, IntPtr count); + + public static void ovrAvatar_GetCombinedMeshAlphaData(IntPtr avatar, ref UInt64 textureID, ref Vector4 offset) + { + System.IntPtr textureIDPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UInt64))); + System.IntPtr offsetPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Vector4))); + + ovrAvatar_GetCombinedMeshAlphaData_Native(avatar, textureIDPtr, offsetPtr); + + textureID = (UInt64)Marshal.PtrToStructure(textureIDPtr, typeof(UInt64)); + offset = (Vector4)Marshal.PtrToStructure(offsetPtr, typeof(Vector4)); + + Marshal.FreeHGlobal(textureIDPtr); + Marshal.FreeHGlobal(offsetPtr); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_GetCombinedMeshAlphaData")] + public static extern IntPtr ovrAvatar_GetCombinedMeshAlphaData_Native(IntPtr avatar, IntPtr textureIDPtr, IntPtr offsetPtr); + + public static ovrAvatarTextureAssetData ovrAvatarAsset_GetTextureData( + IntPtr assetPtr) + { + IntPtr ptr = ovrAvatarAsset_GetTextureData_Native(assetPtr); + return (ovrAvatarTextureAssetData)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarTextureAssetData)); + } + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarAsset_GetTextureData")] + private static extern IntPtr ovrAvatarAsset_GetTextureData_Native(IntPtr assetPtr); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = + "ovrAvatarAsset_GetMaterialData")] + private static extern IntPtr ovrAvatarAsset_GetMaterialData_Native(IntPtr assetPtr); + public static ovrAvatarMaterialState ovrAvatarAsset_GetMaterialState(IntPtr assetPtr) + { + IntPtr ptr = ovrAvatarAsset_GetMaterialData_Native(assetPtr); + return (ovrAvatarMaterialState)Marshal.PtrToStructure(ptr, typeof(ovrAvatarMaterialState)); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarRenderPartType ovrAvatarRenderPart_GetType(IntPtr renderPart); + + public static ovrAvatarRenderPart_SkinnedMeshRender ovrAvatarRenderPart_GetSkinnedMeshRender(IntPtr renderPart) + { + IntPtr ptr = ovrAvatarRenderPart_GetSkinnedMeshRender_Native(renderPart); + return (ovrAvatarRenderPart_SkinnedMeshRender)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarRenderPart_SkinnedMeshRender)); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarRenderPart_GetSkinnedMeshRender")] + private static extern IntPtr ovrAvatarRenderPart_GetSkinnedMeshRender_Native(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarTransform ovrAvatarSkinnedMeshRender_GetTransform(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarTransform ovrAvatarSkinnedMeshRenderPBS_GetTransform(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarTransform ovrAvatarSkinnedMeshRenderPBSV2_GetTransform(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarVisibilityFlags ovrAvatarSkinnedMeshRender_GetVisibilityMask(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern bool ovrAvatarSkinnedMeshRender_MaterialStateChanged(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern bool ovrAvatarSkinnedMeshRenderPBSV2_MaterialStateChanged(IntPtr renderPart); + + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarVisibilityFlags ovrAvatarSkinnedMeshRenderPBS_GetVisibilityMask(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarVisibilityFlags ovrAvatarSkinnedMeshRenderPBSV2_GetVisibilityMask(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarMaterialState ovrAvatarSkinnedMeshRender_GetMaterialState(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarPBSMaterialState ovrAvatarSkinnedMeshRenderPBSV2_GetPBSMaterialState(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarExpressiveParameters ovrAvatar_GetExpressiveParameters(IntPtr avatar); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 ovrAvatarSkinnedMeshRender_GetDirtyJoints(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 ovrAvatarSkinnedMeshRenderPBS_GetDirtyJoints(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 ovrAvatarSkinnedMeshRenderPBSV2_GetDirtyJoints(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarTransform ovrAvatarSkinnedMeshRender_GetJointTransform(IntPtr renderPart, UInt32 jointIndex); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetActionUnitOnsetSpeed(IntPtr avatar, float onsetSpeed); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetActionUnitFalloffSpeed(IntPtr avatar, float falloffSpeed); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetVisemeMultiplier(IntPtr avatar, float visemeMultiplier); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarTransform ovrAvatarSkinnedMeshRenderPBS_GetJointTransform(IntPtr renderPart, UInt32 jointIndex); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern ovrAvatarTransform ovrAvatarSkinnedMeshRenderPBSV2_GetJointTransform(IntPtr renderPart, UInt32 jointIndex); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 ovrAvatarSkinnedMeshRenderPBS_GetAlbedoTextureAssetID(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 ovrAvatarSkinnedMeshRenderPBS_GetSurfaceTextureAssetID(IntPtr renderPart); + + public static ovrAvatarRenderPart_SkinnedMeshRenderPBS ovrAvatarRenderPart_GetSkinnedMeshRenderPBS(IntPtr renderPart) + { + IntPtr ptr = ovrAvatarRenderPart_GetSkinnedMeshRenderPBS_Native(renderPart); + return (ovrAvatarRenderPart_SkinnedMeshRenderPBS)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarRenderPart_SkinnedMeshRenderPBS)); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarRenderPart_GetSkinnedMeshRenderPBS")] + private static extern IntPtr ovrAvatarRenderPart_GetSkinnedMeshRenderPBS_Native(IntPtr renderPart); + + public static ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 ovrAvatarRenderPart_GetSkinnedMeshRenderPBSV2(IntPtr renderPart) + { + IntPtr ptr = ovrAvatarRenderPart_GetSkinnedMeshRenderPBSV2_Native(renderPart); + return (ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2)); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarRenderPart_GetSkinnedMeshRenderPBSV2")] + private static extern IntPtr ovrAvatarRenderPart_GetSkinnedMeshRenderPBSV2_Native(IntPtr renderPart); + + public static void ovrAvatarSkinnedMeshRender_GetBlendShapeParams(IntPtr renderPart, ref ovrAvatarBlendShapeParams blendParams) + { + IntPtr ptr = ovrAvatarSkinnedMeshRender_GetBlendShapeParams_Native(renderPart); + blendParams.blendShapeParamCount = (UInt32)Marshal.ReadInt32(ptr); + Marshal.Copy(new IntPtr(ptr.ToInt64() + ovrAvatarBlendShapeParams_Offsets.blendShapeParams), blendParams.blendShapeParams, 0, (int)blendParams.blendShapeParamCount); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarSkinnedMeshRender_GetBlendShapeParams")] + private static extern IntPtr ovrAvatarSkinnedMeshRender_GetBlendShapeParams_Native(IntPtr renderPart); + + public static ovrAvatarRenderPart_ProjectorRender ovrAvatarRenderPart_GetProjectorRender(IntPtr renderPart) + { + IntPtr ptr = ovrAvatarRenderPart_GetProjectorRender_Native(renderPart); + return (ovrAvatarRenderPart_ProjectorRender)Marshal.PtrToStructure( + ptr, typeof(ovrAvatarRenderPart_ProjectorRender)); + } + + public static ovrAvatarPBSMaterialState[] ovrAvatar_GetBodyPBSMaterialStates(IntPtr renderPart) + { + System.IntPtr countPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(UInt32))); + IntPtr ptrState = ovrAvatar_GetBodyPBSMaterialStates_Native(renderPart, countPtr); + UInt32 count = (UInt32)Marshal.ReadInt32(countPtr); + + ovrAvatarPBSMaterialState[] states = new ovrAvatarPBSMaterialState[count]; + + for (int i = 0; i < states.Length; i++) + { + IntPtr nextItem = new IntPtr(ptrState.ToInt64() + i * Marshal.SizeOf(typeof(ovrAvatarPBSMaterialState))); + states[i] = (ovrAvatarPBSMaterialState)Marshal.PtrToStructure(nextItem, typeof(ovrAvatarPBSMaterialState)); + } + + Marshal.FreeHGlobal(countPtr); + + return states; + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_GetBodyPBSMaterialStates")] + private static extern IntPtr ovrAvatar_GetBodyPBSMaterialStates_Native(IntPtr avatar, IntPtr count); + + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatarRenderPart_GetProjectorRender")] + private static extern IntPtr ovrAvatarRenderPart_GetProjectorRender_Native(IntPtr renderPart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 ovrAvatar_GetReferencedAssetCount(IntPtr avatar); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt64 ovrAvatar_GetReferencedAsset(IntPtr avatar, UInt32 index); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetLeftHandGesture(IntPtr avatar, ovrAvatarHandGesture gesture); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetRightHandGesture(IntPtr avatar, ovrAvatarHandGesture gesture); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetLeftHandCustomGesture(IntPtr avatar, UInt32 jointCount, [In] ovrAvatarTransform[] customJointTransforms); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetRightHandCustomGesture(IntPtr avatar, UInt32 jointCount, [In] ovrAvatarTransform[] customJointTransforms); + + //Native calls for efficient packet updates + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_UpdatePoseFromPacket(IntPtr avatar, IntPtr packet, float secondsFromStart); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarPacket_BeginRecording(IntPtr avatar); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatarPacket_EndRecording(IntPtr avatar); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern UInt32 ovrAvatarPacket_GetSize(IntPtr packet); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern float ovrAvatarPacket_GetDurationSeconds(IntPtr packet); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatarPacket_Free(IntPtr packet); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern bool ovrAvatarPacket_Write(IntPtr packet, UInt32 bufferSize, [Out] byte[] buffer); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern IntPtr ovrAvatarPacket_Read(UInt32 bufferSize, [In] byte[] buffer); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + private static extern void ovrAvatar_SetInternalForceASTCTextures(bool value); + + // Renaming the outward facing method to remove Internal from name + public static void ovrAvatar_SetForceASTCTextures(bool value) + { + ovrAvatar_SetInternalForceASTCTextures(value); + } + + public static void ovrAvatar_OverrideExpressiveLogic(IntPtr avatar, ovrAvatarBlendShapeParams blendParams) + { + IntPtr statePtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(ovrAvatarBlendShapeParams))); + Marshal.StructureToPtr(blendParams, statePtr, false); + ovrAvatar_OverrideExpressiveLogic_Native(avatar, statePtr); + Marshal.FreeHGlobal(statePtr); + } + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_OverrideExpressiveLogic")] + private static extern void ovrAvatar_OverrideExpressiveLogic_Native(IntPtr avatar, IntPtr state); + + public static void ovrAvatar_SetVisemes(IntPtr avatar, ovrAvatarVisemes visemes) + { + Marshal.WriteInt32(nativeVisemeData, (Int32)visemes.visemeParamCount); + Marshal.Copy(visemes.visemeParams, 0, new IntPtr(nativeVisemeData.ToInt64() + ovrAvatarVisemes_Offsets.visemeParams), (int)visemes.visemeParamCount); + + ovrAvatar_SetVisemes_Native(avatar, nativeVisemeData); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_SetVisemes")] + private static extern void ovrAvatar_SetVisemes_Native(IntPtr avatar, IntPtr visemes); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_UpdateWorldTransform(IntPtr avatar, ovrAvatarTransform transform); + + + public static void ovrAvatar_UpdateGazeTargets(ovrAvatarGazeTargets targets) + { + Marshal.WriteInt32(nativeGazeTargetsData, (Int32)targets.targetCount); + + var targetOffset = ovrAvatarGazeTargets_Offsets.targets; + for (uint index = 0; index < targets.targetCount; index++) + { + var baseOffset = targetOffset + index * Marshal.SizeOf(typeof(ovrAvatarGazeTarget)); + + Marshal.WriteInt32(new IntPtr(nativeGazeTargetsData.ToInt64() + baseOffset + ovrAvatarGazeTarget_Offsets.id), (int)targets.targets[index].id); + + scratchBufferFloat[0] = targets.targets[index].worldPosition.x; + scratchBufferFloat[1] = targets.targets[index].worldPosition.y; + scratchBufferFloat[2] = targets.targets[index].worldPosition.z; + Marshal.Copy(scratchBufferFloat, 0, new IntPtr(nativeGazeTargetsData.ToInt64() + baseOffset + ovrAvatarGazeTarget_Offsets.worldPosition), 3); + + Marshal.WriteInt32(new IntPtr(nativeGazeTargetsData.ToInt64() + baseOffset + ovrAvatarGazeTarget_Offsets.type), (int)targets.targets[index].type); + } + + ovrAvatar_UpdateGazeTargets_Native(nativeGazeTargetsData); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_UpdateGazeTargets")] + private static extern void ovrAvatar_UpdateGazeTargets_Native(IntPtr targets); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_RemoveGazeTargets(UInt32 targetCount, UInt32[] ids); + + public static void ovrAvatar_UpdateLights(ovrAvatarLights lights) + { + scratchBufferFloat[0] = lights.ambientIntensity; + Marshal.Copy(scratchBufferFloat, 0, nativeAvatarLightsData, 1); + + Marshal.WriteInt32(new IntPtr(nativeAvatarLightsData.ToInt64() + Marshal.OffsetOf(typeof(ovrAvatarLights), "lightCount").ToInt64()), (int)lights.lightCount); + + var lightsOffset = Marshal.OffsetOf(typeof(ovrAvatarLights), "lights").ToInt64(); + for (uint index = 0; index < lights.lightCount; index++) + { + var baseOffset = lightsOffset + index * Marshal.SizeOf(typeof(ovrAvatarLight)); + + Marshal.WriteInt32(new IntPtr(nativeAvatarLightsData.ToInt64() + baseOffset + Marshal.OffsetOf(typeof(ovrAvatarLight), "id").ToInt64()), (int)lights.lights[index].id); + Marshal.WriteInt32(new IntPtr(nativeAvatarLightsData.ToInt64() + baseOffset + Marshal.OffsetOf(typeof(ovrAvatarLight), "type").ToInt64()), (int)lights.lights[index].type); + + scratchBufferFloat[0] = lights.lights[index].intensity; + Marshal.Copy(scratchBufferFloat, 0, new IntPtr(nativeAvatarLightsData.ToInt64() + baseOffset + Marshal.OffsetOf(typeof(ovrAvatarLight), "intensity").ToInt64()), 1); + + scratchBufferFloat[0] = lights.lights[index].worldDirection.x; + scratchBufferFloat[1] = lights.lights[index].worldDirection.y; + scratchBufferFloat[2] = lights.lights[index].worldDirection.z; + Marshal.Copy(scratchBufferFloat, 0, new IntPtr(nativeAvatarLightsData.ToInt64() + baseOffset + Marshal.OffsetOf(typeof(ovrAvatarLight), "worldDirection").ToInt64()), 3); + + scratchBufferFloat[0] = lights.lights[index].worldPosition.x; + scratchBufferFloat[1] = lights.lights[index].worldPosition.y; + scratchBufferFloat[2] = lights.lights[index].worldPosition.z; + Marshal.Copy(scratchBufferFloat, 0, new IntPtr(nativeAvatarLightsData.ToInt64() + baseOffset + Marshal.OffsetOf(typeof(ovrAvatarLight), "worldPosition").ToInt64()), 3); + + scratchBufferFloat[0] = lights.lights[index].range; + Marshal.Copy(scratchBufferFloat, 0, new IntPtr(nativeAvatarLightsData.ToInt64() + baseOffset + Marshal.OffsetOf(typeof(ovrAvatarLight), "range").ToInt64()), 1); + + scratchBufferFloat[0] = lights.lights[index].spotAngleDeg; + Marshal.Copy(scratchBufferFloat, 0, new IntPtr(nativeAvatarLightsData.ToInt64() + baseOffset + Marshal.OffsetOf(typeof(ovrAvatarLight), "spotAngleDeg").ToInt64()), 1); + } + + ovrAvatar_UpdateLights_Native(nativeAvatarLightsData); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_UpdateLights")] + private static extern void ovrAvatar_UpdateLights_Native(IntPtr lights); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_RemoveLights(UInt32 lightCount, UInt32[] ids); + + private static string SDKRuntimePrefix = "[RUNTIME] - "; + public delegate void LoggingDelegate(IntPtr str); + + [MonoPInvokeCallback(typeof(LoggingDelegate))] + public static void LoggingCallback(IntPtr str) + { + string csharpStr = Marshal.PtrToStringAnsi(str); + AvatarLogger.Log(SDKRuntimePrefix + csharpStr); + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_RegisterLoggingCallback(LoggingDelegate callback); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetLoggingLevel(ovrAvatarLogLevel level); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_GetDebugTransforms")] + public static extern IntPtr ovrAvatar_GetDebugTransforms_Native(IntPtr count); + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrAvatar_GetDebugLines")] + public static extern IntPtr ovrAvatar_GetDebugLines_Native(IntPtr count); + + public static void ovrAvatar_DrawDebugLines() + { + IntPtr debugLinePtr = ovrAvatar_GetDebugLines_Native(DebugLineCountData); + int lineCount = Marshal.ReadInt32(DebugLineCountData); + + ovrAvatarDebugLine tempLine = new ovrAvatarDebugLine(); + for (int i = 0; i < lineCount; i++) + { + var offset = i * Marshal.SizeOf(typeof(ovrAvatarDebugLine)); + Marshal.Copy(new IntPtr(debugLinePtr.ToInt64() + offset), scratchBufferFloat, 0, 9); + tempLine.startPoint.x = scratchBufferFloat[0]; + tempLine.startPoint.y = scratchBufferFloat[1]; + tempLine.startPoint.z = -scratchBufferFloat[2]; + + tempLine.endPoint.x = scratchBufferFloat[3]; + tempLine.endPoint.y = scratchBufferFloat[4]; + tempLine.endPoint.z = -scratchBufferFloat[5]; + + tempLine.color.x = scratchBufferFloat[6]; + tempLine.color.y = scratchBufferFloat[7]; + tempLine.color.z = scratchBufferFloat[8]; + + tempLine.context = (ovrAvatarDebugContext)Marshal.ReadInt32(new IntPtr(debugLinePtr.ToInt64() + offset + Marshal.OffsetOf(typeof(ovrAvatarDebugLine), "context").ToInt64())); + tempLine.text = Marshal.ReadIntPtr(new IntPtr(debugLinePtr.ToInt64() + offset + Marshal.OffsetOf(typeof(ovrAvatarDebugLine), "text").ToInt64())); + + Debug.DrawLine(tempLine.startPoint, tempLine.endPoint, new Color(tempLine.color.x, tempLine.color.y, tempLine.color.z)); + + // TODO: Decide what to do with the text. Can only debug render in OnGUI() + //if (tempLine.text != IntPtr.Zero) + //{ + // string text = Marshal.PtrToStringAnsi(tempLine.text); + // AvatarLogger.Log(text); + //} + } + + debugLinePtr = ovrAvatar_GetDebugTransforms_Native(DebugLineCountData); + lineCount = Marshal.ReadInt32(DebugLineCountData); + + ovrAvatarDebugTransform tempTrans = new ovrAvatarDebugTransform(); + for (int i = 0; i < lineCount; i++) + { + var offset = i * Marshal.SizeOf(typeof(ovrAvatarDebugTransform)); + Marshal.Copy(new IntPtr(debugLinePtr.ToInt64() + offset), scratchBufferFloat, 0, 10); + + OvrAvatar.ConvertTransform(scratchBufferFloat, ref tempTrans.transform); + OvrAvatar.ConvertTransform(tempTrans.transform, debugLineGo.transform); + + tempTrans.context = (ovrAvatarDebugContext)Marshal.ReadInt32(new IntPtr(debugLinePtr.ToInt64() + offset + Marshal.OffsetOf(typeof(ovrAvatarDebugTransform), "context").ToInt64())); + tempTrans.text = Marshal.ReadIntPtr(new IntPtr(debugLinePtr.ToInt64() + offset + Marshal.OffsetOf(typeof(ovrAvatarDebugTransform), "text").ToInt64())); + + const float SCALE_FACTOR = 0.1f; + Vector3 transUp = SCALE_FACTOR * debugLineGo.transform.TransformVector(Vector3.up); + Vector3 transRight = SCALE_FACTOR * debugLineGo.transform.TransformVector(Vector3.right); + Vector3 transFwd = SCALE_FACTOR * debugLineGo.transform.TransformVector(Vector3.forward); + + Debug.DrawLine(debugLineGo.transform.position, debugLineGo.transform.position + transUp, Color.green); + Debug.DrawLine(debugLineGo.transform.position, debugLineGo.transform.position + transRight, Color.red); + Debug.DrawLine(debugLineGo.transform.position, debugLineGo.transform.position + transFwd, Color.blue); + + // TODO: Decide what to do with the text. Can only debug render in OnGUI() + //if (tempTrans.text != IntPtr.Zero) + //{ + // string text = Marshal.PtrToStringAnsi(tempTrans.text); + // AvatarLogger.Log(text); + //} + } + } + + [DllImport(LibFile, CallingConvention = CallingConvention.Cdecl)] + public static extern void ovrAvatar_SetDebugDrawContext(UInt32 context); + + //OvrPlugin Hooks + private const string ovrPluginDLL = "OVRPlugin"; + private static System.Version ovrPluginVersion; + + public enum Result + { + /// Success + Success = 0, + + /// Failure + Failure = -1000, + Failure_InvalidParameter = -1001, + Failure_NotInitialized = -1002, + Failure_InvalidOperation = -1003, + Failure_Unsupported = -1004, + Failure_NotYetImplemented = -1005, + Failure_OperationFailed = -1006, + Failure_InsufficientSize = -1007, + } + + public static bool SendEvent(string name, string param = "", string source = "") + { + try + { + if (ovrPluginVersion == null) + { + string version = ovrp_GetVersion(); + if (!String.IsNullOrEmpty(version)) + { + ovrPluginVersion = new System.Version(version.Split('-')[0]); + } + else + { + ovrPluginVersion = new System.Version(0, 0, 0); + } + } + if (ovrPluginVersion >= OVRP_1_30_0.version) + { + return OVRP_1_30_0.ovrp_SendEvent2(name, param, source.Length == 0 ? "avatar_sdk" : source) == Result.Success; + } + else + { + return false; + } + } + catch (Exception) + { + return false; + } + } + + [DllImport(ovrPluginDLL, CallingConvention = CallingConvention.Cdecl, EntryPoint = "ovrp_GetVersion")] + private static extern IntPtr _ovrp_GetVersion(); + public static string ovrp_GetVersion() { return Marshal.PtrToStringAnsi(_ovrp_GetVersion()); } + + private static class OVRP_1_30_0 + { + public static readonly System.Version version = new System.Version(1, 30, 0); + [DllImport(ovrPluginDLL, CallingConvention = CallingConvention.Cdecl)] + public static extern Result ovrp_SendEvent2(string name, string param, string source); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs.meta new file mode 100644 index 0000000..8bb4f09 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKCAPI.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 0348026b48363904bb332b53a21c35b2 +timeCreated: 1474928508 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs new file mode 100644 index 0000000..e74bebc --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs @@ -0,0 +1,375 @@ +using UnityEngine; +using Oculus.Avatar; +using System; +using System.Collections.Generic; + +public delegate void specificationCallback(IntPtr specification); +public delegate void assetLoadedCallback(OvrAvatarAsset asset); +public delegate void combinedMeshLoadedCallback(IntPtr asset); + +public class OvrAvatarSDKManager : MonoBehaviour +{ + private static OvrAvatarSDKManager _instance; + private bool initialized = false; + private Dictionary> specificationCallbacks; + private Dictionary> assetLoadedCallbacks; + private Dictionary combinedMeshLoadedCallbacks; + private Dictionary assetCache; + private OvrAvatarTextureCopyManager textureCopyManager; + + public ovrAvatarLogLevel LoggingLevel = ovrAvatarLogLevel.Info; + private Queue avatarSpecificationQueue; + private List loadingAvatars; + private bool avatarSpecRequestAvailable = true; + private float lastDispatchedAvatarSpecRequestTime = 0f; + private const float AVATAR_SPEC_REQUEST_TIMEOUT = 5f; + +#if AVATAR_DEBUG + private ovrAvatarDebugContext debugContext = ovrAvatarDebugContext.None; +#endif + + public struct AvatarSpecRequestParams + { + public UInt64 _userId; + public specificationCallback _callback; + public bool _useCombinedMesh; + public ovrAvatarAssetLevelOfDetail _lod; + public bool _forceMobileTextureFormat; + public ovrAvatarLookAndFeelVersion _lookVersion; + public ovrAvatarLookAndFeelVersion _fallbackVersion; + public bool _enableExpressive; + + public AvatarSpecRequestParams( + UInt64 userId, + specificationCallback callback, + bool useCombinedMesh, + ovrAvatarAssetLevelOfDetail lod, + bool forceMobileTextureFormat, + ovrAvatarLookAndFeelVersion lookVersion, + ovrAvatarLookAndFeelVersion fallbackVersion, + bool enableExpressive) + { + _userId = userId; + _callback = callback; + _useCombinedMesh = useCombinedMesh; + _lod = lod; + _forceMobileTextureFormat = forceMobileTextureFormat; + _lookVersion = lookVersion; + _fallbackVersion = fallbackVersion; + _enableExpressive = enableExpressive; + } + } + + public static OvrAvatarSDKManager Instance + { + get + { + if (_instance == null) + { + _instance = GameObject.FindObjectOfType(); + if (_instance == null) + { + GameObject manager = new GameObject("OvrAvatarSDKManager"); + _instance = manager.AddComponent(); + _instance.textureCopyManager = manager.AddComponent(); + _instance.initialized = _instance.Initialize(); + } + } + return _instance.initialized ? _instance : null; + } + } + + private bool Initialize() + { + CAPI.Initialize(); + + string appId = GetAppId(); + + if (appId == "") + { + AvatarLogger.LogError("No Oculus App ID has been provided for target platform. " + + "Go to Oculus Avatar > Edit Configuration to supply one", OvrAvatarSettings.Instance); + appId = "0"; + } + +#if UNITY_ANDROID && !UNITY_EDITOR +#if AVATAR_XPLAT + CAPI.ovrAvatar_Initialize(appId); +#else + CAPI.ovrAvatar_InitializeAndroidUnity(appId); +#endif +#else + CAPI.ovrAvatar_Initialize(appId); + CAPI.SendEvent("initialize", appId); +#endif + specificationCallbacks = new Dictionary>(); + assetLoadedCallbacks = new Dictionary>(); + combinedMeshLoadedCallbacks = new Dictionary(); + assetCache = new Dictionary(); + avatarSpecificationQueue = new Queue(); + loadingAvatars = new List(); + + CAPI.ovrAvatar_SetLoggingLevel(LoggingLevel); + CAPI.ovrAvatar_RegisterLoggingCallback(CAPI.LoggingCallback); +#if AVATAR_DEBUG + CAPI.ovrAvatar_SetDebugDrawContext((uint)debugContext); +#endif + + return true; + } + + void OnDestroy() + { + CAPI.Shutdown(); + CAPI.ovrAvatar_RegisterLoggingCallback(null); + CAPI.ovrAvatar_Shutdown(); + } + + void Update() + { + if (Instance == null) + { + return; + } +#if AVATAR_DEBUG + // Call before ovrAvatarMessage_Pop which flushes the state + CAPI.ovrAvatar_DrawDebugLines(); +#endif + + // Dispatch waiting avatar spec request + if (avatarSpecificationQueue.Count > 0 && + (avatarSpecRequestAvailable || + Time.time - lastDispatchedAvatarSpecRequestTime >= AVATAR_SPEC_REQUEST_TIMEOUT)) + { + avatarSpecRequestAvailable = false; + AvatarSpecRequestParams avatarSpec = avatarSpecificationQueue.Dequeue(); + DispatchAvatarSpecificationRequest(avatarSpec); + lastDispatchedAvatarSpecRequestTime = Time.time; + AvatarLogger.Log("Avatar spec request dispatched: " + avatarSpec._userId); + } + + IntPtr message = CAPI.ovrAvatarMessage_Pop(); + if (message == IntPtr.Zero) + { + return; + } + + ovrAvatarMessageType messageType = CAPI.ovrAvatarMessage_GetType(message); + switch (messageType) + { + case ovrAvatarMessageType.AssetLoaded: + { + ovrAvatarMessage_AssetLoaded assetMessage = CAPI.ovrAvatarMessage_GetAssetLoaded(message); + IntPtr asset = assetMessage.asset; + UInt64 assetID = assetMessage.assetID; + ovrAvatarAssetType assetType = CAPI.ovrAvatarAsset_GetType(asset); + OvrAvatarAsset assetData = null; + IntPtr avatarOwner = IntPtr.Zero; + + switch (assetType) + { + case ovrAvatarAssetType.Mesh: + assetData = new OvrAvatarAssetMesh(assetID, asset, ovrAvatarAssetType.Mesh); + break; + case ovrAvatarAssetType.Texture: + assetData = new OvrAvatarAssetTexture(assetID, asset); + break; + case ovrAvatarAssetType.Material: + assetData = new OvrAvatarAssetMaterial(assetID, asset); + break; + case ovrAvatarAssetType.CombinedMesh: + avatarOwner = CAPI.ovrAvatarAsset_GetAvatar(asset); + assetData = new OvrAvatarAssetMesh(assetID, asset, ovrAvatarAssetType.CombinedMesh); + break; + case ovrAvatarAssetType.FailedLoad: + AvatarLogger.LogWarning("Asset failed to load from SDK " + assetID); + break; + default: + throw new NotImplementedException(string.Format("Unsupported asset type format {0}", assetType.ToString())); + } + + HashSet callbackSet; + if (assetType == ovrAvatarAssetType.CombinedMesh) + { + if (!assetCache.ContainsKey(assetID)) + { + assetCache.Add(assetID, assetData); + } + + combinedMeshLoadedCallback callback; + if (combinedMeshLoadedCallbacks.TryGetValue(avatarOwner, out callback)) + { + callback(asset); + combinedMeshLoadedCallbacks.Remove(avatarOwner); + } + else + { + AvatarLogger.LogWarning("Loaded a combined mesh with no owner: " + assetMessage.assetID); + } + } + else + { + if (assetData != null && assetLoadedCallbacks.TryGetValue(assetMessage.assetID, out callbackSet)) + { + assetCache.Add(assetID, assetData); + + foreach (var callback in callbackSet) + { + callback(assetData); + } + + assetLoadedCallbacks.Remove(assetMessage.assetID); + } + } + break; + } + case ovrAvatarMessageType.AvatarSpecification: + { + avatarSpecRequestAvailable = true; + ovrAvatarMessage_AvatarSpecification spec = CAPI.ovrAvatarMessage_GetAvatarSpecification(message); + HashSet callbackSet; + if (specificationCallbacks.TryGetValue(spec.oculusUserID, out callbackSet)) + { + foreach (var callback in callbackSet) + { + callback(spec.avatarSpec); + } + + specificationCallbacks.Remove(spec.oculusUserID); + } + else + { + AvatarLogger.LogWarning("Error, got an avatar specification callback from a user id we don't have a record for: " + spec.oculusUserID); + } + break; + } + default: + throw new NotImplementedException("Unhandled ovrAvatarMessageType: " + messageType); + } + CAPI.ovrAvatarMessage_Free(message); + } + + public bool IsAvatarSpecWaiting() + { + return avatarSpecificationQueue.Count > 0; + } + + public bool IsAvatarLoading() + { + return loadingAvatars.Count > 0; + } + + // Add avatar gameobject ID to loading list to keep track of loading avatars + public void AddLoadingAvatar(int gameobjectID) + { + loadingAvatars.Add(gameobjectID); + } + + // Remove avatar gameobject ID from loading list + public void RemoveLoadingAvatar(int gameobjectID) + { + loadingAvatars.Remove(gameobjectID); + } + + // Request an avatar specification to be loaded by adding to the queue. + // Requests are dispatched in Update(). + public void RequestAvatarSpecification(AvatarSpecRequestParams avatarSpecRequest) + { + avatarSpecificationQueue.Enqueue(avatarSpecRequest); + AvatarLogger.Log("Avatar spec request queued: " + avatarSpecRequest._userId.ToString()); + } + + private void DispatchAvatarSpecificationRequest(AvatarSpecRequestParams avatarSpecRequest) + { + textureCopyManager.CheckFallbackTextureSet(avatarSpecRequest._lod); + CAPI.ovrAvatar_SetForceASTCTextures(avatarSpecRequest._forceMobileTextureFormat); + + HashSet callbackSet; + if (!specificationCallbacks.TryGetValue(avatarSpecRequest._userId, out callbackSet)) + { + callbackSet = new HashSet(); + specificationCallbacks.Add(avatarSpecRequest._userId, callbackSet); + + IntPtr specRequest = CAPI.ovrAvatarSpecificationRequest_Create(avatarSpecRequest._userId); + CAPI.ovrAvatarSpecificationRequest_SetLookAndFeelVersion(specRequest, avatarSpecRequest._lookVersion); + CAPI.ovrAvatarSpecificationRequest_SetFallbackLookAndFeelVersion(specRequest, avatarSpecRequest._fallbackVersion); + CAPI.ovrAvatarSpecificationRequest_SetLevelOfDetail(specRequest, avatarSpecRequest._lod); + CAPI.ovrAvatarSpecificationRequest_SetCombineMeshes(specRequest, avatarSpecRequest._useCombinedMesh); + CAPI.ovrAvatarSpecificationRequest_SetExpressiveFlag(specRequest, avatarSpecRequest._enableExpressive); + CAPI.ovrAvatar_RequestAvatarSpecificationFromSpecRequest(specRequest); + CAPI.ovrAvatarSpecificationRequest_Destroy(specRequest); + } + + callbackSet.Add(avatarSpecRequest._callback); + } + + public void BeginLoadingAsset( + UInt64 assetId, + ovrAvatarAssetLevelOfDetail lod, + assetLoadedCallback callback) + { + HashSet callbackSet; + if (!assetLoadedCallbacks.TryGetValue(assetId, out callbackSet)) + { + callbackSet = new HashSet(); + assetLoadedCallbacks.Add(assetId, callbackSet); + } + AvatarLogger.Log("Loading Asset ID: " + assetId); + CAPI.ovrAvatarAsset_BeginLoadingLOD(assetId, lod); + callbackSet.Add(callback); + } + + public void RegisterCombinedMeshCallback( + IntPtr sdkAvatar, + combinedMeshLoadedCallback callback) + { + combinedMeshLoadedCallback currentCallback; + if (!combinedMeshLoadedCallbacks.TryGetValue(sdkAvatar, out currentCallback)) + { + combinedMeshLoadedCallbacks.Add(sdkAvatar, callback); + } + else + { + throw new Exception("Adding second combind mesh callback for same avatar"); + } + } + + public OvrAvatarAsset GetAsset(UInt64 assetId) + { + OvrAvatarAsset asset; + if (assetCache.TryGetValue(assetId, out asset)) + { + return asset; + } + else + { + return null; + } + } + + public void DeleteAssetFromCache(UInt64 assetId) + { + if (assetCache.ContainsKey(assetId)) + { + assetCache.Remove(assetId); + } + } + + public string GetAppId() + { + return UnityEngine.Application.platform == RuntimePlatform.Android ? + OvrAvatarSettings.MobileAppID : OvrAvatarSettings.AppID; + } + + public OvrAvatarTextureCopyManager GetTextureCopyManager() + { + if (textureCopyManager != null) + { + return textureCopyManager; + } + else + { + return null; + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs.meta new file mode 100644 index 0000000..aba99e0 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSDKManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 2ba08ec2733a3a54fbc9490f0f4ab2f0 +timeCreated: 1475011862 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs new file mode 100644 index 0000000..38f2366 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs @@ -0,0 +1,65 @@ +using UnityEngine; +using System.Collections; + +#if UNITY_EDITOR + [UnityEditor.InitializeOnLoad] +#endif +public sealed class OvrAvatarSettings : ScriptableObject { + public static string AppID + { + get { return Instance.ovrAppID; } + set { Instance.ovrAppID = value; } + } + + public static string MobileAppID + { + get { return Instance.ovrGearAppID; } + set { Instance.ovrGearAppID = value; } + } + + private static OvrAvatarSettings instance; + public static OvrAvatarSettings Instance + { + get + { + if (instance == null) + { + instance = Resources.Load("OvrAvatarSettings"); + + // This can happen if the developer never input their App Id into the Unity Editor + // Use a dummy object with defaults for the getters so we don't have a null pointer exception + if (instance == null) + { + instance = ScriptableObject.CreateInstance(); + +#if UNITY_EDITOR + // Only in the editor should we save it to disk + string properPath = System.IO.Path.Combine(UnityEngine.Application.dataPath, "Resources"); + if (!System.IO.Directory.Exists(properPath)) + { + UnityEditor.AssetDatabase.CreateFolder("Assets", "Resources"); + } + + string fullPath = System.IO.Path.Combine( + System.IO.Path.Combine("Assets", "Resources"), + "OvrAvatarSettings.asset" + ); + UnityEditor.AssetDatabase.CreateAsset(instance, fullPath); +#endif + } + } + return instance; + } + + set + { + instance = value; + } + } + + [SerializeField] + private string ovrAppID = ""; + + [SerializeField] + private string ovrGearAppID = ""; +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs.meta new file mode 100644 index 0000000..a7d7a4c --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettings.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 70c2f484f132c044097f03d65cac3b24 +timeCreated: 1478024706 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs new file mode 100644 index 0000000..d49293e --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs @@ -0,0 +1,72 @@ +#if UNITY_EDITOR +using UnityEngine; +using System.Collections; +using UnityEditor; +using Oculus.Avatar; + +[CustomEditor(typeof(OvrAvatarSettings))] +[InitializeOnLoadAttribute] +public class OvrAvatarSettingsEditor : Editor { + GUIContent appIDLabel = new GUIContent("Oculus Rift App Id [?]", + "This AppID will be used for OvrAvatar registration."); + + GUIContent mobileAppIDLabel = new GUIContent("Oculus Go/Quest or Gear VR [?]", + "This AppID will be used when building to the Android target"); + + [UnityEditor.MenuItem("Oculus/Avatars/Edit Settings")] + public static void Edit() + { + var settings = OvrAvatarSettings.Instance; + UnityEditor.Selection.activeObject = settings; + CAPI.SendEvent("edit_settings"); + } + + static OvrAvatarSettingsEditor() + { +#if UNITY_2017_2_OR_NEWER + EditorApplication.playModeStateChanged += HandlePlayModeState; +#else + EditorApplication.playmodeStateChanged += () => + { + if (EditorApplication.isPlaying) + { + CAPI.SendEvent("load", CAPI.AvatarSDKVersion.ToString()); + } + }; +#endif + } + +#if UNITY_2017_2_OR_NEWER + private static void HandlePlayModeState(PlayModeStateChange state) + { + if (state == PlayModeStateChange.EnteredPlayMode) + { + CAPI.SendEvent("load", CAPI.AvatarSDKVersion.ToString()); + } + } +#endif + + private static string MakeTextBox(GUIContent label, string variable) { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(label); + GUI.changed = false; + var result = EditorGUILayout.TextField(variable); + if (GUI.changed) + { + EditorUtility.SetDirty(OvrAvatarSettings.Instance); + GUI.changed = false; + } + EditorGUILayout.EndHorizontal(); + return result; + } + public override void OnInspectorGUI() + { + EditorGUILayout.BeginVertical(); + OvrAvatarSettings.AppID = + OvrAvatarSettingsEditor.MakeTextBox(appIDLabel, OvrAvatarSettings.AppID); + OvrAvatarSettings.MobileAppID = + OvrAvatarSettingsEditor.MakeTextBox(mobileAppIDLabel, OvrAvatarSettings.MobileAppID); + EditorGUILayout.EndVertical(); + } +} +#endif diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs.meta new file mode 100644 index 0000000..9a35602 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSettingsEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 1511f2aaa4ab15e4b8a0ac1a805a402b +timeCreated: 1478024800 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderComponent.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderComponent.cs new file mode 100644 index 0000000..ed2ddcd --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderComponent.cs @@ -0,0 +1,50 @@ +using UnityEngine; +using System.Collections; +using System; +using Oculus.Avatar; + +public class OvrAvatarSkinnedMeshRenderComponent : OvrAvatarRenderComponent +{ + Shader surface; + Shader surfaceSelfOccluding; + bool previouslyActive = false; + + internal void Initialize(ovrAvatarRenderPart_SkinnedMeshRender skinnedMeshRender, Shader surface, Shader surfaceSelfOccluding, int thirdPersonLayer, int firstPersonLayer) + { + this.surfaceSelfOccluding = surfaceSelfOccluding != null ? surfaceSelfOccluding : Shader.Find("OvrAvatar/AvatarSurfaceShaderSelfOccluding"); + this.surface = surface != null ? surface : Shader.Find("OvrAvatar/AvatarSurfaceShader"); + this.mesh = CreateSkinnedMesh(skinnedMeshRender.meshAssetID, skinnedMeshRender.visibilityMask, thirdPersonLayer, firstPersonLayer); + bones = mesh.bones; + UpdateMeshMaterial(skinnedMeshRender.visibilityMask, mesh); + } + + public void UpdateSkinnedMeshRender(OvrAvatarComponent component, OvrAvatar avatar, IntPtr renderPart) + { + ovrAvatarVisibilityFlags visibilityMask = CAPI.ovrAvatarSkinnedMeshRender_GetVisibilityMask(renderPart); + ovrAvatarTransform localTransform = CAPI.ovrAvatarSkinnedMeshRender_GetTransform(renderPart); + UpdateSkinnedMesh(avatar, bones, localTransform, visibilityMask, renderPart); + + UpdateMeshMaterial(visibilityMask, mesh); + bool isActive = this.gameObject.activeSelf; + + if( mesh != null ) + { + bool changedMaterial = CAPI.ovrAvatarSkinnedMeshRender_MaterialStateChanged(renderPart); + if (changedMaterial || (!previouslyActive && isActive)) + { + ovrAvatarMaterialState materialState = CAPI.ovrAvatarSkinnedMeshRender_GetMaterialState(renderPart); + component.UpdateAvatarMaterial(mesh.sharedMaterial, materialState); + } + } + previouslyActive = isActive; + } + + private void UpdateMeshMaterial(ovrAvatarVisibilityFlags visibilityMask, SkinnedMeshRenderer rootMesh) + { + Shader shader = (visibilityMask & ovrAvatarVisibilityFlags.SelfOccluding) != 0 ? surfaceSelfOccluding : surface; + if (rootMesh.sharedMaterial == null || rootMesh.sharedMaterial.shader != shader) + { + rootMesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + "_material", shader); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderComponent.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderComponent.cs.meta new file mode 100644 index 0000000..9c16120 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderComponent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 4efdf8bc42b8b8843aff4ca38233f362 +timeCreated: 1479156282 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSComponent.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSComponent.cs new file mode 100644 index 0000000..b0e04db --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSComponent.cs @@ -0,0 +1,38 @@ +using UnityEngine; +using System.Collections; +using System; +using Oculus.Avatar; + +public class OvrAvatarSkinnedMeshRenderPBSComponent : OvrAvatarRenderComponent { + + bool isMaterialInitilized = false; + + internal void Initialize(ovrAvatarRenderPart_SkinnedMeshRenderPBS skinnedMeshRenderPBS, Shader shader, int thirdPersonLayer, int firstPersonLayer) + { + if (shader == null) + { + shader = Shader.Find("OvrAvatar/AvatarSurfaceShaderPBS"); + } + mesh = CreateSkinnedMesh(skinnedMeshRenderPBS.meshAssetID, skinnedMeshRenderPBS.visibilityMask, thirdPersonLayer, firstPersonLayer); + mesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + "_material", shader); + bones = mesh.bones; + } + + internal void UpdateSkinnedMeshRenderPBS(OvrAvatar avatar, IntPtr renderPart, Material mat) + { + if (!isMaterialInitilized) + { + isMaterialInitilized = true; + UInt64 albedoTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetAlbedoTextureAssetID(renderPart); + UInt64 surfaceTextureID = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetSurfaceTextureAssetID(renderPart); + mat.SetTexture("_Albedo", OvrAvatarComponent.GetLoadedTexture(albedoTextureID)); + mat.SetTexture("_Surface", OvrAvatarComponent.GetLoadedTexture(surfaceTextureID)); + } + + ovrAvatarVisibilityFlags visibilityMask = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetVisibilityMask(renderPart); + ovrAvatarTransform localTransform = CAPI.ovrAvatarSkinnedMeshRenderPBS_GetTransform(renderPart); + UpdateSkinnedMesh(avatar, bones, localTransform, visibilityMask, renderPart); + + + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSComponent.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSComponent.cs.meta new file mode 100644 index 0000000..57fb1b6 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSComponent.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 69cc01a6441317c4c8a6e24d979cc1b0 +timeCreated: 1479158964 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSV2Component.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSV2Component.cs new file mode 100644 index 0000000..488a091 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSV2Component.cs @@ -0,0 +1,347 @@ +using UnityEngine; +using System.Collections.Generic; +using System; +using Oculus.Avatar; + +public class OvrAvatarSkinnedMeshPBSV2RenderComponent : OvrAvatarRenderComponent +{ + private OvrAvatarMaterialManager avatarMaterialManager; + private bool previouslyActive = false; + private bool isCombinedMaterial = false; + private ovrAvatarExpressiveParameters ExpressiveParameters; + private bool EnableExpressive = false; + private int blendShapeCount = 0; + private ovrAvatarBlendShapeParams blendShapeParams; + + private const string MAIN_MATERIAL_NAME = "main_material"; + private const string EYE_MATERIAL_NAME = "eye_material"; + private const string DEFAULT_MATERIAL_NAME = "_material"; + + internal void Initialize( + IntPtr renderPart, + ovrAvatarRenderPart_SkinnedMeshRenderPBS_V2 skinnedMeshRender, + OvrAvatarMaterialManager materialManager, + int thirdPersonLayer, + int firstPersonLayer, + bool combinedMesh, + ovrAvatarAssetLevelOfDetail lod, + bool assignExpressiveParams, + OvrAvatar avatar, + bool isControllerModel) + { + avatarMaterialManager = materialManager; + isCombinedMaterial = combinedMesh; + + mesh = CreateSkinnedMesh( + skinnedMeshRender.meshAssetID, + skinnedMeshRender.visibilityMask, + thirdPersonLayer, + firstPersonLayer); + + EnableExpressive = assignExpressiveParams; + +#if UNITY_ANDROID + var singleComponentShader = EnableExpressive + ? avatar.Skinshaded_Expressive_VertFrag_SingleComponent + : avatar.Skinshaded_VertFrag_SingleComponent; +#else + var singleComponentShader = EnableExpressive + ? avatar.Skinshaded_Expressive_SurfaceShader_SingleComponent + : avatar.Skinshaded_SurfaceShader_SingleComponent; +#endif + var combinedComponentShader = EnableExpressive + ? avatar.Skinshaded_Expressive_VertFrag_CombinedMesh + : avatar.Skinshaded_VertFrag_CombinedMesh; + + var mainShader = isCombinedMaterial ? combinedComponentShader : singleComponentShader; + + if (isControllerModel) + { + mainShader = avatar.ControllerShader; + } + + AvatarLogger.Log("OvrAvatarSkinnedMeshPBSV2RenderComponent Shader is: " + mainShader != null + ? mainShader.name : "null"); + + if (EnableExpressive) + { + ExpressiveParameters = CAPI.ovrAvatar_GetExpressiveParameters(avatar.sdkAvatar); + var eyeShader = avatar.EyeLens; + + Material[] matArray = new Material[2]; + matArray[0] = CreateAvatarMaterial(gameObject.name + MAIN_MATERIAL_NAME, mainShader); + matArray[1] = CreateAvatarMaterial(gameObject.name + EYE_MATERIAL_NAME, eyeShader); + + if (avatar.UseTransparentRenderQueue) + { + SetMaterialTransparent(matArray[0]); + } + else + { + SetMaterialOpaque(matArray[0]); + } + // Eye lens shader queue is transparent and set from shader + matArray[1].renderQueue = -1; + mesh.materials = matArray; + } + else + { + mesh.sharedMaterial = CreateAvatarMaterial(gameObject.name + DEFAULT_MATERIAL_NAME, mainShader); + if (avatar.UseTransparentRenderQueue && !isControllerModel) + { + SetMaterialTransparent(mesh.sharedMaterial); + } + else + { + SetMaterialOpaque(mesh.sharedMaterial); + } + } + bones = mesh.bones; + + if (isCombinedMaterial) + { + avatarMaterialManager.SetRenderer(mesh); + InitializeCombinedMaterial(renderPart, (int)lod); + avatarMaterialManager.OnCombinedMeshReady(); + } + + blendShapeParams = new ovrAvatarBlendShapeParams(); + blendShapeParams.blendShapeParamCount = 0; + blendShapeParams.blendShapeParams = new float[64]; + + blendShapeCount = mesh.sharedMesh.blendShapeCount; + } + + public void UpdateSkinnedMeshRender( + OvrAvatarComponent component, + OvrAvatar avatar, + IntPtr renderPart) + { + ovrAvatarVisibilityFlags visibilityMask + = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetVisibilityMask(renderPart); + + ovrAvatarTransform localTransform + = CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetTransform(renderPart); + + UpdateSkinnedMesh(avatar, bones, localTransform, visibilityMask, renderPart); + + bool isActive = gameObject.activeSelf; + + if (mesh != null && !previouslyActive && isActive) + { + if (!isCombinedMaterial) + { + InitializeSingleComponentMaterial(renderPart, (int)avatar.LevelOfDetail - 1); + } + } + + if (blendShapeCount > 0) + { + const float BLEND_MULTIPLIER = 100.0f; + CAPI.ovrAvatarSkinnedMeshRender_GetBlendShapeParams(renderPart, ref blendShapeParams); + for (uint i = 0; i < blendShapeParams.blendShapeParamCount && i < blendShapeCount; i++) + { + float value = blendShapeParams.blendShapeParams[i]; + mesh.SetBlendShapeWeight((int)i, value * BLEND_MULTIPLIER); + } + } + + previouslyActive = isActive; + } + + private void InitializeSingleComponentMaterial(IntPtr renderPart, int lodIndex) + { + ovrAvatarPBSMaterialState materialState = + CAPI.ovrAvatarSkinnedMeshRenderPBSV2_GetPBSMaterialState(renderPart); + + int componentType = (int)OvrAvatarMaterialManager.GetComponentType(gameObject.name); + + Texture2D diffuseTexture = OvrAvatarComponent.GetLoadedTexture(materialState.albedoTextureID); + Texture2D normalTexture = OvrAvatarComponent.GetLoadedTexture(materialState.normalTextureID); + Texture2D metallicTexture = OvrAvatarComponent.GetLoadedTexture(materialState.metallicnessTextureID); + + if (diffuseTexture != null) + { + avatarMaterialManager.AddTextureIDToTextureManager(materialState.albedoTextureID, true); + } + else + { + diffuseTexture = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness; + } + diffuseTexture.anisoLevel = 4; + if (normalTexture != null) + { + avatarMaterialManager.AddTextureIDToTextureManager(materialState.normalTextureID, true); + } + else + { + normalTexture = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].Normal; + } + normalTexture.anisoLevel = 4; + if (metallicTexture != null) + { + avatarMaterialManager.AddTextureIDToTextureManager(materialState.metallicnessTextureID, true); + } + else + { + metallicTexture = OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness; + } + metallicTexture.anisoLevel = 16; + + mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_MAINTEX, diffuseTexture); + mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_NORMALMAP, normalTexture); + mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_ROUGHNESSMAP, metallicTexture); + + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_COLOR, materialState.albedoMultiplier); + + mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_DIFFUSEINTENSITY, + OvrAvatarMaterialManager.DiffuseIntensities[componentType]); + mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_RIMINTENSITY, + OvrAvatarMaterialManager.RimIntensities[componentType]); + mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_REFLECTIONINTENSITY, + OvrAvatarMaterialManager.ReflectionIntensities[componentType]); + + mesh.GetClosestReflectionProbes(avatarMaterialManager.ReflectionProbes); + if (avatarMaterialManager.ReflectionProbes != null && + avatarMaterialManager.ReflectionProbes.Count > 0) + { + mesh.materials[0].SetTexture(OvrAvatarMaterialManager.AVATAR_SHADER_CUBEMAP, + avatarMaterialManager.ReflectionProbes[0].probe.texture); + } + + if (EnableExpressive) + { + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_IRIS_COLOR, + ExpressiveParameters.irisColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_COLOR, + ExpressiveParameters.lipColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_BROW_COLOR, + ExpressiveParameters.browColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LASH_COLOR, + ExpressiveParameters.lashColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_SCLERA_COLOR, + ExpressiveParameters.scleraColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_GUM_COLOR, + ExpressiveParameters.gumColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_TEETH_COLOR, + ExpressiveParameters.teethColor); + mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_SMOOTHNESS, + ExpressiveParameters.lipSmoothness); + } + } + + private void InitializeCombinedMaterial(IntPtr renderPart, int lodIndex) + { + ovrAvatarPBSMaterialState[] materialStates = CAPI.ovrAvatar_GetBodyPBSMaterialStates(renderPart); + + if (materialStates.Length == (int)ovrAvatarBodyPartType.Count) + { + avatarMaterialManager.CreateTextureArrays(); + var localProperties = avatarMaterialManager.LocalAvatarConfig.ComponentMaterialProperties; + + AvatarLogger.Log("InitializeCombinedMaterial - Loading Material States"); + + for (int i = 0; i < materialStates.Length; i++) + { + localProperties[i].TypeIndex = (ovrAvatarBodyPartType)i; + localProperties[i].Color = materialStates[i].albedoMultiplier; + localProperties[i].DiffuseIntensity = OvrAvatarMaterialManager.DiffuseIntensities[i]; + localProperties[i].RimIntensity = OvrAvatarMaterialManager.RimIntensities[i]; + localProperties[i].ReflectionIntensity = OvrAvatarMaterialManager.ReflectionIntensities[i]; + + var diffuse = OvrAvatarComponent.GetLoadedTexture(materialStates[i].albedoTextureID); + var normal = OvrAvatarComponent.GetLoadedTexture(materialStates[i].normalTextureID); + var roughness = OvrAvatarComponent.GetLoadedTexture(materialStates[i].metallicnessTextureID); + + if (diffuse != null) + { + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures] = diffuse; + avatarMaterialManager.AddTextureIDToTextureManager(materialStates[i].albedoTextureID, false); + } + else + { + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures] = + OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness; + } + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.DiffuseTextures].anisoLevel = 4; + + if (normal != null) + { + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps] = normal; + avatarMaterialManager.AddTextureIDToTextureManager(materialStates[i].normalTextureID, false); + } + else + { + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps] = + OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].Normal; + } + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.NormalMaps].anisoLevel = 4; + + if (roughness != null) + { + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps] = roughness; + avatarMaterialManager.AddTextureIDToTextureManager(materialStates[i].metallicnessTextureID, false); + } + else + { + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps] = + OvrAvatarSDKManager.Instance.GetTextureCopyManager().FallbackTextureSets[lodIndex].DiffuseRoughness; + } + localProperties[i].Textures[(int)OvrAvatarMaterialManager.TextureType.RoughnessMaps].anisoLevel = 16; + + AvatarLogger.Log(localProperties[i].TypeIndex.ToString()); + AvatarLogger.Log(AvatarLogger.Tab + "Diffuse: " + materialStates[i].albedoTextureID); + AvatarLogger.Log(AvatarLogger.Tab + "Normal: " + materialStates[i].normalTextureID); + AvatarLogger.Log(AvatarLogger.Tab + "Metallic: " + materialStates[i].metallicnessTextureID); + } + + if (EnableExpressive) + { + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_IRIS_COLOR, + ExpressiveParameters.irisColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_COLOR, + ExpressiveParameters.lipColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_BROW_COLOR, + ExpressiveParameters.browColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_LASH_COLOR, + ExpressiveParameters.lashColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_SCLERA_COLOR, + ExpressiveParameters.scleraColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_GUM_COLOR, + ExpressiveParameters.gumColor); + mesh.materials[0].SetVector(OvrAvatarMaterialManager.AVATAR_SHADER_TEETH_COLOR, + ExpressiveParameters.teethColor); + mesh.materials[0].SetFloat(OvrAvatarMaterialManager.AVATAR_SHADER_LIP_SMOOTHNESS, + ExpressiveParameters.lipSmoothness); + } + + avatarMaterialManager.ValidateTextures(materialStates); + } + } + + private void SetMaterialTransparent(Material mat) + { + // Initialize shader to use transparent render queue with alpha blending + mat.SetOverrideTag("Queue", "Transparent"); + mat.SetOverrideTag("RenderType", "Transparent"); + mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha); + mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha); + mat.EnableKeyword("_ALPHATEST_ON"); + mat.EnableKeyword("_ALPHABLEND_ON"); + mat.EnableKeyword("_ALPHAPREMULTIPLY_ON"); + mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent; + } + + private void SetMaterialOpaque(Material mat) + { + // Initialize shader to use geometry render queue with no blending + mat.SetOverrideTag("Queue", "Geometry"); + mat.SetOverrideTag("RenderType", "Opaque"); + mat.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One); + mat.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero); + mat.DisableKeyword("_ALPHATEST_ON"); + mat.DisableKeyword("_ALPHABLEND_ON"); + mat.DisableKeyword("_ALPHAPREMULTIPLY_ON"); + mat.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry; + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSV2Component.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSV2Component.cs.meta new file mode 100644 index 0000000..a000a15 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarSkinnedMeshRenderPBSV2Component.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c45906825d398024fbe09e47cc72de24 +timeCreated: 1511398456 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs new file mode 100644 index 0000000..02fa142 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs @@ -0,0 +1,284 @@ +using System.Collections; +using System.Collections.Generic; +using Oculus.Avatar; +using UnityEngine; + +public class OvrAvatarTextureCopyManager : MonoBehaviour +{ + [System.Serializable] + public struct FallbackTextureSet + { + public bool Initialized; + public Texture2D DiffuseRoughness; + public Texture2D Normal; + } + // Fallback texture sets are indexed with ovrAvatarAssetLevelOfDetail. + // We currently only use 1, 3 (mobile default), 5 (PC default). + public FallbackTextureSet[] FallbackTextureSets = new FallbackTextureSet[(int)ovrAvatarAssetLevelOfDetail.Highest + 1]; + + struct CopyTextureParams + { + public Texture Src; + public Texture Dst; + public int Mip; + public int SrcSize; + public int DstElement; + + public CopyTextureParams( + Texture src, + Texture dst, + int mip, + int srcSize, + int dstElement) + { + Src = src; + Dst = dst; + Mip = mip; + SrcSize = srcSize; + DstElement = dstElement; + } + } + private Queue texturesToCopy; + + public struct TextureSet + { + // Contains all texture asset IDs that are part of an avatar spec. + // Used by DeleteTextureSet(). + // Textures that are part of combined mesh avatars can be safely deleted once they have been + // uploaded to the texture arrays. + // Textures that are part of single component meshes will remain in memory. + public Dictionary TextureIDSingleMeshPair; + public bool IsProcessed; + + public TextureSet( + Dictionary textureIDSingleMeshPair, + bool isProcessed) + { + TextureIDSingleMeshPair = textureIDSingleMeshPair; + IsProcessed = isProcessed; + } + } + private Dictionary textureSets; + + private const int TEXTURES_TO_COPY_QUEUE_CAPACITY = 256; + private const int COPIES_PER_FRAME = 8; + + // Fallback texture paths are indexed with ovrAvatarAssetLevelOfDetail + // We currently only use 1, 3 (mobile default), 5 (PC default) + private readonly string[] FALLBACK_TEXTURE_PATHS_DIFFUSE_ROUGHNESS = new string[] + { + "null", + PATH_LOWEST_DIFFUSE_ROUGHNESS, + "null", + PATH_MEDIUM_DIFFUSE_ROUGHNESS, + "null", + PATH_HIGHEST_DIFFUSE_ROUGHNESS, + }; + private readonly string[] FALLBACK_TEXTURE_PATHS_NORMAL = new string[] + { + "null", + PATH_LOWEST_NORMAL, + "null", + PATH_MEDIUM_NORMAL, + "null", + PATH_HIGHEST_NORMAL, + }; + + private const string PATH_HIGHEST_DIFFUSE_ROUGHNESS = "FallbackTextures/fallback_diffuse_roughness_2048"; + private const string PATH_MEDIUM_DIFFUSE_ROUGHNESS = "FallbackTextures/fallback_diffuse_roughness_1024"; + private const string PATH_LOWEST_DIFFUSE_ROUGHNESS = "FallbackTextures/fallback_diffuse_roughness_256"; + private const string PATH_HIGHEST_NORMAL = "FallbackTextures/fallback_normal_2048"; + private const string PATH_MEDIUM_NORMAL = "FallbackTextures/fallback_normal_1024"; + private const string PATH_LOWEST_NORMAL = "FallbackTextures/fallback_normal_256"; + + private const int GPU_TEXTURE_COPY_WAIT_TIME = 10; + + public OvrAvatarTextureCopyManager() + { + texturesToCopy = new Queue(TEXTURES_TO_COPY_QUEUE_CAPACITY); + textureSets = new Dictionary(); + } + + public void Update() + { + if (texturesToCopy.Count == 0) + { + return; + } + + lock (texturesToCopy) + { + for (int i = 0; i < Mathf.Min(COPIES_PER_FRAME, texturesToCopy.Count); ++i) + { + CopyTexture(texturesToCopy.Dequeue()); + } + } + } + + public int GetTextureCount() + { + return texturesToCopy.Count; + } + + public void CopyTexture( + Texture src, + Texture dst, + int mipLevel, + int mipSize, + int dstElement, + bool useQueue = true) + { + var copyTextureParams = new CopyTextureParams(src, dst, mipLevel, mipSize, dstElement); + + if (useQueue) + { + lock (texturesToCopy) + { + if (texturesToCopy.Count < TEXTURES_TO_COPY_QUEUE_CAPACITY) + { + texturesToCopy.Enqueue(copyTextureParams); + } + else + { + // Queue is full so copy texture immediately + CopyTexture(copyTextureParams); + } + } + } + else + { + CopyTexture(copyTextureParams); + } + } + + private void CopyTexture(CopyTextureParams copyTextureParams) + { + Graphics.CopyTexture( + copyTextureParams.Src, + 0, + copyTextureParams.Mip, + copyTextureParams.Dst, + copyTextureParams.DstElement, + copyTextureParams.Mip); + } + + public void AddTextureIDToTextureSet(int gameobjectID, ulong textureID, bool isSingleMesh) + { + if (!textureSets.ContainsKey(gameobjectID)) + { + TextureSet newTextureSet = new TextureSet(new Dictionary(), false); + newTextureSet.TextureIDSingleMeshPair.Add(textureID, isSingleMesh); + textureSets.Add(gameobjectID, newTextureSet); + } + else + { + bool TexIDSingleMesh; + if (textureSets[gameobjectID].TextureIDSingleMeshPair.TryGetValue(textureID, out TexIDSingleMesh)) + { + if (!TexIDSingleMesh && isSingleMesh) + { + textureSets[gameobjectID].TextureIDSingleMeshPair[textureID] = true; + } + } + else + { + textureSets[gameobjectID].TextureIDSingleMeshPair.Add(textureID, isSingleMesh); + } + } + } + + // This is called by a fully loaded avatar using combined mesh to safely delete unused textures. + public void DeleteTextureSet(int gameobjectID) + { + TextureSet textureSetToDelete; + if (!textureSets.TryGetValue(gameobjectID, out textureSetToDelete)) + { + return; + }; + + if (textureSetToDelete.IsProcessed) + { + return; + } + + StartCoroutine(DeleteTextureSetCoroutine(textureSetToDelete, gameobjectID)); + } + + private IEnumerator DeleteTextureSetCoroutine(TextureSet textureSetToDelete, int gameobjectID) + { + // Wait a conservative amount of time for gpu upload to finish. Unity 2017 doesn't support async GPU calls, + // so this 10 second time is a very conservative delay for this process to occur, which should be <1 sec. + yield return new WaitForSeconds(GPU_TEXTURE_COPY_WAIT_TIME); + + // Spin if an avatar is loading + while (OvrAvatarSDKManager.Instance.IsAvatarLoading()) + { + yield return null; + } + + // The avatar's texture set is compared against all other loaded or loading avatar texture sets. + foreach (var textureIdAndSingleMeshFlag in textureSetToDelete.TextureIDSingleMeshPair) + { + bool triggerDelete = !textureIdAndSingleMeshFlag.Value; + if (triggerDelete) + { + foreach (KeyValuePair textureSet in textureSets) + { + if (textureSet.Key == gameobjectID) + { + continue; + } + + foreach (var comparisonTextureIDSingleMeshPair in textureSet.Value.TextureIDSingleMeshPair) + { + // Mark the texture as not deletable if it's present in another set and that set hasn't been processed + // or that texture ID is marked as part of a single mesh component. + if (comparisonTextureIDSingleMeshPair.Key == textureIdAndSingleMeshFlag.Key && + (!textureSet.Value.IsProcessed || comparisonTextureIDSingleMeshPair.Value)) + { + triggerDelete = false; + break; + } + } + + if (!triggerDelete) + { + break; + } + } + } + + if (triggerDelete) + { + Texture2D textureToDelete = OvrAvatarComponent.GetLoadedTexture(textureIdAndSingleMeshFlag.Key); + if (textureToDelete != null) + { + AvatarLogger.Log("Deleting texture " + textureIdAndSingleMeshFlag.Key); + OvrAvatarSDKManager.Instance.DeleteAssetFromCache(textureIdAndSingleMeshFlag.Key); + Destroy(textureToDelete); + } + } + } + textureSetToDelete.IsProcessed = true; + textureSets.Remove(gameobjectID); + } + + public void CheckFallbackTextureSet(ovrAvatarAssetLevelOfDetail lod) + { + if (FallbackTextureSets[(int)lod].Initialized) + { + return; + } + + InitFallbackTextureSet(lod); + } + + private void InitFallbackTextureSet(ovrAvatarAssetLevelOfDetail lod) + { + FallbackTextureSets[(int)lod].DiffuseRoughness = FallbackTextureSets[(int)lod].DiffuseRoughness = + Resources.Load(FALLBACK_TEXTURE_PATHS_DIFFUSE_ROUGHNESS[(int)lod]); + FallbackTextureSets[(int)lod].Normal = FallbackTextureSets[(int)lod].Normal = + Resources.Load(FALLBACK_TEXTURE_PATHS_NORMAL[(int)lod]); + FallbackTextureSets[(int)lod].Initialized = true; + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs.meta new file mode 100644 index 0000000..bdb0d1a --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarTextureCopyManager.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bb5b00817cd46d645ac8b607693c37ce +timeCreated: 1519680044 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs b/Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs new file mode 100644 index 0000000..801bd75 --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs @@ -0,0 +1,44 @@ +using Oculus.Avatar; + +public class OvrAvatarTouchController : OvrAvatarComponent +{ + public bool isLeftHand = true; + ovrAvatarControllerComponent component = new ovrAvatarControllerComponent(); + + void Update() + { + if (owner == null) + { + return; + } + + bool hasComponent = false; + if (isLeftHand) + { + hasComponent = CAPI.ovrAvatarPose_GetLeftControllerComponent(owner.sdkAvatar, ref component); + } + else + { + hasComponent = CAPI.ovrAvatarPose_GetRightControllerComponent(owner.sdkAvatar, ref component); + } + + if (hasComponent) + { + UpdateAvatar(component.renderComponent); + } + else + { + if (isLeftHand) + { + owner.ControllerLeft = null; + + } + else + { + owner.ControllerRight = null; + } + + Destroy(this); + } + } +} diff --git a/Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs.meta b/Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs.meta new file mode 100644 index 0000000..2838f2a --- /dev/null +++ b/Assets/Oculus/Avatar/Scripts/OvrAvatarTouchController.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 77e19ec58d4a9e844970103e5bd8946a +timeCreated: 1464050556 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync.meta b/Assets/Oculus/LipSync.meta new file mode 100644 index 0000000..8ca8805 --- /dev/null +++ b/Assets/Oculus/LipSync.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: be2772cc99fe640cf9d487c51f98f30e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Assets.meta b/Assets/Oculus/LipSync/Assets.meta new file mode 100644 index 0000000..c12913e --- /dev/null +++ b/Assets/Oculus/LipSync/Assets.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 404b6b1044f864c83becc58f44a8dff5 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Assets/OfflineModel.meta b/Assets/Oculus/LipSync/Assets/OfflineModel.meta new file mode 100644 index 0000000..9c2b996 --- /dev/null +++ b/Assets/Oculus/LipSync/Assets/OfflineModel.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b2d242d170b44fc3b3a1b9ba4adc0a7 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Assets/OfflineModel/ovrlipsync_offline_model.pb b/Assets/Oculus/LipSync/Assets/OfflineModel/ovrlipsync_offline_model.pb new file mode 100644 index 0000000..df5fadf Binary files /dev/null and b/Assets/Oculus/LipSync/Assets/OfflineModel/ovrlipsync_offline_model.pb differ diff --git a/Assets/Oculus/LipSync/Assets/OfflineModel/ovrlipsync_offline_model.pb.meta b/Assets/Oculus/LipSync/Assets/OfflineModel/ovrlipsync_offline_model.pb.meta new file mode 100644 index 0000000..c8de439 --- /dev/null +++ b/Assets/Oculus/LipSync/Assets/OfflineModel/ovrlipsync_offline_model.pb.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3e1d42ccc29c54bf68636db8acf2eed8 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Audio.meta b/Assets/Oculus/LipSync/Audio.meta new file mode 100644 index 0000000..33e844c --- /dev/null +++ b/Assets/Oculus/LipSync/Audio.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 76b873b07f695cb4cb6515ecf670c814 +folderAsset: yes +timeCreated: 1441295107 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Audio/vox_lp_01.wav b/Assets/Oculus/LipSync/Audio/vox_lp_01.wav new file mode 100644 index 0000000..4510617 --- /dev/null +++ b/Assets/Oculus/LipSync/Audio/vox_lp_01.wav @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:5dc180c440bace557813d22fb4330d0ff6231e68745bba4ce39150b02e741d33 +size 3551236 diff --git a/Assets/Oculus/LipSync/Audio/vox_lp_01.wav.meta b/Assets/Oculus/LipSync/Audio/vox_lp_01.wav.meta new file mode 100644 index 0000000..79ef45d --- /dev/null +++ b/Assets/Oculus/LipSync/Audio/vox_lp_01.wav.meta @@ -0,0 +1,24 @@ +fileFormatVersion: 2 +guid: e21cea670b0f32c428ee862e590a7108 +timeCreated: 1528844468 +licenseType: Pro +AudioImporter: + externalObjects: {} + serializedVersion: 6 + defaultSettings: + loadType: 0 + sampleRateSetting: 0 + sampleRateOverride: 44100 + compressionFormat: 1 + quality: 1 + conversionMode: 0 + platformSettingOverrides: {} + forceToMono: 0 + normalize: 1 + preloadAudioData: 1 + loadInBackground: 0 + ambisonic: 0 + 3D: 1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Audio/vox_lp_01_lipSync.asset b/Assets/Oculus/LipSync/Audio/vox_lp_01_lipSync.asset new file mode 100644 index 0000000..4b90d81 --- /dev/null +++ b/Assets/Oculus/LipSync/Audio/vox_lp_01_lipSync.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28325c81d3c0c5db6f85d1084af9aae5ee66be136384d41396d907a3ee44c25e +size 573541 diff --git a/Assets/Oculus/LipSync/Audio/vox_lp_01_lipSync.asset.meta b/Assets/Oculus/LipSync/Audio/vox_lp_01_lipSync.asset.meta new file mode 100644 index 0000000..31043f8 --- /dev/null +++ b/Assets/Oculus/LipSync/Audio/vox_lp_01_lipSync.asset.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1ccea2acd443f4ad4bb9a9f33fc960c0 +timeCreated: 1536698747 +licenseType: Pro +NativeFormatImporter: + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Editor.meta b/Assets/Oculus/LipSync/Editor.meta new file mode 100644 index 0000000..b03ec35 --- /dev/null +++ b/Assets/Oculus/LipSync/Editor.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 7152fa4bbe0044f12886bfb6274626bf +folderAsset: yes +timeCreated: 1496772356 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Editor/OVRLipSyncBuildPostProcessor.cs b/Assets/Oculus/LipSync/Editor/OVRLipSyncBuildPostProcessor.cs new file mode 100644 index 0000000..80ef8cc --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRLipSyncBuildPostProcessor.cs @@ -0,0 +1,99 @@ +/************************************************************************************ +Filename : OVRLipSyncBuildPostProcessor.cs +Content : Editor extension to generate LipSync-powered iOS apps +Created : Feb 11th, 2019 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +#if UNITY_IOS +using UnityEngine; +using UnityEditor; +using UnityEditor.Callbacks; +using UnityEditor.iOS.Xcode; +using System.IO; +using System.Text.RegularExpressions; + +class OVRLipSyncBuildPostProcessor : MonoBehaviour +{ + [PostProcessBuildAttribute(1)] + public static void OnPostprocessBuild(BuildTarget target, string pathToBuiltProject) + { + if (target == BuildTarget.iOS) + { + AddMicrophoneAccess(Path.Combine(pathToBuiltProject, "Info.plist")); + AddEmbeddedBinary(PBXProject.GetPBXProjectPath(pathToBuiltProject)); + } + } + + private static void AddMicrophoneAccess(string infoPlistPath) + { + const string micUsageProperty = "NSMicrophoneUsageDescription"; + + var plist = new PlistDocument(); + plist.ReadFromFile(infoPlistPath); + var rootDict = plist.root.AsDict(); + // Don't override the description other might have edited already + if (rootDict.values.ContainsKey(micUsageProperty)) + { + return; + } + rootDict.SetString(micUsageProperty, "To lipsync you"); + plist.WriteToFile(infoPlistPath); + } + + private static void AddEmbeddedBinary(string projectPath) + { + const string buildPhaseName = "Embed Libraries"; + const string dylibName = "libOVRLipSync.dylib"; + + var project = new PBXProject(); + project.ReadFromFile(projectPath); + + // Don't add the same library twice + if (project.FindFileGuidByProjectPath(dylibName) != null) + { + return; + } + + var targetGUID = project.TargetGuidByName(PBXProject.GetUnityTargetName()); + // Limit the target to ARM64 + project.SetBuildProperty(targetGUID, "ARCHS", "arm64"); + + // Add dylib to the project + var dylibGUID = project.AddFile( + Path.Combine(Application.dataPath, "Oculus/LipSync/Plugins/iOS/" + dylibName), + dylibName); + // Copy it to the same folder as executable + var embedPhaseGuid = project.AddCopyFilesBuildPhase(targetGUID, buildPhaseName, "", "6"); + project.AddFileToBuildSection(targetGUID, embedPhaseGuid, dylibGUID); + var content = project.WriteToString(); + + // Add CodeSignOnCopy attribute ot the library using an ugly regex + content = Regex.Replace(content, + "(?<="+ buildPhaseName + ")(?:.*)(\\/\\* " + Regex.Escape(dylibName) + " \\*\\/)(?=; };)", + m => m.Value.Replace( + "/* " + dylibName + " */", + "/* " + dylibName + " */; settings = {ATTRIBUTES = (CodeSignOnCopy, );}" + ) + ); + File.WriteAllText(projectPath, content); + } + +} + +#endif diff --git a/Assets/Oculus/LipSync/Editor/OVRLipSyncBuildPostProcessor.cs.meta b/Assets/Oculus/LipSync/Editor/OVRLipSyncBuildPostProcessor.cs.meta new file mode 100644 index 0000000..ecf2ebf --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRLipSyncBuildPostProcessor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 73f38d977e4ed45f48b632a00fb9c579 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Editor/OVRLipSyncContextMorphTargetEditor.cs b/Assets/Oculus/LipSync/Editor/OVRLipSyncContextMorphTargetEditor.cs new file mode 100644 index 0000000..a9b58a4 --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRLipSyncContextMorphTargetEditor.cs @@ -0,0 +1,125 @@ +/************************************************************************************ +Filename : OVRLipSyncContextMorphTargetEditor.cs +Content : This bridges the viseme output to the morph targets +Created : December 21st, 2018 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using UnityEditor; + +[CustomEditor(typeof(OVRLipSyncContextMorphTarget))] +public class OVRLipSyncContextMorphTargetEditor : Editor +{ + SerializedProperty skinnedMeshRenderer; + SerializedProperty visemeToBlendTargets; + SerializedProperty visemeTestKeys; + SerializedProperty laughterKey; + SerializedProperty laughterBlendTarget; + SerializedProperty laughterThreshold; + SerializedProperty laughterMultiplier; + SerializedProperty smoothAmounth; + private static string[] visemeNames = new string[] { + "sil", "PP", "FF", "TH", + "DD", "kk", "CH", "SS", + "nn", "RR", "aa", "E", + "ih", "oh", "ou" }; + void OnEnable() + { + skinnedMeshRenderer = serializedObject.FindProperty("skinnedMeshRenderer"); + visemeToBlendTargets = serializedObject.FindProperty("visemeToBlendTargets"); + visemeTestKeys = serializedObject.FindProperty("visemeTestKeys"); + laughterKey = serializedObject.FindProperty("laughterKey"); + laughterBlendTarget = serializedObject.FindProperty("laughterBlendTarget"); + laughterThreshold = serializedObject.FindProperty("laughterThreshold"); + laughterMultiplier = serializedObject.FindProperty("laughterMultiplier"); + smoothAmounth = serializedObject.FindProperty("smoothAmount"); + } + + private void BlendNameProperty(SerializedProperty prop, string name, string[] blendNames = null) + { + if (blendNames == null) + { + EditorGUILayout.PropertyField(prop, new GUIContent(name)); + return; + } + var values = new int[blendNames.Length + 1]; + var options = new GUIContent[blendNames.Length + 1]; + values[0] = -1; + options[0] = new GUIContent(" "); + for(int i = 0; i < blendNames.Length; ++i) + { + values[i + 1] = i; + options[i + 1] = new GUIContent(blendNames[i]); + } + EditorGUILayout.IntPopup(prop, options, values, new GUIContent(name)); + } + + private string[] GetMeshBlendNames() + { + var morphTarget = (OVRLipSyncContextMorphTarget)serializedObject.targetObject; + if (morphTarget == null || morphTarget.skinnedMeshRenderer == null) + { + return null; + } + var mesh = morphTarget.skinnedMeshRenderer.sharedMesh; + var blendshapeCount = mesh.blendShapeCount; + var blendNames = new string[blendshapeCount]; + for(int i = 0; i < mesh.blendShapeCount; ++i) + { + blendNames[i] = mesh.GetBlendShapeName(i); + } + return blendNames; + } + public override void OnInspectorGUI() + { + var blendNames = GetMeshBlendNames(); + var morphTarget = (OVRLipSyncContextMorphTarget)serializedObject.targetObject; + + serializedObject.Update(); + EditorGUILayout.PropertyField(skinnedMeshRenderer); + if (EditorGUILayout.PropertyField(visemeToBlendTargets)) + { + EditorGUI.indentLevel++; + for(int i = 1; i < visemeNames.Length; ++i) + { + BlendNameProperty(visemeToBlendTargets.GetArrayElementAtIndex(i), visemeNames[i], blendNames); + } + BlendNameProperty(laughterBlendTarget, "Laughter", blendNames); + EditorGUI.indentLevel--; + } + if (morphTarget) + { + morphTarget.enableVisemeTestKeys = EditorGUILayout.ToggleLeft("Enable Viseme Test Keys", morphTarget.enableVisemeTestKeys); + } + if (EditorGUILayout.PropertyField(visemeTestKeys)) + { + EditorGUI.indentLevel++; + for(int i = 1; i < visemeNames.Length; ++i) + { + EditorGUILayout.PropertyField(visemeTestKeys.GetArrayElementAtIndex(i), new GUIContent(visemeNames[i])); + } + EditorGUILayout.PropertyField(laughterKey, new GUIContent("Laughter")); + EditorGUI.indentLevel--; + } + EditorGUILayout.PropertyField(laughterThreshold); + EditorGUILayout.PropertyField(laughterMultiplier); + EditorGUILayout.PropertyField(smoothAmounth); + serializedObject.ApplyModifiedProperties(); + } +} diff --git a/Assets/Oculus/LipSync/Editor/OVRLipSyncContextMorphTargetEditor.cs.meta b/Assets/Oculus/LipSync/Editor/OVRLipSyncContextMorphTargetEditor.cs.meta new file mode 100644 index 0000000..5a41a7f --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRLipSyncContextMorphTargetEditor.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a7d01b0eb149d9945a23728e5c7f5fcb +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Editor/OVRLipSyncTool.cs b/Assets/Oculus/LipSync/Editor/OVRLipSyncTool.cs new file mode 100644 index 0000000..6cde1e3 --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRLipSyncTool.cs @@ -0,0 +1,166 @@ +/************************************************************************************ +Filename : OVRLipSyncTool.cs +Content : Editor tool for generating lip sync assets +Created : May 17th, 2018 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using UnityEditor; +using System.IO; +using System.Collections; +using System.Collections.Generic; + +class OVRLipSyncToolLoader +{ + public static List clipQueue; + public static IEnumerator processor; + + // To show progress we use the total seconds of clip + public static float totalLengthOfClips; + public static float totalLengthOfClipsProcessed; + + public static IEnumerator ProcessClips(bool useOfflineModel) + { + if (clipQueue == null || clipQueue.Count == 0) + { + yield break; + } + + while (clipQueue.Count > 0) + { + // Pop a clip off the list + AudioClip clip = clipQueue[0]; + clipQueue.RemoveAt(0); + + if (clip.loadType != AudioClipLoadType.DecompressOnLoad) + { + Debug.LogError(clip.name + + ": Cannot process phonemes from an audio clip unless " + + "its load type is set to DecompressOnLoad."); + continue; + } + + // Update progress + if (totalLengthOfClips > 0.0f) + { + EditorUtility.DisplayProgressBar("Generating Lip Sync Assets...", "Processing clip " + clip.name + "...", + totalLengthOfClipsProcessed / totalLengthOfClips); + } + + if (!clip.preloadAudioData) + { + clip.LoadAudioData(); + + Debug.LogWarning(clip.name + + ": Audio data is not pre-loaded. Data will be loaded then" + + "unloaded on completion."); + + while (clip.loadState != AudioDataLoadState.Loaded) + { + yield return new WaitForSeconds(0.1f); + } + } + + var sequence = + OVRLipSyncSequence.CreateSequenceFromAudioClip(clip, useOfflineModel); + if (sequence != null) + { + var path = AssetDatabase.GetAssetPath(clip); + var newPath = path.Replace(Path.GetExtension(path), "_lipSync.asset"); + var existingSequence = AssetDatabase.LoadAssetAtPath(newPath); + if (existingSequence != null) + { + EditorUtility.CopySerialized(sequence, existingSequence); + AssetDatabase.SaveAssets(); + } + else + { + AssetDatabase.CreateAsset(sequence, newPath); + + } + } + AssetDatabase.Refresh(); + + if (!clip.preloadAudioData) + { + clip.UnloadAudioData(); + } + + totalLengthOfClipsProcessed += clip.length; + } + + EditorUtility.ClearProgressBar(); + } + + static OVRLipSyncToolLoader() + { + processor = null; + EditorApplication.update += Update; + } + static void Update() + { + if (processor != null) + { + processor.MoveNext(); + } + } +} + +class OVRLipSyncTool +{ + [MenuItem("Oculus/Lip Sync/Generate Lip Sync Assets", false, 2000000)] + static void GenerateLipSyncAssets() + { + GenerateLipSyncAssetsInternal(false); + } + + [MenuItem("Oculus/Lip Sync/Generate Lip Sync Assets With Offline Model", false, 2500000)] + static void GenerateLipSyncAssetsOffline() + { + GenerateLipSyncAssetsInternal(true); + } + + private static void GenerateLipSyncAssetsInternal(bool useOfflineModel) + + { + + if (OVRLipSyncToolLoader.clipQueue == null) + { + OVRLipSyncToolLoader.clipQueue = new List(); + } + + OVRLipSyncToolLoader.totalLengthOfClips = 0.0f; + OVRLipSyncToolLoader.totalLengthOfClipsProcessed = 0.0f; + + for (int i = 0; i < Selection.objects.Length; ++i) + { + Object obj = Selection.objects[i]; + if (obj is AudioClip) + { + AudioClip clip = (AudioClip)obj; + + OVRLipSyncToolLoader.clipQueue.Add(clip); + + OVRLipSyncToolLoader.totalLengthOfClips += clip.length; + } + } + + OVRLipSyncToolLoader.processor = OVRLipSyncToolLoader.ProcessClips(useOfflineModel); + } +} diff --git a/Assets/Oculus/LipSync/Editor/OVRLipSyncTool.cs.meta b/Assets/Oculus/LipSync/Editor/OVRLipSyncTool.cs.meta new file mode 100644 index 0000000..9bba43d --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRLipSyncTool.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 08b0ff764adc142d79bfae7dd917cc16 +timeCreated: 1491977874 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Editor/OVRNamedArrayPropertyDrawer.cs b/Assets/Oculus/LipSync/Editor/OVRNamedArrayPropertyDrawer.cs new file mode 100644 index 0000000..e8205a5 --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRNamedArrayPropertyDrawer.cs @@ -0,0 +1,38 @@ +/************************************************************************************ +Filename : OVRNamedArrayPropertyDrawer.cs +Content : Adds a custom named array drawer to the Unity editor +Created : May 17th, 2018 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using UnityEditor; + +// Adds a custom named array drawer to the Unity editor +[CustomPropertyDrawer( typeof(OVRNamedArrayAttribute) )] +public class OVRNamedArrayPropertyDrawer : PropertyDrawer { + public override void OnGUI( Rect rect, SerializedProperty property, GUIContent label ) { + try { + int pos = int.Parse(property.propertyPath.Split('[', ']')[1]); + EditorGUI.PropertyField( rect, property, + new GUIContent( ( (OVRNamedArrayAttribute)attribute ).names[pos] ) ); + } catch { + EditorGUI.PropertyField( rect, property, label ); + } + } +} diff --git a/Assets/Oculus/LipSync/Editor/OVRNamedArrayPropertyDrawer.cs.meta b/Assets/Oculus/LipSync/Editor/OVRNamedArrayPropertyDrawer.cs.meta new file mode 100644 index 0000000..55dd958 --- /dev/null +++ b/Assets/Oculus/LipSync/Editor/OVRNamedArrayPropertyDrawer.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c2d166626e0b34a40b774467cc6c5868 +timeCreated: 1534993516 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models.meta b/Assets/Oculus/LipSync/Models.meta new file mode 100644 index 0000000..01ed6cb --- /dev/null +++ b/Assets/Oculus/LipSync/Models.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: fe1e90827fcfcac4883e383c51a78ddd +folderAsset: yes +timeCreated: 1437169289 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph.meta new file mode 100644 index 0000000..31ee72f --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 196133c6d4044404698c27b5d1724e2a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm.meta new file mode 100644 index 0000000..ea31c0d --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 39e3127a140761448a38ba5e62822523 +folderAsset: yes +timeCreated: 1571342691 +licenseType: Store +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm/melinda_DIFF.png b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm/melinda_DIFF.png new file mode 100644 index 0000000..c795959 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm/melinda_DIFF.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:815839d03d7fbe191b9f7da92531598db27bf1432cb88235ffde30458231980b +size 1671848 diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm/melinda_DIFF.png.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm/melinda_DIFF.png.meta new file mode 100644 index 0000000..474ae62 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbm/melinda_DIFF.png.meta @@ -0,0 +1,68 @@ +fileFormatVersion: 2 +guid: dab49ccccea81c4469fd0901d806845b +timeCreated: 1573650766 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbx b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbx new file mode 100644 index 0000000..7106de1 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbx @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:a10776afd88cfa70288ac4151b4780bfbd06d5b2338d899887e2eff617c87a89 +size 2787536 diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbx.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbx.meta new file mode 100644 index 0000000..5870bae --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Female.fbx.meta @@ -0,0 +1,156 @@ +fileFormatVersion: 2 +guid: cbaf1c32e7ec84f10a51be1b09c0ef46 +ModelImporter: + serializedVersion: 22 + fileIDToRecycleName: + 100000: avatar_rig_GRP + 100002: AVATARS_geom + 100004: body + 100006: body_gen_PLY + 100008: body_JNT + 100010: chest_JNT + 100012: hair_gen_PLY + 100014: head_JNT + 100016: //RootNode + 100018: neck_JNT + 100020: neckBase_JNT + 100022: root_JNT + 100024: shirt_PLY + 400000: avatar_rig_GRP + 400002: AVATARS_geom + 400004: body + 400006: body_gen_PLY + 400008: body_JNT + 400010: chest_JNT + 400012: hair_gen_PLY + 400014: head_JNT + 400016: //RootNode + 400018: neck_JNT + 400020: neckBase_JNT + 400022: root_JNT + 400024: shirt_PLY + 2100000: shirt + 2100002: innerEye + 2100004: eyelashes + 2100006: outerEyeShell + 2100008: head + 2100010: hair + 2300000: hair_gen_PLY + 2300002: shirt_PLY + 3300000: hair_gen_PLY + 3300002: shirt_PLY + 4300000: shirt_PLY + 4300002: body_gen_PLY + 4300004: hair_gen_PLY + 9500000: //RootNode + 13700000: body_gen_PLY + externalObjects: + - first: + type: UnityEngine:Material + assembly: UnityEngine.CoreModule + name: eyelashes + second: {fileID: 2100000, guid: e906d4c6bf3304d5dac06eee4fe24c54, type: 2} + - first: + type: UnityEngine:Material + assembly: UnityEngine.CoreModule + name: hair + second: {fileID: 2100000, guid: d0455a0ebc21e4c758037cb4b82bebd2, type: 2} + - first: + type: UnityEngine:Material + assembly: UnityEngine.CoreModule + name: head + second: {fileID: 2100000, guid: 3d380053edac948aa9d428fce6a5288b, type: 2} + - first: + type: UnityEngine:Material + assembly: UnityEngine.CoreModule + name: innerEye + second: {fileID: 2100000, guid: 3d380053edac948aa9d428fce6a5288b, type: 2} + - first: + type: UnityEngine:Material + assembly: UnityEngine.CoreModule + name: outerEyeShell + second: {fileID: 2100000, guid: 76f25b997543f432bbe00737485b392e, type: 2} + - first: + type: UnityEngine:Material + assembly: UnityEngine.CoreModule + name: shirt + second: {fileID: 2100000, guid: 0ad01ecbcffbb4c91af7ffa1ebc14f74, type: 2} + materials: + importMaterials: 1 + materialName: 0 + materialSearch: 1 + materialLocation: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + resampleCurves: 1 + optimizeGameObjects: 0 + motionNodeName: + rigImportErrors: + rigImportWarnings: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + importAnimatedCustomProperties: 0 + animationCompression: 1 + animationRotationError: 0.5 + animationPositionError: 0.5 + animationScaleError: 0.5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + extraUserProperties: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + importVisibility: 1 + importBlendShapes: 1 + importCameras: 1 + importLights: 1 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + optimizeMeshForGPU: 1 + keepQuads: 0 + weldVertices: 1 + preserveHierarchy: 0 + indexFormat: 0 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVPackMargin: 4 + useFileScale: 1 + tangentSpace: + normalSmoothAngle: 60 + normalImportMode: 0 + tangentImportMode: 3 + normalCalculationMode: 4 + importAnimation: 1 + copyAvatar: 0 + humanDescription: + serializedVersion: 2 + human: [] + skeleton: [] + armTwist: 0.5 + foreArmTwist: 0.5 + upperLegTwist: 0.5 + legTwist: 0.5 + armStretch: 0.05 + legStretch: 0.05 + feetSpacing: 0 + rootMotionBoneName: + rootMotionBoneRotation: {x: 0, y: 0, z: 0, w: 1} + hasTranslationDoF: 0 + hasExtraRoot: 0 + skeletonHasParents: 1 + lastHumanDescriptionAvatarSource: {instanceID: 0} + animationType: 2 + humanoidOversampling: 1 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials.meta new file mode 100644 index 0000000..c982367 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: fd2bb13164cc64a2087f565d8c66af4f +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/eyelashes.mat b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/eyelashes.mat new file mode 100644 index 0000000..b950cac --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/eyelashes.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: eyelashes + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _ALPHATEST_ON _NORMALMAP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 2450 + stringTagMap: + RenderType: TransparentCutout + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: e2d7f58dd4c84431b994602bf58090de, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 466d221c743ab400a8318afe7b830593, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 1 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.5, g: 0.5, b: 0.5, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 0} diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/eyelashes.mat.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/eyelashes.mat.meta new file mode 100644 index 0000000..00389d4 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/eyelashes.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e906d4c6bf3304d5dac06eee4fe24c54 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/hair.mat b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/hair.mat new file mode 100644 index 0000000..0d1ea40 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/hair.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: hair + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _NORMALMAP + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: e59519b819b1843cb94acf4e281e8c45, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.531 + - _GlossyReflections: 1 + - _Metallic: 0.107 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0, g: 0, b: 0, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 0} diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/hair.mat.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/hair.mat.meta new file mode 100644 index 0000000..0835603 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/hair.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d0455a0ebc21e4c758037cb4b82bebd2 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/melinda_DIFF.mat b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/melinda_DIFF.mat new file mode 100644 index 0000000..bc3ddfc --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/melinda_DIFF.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: melinda_DIFF + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: dab49ccccea81c4469fd0901d806845b, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 1, b: 1, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/melinda_DIFF.mat.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/melinda_DIFF.mat.meta new file mode 100644 index 0000000..b788049 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/melinda_DIFF.mat.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c11eea25db1a81c429314ae5ac32dc48 +timeCreated: 1573650769 +licenseType: Pro +NativeFormatImporter: + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/outerEyeShell.mat b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/outerEyeShell.mat new file mode 100644 index 0000000..4a64d22 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/outerEyeShell.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: outerEyeShell + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _ALPHAPREMULTIPLY_ON _EMISSION _NORMALMAP _SPECULARHIGHLIGHTS_OFF + m_LightmapFlags: 0 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 3000 + stringTagMap: + RenderType: Transparent + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: e2d7f58dd4c84431b994602bf58090de, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 466d221c743ab400a8318afe7b830593, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 10 + - _GlossMapScale: 1 + - _Glossiness: 0 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 3 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 0 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 0 + m_Colors: + - _Color: {r: 1, g: 0.9937241, b: 0.987, a: 0.09803922} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 0} diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/outerEyeShell.mat.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/outerEyeShell.mat.meta new file mode 100644 index 0000000..1dd8d03 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/outerEyeShell.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 76f25b997543f432bbe00737485b392e +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/shirt.mat b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/shirt.mat new file mode 100644 index 0000000..11b926c --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/shirt.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: shirt + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 1 + - _Glossiness: 0 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.894, g: 0.6504, b: 0.0697, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 0} diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/shirt.mat.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/shirt.mat.meta new file mode 100644 index 0000000..4df7211 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/shirt.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0ad01ecbcffbb4c91af7ffa1ebc14f74 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/skin_DIFF.mat b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/skin_DIFF.mat new file mode 100644 index 0000000..4656950 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/skin_DIFF.mat @@ -0,0 +1,76 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: skin_DIFF + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _EMISSION _METALLICGLOSSMAP _NORMALMAP _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A + m_LightmapFlags: 2 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 2800000, guid: e2d7f58dd4c84431b994602bf58090de, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 2800000, guid: 466d221c743ab400a8318afe7b830593, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 466d221c743ab400a8318afe7b830593, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 2800000, guid: 466d221c743ab400a8318afe7b830593, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _GlossMapScale: 0.105 + - _Glossiness: 0.347 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 1 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 1, g: 0.934, b: 1, a: 1} + - _EmissionColor: {r: 0.1, g: 0.1, b: 0.1, a: 1} diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/skin_DIFF.mat.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/skin_DIFF.mat.meta new file mode 100644 index 0000000..87bee8f --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/Materials/skin_DIFF.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d380053edac948aa9d428fce6a5288b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 2100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/hair_NRM.tga b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/hair_NRM.tga new file mode 100644 index 0000000..2d6ab00 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/hair_NRM.tga @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:52e0d37def5ccdd82a9598fde9e099cf4d41981a36f5b57f5ad1a186cd73c9bf +size 16777234 diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/hair_NRM.tga.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/hair_NRM.tga.meta new file mode 100644 index 0000000..be39aef --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/hair_NRM.tga.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: e59519b819b1843cb94acf4e281e8c45 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 1 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_DIFF.png b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_DIFF.png new file mode 100644 index 0000000..c795959 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_DIFF.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:815839d03d7fbe191b9f7da92531598db27bf1432cb88235ffde30458231980b +size 1671848 diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_DIFF.png.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_DIFF.png.meta new file mode 100644 index 0000000..e7f0bfc --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_DIFF.png.meta @@ -0,0 +1,76 @@ +fileFormatVersion: 2 +guid: 466d221c743ab400a8318afe7b830593 +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 1 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 0 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_NRM.tga b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_NRM.tga new file mode 100644 index 0000000..35afc70 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_NRM.tga @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:280745a3ac465a1ab6274b78739bb99a8a6d7507f698440c2836006dbeba6421 +size 12582956 diff --git a/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_NRM.tga.meta b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_NRM.tga.meta new file mode 100644 index 0000000..d632ec8 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/FemaleHead_Morph/skin_NRM.tga.meta @@ -0,0 +1,86 @@ +fileFormatVersion: 2 +guid: e2d7f58dd4c84431b994602bf58090de +TextureImporter: + fileIDToRecycleName: {} + externalObjects: {} + serializedVersion: 4 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + sRGBTexture: 0 + linearTexture: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapsPreserveCoverage: 0 + alphaTestReferenceValue: 0.5 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: 0.25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 6 + cubemapConvolution: 0 + seamlessCubemap: 0 + textureFormat: 1 + maxTextureSize: 2048 + textureSettings: + serializedVersion: 2 + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapU: -1 + wrapV: -1 + wrapW: -1 + nPOTScale: 1 + lightmap: 0 + compressionQuality: 50 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: 0.5, y: 0.5} + spritePixelsToUnits: 100 + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spriteGenerateFallbackPhysicsShape: 1 + alphaUsage: 1 + alphaIsTransparency: 0 + spriteTessellationDetail: -1 + textureType: 1 + textureShape: 1 + maxTextureSizeSet: 0 + compressionQualitySet: 0 + textureFormatSet: 0 + platformSettings: + - buildTarget: DefaultTexturePlatform + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + - buildTarget: Standalone + maxTextureSize: 2048 + resizeAlgorithm: 0 + textureFormat: -1 + textureCompression: 1 + compressionQuality: 50 + crunchedCompression: 0 + allowsAlphaSplitting: 0 + overridden: 0 + androidETC2FallbackOverride: 0 + spriteSheet: + serializedVersion: 2 + sprites: [] + outline: [] + physicsShape: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip.meta new file mode 100644 index 0000000..5e4433a --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a4624e55b9bd82444bf4687fee7e9346 +folderAsset: yes +timeCreated: 1444079114 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/CH.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/CH.png new file mode 100644 index 0000000..ec60ad1 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/CH.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd6fc954458a0f6f656787fe01971839555eb2c673c611532e96b5dd72774cf3 +size 25451 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/CH.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/CH.png.meta new file mode 100644 index 0000000..ff65f05 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/CH.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 5e6531e8f56b42547b8d2ddf7a7363d1 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/DD.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/DD.png new file mode 100644 index 0000000..35606e8 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/DD.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8da95fa86608dacdbc7925928b7003009401d4ea5f3759c3a00084f5795d7a40 +size 33552 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/DD.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/DD.png.meta new file mode 100644 index 0000000..6fe68cc --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/DD.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: ffbd7db31d3ad6e4a97a2f312babdcb6 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/E.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/E.png new file mode 100644 index 0000000..60ada66 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/E.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:670fb902a59f2c3b1ffd8c9d62bf8d218e9cdbee0cafed0a69a8624e41b52f9f +size 35533 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/E.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/E.png.meta new file mode 100644 index 0000000..f8f6111 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/E.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 29a06a0eefee1b542a7c286f1689ffab +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/FF.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/FF.png new file mode 100644 index 0000000..0002080 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/FF.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:4c746a538da229cfc27333b2adab082585149a4af4ef15e1f7673df56dd9ae83 +size 29052 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/FF.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/FF.png.meta new file mode 100644 index 0000000..7ee551e --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/FF.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 5563aa34057c347499c480ea33c5d593 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Head-2.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Head-2.png new file mode 100644 index 0000000..28db555 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Head-2.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:610272aa8477cf1aa070ea3ca1ed0490ebdd9b8dfdbab9b4cc3cfcbddeba89d2 +size 929032 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Head-2.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Head-2.png.meta new file mode 100644 index 0000000..8c53553 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Head-2.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 49ba9bfa609aed54ea6d5d1c1390bc15 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials.meta new file mode 100644 index 0000000..9865a67 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 6c05c00fcd925e1469ab8cab6316329f +folderAsset: yes +timeCreated: 1444079116 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/Head-2.mat b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/Head-2.mat new file mode 100644 index 0000000..84a745f --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/Head-2.mat @@ -0,0 +1,91 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: Head-2 + m_Shader: {fileID: 10800, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: + m_LightmapFlags: 4 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: -1 + stringTagMap: {} + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _AlphaTex: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: 49ba9bfa609aed54ea6d5d1c1390bc15, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _SpecGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - PixelSnap: 0 + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 0 + - _EnableExternalAlpha: 0 + - _GlossMapScale: 1 + - _Glossiness: 0.396 + - _GlossyReflections: 1 + - _InvFade: 1 + - _Metallic: 0 + - _Mode: 0 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 1 + m_Colors: + - _Color: {r: 0.5882353, g: 0.5882353, b: 0.5882353, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} + - _Flip: {r: 1, g: 1, b: 1, a: 1} + - _RendererColor: {r: 1, g: 1, b: 1, a: 1} + - _SpecColor: {r: 0.2, g: 0.2, b: 0.2, a: 1} + - _TintColor: {r: 0.5, g: 0.5, b: 0.5, a: 0.5} diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/Head-2.mat.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/Head-2.mat.meta new file mode 100644 index 0000000..6bf9955 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/Head-2.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b8f002f88e9d7e847b5306f3338f80db +timeCreated: 1444079116 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/sil.mat b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/sil.mat new file mode 100644 index 0000000..8dd227b --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/sil.mat @@ -0,0 +1,77 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!21 &2100000 +Material: + serializedVersion: 6 + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 0} + m_Name: sil + m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0} + m_ShaderKeywords: _ALPHAPREMULTIPLY_ON + m_LightmapFlags: 5 + m_EnableInstancingVariants: 0 + m_DoubleSidedGI: 0 + m_CustomRenderQueue: 3000 + stringTagMap: + RenderType: Transparent + disabledShaderPasses: [] + m_SavedProperties: + serializedVersion: 3 + m_TexEnvs: + - _BumpMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailAlbedoMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailMask: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _DetailNormalMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _EmissionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MainTex: + m_Texture: {fileID: 2800000, guid: bea5b996ab6235c4aaa1be9b11aea8c4, type: 3} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _MetallicGlossMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _OcclusionMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + - _ParallaxMap: + m_Texture: {fileID: 0} + m_Scale: {x: 1, y: 1} + m_Offset: {x: 0, y: 0} + m_Floats: + - _BumpScale: 1 + - _Cutoff: 0.5 + - _DetailNormalMapScale: 1 + - _DstBlend: 10 + - _GlossMapScale: 1 + - _Glossiness: 0.5 + - _GlossyReflections: 1 + - _Metallic: 0 + - _Mode: 3 + - _OcclusionStrength: 1 + - _Parallax: 0.02 + - _SmoothnessTextureChannel: 0 + - _SpecularHighlights: 1 + - _SrcBlend: 1 + - _UVSec: 0 + - _ZWrite: 0 + m_Colors: + - _Color: {r: 0.5882353, g: 0.5882353, b: 0.5882353, a: 1} + - _EmissionColor: {r: 0, g: 0, b: 0, a: 1} diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/sil.mat.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/sil.mat.meta new file mode 100644 index 0000000..34ed9c4 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/Materials/sil.mat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5290b3a55eaa1b7458665dc2d856c042 +timeCreated: 1444079116 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/PP.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/PP.png new file mode 100644 index 0000000..60d0eaa --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/PP.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:337f28092df83065807ad8fa3b340572a1547fbc951bc26afa949aa362d19adc +size 23424 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/PP.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/PP.png.meta new file mode 100644 index 0000000..20a2e8c --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/PP.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: bea5b996ab6235c4aaa1be9b11aea8c4 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RR.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RR.png new file mode 100644 index 0000000..438d340 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RR.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:edc300bbfe18b84486b4afcdb5eed82a9e343bc1d241c84600e773859b62a354 +size 30364 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RR.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RR.png.meta new file mode 100644 index 0000000..fb8292f --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RR.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 6d47a54f2b89a59459fd7561d360bab2 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RobotHead_TextureFlip.FBX b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RobotHead_TextureFlip.FBX new file mode 100644 index 0000000..f8da8d1 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RobotHead_TextureFlip.FBX @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6ea15d56daa390cf886d6bd9b0e00e15fef73d2840e15183ba7074ca3874fa76 +size 412016 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RobotHead_TextureFlip.FBX.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RobotHead_TextureFlip.FBX.meta new file mode 100644 index 0000000..57761a6 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/RobotHead_TextureFlip.FBX.meta @@ -0,0 +1,118 @@ +fileFormatVersion: 2 +guid: f82b1e3c015abaa409d91ab8eb628ac4 +timeCreated: 1444079116 +licenseType: Pro +ModelImporter: + serializedVersion: 18 + fileIDToRecycleName: + 100000: Eye-l + 100002: Eye-r + 100004: Head-0 + 100006: Head-1 + 100008: Head-2 + 100010: //RootNode + 100012: Head-3 + 100014: Head-4 + 100016: Head-5 + 100018: mouth + 400000: Eye-l + 400002: Eye-r + 400004: Head-0 + 400006: Head-1 + 400008: Head-2 + 400010: //RootNode + 400012: Head-3 + 400014: Head-4 + 400016: Head-5 + 400018: mouth + 2300000: Eye-l + 2300002: Eye-r + 2300004: Head-0 + 2300006: Head-1 + 2300008: Head-2 + 2300010: Head-3 + 2300012: Head-4 + 2300014: Head-5 + 2300016: mouth + 3300000: Eye-l + 3300002: Eye-r + 3300004: Head-0 + 3300006: Head-1 + 3300008: Head-2 + 3300010: Head-3 + 3300012: Head-4 + 3300014: Head-5 + 3300016: mouth + 4300000: Head-0 + 4300002: Eye-r + 4300004: Eye-l + 4300006: Head-5 + 4300008: Head-3 + 4300010: Head-4 + 4300012: Head-2 + 4300014: Head-1 + 4300016: mouth + materials: + importMaterials: 1 + materialName: 0 + materialSearch: 1 + animations: + legacyGenerateAnimations: 4 + bakeSimulation: 0 + optimizeGameObjects: 0 + motionNodeName: + animationImportErrors: + animationImportWarnings: + animationRetargetingWarnings: + animationDoRetargetingWarnings: 0 + animationCompression: 1 + animationRotationError: .5 + animationPositionError: .5 + animationScaleError: .5 + animationWrapMode: 0 + extraExposedTransformPaths: [] + clipAnimations: [] + isReadable: 1 + meshes: + lODScreenPercentages: [] + globalScale: 1 + meshCompression: 0 + addColliders: 0 + importBlendShapes: 1 + swapUVChannels: 0 + generateSecondaryUV: 0 + useFileUnits: 1 + optimizeMeshForGPU: 1 + keepQuads: 0 + weldVertices: 1 + secondaryUVAngleDistortion: 8 + secondaryUVAreaDistortion: 15.000001 + secondaryUVHardAngle: 88 + secondaryUVPackMargin: 4 + useFileScale: 1 + tangentSpace: + normalSmoothAngle: 60 + splitTangentsAcrossUV: 1 + normalImportMode: 0 + tangentImportMode: 1 + importAnimation: 1 + copyAvatar: 0 + humanDescription: + human: [] + skeleton: [] + armTwist: .5 + foreArmTwist: .5 + upperLegTwist: .5 + legTwist: .5 + armStretch: .0500000007 + legStretch: .0500000007 + feetSpacing: 0 + rootMotionBoneName: + hasTranslationDoF: 0 + lastHumanDescriptionAvatarSource: {instanceID: 0} + animationType: 0 + humanoidOversampling: 1 + additionalBone: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/SS.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/SS.png new file mode 100644 index 0000000..b9c281c --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/SS.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ee58de36e2fa3845ee229e2dcb83ad61241450a82e0728acd244f642de1651ad +size 31078 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/SS.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/SS.png.meta new file mode 100644 index 0000000..33525bf --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/SS.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 31e6326c0bd6143479322c5b4a5fe949 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/TH.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/TH.png new file mode 100644 index 0000000..e5c6f10 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/TH.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:abb274643d5d04ee1de5dac64249ef9d34dfb6f3e85a0b6b080ade08fbda69d3 +size 30408 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/TH.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/TH.png.meta new file mode 100644 index 0000000..6ff617a --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/TH.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: d14bb80824ed25b44a65ddfc7f591e29 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/aa.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/aa.png new file mode 100644 index 0000000..6a4818b --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/aa.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:44e7120534711f99e8271b829f21fc392711501f18719fb21a8d7c4384230503 +size 36059 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/aa.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/aa.png.meta new file mode 100644 index 0000000..d6d1235 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/aa.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 5c06354455999f94ea26114e261dde6d +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ih.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ih.png new file mode 100644 index 0000000..d99fe39 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ih.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:6786a7ee82685decbab0c0cd46e3361bf3b8b5a7f056a8ba913f28c920196821 +size 34404 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ih.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ih.png.meta new file mode 100644 index 0000000..63d7574 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ih.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: ad60c8114191fdf41aa0ea64e132add9 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/kk.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/kk.png new file mode 100644 index 0000000..ec60ad1 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/kk.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:cd6fc954458a0f6f656787fe01971839555eb2c673c611532e96b5dd72774cf3 +size 25451 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/kk.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/kk.png.meta new file mode 100644 index 0000000..8af7576 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/kk.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: ba0b9f69af91c5f46b490346e5552136 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/nn.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/nn.png new file mode 100644 index 0000000..8f9d1cf --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/nn.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b412668d470e00478618379d0c15a1799d6207769477f341f0295068c572e22e +size 28771 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/nn.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/nn.png.meta new file mode 100644 index 0000000..d6fdebc --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/nn.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 9c21cf8c4dffca9418cebd0a578972b4 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/oh.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/oh.png new file mode 100644 index 0000000..a2d1f83 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/oh.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8ef7c2ef17a3b5d2133c5675dbf710908b1f240eb7e18d9641d4f3e42cf78d2c +size 24218 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/oh.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/oh.png.meta new file mode 100644 index 0000000..619ecbc --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/oh.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 5f658e6e48970d340b4491a5fc959251 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ou.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ou.png new file mode 100644 index 0000000..92f7704 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ou.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8c00dc683934eb5d429db643105c6f09500659c3bcae8a4f8d1c59ada7511d62 +size 23355 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ou.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ou.png.meta new file mode 100644 index 0000000..fcd9e05 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/ou.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 660be1fdb8590b14bab012a991bdeb86 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/sil.png b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/sil.png new file mode 100644 index 0000000..adf018f --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/sil.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bf21f2138ec014003ec53db23a2fffe08ea49156024cb11312523da4c1ee2dbc +size 32716 diff --git a/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/sil.png.meta b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/sil.png.meta new file mode 100644 index 0000000..a543741 --- /dev/null +++ b/Assets/Oculus/LipSync/Models/RobotHead_TextureFlip/sil.png.meta @@ -0,0 +1,56 @@ +fileFormatVersion: 2 +guid: 46b2920291e9b8c4888ad3fe3f5e5e69 +timeCreated: 1444079115 +licenseType: Pro +TextureImporter: + fileIDToRecycleName: {} + serializedVersion: 2 + mipmaps: + mipMapMode: 0 + enableMipMap: 1 + linearTexture: 0 + correctGamma: 0 + fadeOut: 0 + borderMipMap: 0 + mipMapFadeDistanceStart: 1 + mipMapFadeDistanceEnd: 3 + bumpmap: + convertToNormalMap: 0 + externalNormalMap: 0 + heightScale: .25 + normalMapFilter: 0 + isReadable: 0 + grayScaleToAlpha: 0 + generateCubemap: 0 + cubemapConvolution: 0 + cubemapConvolutionSteps: 8 + cubemapConvolutionExponent: 1.5 + seamlessCubemap: 0 + textureFormat: -1 + maxTextureSize: 2048 + textureSettings: + filterMode: -1 + aniso: -1 + mipBias: -1 + wrapMode: -1 + nPOTScale: 1 + lightmap: 0 + rGBM: 0 + compressionQuality: 50 + allowsAlphaSplitting: 0 + spriteMode: 0 + spriteExtrude: 1 + spriteMeshType: 1 + alignment: 0 + spritePivot: {x: .5, y: .5} + spriteBorder: {x: 0, y: 0, z: 0, w: 0} + spritePixelsToUnits: 100 + alphaIsTransparency: 0 + textureType: -1 + buildTargetSettings: [] + spriteSheet: + sprites: [] + spritePackingTag: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins.meta b/Assets/Oculus/LipSync/Plugins.meta new file mode 100644 index 0000000..9acf7ec --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0cd9cc8c2d1778943869a1c67c9da38f +folderAsset: yes +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/Android32.meta b/Assets/Oculus/LipSync/Plugins/Android32.meta new file mode 100644 index 0000000..cc03a73 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/Android32.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: bbaa933ce12896e4eb67e30b96d795e9 +folderAsset: yes +timeCreated: 1536610734 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/Android32/libOVRLipSync.so b/Assets/Oculus/LipSync/Plugins/Android32/libOVRLipSync.so new file mode 100644 index 0000000..d6b582a Binary files /dev/null and b/Assets/Oculus/LipSync/Plugins/Android32/libOVRLipSync.so differ diff --git a/Assets/Oculus/LipSync/Plugins/Android32/libOVRLipSync.so.meta b/Assets/Oculus/LipSync/Plugins/Android32/libOVRLipSync.so.meta new file mode 100644 index 0000000..6108baf --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/Android32/libOVRLipSync.so.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 1be7ff64e219f4e44b17e7a42f13247b +timeCreated: 1536610736 +licenseType: Pro +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/Android64.meta b/Assets/Oculus/LipSync/Plugins/Android64.meta new file mode 100644 index 0000000..d3f0eac --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/Android64.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: c1eb8c88592ff744ca29ebf826bb58e1 +folderAsset: yes +timeCreated: 1536610734 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/Android64/libOVRLipSync.so b/Assets/Oculus/LipSync/Plugins/Android64/libOVRLipSync.so new file mode 100644 index 0000000..4c34416 Binary files /dev/null and b/Assets/Oculus/LipSync/Plugins/Android64/libOVRLipSync.so differ diff --git a/Assets/Oculus/LipSync/Plugins/Android64/libOVRLipSync.so.meta b/Assets/Oculus/LipSync/Plugins/Android64/libOVRLipSync.so.meta new file mode 100644 index 0000000..76338d0 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/Android64/libOVRLipSync.so.meta @@ -0,0 +1,96 @@ +fileFormatVersion: 2 +guid: 57850b02365448041958df056264b3e3 +timeCreated: 1536610736 +licenseType: Pro +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 0 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude WebGL: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARM64 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/MacOSX.meta b/Assets/Oculus/LipSync/Plugins/MacOSX.meta new file mode 100644 index 0000000..6a08734 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/MacOSX.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a6504b8c29dd76d4388eef4c5458c108 +folderAsset: yes +timeCreated: 1536866262 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/MacOSX/OVRLipSync.bundle b/Assets/Oculus/LipSync/Plugins/MacOSX/OVRLipSync.bundle new file mode 100644 index 0000000..1a59921 Binary files /dev/null and b/Assets/Oculus/LipSync/Plugins/MacOSX/OVRLipSync.bundle differ diff --git a/Assets/Oculus/LipSync/Plugins/MacOSX/OVRLipSync.bundle.meta b/Assets/Oculus/LipSync/Plugins/MacOSX/OVRLipSync.bundle.meta new file mode 100644 index 0000000..e477cb9 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/MacOSX/OVRLipSync.bundle.meta @@ -0,0 +1,122 @@ +fileFormatVersion: 2 +guid: 79c2e7f7b1a214443ab64ef151d6bd36 +timeCreated: 1529454298 +licenseType: Pro +PluginImporter: + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + data: + first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 0 + Exclude Win: 1 + Exclude Win64: 1 + data: + first: + '': Editor + second: + enabled: 0 + settings: + CPU: x86_64 + OS: OSX + data: + first: + Any: + second: + enabled: 0 + settings: {} + data: + first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: OSX + data: + first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + data: + first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + data: + first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + data: + first: + Standalone: OSXIntel + second: + enabled: 0 + settings: + CPU: None + data: + first: + Standalone: OSXIntel64 + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: + CPU: AnyCPU + data: + first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/Win64.meta b/Assets/Oculus/LipSync/Plugins/Win64.meta new file mode 100644 index 0000000..50aeff1 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/Win64.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 1c5d549bd7e8f2142b88f679c5b3d73e +folderAsset: yes +timeCreated: 1536866262 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/Win64/OVRLipSync.dll b/Assets/Oculus/LipSync/Plugins/Win64/OVRLipSync.dll new file mode 100644 index 0000000..27fb4eb --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/Win64/OVRLipSync.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:7ac3794e1cd5b2672d25d21bfe9861813168d06dc8bdfa1d70e3b6fb3c6538a4 +size 40433080 diff --git a/Assets/Oculus/LipSync/Plugins/Win64/OVRLipSync.dll.meta b/Assets/Oculus/LipSync/Plugins/Win64/OVRLipSync.dll.meta new file mode 100644 index 0000000..540d473 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/Win64/OVRLipSync.dll.meta @@ -0,0 +1,121 @@ +fileFormatVersion: 2 +guid: cffe8c2b7142fa3438fc1b6ccaeda372 +timeCreated: 1527615925 +licenseType: Pro +PluginImporter: + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + data: + first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXIntel: 1 + Exclude OSXIntel64: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 0 + data: + first: + '': Editor + second: + enabled: 0 + settings: + CPU: x86_64 + OS: Windows + data: + first: + Any: + second: + enabled: 0 + settings: {} + data: + first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + data: + first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: None + data: + first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: None + data: + first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + data: + first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Standalone: OSXIntel + second: + enabled: 0 + settings: + CPU: None + data: + first: + Standalone: OSXIntel64 + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + data: + first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: None + data: + first: + Standalone: Win64 + second: + enabled: 1 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/iOS.meta b/Assets/Oculus/LipSync/Plugins/iOS.meta new file mode 100644 index 0000000..16430c9 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/iOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f3ffa7a9d7a87466691fa59d187d0f5a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSync.dylib b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSync.dylib new file mode 100644 index 0000000..177d53c Binary files /dev/null and b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSync.dylib differ diff --git a/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSync.dylib.meta b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSync.dylib.meta new file mode 100644 index 0000000..6a72adf --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSync.dylib.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f5b1c127a92bb426f8f5636c5ea8ab34 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSyncShim.a b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSyncShim.a new file mode 100644 index 0000000..0bb3a13 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSyncShim.a @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:defc22eedbacd3ac7559ea0d05c6a35ccb048e221b71391238c39c5c598fab02 +size 30248 diff --git a/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSyncShim.a.meta b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSyncShim.a.meta new file mode 100644 index 0000000..ee18652 --- /dev/null +++ b/Assets/Oculus/LipSync/Plugins/iOS/libOVRLipSyncShim.a.meta @@ -0,0 +1,101 @@ +fileFormatVersion: 2 +guid: 7bdb12c9252924dd0bf9d2809e01adaf +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Android: 1 + Exclude Editor: 1 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + Exclude iOS: 0 + - first: + Android: Android + second: + enabled: 0 + settings: + CPU: ARM64 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + CPU: AnyCPU + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: LinuxUniversal + second: + enabled: 0 + settings: + CPU: None + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + iPhone: iOS + second: + enabled: 1 + settings: + CompileFlags: + FrameworkDependencies: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Prefabs.meta b/Assets/Oculus/LipSync/Prefabs.meta new file mode 100644 index 0000000..cafc478 --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 4b22c2612a8292646806a50f38127837 +folderAsset: yes +timeCreated: 1439846444 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncDebugConsole.prefab b/Assets/Oculus/LipSync/Prefabs/LipSyncDebugConsole.prefab new file mode 100644 index 0000000..73e26f3 --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncDebugConsole.prefab @@ -0,0 +1,231 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &100658 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 22469590} + - component: {fileID: 22212472} + - component: {fileID: 11460950} + m_Layer: 0 + m_Name: Text + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &130260 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 22402796} + - component: {fileID: 22301806} + - component: {fileID: 11495334} + - component: {fileID: 11476360} + - component: {fileID: 114222500392608660} + m_Layer: 0 + m_Name: LipSyncDebugConsole + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!114 &11460950 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100658} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 1, g: 1, b: 1, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 5 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 5 + m_MaxSize: 40 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 0 + m_LineSpacing: 1 + m_Text: '1 + + 2 + + 3 + + 4 + + 5 + + 6 + + 7 + + 8 + + 9 + + 10 + + 11 + + 12 + + 13 + + 14 + + 15' +--- !u!114 &11476360 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 130260} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &11495334 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 130260} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f5f67c52d1564df4a8936ccd202a3bd8, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 10 +--- !u!222 &22212472 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100658} +--- !u!223 &22301806 +Canvas: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 130260} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 25 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &22402796 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 130260} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 3.5} + m_LocalScale: {x: 0.05, y: 0.05, z: 0.2} + m_Children: + - {fileID: 22469590} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: 0.18, y: 0} + m_SizeDelta: {x: 1024, y: 1024} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &22469590 +RectTransform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 100658} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: -19.76} + m_LocalScale: {x: 0.3, y: 0.3, z: 1} + m_Children: [] + m_Father: {fileID: 22402796} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 120, y: 90} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 0} + propertyPath: m_AnchoredPosition.x + value: .200000003 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: m_AnchoredPosition.y + value: 0 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 130260} + m_IsPrefabParent: 1 +--- !u!114 &114222500392608660 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 130260} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: c60ad94815c68aa41a786306cd588495, type: 3} + m_Name: + m_EditorClassIdentifier: + maxMessages: 15 + textMsg: {fileID: 11460950} diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncDebugConsole.prefab.meta b/Assets/Oculus/LipSync/Prefabs/LipSyncDebugConsole.prefab.meta new file mode 100644 index 0000000..68bb09b --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncDebugConsole.prefab.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e4c63fc874ed2ed42b7808b1a310238a +timeCreated: 1531440959 +licenseType: Pro +NativeFormatImporter: + mainObjectFileID: -1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncInterface.prefab b/Assets/Oculus/LipSync/Prefabs/LipSyncInterface.prefab new file mode 100644 index 0000000..35c31fd --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncInterface.prefab @@ -0,0 +1,52 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &135588 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 4 + m_Component: + - 4: {fileID: 452380} + - 114: {fileID: 11448948} + m_Layer: 0 + m_Name: LipSyncInterface + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &452380 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 135588} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 +--- !u!114 &11448948 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 135588} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 82aa5cb7a870de440baadff9083be41c, type: 3} + m_Name: + m_EditorClassIdentifier: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 135588} + m_IsPrefabParent: 1 diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncInterface.prefab.meta b/Assets/Oculus/LipSync/Prefabs/LipSyncInterface.prefab.meta new file mode 100644 index 0000000..5815f63 --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncInterface.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 4dd277bd9572488489906165e0931952 +timeCreated: 1444054820 +licenseType: Pro +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncMorphTarget_Female.prefab b/Assets/Oculus/LipSync/Prefabs/LipSyncMorphTarget_Female.prefab new file mode 100644 index 0000000..50add15 --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncMorphTarget_Female.prefab @@ -0,0 +1,548 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1729616000960218} + m_IsPrefabParent: 1 +--- !u!1 &1139795683760258 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4823660823247402} + m_Layer: 0 + m_Name: AVATARS_geom + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1192703335975574 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4274635960196998} + m_Layer: 0 + m_Name: root_JNT + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1278477851109110 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4757718351805666} + m_Layer: 0 + m_Name: body_JNT + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1330161294847844 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4272445540477860} + m_Layer: 0 + m_Name: avatar_rig_GRP + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1465706260390400 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4241946589080730} + - component: {fileID: 137395340853046402} + m_Layer: 0 + m_Name: body_gen_PLY + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1558813331645872 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4299292143475712} + m_Layer: 0 + m_Name: body + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1624604992715440 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4217607272013336} + m_Layer: 0 + m_Name: head_JNT + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1729616000960218 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4575382478150018} + - component: {fileID: 95057139371591416} + m_Layer: 0 + m_Name: LipSyncMorphTarget_Female + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1744178946087314 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4450209389554888} + m_Layer: 0 + m_Name: neckBase_JNT + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1744500438761354 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4442710651062634} + m_Layer: 0 + m_Name: chest_JNT + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1769002904512266 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4257558602553876} + - component: {fileID: 33898072723145610} + - component: {fileID: 23664444766217582} + m_Layer: 0 + m_Name: shirt_PLY + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1842632657789390 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4890642429627224} + - component: {fileID: 33200345887729738} + - component: {fileID: 23892122652269546} + m_Layer: 0 + m_Name: hair_gen_PLY + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1849074270389474 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4020040387331986} + m_Layer: 0 + m_Name: neck_JNT + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4020040387331986 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1849074270389474} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0.10268402, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4217607272013336} + m_Father: {fileID: 4450209389554888} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4217607272013336 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1624604992715440} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0.09341904, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4020040387331986} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4241946589080730 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1465706260390400} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4299292143475712} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4257558602553876 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1769002904512266} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4299292143475712} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4272445540477860 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1330161294847844} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4274635960196998} + m_Father: {fileID: 4575382478150018} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4274635960196998 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1192703335975574} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4757718351805666} + m_Father: {fileID: 4272445540477860} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4299292143475712 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1558813331645872} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4241946589080730} + - {fileID: 4890642429627224} + - {fileID: 4257558602553876} + m_Father: {fileID: 4823660823247402} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4442710651062634 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1744500438761354} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0.48086593, z: 0.00000002} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4450209389554888} + m_Father: {fileID: 4757718351805666} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4450209389554888 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1744178946087314} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0.11862487, z: 0.00000001} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4020040387331986} + m_Father: {fileID: 4442710651062634} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4575382478150018 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1729616000960218} + m_LocalRotation: {x: 0, y: 1, z: 0, w: 0} + m_LocalPosition: {x: 0, y: -8.56, z: 0.05} + m_LocalScale: {x: 5, y: 5, z: 5} + m_Children: + - {fileID: 4272445540477860} + - {fileID: 4823660823247402} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 180, z: 0} +--- !u!4 &4757718351805666 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1278477851109110} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0.9306018, z: 0.00000004} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4442710651062634} + m_Father: {fileID: 4274635960196998} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4823660823247402 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1139795683760258} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 4299292143475712} + m_Father: {fileID: 4575382478150018} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &4890642429627224 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1842632657789390} + m_LocalRotation: {x: 0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: -0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 4299292143475712} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &23664444766217582 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1769002904512266} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: 0ad01ecbcffbb4c91af7ffa1ebc14f74, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &23892122652269546 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1842632657789390} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: d0455a0ebc21e4c758037cb4b82bebd2, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33200345887729738 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1842632657789390} + m_Mesh: {fileID: 4300004, guid: cbaf1c32e7ec84f10a51be1b09c0ef46, type: 3} +--- !u!33 &33898072723145610 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1769002904512266} + m_Mesh: {fileID: 4300000, guid: cbaf1c32e7ec84f10a51be1b09c0ef46, type: 3} +--- !u!95 &95057139371591416 +Animator: + serializedVersion: 3 + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1729616000960218} + m_Enabled: 1 + m_Avatar: {fileID: 9000000, guid: cbaf1c32e7ec84f10a51be1b09c0ef46, type: 3} + m_Controller: {fileID: 0} + m_CullingMode: 1 + m_UpdateMode: 0 + m_ApplyRootMotion: 0 + m_LinearVelocityBlending: 0 + m_WarningMessage: + m_HasTransformHierarchy: 1 + m_AllowConstantClipSamplingOptimization: 1 +--- !u!137 &137395340853046402 +SkinnedMeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1465706260390400} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: 3d380053edac948aa9d428fce6a5288b, type: 2} + - {fileID: 2100000, guid: e906d4c6bf3304d5dac06eee4fe24c54, type: 2} + - {fileID: 2100000, guid: 76f25b997543f432bbe00737485b392e, type: 2} + - {fileID: 2100000, guid: 3d380053edac948aa9d428fce6a5288b, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 + serializedVersion: 2 + m_Quality: 0 + m_UpdateWhenOffscreen: 0 + m_SkinnedMotionVectors: 1 + m_Mesh: {fileID: 4300002, guid: cbaf1c32e7ec84f10a51be1b09c0ef46, type: 3} + m_Bones: + - {fileID: 4757718351805666} + - {fileID: 4442710651062634} + - {fileID: 4450209389554888} + - {fileID: 4020040387331986} + - {fileID: 4217607272013336} + m_BlendShapeWeights: [] + m_RootBone: {fileID: 4757718351805666} + m_AABB: + m_Center: {x: 0, y: 0.64820504, z: 0.021016505} + m_Extent: {x: 0.1376345, y: 0.24974602, z: 0.12161067} + m_DirtyAABB: 0 diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncMorphTarget_Female.prefab.meta b/Assets/Oculus/LipSync/Prefabs/LipSyncMorphTarget_Female.prefab.meta new file mode 100644 index 0000000..6163ba4 --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncMorphTarget_Female.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0d336f164a5a4454db3960b2f9fc7a85 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 100100000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncTextureFlipTarget_Robot.prefab b/Assets/Oculus/LipSync/Prefabs/LipSyncTextureFlipTarget_Robot.prefab new file mode 100644 index 0000000..51c1085 --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncTextureFlipTarget_Robot.prefab @@ -0,0 +1,883 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1 &103710 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 491976} + - component: {fileID: 3309526} + - component: {fileID: 2396152} + m_Layer: 0 + m_Name: Head-0 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &112224 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 434670} + - component: {fileID: 3317174} + - component: {fileID: 2383438} + m_Layer: 0 + m_Name: Head-3 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &115398 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 470322} + - component: {fileID: 3318132} + - component: {fileID: 2341214} + m_Layer: 0 + m_Name: Head-2 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &116614 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 495278} + - component: {fileID: 3338656} + - component: {fileID: 2347176} + m_Layer: 0 + m_Name: mouth + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &117196 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 432198} + - component: {fileID: 8298520} + - component: {fileID: 11445718} + - component: {fileID: 11420510} + - component: {fileID: 11441082} + m_Layer: 0 + m_Name: LipSyncTextureFlipTarget_Robot + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &134126 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 424882} + m_Layer: 0 + m_Name: RobotHead_TextureFlip + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &150352 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 494442} + - component: {fileID: 3309632} + - component: {fileID: 2341078} + m_Layer: 0 + m_Name: Head-5 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &167146 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 426320} + - component: {fileID: 3353070} + - component: {fileID: 2371382} + m_Layer: 0 + m_Name: Eye-r + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &171898 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 470930} + - component: {fileID: 3350328} + - component: {fileID: 2316538} + m_Layer: 0 + m_Name: Head-4 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &179166 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 422502} + - component: {fileID: 3346774} + - component: {fileID: 2317534} + m_Layer: 0 + m_Name: Head-1 + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &192526 +GameObject: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 401646} + - component: {fileID: 3367782} + - component: {fileID: 2319444} + m_Layer: 0 + m_Name: Eye-l + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &401646 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 192526} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: -0.04058239, y: 0, z: 0.0022434187} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &422502 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 179166} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 3 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &424882 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 134126} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 401646} + - {fileID: 426320} + - {fileID: 491976} + - {fileID: 422502} + - {fileID: 470322} + - {fileID: 434670} + - {fileID: 470930} + - {fileID: 494442} + - {fileID: 495278} + m_Father: {fileID: 432198} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &426320 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 167146} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0.04058, y: 0, z: 0.0022309874} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &432198 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 117196} + m_LocalRotation: {x: 0, y: 1, z: 0, w: -0.00000004371139} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 5.275625, y: 5.2756267, z: 5.2756267} + m_Children: + - {fileID: 424882} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &434670 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 112224} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 5 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &470322 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 115398} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 4 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &470930 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 171898} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 6 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &491976 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 103710} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 2 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &494442 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 150352} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 7 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!4 &495278 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 116614} + m_LocalRotation: {x: -0.7071068, y: 0, z: -0, w: 0.7071068} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 424882} + m_RootOrder: 8 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &2316538 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 171898} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2317534 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 179166} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2319444 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 192526} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2341078 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 150352} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2341214 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 115398} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2347176 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 116614} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: 5290b3a55eaa1b7458665dc2d856c042, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2371382 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 167146} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2383438 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 112224} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!23 &2396152 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 103710} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_DynamicOccludee: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 2100000, guid: b8f002f88e9d7e847b5306f3338f80db, type: 2} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 0 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_StitchLightmapSeams: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &3309526 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 103710} + m_Mesh: {fileID: 4300000, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3309632 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 150352} + m_Mesh: {fileID: 4300006, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3317174 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 112224} + m_Mesh: {fileID: 4300008, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3318132 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 115398} + m_Mesh: {fileID: 4300012, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3338656 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 116614} + m_Mesh: {fileID: 4300016, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3346774 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 179166} + m_Mesh: {fileID: 4300014, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3350328 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 171898} + m_Mesh: {fileID: 4300010, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3353070 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 167146} + m_Mesh: {fileID: 4300002, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!33 &3367782 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 192526} + m_Mesh: {fileID: 4300004, guid: f82b1e3c015abaa409d91ab8eb628ac4, type: 3} +--- !u!82 &8298520 +AudioSource: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 117196} + m_Enabled: 1 + serializedVersion: 4 + OutputAudioMixerGroup: {fileID: 0} + m_audioClip: {fileID: 0} + m_PlayOnAwake: 1 + m_Volume: 1 + m_Pitch: 1 + Loop: 1 + Mute: 0 + Spatialize: 0 + SpatializePostEffects: 0 + Priority: 128 + DopplerLevel: 1 + MinDistance: 1 + MaxDistance: 500 + Pan2D: 0 + rolloffMode: 0 + BypassEffects: 0 + BypassListenerEffects: 0 + BypassReverbZones: 0 + rolloffCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + - serializedVersion: 2 + time: 1 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + panLevelCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 0 + spreadCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 0 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 4 + reverbZoneMixCustomCurve: + serializedVersion: 2 + m_Curve: + - serializedVersion: 2 + time: 0 + value: 1 + inSlope: 0 + outSlope: 0 + tangentMode: 0 + m_PreInfinity: 2 + m_PostInfinity: 2 + m_RotationOrder: 0 +--- !u!114 &11420510 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 117196} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: f43c520a9bad8a3489109c869f454576, type: 3} + m_Name: + m_EditorClassIdentifier: + audioSource: {fileID: 0} + provider: 0 + enableAcceleration: 1 + enableKeyboardInput: 0 + enableTouchInput: 0 + audioLoopback: 0 + loopbackKey: 108 + showVisemes: 0 + debugVisemesKey: 100 + skipAudioSource: 0 + gain: 1 + debugLaughterKey: 104 + showLaughter: 0 + laughterScore: 0 +--- !u!114 &11441082 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 117196} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: bc30a49f30010eb42a8b59ec685eac57, type: 3} + m_Name: + m_EditorClassIdentifier: + material: {fileID: 2100000, guid: 5290b3a55eaa1b7458665dc2d856c042, type: 2} + Textures: + - {fileID: 2800000, guid: 46b2920291e9b8c4888ad3fe3f5e5e69, type: 3} + - {fileID: 2800000, guid: bea5b996ab6235c4aaa1be9b11aea8c4, type: 3} + - {fileID: 2800000, guid: 5563aa34057c347499c480ea33c5d593, type: 3} + - {fileID: 2800000, guid: d14bb80824ed25b44a65ddfc7f591e29, type: 3} + - {fileID: 2800000, guid: ffbd7db31d3ad6e4a97a2f312babdcb6, type: 3} + - {fileID: 2800000, guid: ba0b9f69af91c5f46b490346e5552136, type: 3} + - {fileID: 2800000, guid: 5e6531e8f56b42547b8d2ddf7a7363d1, type: 3} + - {fileID: 2800000, guid: 31e6326c0bd6143479322c5b4a5fe949, type: 3} + - {fileID: 2800000, guid: 9c21cf8c4dffca9418cebd0a578972b4, type: 3} + - {fileID: 2800000, guid: 6d47a54f2b89a59459fd7561d360bab2, type: 3} + - {fileID: 2800000, guid: 5c06354455999f94ea26114e261dde6d, type: 3} + - {fileID: 2800000, guid: 29a06a0eefee1b542a7c286f1689ffab, type: 3} + - {fileID: 2800000, guid: ad60c8114191fdf41aa0ea64e132add9, type: 3} + - {fileID: 2800000, guid: 5f658e6e48970d340b4491a5fc959251, type: 3} + - {fileID: 2800000, guid: 660be1fdb8590b14bab012a991bdeb86, type: 3} + smoothAmount: 70 +--- !u!114 &11445718 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 117196} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 02d5ed157083b494e85013bad8fd5e12, type: 3} + m_Name: + m_EditorClassIdentifier: + audioSource: {fileID: 0} + enableMicSelectionGUI: 0 + micSelectionGUIKey: 109 + micInputVolume: 100 + micFrequency: 44100 + micControl: 2 + micActivationKey: 32 + selectedDevice: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: + - target: {fileID: 0} + propertyPath: m_LocalPosition.z + value: -.0199999996 + objectReference: {fileID: 0} + - target: {fileID: 0} + propertyPath: smoothing + value: .100000001 + objectReference: {fileID: 0} + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 117196} + m_IsPrefabParent: 1 diff --git a/Assets/Oculus/LipSync/Prefabs/LipSyncTextureFlipTarget_Robot.prefab.meta b/Assets/Oculus/LipSync/Prefabs/LipSyncTextureFlipTarget_Robot.prefab.meta new file mode 100644 index 0000000..433b505 --- /dev/null +++ b/Assets/Oculus/LipSync/Prefabs/LipSyncTextureFlipTarget_Robot.prefab.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 8dc55266323c0ad439967b2975af7840 +timeCreated: 1531443155 +licenseType: Pro +NativeFormatImporter: + mainObjectFileID: -1 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scenes.meta b/Assets/Oculus/LipSync/Scenes.meta new file mode 100644 index 0000000..0c0b978 --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: e63268aff72466742ada144924d3f899 +folderAsset: yes +timeCreated: 1437169810 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scenes/LipSync_Demo.unity b/Assets/Oculus/LipSync/Scenes/LipSync_Demo.unity new file mode 100644 index 0000000..ac61f56 --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/LipSync_Demo.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b38b43922c68c0606db4508eaef50aba054a2fdb22f5ebe3c728b71886bca049 +size 161844 diff --git a/Assets/Oculus/LipSync/Scenes/LipSync_Demo.unity.meta b/Assets/Oculus/LipSync/Scenes/LipSync_Demo.unity.meta new file mode 100644 index 0000000..03bca8e --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/LipSync_Demo.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 0a5206cd53b21be4588ef635952929e9 +timeCreated: 1445011372 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scenes/Scripts.meta b/Assets/Oculus/LipSync/Scenes/Scripts.meta new file mode 100644 index 0000000..d9e80f3 --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a59ddab39a70b984f94af4f1ceb261d2 +folderAsset: yes +timeCreated: 1445015254 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scenes/Scripts/EnableSwitch.cs b/Assets/Oculus/LipSync/Scenes/Scripts/EnableSwitch.cs new file mode 100644 index 0000000..0ba99c4 --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/Scripts/EnableSwitch.cs @@ -0,0 +1,42 @@ +using UnityEngine; + +public class EnableSwitch : MonoBehaviour +{ + public GameObject[] SwitchTargets; + + /// + /// Sets the active GameObject + /// + /// true, if active was set, false otherwise. + /// Target. + public bool SetActive(int target) where T : MonoBehaviour + { + if((target < 0) || (target >= SwitchTargets.Length)) + return false; + + for (int i = 0; i < SwitchTargets.Length; i++) + { + SwitchTargets[i].SetActive(false); + + // Disable texture flip or morph target + OVRLipSyncContextMorphTarget lipsyncContextMorph = + SwitchTargets[i].GetComponent(); + if (lipsyncContextMorph) + lipsyncContextMorph.enabled = false; + OVRLipSyncContextTextureFlip lipsyncContextTexture = + SwitchTargets[i].GetComponent(); + if (lipsyncContextTexture) + lipsyncContextTexture.enabled = false; + } + + SwitchTargets[target].SetActive(true); + MonoBehaviour lipsyncContext = SwitchTargets[target].GetComponent(); + if (lipsyncContext != null) + { + lipsyncContext.enabled = true; + } + + return true; + } +} + diff --git a/Assets/Oculus/LipSync/Scenes/Scripts/EnableSwitch.cs.meta b/Assets/Oculus/LipSync/Scenes/Scripts/EnableSwitch.cs.meta new file mode 100644 index 0000000..da758f8 --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/Scripts/EnableSwitch.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 50cd36abe38c57646bcd09be2353f905 +timeCreated: 1445017324 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_Control.cs b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_Control.cs new file mode 100644 index 0000000..93314fc --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_Control.cs @@ -0,0 +1,88 @@ +/************************************************************************************ +Filename : LipSyncDemo_Control.cs +Content : LipSync Demo controls +Created : July 11, 2018 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +public class LipSyncDemo_Control : MonoBehaviour { + + [Tooltip("Key used to rotate the demo object up to 45 degrees to the left.")] + public KeyCode rotateLeftKey = KeyCode.LeftArrow; + [Tooltip("Key used to rotate the demo object up to 45 degrees to the right.")] + public KeyCode rotateRightKey = KeyCode.RightArrow; + [Tooltip("Key used to reset demo object rotation.")] + public KeyCode resetRotationKey = KeyCode.DownArrow; + + private float resetRotation = 180.0f; + private float rotationAmount = 20.0f; + private float rotationMax = 45.0f; + + // Use this for initialization + void Start () { + } + + // Update is called once per frame + void Update () { + if (Input.GetKey(rotateLeftKey)) + { + RotateObject(rotationAmount); + } + else if (Input.GetKey(rotateRightKey)) + { + RotateObject(-rotationAmount); + } + else if (Input.GetKey(resetRotationKey)) + { + RotateObject(resetRotation, true); + } + } + + void RotateObject(float amountDegrees, bool absolute = false) + { + GameObject target = GameObject.Find("LipSyncMorphTarget_Female"); + + if (target == null) + { + // Try for other scene object + target = GameObject.Find("RobotHead_TextureFlip"); + } + + if (target) + { + if (absolute) + { + float deltaRotate = amountDegrees - target.transform.eulerAngles.y; + target.transform.Rotate(Vector3.up * deltaRotate); + } + else + { + float deltaRotate = Time.deltaTime * amountDegrees; + if (deltaRotate + target.transform.eulerAngles.y >= resetRotation - rotationMax && + deltaRotate + target.transform.eulerAngles.y <= resetRotation + rotationMax) + { + target.transform.Rotate(Vector3.up * deltaRotate); + } + } + } + } +} diff --git a/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_Control.cs.meta b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_Control.cs.meta new file mode 100644 index 0000000..a1e0c3e --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_Control.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 8a6c32d06b48d244b9c65729404d2afe +timeCreated: 1531249571 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_SetCurrentTarget.cs b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_SetCurrentTarget.cs new file mode 100644 index 0000000..3f001c7 --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_SetCurrentTarget.cs @@ -0,0 +1,149 @@ +/************************************************************************************ +Filename : LipSyncDemo_SetCurrentTarget.cs +Content : Update LipSync Demo current target +Created : July 11, 2018 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using System.Collections; + +public class LipSyncDemo_SetCurrentTarget : MonoBehaviour +{ + public EnableSwitch[] SwitchTargets; + + private int targetSet = 0; + private int maxTarget = 6; + + // Use this for initialization + void Start () + { + // Add a listener to the OVRTouchpad for touch events + OVRTouchpad.AddListener(LocalTouchEventCallback); + + // Initialize the proper target set + targetSet = 0; + SwitchTargets[0].SetActive(0); + SwitchTargets[1].SetActive(0); + } + + // Update is called once per frame + // Logic for LipSync_Demo + void Update () + { + if (Input.GetKeyDown(KeyCode.Alpha1)) + { + targetSet = 0; + SetCurrentTarget(); + } + else if (Input.GetKeyDown(KeyCode.Alpha2)) + { + targetSet = 1; + SetCurrentTarget(); + } + else if (Input.GetKeyDown(KeyCode.Alpha3)) + { + targetSet = 2; + SetCurrentTarget(); + } + else if (Input.GetKeyDown(KeyCode.Alpha4)) + { + targetSet = 3; + SetCurrentTarget(); + } + else if (Input.GetKeyDown(KeyCode.Alpha5)) + { + targetSet = 4; + SetCurrentTarget(); + } + else if (Input.GetKeyDown(KeyCode.Alpha6)) + { + targetSet = 5; + SetCurrentTarget(); + } + + // Close app + if(Input.GetKeyDown (KeyCode.Escape)) + Application.Quit(); + } + + /// + /// Sets the current target. + /// + void SetCurrentTarget() + { + switch(targetSet) + { + case(0): + SwitchTargets[0].SetActive(0); + SwitchTargets[1].SetActive(0); + break; + case(1): + SwitchTargets[0].SetActive(0); + SwitchTargets[1].SetActive(1); + break; + case(2): + SwitchTargets[0].SetActive(1); + SwitchTargets[1].SetActive(2); + break; + case(3): + SwitchTargets[0].SetActive(1); + SwitchTargets[1].SetActive(3); + break; + case(4): + SwitchTargets[0].SetActive(2); + SwitchTargets[1].SetActive(4); + break; + case(5): + SwitchTargets[0].SetActive(2); + SwitchTargets[1].SetActive(5); + break; + } + OVRLipSyncDebugConsole.Clear(); + } + + /// + /// Local touch event callback. + /// + /// Touch event. + void LocalTouchEventCallback(OVRTouchpad.TouchEvent touchEvent) + { + switch(touchEvent) + { + case(OVRTouchpad.TouchEvent.Left): + + targetSet--; + if(targetSet < 0) + targetSet = maxTarget - 1; + + SetCurrentTarget(); + + break; + + case(OVRTouchpad.TouchEvent.Right): + + targetSet++; + if(targetSet >= maxTarget) + targetSet = 0; + + SetCurrentTarget(); + + break; + } + } +} diff --git a/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_SetCurrentTarget.cs.meta b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_SetCurrentTarget.cs.meta new file mode 100644 index 0000000..11ffd18 --- /dev/null +++ b/Assets/Oculus/LipSync/Scenes/Scripts/LipSyncDemo_SetCurrentTarget.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c62f9b5ef85d22f449e72c67c610059d +timeCreated: 1445018007 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts.meta b/Assets/Oculus/LipSync/Scripts.meta new file mode 100644 index 0000000..c288da5 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: a96f219c252e0cc4eb074d5b7bbda9b3 +folderAsset: yes +timeCreated: 1437169844 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/Helpers.meta b/Assets/Oculus/LipSync/Scripts/Helpers.meta new file mode 100644 index 0000000..f4682e6 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/Helpers.meta @@ -0,0 +1,9 @@ +fileFormatVersion: 2 +guid: 27d84f95a4766db44a26aea09cc67373 +folderAsset: yes +timeCreated: 1444949045 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/Helpers/OVRLipSyncDebugConsole.cs b/Assets/Oculus/LipSync/Scripts/Helpers/OVRLipSyncDebugConsole.cs new file mode 100644 index 0000000..2d04800 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/Helpers/OVRLipSyncDebugConsole.cs @@ -0,0 +1,224 @@ +/************************************************************************************ +Filename : OVRLipSyncDebugConsole.cs +Content : Write to a text string, used by UI.Text +Created : May 22, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using UnityEngine.UI; +using System.Collections; + +public class OVRLipSyncDebugConsole : MonoBehaviour +{ + public ArrayList messages = new ArrayList(); + public int maxMessages = 15; // The max number of messages displayed + public Text textMsg; // text string to display + + // Our instance to allow this script to be called without a direct connection. + private static OVRLipSyncDebugConsole s_Instance = null; + + // Clear timeout + private bool clearTimeoutOn = false; + private float clearTimeout = 0.0f; + + /// + /// Gets the instance. + /// + /// The instance. + public static OVRLipSyncDebugConsole instance + { + get + { + if (s_Instance == null) + { + s_Instance = FindObjectOfType(typeof(OVRLipSyncDebugConsole)) as OVRLipSyncDebugConsole; + + if (s_Instance == null) + { + GameObject console = new GameObject(); + console.AddComponent(); + console.name = "OVRLipSyncDebugConsole"; + s_Instance = FindObjectOfType(typeof(OVRLipSyncDebugConsole)) as OVRLipSyncDebugConsole; + } + } + + return s_Instance; + } + } + + /// + /// Awake this instance. + /// + void Awake() + { + s_Instance = this; + Init(); + + } + + /// + /// Update this instance. + /// + void Update() + { + if(clearTimeoutOn == true) + { + clearTimeout -= Time.deltaTime; + if(clearTimeout < 0.0f) + { + Clear(); + clearTimeout = 0.0f; + clearTimeoutOn = false; + } + } + } + + /// + /// Init this instance. + /// + public void Init() + { + if(textMsg == null) + { + Debug.LogWarning("DebugConsole Init WARNING::UI text not set. Will not be able to display anything."); + } + + Clear(); + } + + + //+++++++++ INTERFACE FUNCTIONS ++++++++++++++++++++++++++++++++ + + /// + /// Log the specified message. + /// + /// Message. + public static void Log(string message) + { + OVRLipSyncDebugConsole.instance.AddMessage(message, Color.white); + } + + /// + /// Log the specified message and color. + /// + /// Message. + /// Color. + public static void Log(string message, Color color) + { + OVRLipSyncDebugConsole.instance.AddMessage(message, color); + } + + /// + /// Clear this instance. + /// + public static void Clear() + { + OVRLipSyncDebugConsole.instance.ClearMessages(); + } + + /// + /// Calls clear after a certain time. + /// + /// Time to clear. + public static void ClearTimeout(float timeToClear) + { + OVRLipSyncDebugConsole.instance.SetClearTimeout(timeToClear); + } + + //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + + + /// + /// Adds the message. + /// + /// Message. + /// Color. + public void AddMessage(string message, Color color) + { + messages.Add(message); + + if(textMsg != null) + textMsg.color = color; + + Display(); + } + + /// + /// Clears the messages. + /// + public void ClearMessages() + { + messages.Clear(); + Display(); + } + + /// + /// Sets the clear timeout. + /// + /// Timeout. + public void SetClearTimeout(float timeout) + { + clearTimeout = timeout; + clearTimeoutOn = true; + } + + /// + // Prunes the array to fit within the maxMessages limit + /// + void Prune() + { + int diff; + if (messages.Count > maxMessages) + { + if (messages.Count <= 0) + { + diff = 0; + } + else + { + diff = messages.Count - maxMessages; + } + messages.RemoveRange(0, (int)diff); + } + } + + /// + /// Display this instance. + /// + void Display() + { + if (messages.Count > maxMessages) + { + Prune(); + } + + if(textMsg != null) + { + textMsg.text = ""; // Clear text out + int x = 0; + + while (x < messages.Count) + { + textMsg.text += (string)messages[x]; + textMsg.text +='\n'; + x += 1; + } + } + } +} diff --git a/Assets/Oculus/LipSync/Scripts/Helpers/OVRLipSyncDebugConsole.cs.meta b/Assets/Oculus/LipSync/Scripts/Helpers/OVRLipSyncDebugConsole.cs.meta new file mode 100644 index 0000000..72c784e --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/Helpers/OVRLipSyncDebugConsole.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c60ad94815c68aa41a786306cd588495 +timeCreated: 1439845885 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/Helpers/OVRNamedArrayAttribute.cs b/Assets/Oculus/LipSync/Scripts/Helpers/OVRNamedArrayAttribute.cs new file mode 100644 index 0000000..36cb9d2 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/Helpers/OVRNamedArrayAttribute.cs @@ -0,0 +1,29 @@ +/************************************************************************************ +Filename : OVRNamedArrayAttribute.cs +Content : Adds support for a named array attribute in the editor +Created : May 17th, 2018 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; + +// Adds support for a named array attribute in the editor +public class OVRNamedArrayAttribute : PropertyAttribute { + public readonly string[] names; + public OVRNamedArrayAttribute( string[] names ) { this.names = names; } +} diff --git a/Assets/Oculus/LipSync/Scripts/Helpers/OVRNamedArrayAttribute.cs.meta b/Assets/Oculus/LipSync/Scripts/Helpers/OVRNamedArrayAttribute.cs.meta new file mode 100644 index 0000000..3632eb0 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/Helpers/OVRNamedArrayAttribute.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 7537accd8e2c6024c860b20e3e7e3424 +timeCreated: 1534993516 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/Helpers/OVRTouchpad.cs b/Assets/Oculus/LipSync/Scripts/Helpers/OVRTouchpad.cs new file mode 100644 index 0000000..a7b4845 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/Helpers/OVRTouchpad.cs @@ -0,0 +1,201 @@ +/************************************************************************************ +Filename : OVRTouchpad.cs +Content : Interface to touchpad +Created : November 13, 2013 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using System; + +//------------------------------------------------------------------------------------- +// ***** OVRTouchpad +// +// OVRTouchpad is an interface class to a touchpad. +// +public static class OVRTouchpad +{ + //------------------------- + // Input enums + public enum TouchEvent { SingleTap, DoubleTap, Left, Right, Up, Down }; + + // mouse + static Vector3 moveAmountMouse; + static float minMovMagnitudeMouse = 25.0f; + + public delegate void OVRTouchpadCallback(TouchEvent arg); + static public Delegate touchPadCallbacks = null; + + //Disable the unused variable warning +#pragma warning disable 0414 + + //Ensures that the TouchpadHelper will be created automatically upon start of the game. + static private OVRTouchpadHelper touchpadHelper = + ( new GameObject("OVRTouchpadHelper") ).AddComponent< OVRTouchpadHelper >(); + +#pragma warning restore 0414 + + // We will call this to create the TouchpadHelper class. This will + // add the Touchpad game object into the world and we can call into + // TouchEvent static functions to hook delegates into for touch capture + static public void Create() + { + // Does nothing but call constructor to add game object into scene + } + + // Update + static public void Update() + { + // MOUSE INPUT + + if(Input.GetMouseButtonDown(0)) + { + moveAmountMouse = Input.mousePosition; + } + else if(Input.GetMouseButtonUp(0)) + { + moveAmountMouse -= Input.mousePosition; + HandleInputMouse(ref moveAmountMouse); + } + } + + // OnDisable + static public void OnDisable() + { + } + + // HandleInputMouse + static void HandleInputMouse(ref Vector3 move) + { + if (touchPadCallbacks == null) + { + return; + } + OVRTouchpadCallback callback = touchPadCallbacks as OVRTouchpadCallback; + + if ( move.magnitude < minMovMagnitudeMouse) + { + callback(TouchEvent.SingleTap); + } + else + { + move.Normalize(); + + // Left/Right + if (Mathf.Abs(move.x) > Mathf.Abs(move.y)) + { + if (move.x > 0.0f) + callback(TouchEvent.Left); + else + callback(TouchEvent.Right); + } + // Up/Down + else + { + if (move.y > 0.0f) + callback(TouchEvent.Down); + else + callback(TouchEvent.Up); + } + } + } + + static public void AddListener(OVRTouchpadCallback handler) + { + touchPadCallbacks = (OVRTouchpadCallback)touchPadCallbacks + handler; + } +} + +//------------------------------------------------------------------------------------- +// ***** OVRTouchpadHelper +// +// This singleton class gets created and stays resident in the application. It is used to +// trap the touchpad values, which get broadcast to any listener on the "Touchpad" channel. +// +// This class also demontrates how to make calls from any class that needs these events by +// setting up a listener to "Touchpad" channel. +public sealed class OVRTouchpadHelper : MonoBehaviour +{ + void Awake () + { + DontDestroyOnLoad(gameObject); + } + + void Start () + { + // Add a listener to the OVRTouchpad for testing + OVRTouchpad.AddListener(LocalTouchEventCallback); + } + + + void Update () + { + OVRTouchpad.Update(); + } + + + public void OnDisable() + { + OVRTouchpad.OnDisable(); + } + + // LocalTouchEventCallback + void LocalTouchEventCallback(OVRTouchpad.TouchEvent touchEvent) + { + switch(touchEvent) + { + case(OVRTouchpad.TouchEvent.SingleTap): +// OVRLipSyncDebugConsole.Clear(); +// OVRLipSyncDebugConsole.ClearTimeout(1.5f); +// OVRLipSyncDebugConsole.Log("TP-SINGLE TAP"); + break; + + case(OVRTouchpad.TouchEvent.DoubleTap): +// OVRLipSyncDebugConsole.Clear(); +// OVRLipSyncDebugConsole.ClearTimeout(1.5f); +// OVRLipSyncDebugConsole.Log("TP-DOUBLE TAP"); + break; + + case(OVRTouchpad.TouchEvent.Left): +// OVRLipSyncDebugConsole.Clear(); +// OVRLipSyncDebugConsole.ClearTimeout(1.5f); +// OVRLipSyncDebugConsole.Log("TP-SWIPE LEFT"); + break; + + case(OVRTouchpad.TouchEvent.Right): +// OVRLipSyncDebugConsole.Clear(); +// OVRLipSyncDebugConsole.ClearTimeout(1.5f); +// OVRLipSyncDebugConsole.Log("TP-SWIPE RIGHT"); + break; + + case(OVRTouchpad.TouchEvent.Up): +// OVRLipSyncDebugConsole.Clear(); +// OVRLipSyncDebugConsole.ClearTimeout(1.5f); +// OVRLipSyncDebugConsole.Log("TP-SWIPE UP"); + break; + + case(OVRTouchpad.TouchEvent.Down): +// OVRLipSyncDebugConsole.Clear(); +// OVRLipSyncDebugConsole.ClearTimeout(1.5f); +// OVRLipSyncDebugConsole.Log("TP-SWIPE DOWN"); + break; + } + } + +} + diff --git a/Assets/Oculus/LipSync/Scripts/Helpers/OVRTouchpad.cs.meta b/Assets/Oculus/LipSync/Scripts/Helpers/OVRTouchpad.cs.meta new file mode 100644 index 0000000..7d0c538 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/Helpers/OVRTouchpad.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: edde1cb2a78471f409fce5084e6c720c +timeCreated: 1528830158 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSync.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSync.cs new file mode 100644 index 0000000..d5c8237 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSync.cs @@ -0,0 +1,441 @@ +/************************************************************************************ +Filename : OVRLipSync.cs +Content : Interface to Oculus Lip Sync engine +Created : August 4th, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using System; +using System.Runtime.InteropServices; + +//------------------------------------------------------------------------------------- +// ***** OVRLipSync +// +/// +/// OVRLipSync interfaces into the Oculus lip sync engine. This component should be added +/// into the scene once. +/// +/// +public class OVRLipSync : MonoBehaviour +{ + // Error codes that may return from Lip Sync engine + public enum Result + { + Success = 0, + Unknown = -2200, //< An unknown error has occurred + CannotCreateContext = -2201, //< Unable to create a context + InvalidParam = -2202, //< An invalid parameter, e.g. NULL pointer or out of range + BadSampleRate = -2203, //< An unsupported sample rate was declared + MissingDLL = -2204, //< The DLL or shared library could not be found + BadVersion = -2205, //< Mismatched versions between header and libs + UndefinedFunction = -2206 //< An undefined function + }; + + // Audio buffer data type + public enum AudioDataType + { + // Signed 16-bit integer mono audio stream + S16_Mono, + // Signed 16-bit integer stereo audio stream + S16_Stereo, + // Signed 32-bit float mono audio stream + F32_Mono, + // Signed 32-bit float stereo audio stream + F32_Stereo + }; + + // Various visemes + public enum Viseme + { + sil, + PP, + FF, + TH, + DD, + kk, + CH, + SS, + nn, + RR, + aa, + E, + ih, + oh, + ou + }; + + public static readonly int VisemeCount = Enum.GetNames(typeof(Viseme)).Length; + + // Enum for sending lip-sync engine specific signals + public enum Signals + { + VisemeOn, + VisemeOff, + VisemeAmount, + VisemeSmoothing, + LaughterAmount + }; + + public static readonly int SignalCount = Enum.GetNames(typeof(Signals)).Length; + + // Enum for provider context to create + public enum ContextProviders + { + Original, + Enhanced, + Enhanced_with_Laughter, + }; + + /// NOTE: Opaque typedef for lip-sync context is an unsigned int (uint) + + /// Current phoneme frame results + [System.Serializable] + public class Frame + { + public void CopyInput(Frame input) + { + frameNumber = input.frameNumber; + frameDelay = input.frameDelay; + input.Visemes.CopyTo(Visemes, 0); + laughterScore = input.laughterScore; + } + + public void Reset() + { + frameNumber = 0; + frameDelay = 0; + Array.Clear(Visemes, 0, VisemeCount); + laughterScore = 0; + } + + public int frameNumber; // count from start of recognition + public int frameDelay; // in ms + public float[] Visemes = new float[VisemeCount]; // Array of floats for viseme frame. Size of Viseme Count, above + public float laughterScore; // probability of laughter presence. + }; + + // * * * * * * * * * * * * * + // Import functions + #if !UNITY_IOS || UNITY_EDITOR + public const string strOVRLS = "OVRLipSync"; + #else + public const string strOVRLS = "__Internal"; + #endif + [DllImport(strOVRLS)] + private static extern int ovrLipSyncDll_Initialize(int samplerate, int buffersize); + [DllImport(strOVRLS)] + private static extern void ovrLipSyncDll_Shutdown(); + [DllImport(strOVRLS)] + private static extern IntPtr ovrLipSyncDll_GetVersion(ref int Major, + ref int Minor, + ref int Patch); + [DllImport(strOVRLS)] + private static extern int ovrLipSyncDll_CreateContextEx(ref uint context, + ContextProviders provider, + int sampleRate, + bool enableAcceleration); + + [DllImport(strOVRLS)] + private static extern int ovrLipSyncDll_CreateContextWithModelFile(ref uint context, + ContextProviders provider, + string modelPath, + int sampleRate, + bool enableAcceleration); + + [DllImport(strOVRLS)] + private static extern int ovrLipSyncDll_DestroyContext(uint context); + + + [DllImport(strOVRLS)] + private static extern int ovrLipSyncDll_ResetContext(uint context); + [DllImport(strOVRLS)] + private static extern int ovrLipSyncDll_SendSignal(uint context, + Signals signal, + int arg1, int arg2); + [DllImport(strOVRLS)] + private static extern int ovrLipSyncDll_ProcessFrameEx( + uint context, + IntPtr audioBuffer, + uint bufferSize, + AudioDataType dataType, + ref int frameNumber, + ref int frameDelay, + float[] visemes, + int visemeCount, + ref float laughterScore, + float[] laughterCategories, + int laughterCategoriesLength); + + // * * * * * * * * * * * * * + // Public members + + // * * * * * * * * * * * * * + // Static members + private static Result sInitialized = Result.Unknown; + + // interface through this static member. + public static OVRLipSync sInstance = null; + + + // * * * * * * * * * * * * * + // MonoBehaviour overrides + + /// + /// Awake this instance. + /// + void Awake() + { + // We can only have one instance of OVRLipSync in a scene (use this for local property query) + if (sInstance == null) + { + sInstance = this; + } + else + { + Debug.LogWarning(System.String.Format("OVRLipSync Awake: Only one instance of OVRPLipSync can exist in the scene.")); + return; + } + + if (IsInitialized() != Result.Success) + { + sInitialized = Initialize(); + + if (sInitialized != Result.Success) + { + Debug.LogWarning(System.String.Format + ("OvrLipSync Awake: Failed to init Speech Rec library")); + } + } + + // Important: Use the touchpad mechanism for input, call Create on the OVRTouchpad helper class + OVRTouchpad.Create(); + + } + + /// + /// Raises the destroy event. + /// + void OnDestroy() + { + if (sInstance != this) + { + Debug.LogWarning( + "OVRLipSync OnDestroy: This is not the correct OVRLipSync instance."); + return; + } + + // Do not shut down at this time + // ovrLipSyncDll_Shutdown(); + // sInitialized = (int)Result.Unknown; + } + + + // * * * * * * * * * * * * * + // Public Functions + + public static Result Initialize() + { + int sampleRate; + int bufferSize; + int numbuf; + + // Get the current sample rate + sampleRate = AudioSettings.outputSampleRate; + // Get the current buffer size and number of buffers + AudioSettings.GetDSPBufferSize(out bufferSize, out numbuf); + + String str = System.String.Format + ("OvrLipSync Awake: Queried SampleRate: {0:F0} BufferSize: {1:F0}", sampleRate, bufferSize); + Debug.LogWarning(str); + + sInitialized = (Result)ovrLipSyncDll_Initialize(sampleRate, bufferSize); + return sInitialized; + } + + public static Result Initialize(int sampleRate, int bufferSize) + { + String str = System.String.Format + ("OvrLipSync Awake: Queried SampleRate: {0:F0} BufferSize: {1:F0}", sampleRate, bufferSize); + Debug.LogWarning(str); + + sInitialized = (Result)ovrLipSyncDll_Initialize(sampleRate, bufferSize); + return sInitialized; + } + + public static void Shutdown() + { + ovrLipSyncDll_Shutdown(); + sInitialized = Result.Unknown; + } + + /// + /// Determines if is initialized. + /// + /// true if is initialized; otherwise, false. + public static Result IsInitialized() + { + return sInitialized; + } + + /// + /// Creates a lip-sync context. + /// + /// error code + /// Context. + /// Provider. + /// Enable DSP Acceleration. + public static Result CreateContext( + ref uint context, + ContextProviders provider, + int sampleRate = 0, + bool enableAcceleration = false) + { + if (IsInitialized() != Result.Success && Initialize() != Result.Success) + return Result.CannotCreateContext; + + return (Result)ovrLipSyncDll_CreateContextEx(ref context, provider, sampleRate, enableAcceleration); + } + + /// + /// Creates a lip-sync context with specified model file. + /// + /// error code + /// Context. + /// Provider. + /// Model Dir. + /// Sampling Rate. + /// Enable DSP Acceleration. + public static Result CreateContextWithModelFile( + ref uint context, + ContextProviders provider, + string modelPath, + int sampleRate = 0, + bool enableAcceleration = false) + { + if (IsInitialized() != Result.Success && Initialize() != Result.Success) + return Result.CannotCreateContext; + + return (Result)ovrLipSyncDll_CreateContextWithModelFile( + ref context, + provider, + modelPath, + sampleRate, + enableAcceleration); + } + + /// + /// Destroy a lip-sync context. + /// + /// The context. + /// Context. + public static Result DestroyContext(uint context) + { + if (IsInitialized() != Result.Success) + return Result.Unknown; + + return (Result)ovrLipSyncDll_DestroyContext(context); + } + + /// + /// Resets the context. + /// + /// error code + /// Context. + public static Result ResetContext(uint context) + { + if (IsInitialized() != Result.Success) + return Result.Unknown; + + return (Result)ovrLipSyncDll_ResetContext(context); + } + + /// + /// Sends a signal to the lip-sync engine. + /// + /// error code + /// Context. + /// Signal. + /// Arg1. + /// Arg2. + public static Result SendSignal(uint context, Signals signal, int arg1, int arg2) + { + if (IsInitialized() != Result.Success) + return Result.Unknown; + + return (Result)ovrLipSyncDll_SendSignal(context, signal, arg1, arg2); + } + + /// + /// Process float[] audio buffer by lip-sync engine. + /// + /// error code + /// Context. + /// PCM audio buffer. + /// Lip-sync Frame. + /// Whether buffer is part of stereo or mono stream. + public static Result ProcessFrame( + uint context, float[] audioBuffer, Frame frame, bool stereo = true) + { + if (IsInitialized() != Result.Success) + return Result.Unknown; + + var dataType = stereo ? AudioDataType.F32_Stereo : AudioDataType.F32_Mono; + var numSamples = (uint)(stereo ? audioBuffer.Length / 2 : audioBuffer.Length); + var handle = GCHandle.Alloc(audioBuffer, GCHandleType.Pinned); + var rc = ovrLipSyncDll_ProcessFrameEx(context, + handle.AddrOfPinnedObject(), numSamples, dataType, + ref frame.frameNumber, ref frame.frameDelay, + frame.Visemes, frame.Visemes.Length, + ref frame.laughterScore, + null, 0 + ); + handle.Free(); + return (Result)rc; + + } + + /// + /// Process short[] audio buffer by lip-sync engine. + /// + /// error code + /// Context. + /// PCM audio buffer. + /// Lip-sync Frame. + /// Whether buffer is part of stereo or mono stream. + public static Result ProcessFrame( + uint context, short[] audioBuffer, Frame frame, bool stereo = true) + { + if (IsInitialized() != Result.Success) + return Result.Unknown; + + var dataType = stereo ? AudioDataType.S16_Stereo : AudioDataType.S16_Mono; + var numSamples = (uint)(stereo ? audioBuffer.Length / 2 : audioBuffer.Length); + var handle = GCHandle.Alloc(audioBuffer, GCHandleType.Pinned); + var rc = ovrLipSyncDll_ProcessFrameEx(context, + handle.AddrOfPinnedObject(), numSamples, dataType, + ref frame.frameNumber, ref frame.frameDelay, + frame.Visemes, frame.Visemes.Length, + ref frame.laughterScore, + null, 0 + ); + handle.Free(); + return (Result)rc; + } + +} diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSync.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSync.cs.meta new file mode 100644 index 0000000..377e203 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSync.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 82aa5cb7a870de440baadff9083be41c +timeCreated: 1444935432 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContext.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContext.cs new file mode 100644 index 0000000..9499e33 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContext.cs @@ -0,0 +1,391 @@ +/************************************************************************************ +Filename : OVRLipSyncContext.cs +Content : Interface to Oculus Lip-Sync engine +Created : August 6th, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; + +[RequireComponent(typeof(AudioSource))] + +//------------------------------------------------------------------------------------- +// ***** OVRLipSyncContext +// +/// +/// OVRLipSyncContext interfaces into the Oculus phoneme recognizer. +/// This component should be added into the scene once for each Audio Source. +/// +/// +public class OVRLipSyncContext : OVRLipSyncContextBase +{ + // * * * * * * * * * * * * * + // Public members + + + [Tooltip("Allow capturing of keyboard input to control operation.")] + public bool enableKeyboardInput = false; + [Tooltip("Register a mouse/touch callback to control loopback and gain (requires script restart).")] + public bool enableTouchInput = false; + [Tooltip("Play input audio back through audio output.")] + public bool audioLoopback = false; + [Tooltip("Key to toggle audio loopback.")] + public KeyCode loopbackKey = KeyCode.L; + [Tooltip("Show viseme scores in an OVRLipSyncDebugConsole display.")] + public bool showVisemes = false; + [Tooltip("Key to toggle viseme score display.")] + public KeyCode debugVisemesKey = KeyCode.D; + [Tooltip("Skip data from the Audio Source. Use if you intend to pass audio data in manually.")] + public bool skipAudioSource = false; + [Tooltip("Adjust the linear audio gain multiplier before processing lipsync")] + public float gain = 1.0f; + + private bool hasDebugConsole = false; + + public KeyCode debugLaughterKey = KeyCode.H; + public bool showLaughter = false; + public float laughterScore = 0.0f; + + // * * * * * * * * * * * * * + // Private members + + /// + /// Start this instance. + /// Note: make sure to always have a Start function for classes that have editor scripts. + /// + void Start() + { + // Add a listener to the OVRTouchpad for touch events + if (enableTouchInput) + { + OVRTouchpad.AddListener(LocalTouchEventCallback); + } + + // Find console + OVRLipSyncDebugConsole[] consoles = FindObjectsOfType(); + if (consoles.Length > 0) + { + hasDebugConsole = consoles[0]; + } + } + + /// + /// Handle keyboard input + /// + void HandleKeyboard() + { + // Turn loopback on/off + if (Input.GetKeyDown(loopbackKey)) + { + ToggleAudioLoopback(); + } + else if (Input.GetKeyDown(debugVisemesKey)) + { + showVisemes = !showVisemes; + + if (showVisemes) + { + if (hasDebugConsole) + { + Debug.Log("DEBUG SHOW VISEMES: ENABLED"); + } + else + { + Debug.LogWarning("Warning: No OVRLipSyncDebugConsole in the scene!"); + showVisemes = false; + } + } + else + { + if (hasDebugConsole) + { + OVRLipSyncDebugConsole.Clear(); + } + Debug.Log("DEBUG SHOW VISEMES: DISABLED"); + } + } + else if (Input.GetKeyDown(debugLaughterKey)) + { + showLaughter = !showLaughter; + + if (showLaughter) + { + if (hasDebugConsole) + { + Debug.Log("DEBUG SHOW LAUGHTER: ENABLED"); + } + else + { + Debug.LogWarning("Warning: No OVRLipSyncDebugConsole in the scene!"); + showLaughter = false; + } + } + else + { + if (hasDebugConsole) + { + OVRLipSyncDebugConsole.Clear(); + } + Debug.Log("DEBUG SHOW LAUGHTER: DISABLED"); + } + } + else if (Input.GetKeyDown(KeyCode.LeftArrow)) + { + gain -= 1.0f; + if (gain < 1.0f) gain = 1.0f; + + string g = "LINEAR GAIN: "; + g += gain; + + if (hasDebugConsole) + { + OVRLipSyncDebugConsole.Clear(); + OVRLipSyncDebugConsole.Log(g); + OVRLipSyncDebugConsole.ClearTimeout(1.5f); + } + } + else if (Input.GetKeyDown(KeyCode.RightArrow)) + { + gain += 1.0f; + if (gain > 15.0f) + gain = 15.0f; + + string g = "LINEAR GAIN: "; + g += gain; + + if (hasDebugConsole) + { + OVRLipSyncDebugConsole.Clear(); + OVRLipSyncDebugConsole.Log(g); + OVRLipSyncDebugConsole.ClearTimeout(1.5f); + } + } + } + + /// + /// Run processes that need to be updated in our game thread + /// + void Update() + { + if (enableKeyboardInput) + { + HandleKeyboard(); + } + laughterScore = this.Frame.laughterScore; + DebugShowVisemesAndLaughter(); + } + + /// + /// Preprocess F32 PCM audio buffer + /// + /// Data. + /// Channels. + public void PreprocessAudioSamples(float[] data, int channels) + { + // Increase the gain of the input + for (int i = 0; i < data.Length; ++i) + { + data[i] = data[i] * gain; + } + } + + /// + /// Postprocess F32 PCM audio buffer + /// + /// Data. + /// Channels. + public void PostprocessAudioSamples(float[] data, int channels) + { + // Turn off output (so that we don't get feedback from mics too close to speakers) + if (!audioLoopback) + { + for (int i = 0; i < data.Length; ++i) + data[i] = data[i] * 0.0f; + } + } + + /// + /// Pass F32 PCM audio buffer to the lip sync module + /// + /// Data. + /// Channels. + public void ProcessAudioSamplesRaw(float[] data, int channels) + { + // Send data into Phoneme context for processing (if context is not 0) + lock (this) + { + if (Context == 0 || OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) + { + return; + } + var frame = this.Frame; + OVRLipSync.ProcessFrame(Context, data, frame, channels == 2); + } + } + + /// + /// Pass S16 PCM audio buffer to the lip sync module + /// + /// Data. + /// Channels. + public void ProcessAudioSamplesRaw(short[] data, int channels) + { + // Send data into Phoneme context for processing (if context is not 0) + lock (this) + { + if (Context == 0 || OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) + { + return; + } + var frame = this.Frame; + OVRLipSync.ProcessFrame(Context, data, frame, channels == 2); + } + } + + + /// + /// Process F32 audio sample and pass it to the lip sync module for computation + /// + /// Data. + /// Channels. + public void ProcessAudioSamples(float[] data, int channels) + { + // Do not process if we are not initialized, or if there is no + // audio source attached to game object + if ((OVRLipSync.IsInitialized() != OVRLipSync.Result.Success) || audioSource == null) + { + return; + } + PreprocessAudioSamples(data, channels); + ProcessAudioSamplesRaw(data, channels); + PostprocessAudioSamples(data, channels); + } + + /// + /// Raises the audio filter read event. + /// + /// Data. + /// Channels. + void OnAudioFilterRead(float[] data, int channels) + { + if (!skipAudioSource) + { + ProcessAudioSamples(data, channels); + } + } + + /// + /// Print the visemes and laughter score to game window + /// + void DebugShowVisemesAndLaughter() + { + if (hasDebugConsole) + { + string seq = ""; + if (showLaughter) + { + seq += "Laughter:"; + int count = (int)(50.0f * this.Frame.laughterScore); + for (int c = 0; c < count; c++) + seq += "*"; + seq += "\n"; + } + if (showVisemes) + { + for (int i = 0; i < this.Frame.Visemes.Length; i++) + { + seq += ((OVRLipSync.Viseme)i).ToString(); + seq += ":"; + + int count = (int)(50.0f * this.Frame.Visemes[i]); + for (int c = 0; c < count; c++) + seq += "*"; + + seq += "\n"; + } + } + + OVRLipSyncDebugConsole.Clear(); + + if (seq != "") + { + OVRLipSyncDebugConsole.Log(seq); + } + } + } + + void ToggleAudioLoopback() + { + audioLoopback = !audioLoopback; + + if (hasDebugConsole) + { + OVRLipSyncDebugConsole.Clear(); + OVRLipSyncDebugConsole.ClearTimeout(1.5f); + + if (audioLoopback) + OVRLipSyncDebugConsole.Log("LOOPBACK MODE: ENABLED"); + else + OVRLipSyncDebugConsole.Log("LOOPBACK MODE: DISABLED"); + } + } + + // LocalTouchEventCallback + void LocalTouchEventCallback(OVRTouchpad.TouchEvent touchEvent) + { + string g = "LINEAR GAIN: "; + + switch (touchEvent) + { + case (OVRTouchpad.TouchEvent.SingleTap): + ToggleAudioLoopback(); + break; + + case (OVRTouchpad.TouchEvent.Up): + gain += 1.0f; + if (gain > 15.0f) + gain = 15.0f; + + g += gain; + + if (hasDebugConsole) + { + OVRLipSyncDebugConsole.Clear(); + OVRLipSyncDebugConsole.Log(g); + OVRLipSyncDebugConsole.ClearTimeout(1.5f); + } + + break; + + case (OVRTouchpad.TouchEvent.Down): + gain -= 1.0f; + if (gain < 1.0f) gain = 1.0f; + + g += gain; + + if (hasDebugConsole) + { + OVRLipSyncDebugConsole.Clear(); + OVRLipSyncDebugConsole.Log(g); + OVRLipSyncDebugConsole.ClearTimeout(1.5f); + } + + break; + } + } +} diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContext.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContext.cs.meta new file mode 100644 index 0000000..f02194c --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContext.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: f43c520a9bad8a3489109c869f454576 +timeCreated: 1438890961 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextBase.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextBase.cs new file mode 100644 index 0000000..ead942d --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextBase.cs @@ -0,0 +1,208 @@ +/************************************************************************************ +Filename : OVRLipSyncContext.cs +Content : Interface to Oculus Lip-Sync engine +Created : August 6th, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; + + +[RequireComponent(typeof(AudioSource))] + +//------------------------------------------------------------------------------------- +// ***** OVRLipSyncContextBase +// +/// +/// OVRLipSyncContextBase interfaces into the Oculus phoneme recognizer. +/// This component should be added into the scene once for each Audio Source. +/// +/// +public class OVRLipSyncContextBase : MonoBehaviour +{ + // * * * * * * * * * * * * * + // Public members + public AudioSource audioSource = null; + + [Tooltip("Which lip sync provider to use for viseme computation.")] + public OVRLipSync.ContextProviders provider = OVRLipSync.ContextProviders.Enhanced; + [Tooltip("Enable DSP offload on supported Android devices.")] + public bool enableAcceleration = true; + + // * * * * * * * * * * * * * + // Private members + private OVRLipSync.Frame frame = new OVRLipSync.Frame(); + private uint context = 0; // 0 is no context + + private int _smoothing; + public int Smoothing + { + set + { + OVRLipSync.Result result = + OVRLipSync.SendSignal(context, OVRLipSync.Signals.VisemeSmoothing, value, 0); + + if (result != OVRLipSync.Result.Success) + { + if (result == OVRLipSync.Result.InvalidParam) + { + Debug.LogError("OVRLipSyncContextBase.SetSmoothing: A viseme smoothing" + + " parameter is invalid, it should be between 1 and 100!"); + } + else + { + Debug.LogError("OVRLipSyncContextBase.SetSmoothing: An unexpected" + + " error occured."); + } + } + + _smoothing = value; + } + get + { + return _smoothing; + } + } + + public uint Context + { + get + { + return context; + } + } + + protected OVRLipSync.Frame Frame + { + get + { + return frame; + } + } + + /// + /// Awake this instance. + /// + void Awake() + { + // Cache the audio source we are going to be using to pump data to the SR + if (!audioSource) + { + audioSource = GetComponent(); + } + + lock (this) + { + if (context == 0) + { + if (OVRLipSync.CreateContext(ref context, provider, 0, enableAcceleration) + != OVRLipSync.Result.Success) + { + Debug.LogError("OVRLipSyncContextBase.Start ERROR: Could not create" + + " Phoneme context."); + return; + } + } + } + } + + + /// + /// Raises the destroy event. + /// + void OnDestroy() + { + // Create the context that we will feed into the audio buffer + lock (this) + { + if (context != 0) + { + if (OVRLipSync.DestroyContext(context) != OVRLipSync.Result.Success) + { + Debug.LogError("OVRLipSyncContextBase.OnDestroy ERROR: Could not delete" + + " Phoneme context."); + } + } + } + } + + // * * * * * * * * * * * * * + // Public Functions + + /// + /// Gets the current phoneme frame (lock and copy current frame to caller frame) + /// + /// error code + /// In frame. + public OVRLipSync.Frame GetCurrentPhonemeFrame() + { + return frame; + } + + /// + /// Sets a given viseme id blend weight to a given amount + /// + /// Integer viseme ID + /// Integer viseme amount + public void SetVisemeBlend(int viseme, int amount) + { + OVRLipSync.Result result = + OVRLipSync.SendSignal(context, OVRLipSync.Signals.VisemeAmount, viseme, amount); + + if (result != OVRLipSync.Result.Success) + { + if (result == OVRLipSync.Result.InvalidParam) + { + Debug.LogError("OVRLipSyncContextBase.SetVisemeBlend: Viseme ID is invalid."); + } + else + { + Debug.LogError("OVRLipSyncContextBase.SetVisemeBlend: An unexpected" + + " error occured."); + } + } + } + + /// + /// Sets a given viseme id blend weight to a given amount + /// + /// Integer viseme amount + public void SetLaughterBlend(int amount) + { + OVRLipSync.Result result = + OVRLipSync.SendSignal(context, OVRLipSync.Signals.LaughterAmount, amount, 0); + + if (result != OVRLipSync.Result.Success) + { + Debug.LogError("OVRLipSyncContextBase.SetLaughterBlend: An unexpected" + + " error occured."); + } + } + + /// + /// Resets the context. + /// + /// error code + public OVRLipSync.Result ResetContext() + { + // Reset visemes to silence etc. + frame.Reset(); + + return OVRLipSync.ResetContext(context); + } +} diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextBase.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextBase.cs.meta new file mode 100644 index 0000000..daeb68c --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextBase.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: c0d528b758a004fcaac677043e8de6ad +timeCreated: 1496772358 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextCanned.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextCanned.cs new file mode 100644 index 0000000..af7a769 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextCanned.cs @@ -0,0 +1,51 @@ +/************************************************************************************ +Filename : OVRLipSyncContextCanned.cs +Content : Interface to Oculus Lip-Sync engine +Created : August 6th, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; + + +[RequireComponent(typeof(AudioSource))] + +//------------------------------------------------------------------------------------- +// ***** OVRLipSyncContextCanned +// +/// +/// OVRLipSyncContextCanned drives a canned phoneme sequence based on a pre-generated asset. +/// +/// +public class OVRLipSyncContextCanned : OVRLipSyncContextBase +{ + [Tooltip("Pre-computed viseme sequence asset. Compute from audio in Unity with Tools -> Oculus -> Generate Lip Sync Assets.")] + public OVRLipSyncSequence currentSequence; + + /// + /// Run processes that need to be updated in game thread + /// + void Update() + { + if (audioSource.isPlaying && currentSequence != null) + { + OVRLipSync.Frame currentFrame = currentSequence.GetFrameAtTime(audioSource.time); + this.Frame.CopyInput(currentFrame); + } + } +} diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextCanned.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextCanned.cs.meta new file mode 100644 index 0000000..14875ba --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextCanned.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e073e338e215b4ae9a7fcdf6891e7955 +timeCreated: 1496772358 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextMorphTarget.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextMorphTarget.cs new file mode 100644 index 0000000..069ad0e --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextMorphTarget.cs @@ -0,0 +1,227 @@ +/************************************************************************************ +Filename : OVRLipSyncContextMorphTarget.cs +Content : This bridges the viseme output to the morph targets +Created : August 7th, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; +using System.Linq; + +public class OVRLipSyncContextMorphTarget : MonoBehaviour +{ + // PUBLIC + + // Manually assign the skinned mesh renderer to this script + [Tooltip("Skinned Mesh Rendered target to be driven by Oculus Lipsync")] + public SkinnedMeshRenderer skinnedMeshRenderer = null; + + // Set the blendshape index to go to (-1 means there is not one assigned) + [Tooltip("Blendshape index to trigger for each viseme.")] + public int [] visemeToBlendTargets = Enumerable.Range(0, OVRLipSync.VisemeCount).ToArray(); + + // enable/disable sending signals to viseme engine + [Tooltip("Enable using the test keys defined below to manually trigger each viseme.")] + public bool enableVisemeTestKeys = false; + [Tooltip("Test keys used to manually trigger an individual viseme - by " + + "default the QWERTY row of a US keyboard.")] + public KeyCode[] visemeTestKeys = + { + KeyCode.BackQuote, + KeyCode.Tab, + KeyCode.Q, + KeyCode.W, + KeyCode.E, + KeyCode.R, + KeyCode.T, + KeyCode.Y, + KeyCode.U, + KeyCode.I, + KeyCode.O, + KeyCode.P, + KeyCode.LeftBracket, + KeyCode.RightBracket, + KeyCode.Backslash, + }; + + [Tooltip("Test key used to manually trigger laughter and visualise the results")] + public KeyCode laughterKey = KeyCode.CapsLock; + + [Tooltip("Blendshape index to trigger for laughter")] + public int laughterBlendTarget = OVRLipSync.VisemeCount; + + [Range(0.0f, 1.0f)] + [Tooltip("Laughter probability threshold above which the laughter blendshape will be activated")] + public float laughterThreshold = 0.5f; + + [Range(0.0f, 3.0f)] + [Tooltip("Laughter animation linear multiplier, the final output will be clamped to 1.0")] + public float laughterMultiplier = 1.5f; + + // smoothing amount + [Range(1, 100)] + [Tooltip("Smoothing of 1 will yield only the current predicted viseme, 100 will yield an extremely smooth viseme response.")] + public int smoothAmount = 70; + + // PRIVATE + + // Look for a lip-sync Context (should be set at the same level as this component) + private OVRLipSyncContextBase lipsyncContext = null; + + + /// + /// Start this instance. + /// + void Start () + { + // morph target needs to be set manually; possibly other components will need the same + if(skinnedMeshRenderer == null) + { + Debug.LogError("LipSyncContextMorphTarget.Start Error: " + + "Please set the target Skinned Mesh Renderer to be controlled!"); + return; + } + + // make sure there is a phoneme context assigned to this object + lipsyncContext = GetComponent(); + if(lipsyncContext == null) + { + Debug.LogError("LipSyncContextMorphTarget.Start Error: " + + "No OVRLipSyncContext component on this object!"); + } + else + { + // Send smoothing amount to context + lipsyncContext.Smoothing = smoothAmount; + } + } + + /// + /// Update this instance. + /// + void Update () + { + if((lipsyncContext != null) && (skinnedMeshRenderer != null)) + { + // get the current viseme frame + OVRLipSync.Frame frame = lipsyncContext.GetCurrentPhonemeFrame(); + if (frame != null) + { + SetVisemeToMorphTarget(frame); + + SetLaughterToMorphTarget(frame); + } + + // TEST visemes by capturing key inputs and sending a signal + CheckForKeys(); + + // Update smoothing value + if (smoothAmount != lipsyncContext.Smoothing) + { + lipsyncContext.Smoothing = smoothAmount; + } + } + } + + /// + /// Sends the signals. + /// + void CheckForKeys() + { + if (enableVisemeTestKeys) + { + for (int i = 0; i < OVRLipSync.VisemeCount; ++i) + { + CheckVisemeKey(visemeTestKeys[i], i, 100); + } + } + + CheckLaughterKey(); + } + + /// + /// Sets the viseme to morph target. + /// + void SetVisemeToMorphTarget(OVRLipSync.Frame frame) + { + for (int i = 0; i < visemeToBlendTargets.Length; i++) + { + if (visemeToBlendTargets[i] != -1) + { + // Viseme blend weights are in range of 0->1.0, we need to make range 100 + skinnedMeshRenderer.SetBlendShapeWeight( + visemeToBlendTargets[i], + frame.Visemes[i] * 100.0f); + } + } + } + + /// + /// Sets the laughter to morph target. + /// + void SetLaughterToMorphTarget(OVRLipSync.Frame frame) + { + if (laughterBlendTarget != -1) + { + // Laughter score will be raw classifier output in [0,1] + float laughterScore = frame.laughterScore; + + // Threshold then re-map to [0,1] + laughterScore = laughterScore < laughterThreshold ? 0.0f : laughterScore - laughterThreshold; + laughterScore = Mathf.Min(laughterScore * laughterMultiplier, 1.0f); + laughterScore *= 1.0f / laughterThreshold; + + skinnedMeshRenderer.SetBlendShapeWeight( + laughterBlendTarget, + laughterScore * 100.0f); + } + } + + /// + /// Sends the viseme signal. + /// + /// Key. + /// Viseme. + /// Arg1. + void CheckVisemeKey(KeyCode key, int viseme, int amount) + { + if (Input.GetKeyDown(key)) + { + lipsyncContext.SetVisemeBlend(visemeToBlendTargets[viseme], amount); + } + if (Input.GetKeyUp(key)) + { + lipsyncContext.SetVisemeBlend(visemeToBlendTargets[viseme], 0); + } + } + + /// + /// Sends the laughter signal. + /// + void CheckLaughterKey() + { + if (Input.GetKeyDown(laughterKey)) + { + lipsyncContext.SetLaughterBlend(100); + } + if (Input.GetKeyUp(laughterKey)) + { + lipsyncContext.SetLaughterBlend(0); + } + } +} diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextMorphTarget.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextMorphTarget.cs.meta new file mode 100644 index 0000000..e3fb346 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextMorphTarget.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: b0b97b38f2f1fd24185315141a6c6a56 +timeCreated: 1438985973 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextTextureFlip.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextTextureFlip.cs new file mode 100644 index 0000000..9bd279f --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextTextureFlip.cs @@ -0,0 +1,150 @@ +/************************************************************************************ +Filename : OVRLipSyncContextTextureFlip.cs +Content : This bridges the phoneme/viseme output to texture flip targets +Created : August 7th, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using UnityEngine; + +public class OVRLipSyncContextTextureFlip : MonoBehaviour +{ + // PUBLIC + + // Manually assign the material + public Material material = null; + + // Set the textures for each viseme. We should follow the viseme order as specified + // by the Phoneme list + [Tooltip("The texture used for each viseme.")] + [OVRNamedArray(new string[] { "sil", "PP", "FF", "TH", "DD", "kk", "CH", + "SS", "nn", "RR", "aa", "E", "ih", "oh", "ou" })] + public Texture[] Textures = new Texture[OVRLipSync.VisemeCount]; + + // smoothing amount + [Range(1, 100)] + [Tooltip("Smoothing of 1 will yield only the current predicted viseme," + + "100 will yield an extremely smooth viseme response.")] + public int smoothAmount = 70; + + // PRIVATE + + // Look for a Phoneme Context (should be set at the same level as this component) + private OVRLipSyncContextBase lipsyncContext = null; + + // Capture the old viseme frame (we will write back into this one) + private OVRLipSync.Frame oldFrame = new OVRLipSync.Frame(); + + /// + /// Start this instance. + /// + void Start() + { + // make sure there is a phoneme context assigned to this object + lipsyncContext = GetComponent(); + if (lipsyncContext == null) + { + Debug.LogWarning("LipSyncContextTextureFlip.Start WARNING:" + + " No lip sync context component set to object"); + } + else + { + // Send smoothing amount to context + lipsyncContext.Smoothing = smoothAmount; + } + + if (material == null) + { + Debug.LogWarning("LipSyncContextTextureFlip.Start WARNING:" + + " Lip sync context texture flip has no material target to control!"); + } + } + + /// + /// Update this instance. + /// + void Update () + { + if((lipsyncContext != null) && (material != null)) + { + // trap inputs and send signals to phoneme engine for testing purposes + + // get the current viseme frame + OVRLipSync.Frame frame = lipsyncContext.GetCurrentPhonemeFrame(); + if (frame != null) + { + // Perform smoothing here if on original provider + if (lipsyncContext.provider == OVRLipSync.ContextProviders.Original) + { + // Go through the current and old + for (int i = 0; i < frame.Visemes.Length; i++) + { + // Convert 1-100 to old * (0.00 - 0.99) + float smoothing = ((smoothAmount - 1) / 100.0f); + oldFrame.Visemes[i] = + oldFrame.Visemes[i] * smoothing + + frame.Visemes[i] * (1.0f - smoothing); + } + } + else + { + oldFrame.Visemes = frame.Visemes; + } + + SetVisemeToTexture(); + } + } + + // Update smoothing value in context + if (smoothAmount != lipsyncContext.Smoothing) + { + lipsyncContext.Smoothing = smoothAmount; + } + } + + /// + /// Sets the viseme to texture. + /// + void SetVisemeToTexture() + { + // This setting will run through all the Visemes, find the + // one with the greatest amplitude and set it to max value. + // all other visemes will be set to zero. + int gV = -1; + float gA = 0.0f; + + for (int i = 0; i < oldFrame.Visemes.Length; i++) + { + if(oldFrame.Visemes[i] > gA) + { + gV = i; + gA = oldFrame.Visemes[i]; + } + } + + if ((gV != -1) && (gV < Textures.Length)) + { + Texture t = Textures[gV]; + + if(t != null) + { + material.SetTexture("_MainTex", t); + } + } + } +} diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextTextureFlip.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextTextureFlip.cs.meta new file mode 100644 index 0000000..dc9da2d --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncContextTextureFlip.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: bc30a49f30010eb42a8b59ec685eac57 +timeCreated: 1444164852 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncMicInput.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSyncMicInput.cs new file mode 100644 index 0000000..2a0c2e6 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncMicInput.cs @@ -0,0 +1,372 @@ +/************************************************************************************ +Filename : OVRLipSyncMicInput.cs +Content : Interface to microphone input +Created : May 12, 2015 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ + +using System; +using UnityEngine; +using System.Diagnostics; +using Debug = UnityEngine.Debug; +using System.Threading; + +[RequireComponent(typeof(AudioSource))] + +public class OVRLipSyncMicInput : MonoBehaviour +{ + public enum micActivation + { + HoldToSpeak, + PushToSpeak, + ConstantSpeak + } + + // PUBLIC MEMBERS + [Tooltip("Manual specification of Audio Source - " + + "by default will use any attached to the same object.")] + public AudioSource audioSource = null; + + + [Tooltip("Enable a keypress to toggle the microphone device selection GUI.")] + public bool enableMicSelectionGUI = false; + [Tooltip("Key to toggle the microphone selection GUI if enabled.")] + public KeyCode micSelectionGUIKey = KeyCode.M; + + [SerializeField] + [Range(0.0f, 100.0f)] + [Tooltip("Microphone input volume control.")] + private float micInputVolume = 100; + + [SerializeField] + [Tooltip("Requested microphone input frequency")] + private int micFrequency = 48000; + public float MicFrequency + { + get { return micFrequency; } + set { micFrequency = (int)Mathf.Clamp((float)value, 0, 96000); } + } + + [Tooltip("Microphone input control method. Hold To Speak and Push" + + " To Speak are driven with the Mic Activation Key.")] + public micActivation micControl = micActivation.ConstantSpeak; + [Tooltip("Key used to drive Hold To Speak and Push To Speak methods" + + " of microphone input control.")] + public KeyCode micActivationKey = KeyCode.Space; + + [Tooltip("Will contain the string name of the selected microphone device - read only.")] + public string selectedDevice; + + // PRIVATE MEMBERS + private bool micSelected = false; + private int minFreq, maxFreq; + private bool focused = true; + private bool initialized = false; + + //---------------------------------------------------- + // MONOBEHAVIOUR OVERRIDE FUNCTIONS + //---------------------------------------------------- + + /// + /// Awake this instance. + /// + void Awake() + { + // First thing to do, cache the unity audio source (can be managed by the + // user if audio source can change) + if (!audioSource) audioSource = GetComponent(); + if (!audioSource) return; // this should never happen + } + + /// + /// Start this instance. + /// + void Start() + { + audioSource.loop = true; // Set the AudioClip to loop + audioSource.mute = false; + + InitializeMicrophone(); + } + + /// + /// Initializes the microphone. + /// + private void InitializeMicrophone() + { + if (initialized) + { + return; + } + if (Microphone.devices.Length == 0) + { + return; + } + selectedDevice = Microphone.devices[0].ToString(); + micSelected = true; + GetMicCaps(); + initialized = true; + } + + + /// + /// Update this instance. + /// + void Update() + { + if (!focused) + { + if (Microphone.IsRecording(selectedDevice)) + { + StopMicrophone(); + } + return; + } + + if (!Application.isPlaying) + { + StopMicrophone(); + return; + } + + // Lazy Microphone initialization (needed on Android) + if (!initialized) + { + InitializeMicrophone(); + } + + audioSource.volume = (micInputVolume / 100); + + //Hold To Speak + if (micControl == micActivation.HoldToSpeak) + { + if (Input.GetKey(micActivationKey)) + { + if (!Microphone.IsRecording(selectedDevice)) + { + StartMicrophone(); + } + } + else + { + if (Microphone.IsRecording(selectedDevice)) + { + StopMicrophone(); + } + } + } + + //Push To Talk + if (micControl == micActivation.PushToSpeak) + { + if (Input.GetKeyDown(micActivationKey)) + { + if (Microphone.IsRecording(selectedDevice)) + { + StopMicrophone(); + } + else if (!Microphone.IsRecording(selectedDevice)) + { + StartMicrophone(); + } + } + } + + //Constant Speak + if (micControl == micActivation.ConstantSpeak) + { + if (!Microphone.IsRecording(selectedDevice)) + { + StartMicrophone(); + } + } + + + //Mic Selected = False + if (enableMicSelectionGUI) + { + if (Input.GetKeyDown(micSelectionGUIKey)) + { + micSelected = false; + } + } + } + + + /// + /// Raises the application focus event. + /// + /// If set to true: focused. + void OnApplicationFocus(bool focus) + { + focused = focus; + + if (!focused) + StopMicrophone(); + } + + /// + /// Raises the application pause event. + /// + /// If set to true: paused. + void OnApplicationPause(bool pauseStatus) + { + focused = !pauseStatus; + + if (!focused) + StopMicrophone(); + } + + void OnDisable() + { + StopMicrophone(); + } + + /// + /// Raises the GU event. + /// + void OnGUI() + { + MicDeviceGUI((Screen.width / 2) - 150, (Screen.height / 2) - 75, 300, 50, 10, -300); + } + + //---------------------------------------------------- + // PUBLIC FUNCTIONS + //---------------------------------------------------- + + /// + /// Mics the device GU. + /// + /// Left. + /// Top. + /// Width. + /// Height. + /// Button space top. + /// Button space left. + public void MicDeviceGUI( + float left, + float top, + float width, + float height, + float buttonSpaceTop, + float buttonSpaceLeft) + { + //If there is more than one device, choose one. + if (Microphone.devices.Length >= 1 && enableMicSelectionGUI == true && micSelected == false) + { + for (int i = 0; i < Microphone.devices.Length; ++i) + { + if (GUI.Button(new Rect(left + ((width + buttonSpaceLeft) * i), + top + ((height + buttonSpaceTop) * i), width, height), + Microphone.devices[i].ToString())) + { + StopMicrophone(); + selectedDevice = Microphone.devices[i].ToString(); + micSelected = true; + GetMicCaps(); + StartMicrophone(); + } + } + } + } + + /// + /// Gets the mic caps. + /// + public void GetMicCaps() + { + if (micSelected == false) return; + + //Gets the frequency of the device + Microphone.GetDeviceCaps(selectedDevice, out minFreq, out maxFreq); + + if (minFreq == 0 && maxFreq == 0) + { + Debug.LogWarning("GetMicCaps warning:: min and max frequencies are 0"); + minFreq = 44100; + maxFreq = 44100; + } + + if (micFrequency > maxFreq) + micFrequency = maxFreq; + } + + /// + /// Starts the microphone. + /// + public void StartMicrophone() + { + if (micSelected == false) return; + + //Starts recording + audioSource.clip = Microphone.Start(selectedDevice, true, 1, micFrequency); + + Stopwatch timer = Stopwatch.StartNew(); + + // Wait until the recording has started + while (!(Microphone.GetPosition(selectedDevice) > 0) && timer.Elapsed.TotalMilliseconds < 1000) { + Thread.Sleep(50); + } + + if (Microphone.GetPosition(selectedDevice) <= 0) + { + throw new Exception("Timeout initializing microphone " + selectedDevice); + } + // Play the audio source + audioSource.Play(); + } + + /// + /// Stops the microphone. + /// + public void StopMicrophone() + { + if (micSelected == false) return; + + // Overriden with a clip to play? Don't stop the audio source + if ((audioSource != null) && + (audioSource.clip != null) && + (audioSource.clip.name == "Microphone")) + { + audioSource.Stop(); + } + + // Reset to stop mouth movement + OVRLipSyncContext context = GetComponent(); + context.ResetContext(); + + Microphone.End(selectedDevice); + } + + + //---------------------------------------------------- + // PRIVATE FUNCTIONS + //---------------------------------------------------- + + /// + /// Gets the averaged volume. + /// + /// The averaged volume. + float GetAveragedVolume() + { + // We will use the SR to get average volume + // return OVRSpeechRec.GetAverageVolume(); + return 0.0f; + } +} diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncMicInput.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSyncMicInput.cs.meta new file mode 100644 index 0000000..d8af3f7 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncMicInput.cs.meta @@ -0,0 +1,13 @@ +fileFormatVersion: 2 +guid: 02d5ed157083b494e85013bad8fd5e12 +timeCreated: 1437430905 +licenseType: Pro +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncSequence.cs b/Assets/Oculus/LipSync/Scripts/OVRLipSyncSequence.cs new file mode 100644 index 0000000..292cc42 --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncSequence.cs @@ -0,0 +1,162 @@ +/************************************************************************************ +Filename : OVRLipSyncSequence.cs +Content : LipSync frames container +Created : May 17th, 2018 +Copyright : Copyright Facebook Technologies, LLC and its affiliates. + All rights reserved. + +Licensed under the Oculus Audio SDK License Version 3.3 (the "License"); +you may not use the Oculus Audio SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/audio-3.3/ + +Unless required by applicable law or agreed to in writing, the Oculus Audio SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +************************************************************************************/ +using System; +using System.Collections.Generic; +using System.IO; +using UnityEngine; + +// Sequence - holds ordered entries for playback +[System.Serializable] +public class OVRLipSyncSequence : ScriptableObject +{ + public List entries = new List(); + public float length; // in seconds + + public OVRLipSync.Frame GetFrameAtTime(float time) + { + OVRLipSync.Frame frame = null; + if (time < length && entries.Count > 0) + { + float percentComplete = time / length; + frame = entries[(int)(entries.Count * percentComplete)]; + } + return frame; + } + +#if UNITY_EDITOR + + private static readonly int sSampleSize = 1024; + + public static OVRLipSyncSequence CreateSequenceFromAudioClip( + AudioClip clip, bool useOfflineModel = false) + { + OVRLipSyncSequence sequence = null; + + if (clip.channels > 2) + { + Debug.LogError(clip.name + + ": Cannot process phonemes from an audio clip with " + + "more than 2 channels"); + return null; + } + + if (clip.loadType != AudioClipLoadType.DecompressOnLoad) + { + Debug.LogError(clip.name + + ": Cannot process phonemes from an audio clip unless " + + "its load type is set to DecompressOnLoad."); + return null; + } + + if (OVRLipSync.Initialize(clip.frequency, sSampleSize) != OVRLipSync.Result.Success) + { + Debug.LogError("Could not create Lip Sync engine."); + return null; + } + + if (clip.loadState != AudioDataLoadState.Loaded) + { + Debug.LogError("Clip is not loaded!"); + return null; + } + + uint context = 0; + + OVRLipSync.Result result = useOfflineModel + ? OVRLipSync.CreateContextWithModelFile( + ref context, + OVRLipSync.ContextProviders.Enhanced, + Path.Combine(Application.dataPath, "Oculus/LipSync/Assets/OfflineModel/ovrlipsync_offline_model.pb")) + : OVRLipSync.CreateContext(ref context, OVRLipSync.ContextProviders.Enhanced); + + if (result != OVRLipSync.Result.Success) + { + Debug.LogError("Could not create Phoneme context. (" + result + ")"); + OVRLipSync.Shutdown(); + return null; + } + + List frames = new List(); + float[] samples = new float[sSampleSize * clip.channels]; + + OVRLipSync.Frame dummyFrame = new OVRLipSync.Frame(); + OVRLipSync.ProcessFrame( + context, + samples, + dummyFrame, + (clip.channels == 2) ? true : false + ); + // frame delay in ms + float frameDelayInMs = dummyFrame.frameDelay; + + int frameOffset = (int)(frameDelayInMs * clip.frequency / 1000); + + int totalSamples = clip.samples; + for (int x = 0; x < totalSamples + frameOffset; x += sSampleSize) + { + int remainingSamples = totalSamples - x; + if (remainingSamples >= sSampleSize) { + clip.GetData(samples, x); + } else if (remainingSamples > 0) { + float[] samples_clip = new float[remainingSamples * clip.channels]; + clip.GetData(samples_clip, x); + Array.Copy(samples_clip, samples, samples_clip.Length); + Array.Clear(samples, samples_clip.Length, samples.Length - samples_clip.Length); + } else { + Array.Clear(samples, 0, samples.Length); + } + + OVRLipSync.Frame frame = new OVRLipSync.Frame(); + if (clip.channels == 2) + { + // interleaved = stereo data, alternating floats + OVRLipSync.ProcessFrame(context, samples, frame); + } + else + { + // mono + OVRLipSync.ProcessFrame(context, samples, frame, false); + } + + if (x < frameOffset) + { + continue; + } + + frames.Add(frame); + } + + Debug.Log(clip.name + " produced " + frames.Count + + " viseme frames, playback rate is " + (frames.Count / clip.length) + + " fps"); + OVRLipSync.DestroyContext(context); + OVRLipSync.Shutdown(); + + sequence = ScriptableObject.CreateInstance(); + sequence.entries = frames; + sequence.length = clip.length; + + return sequence; + } +#endif +}; diff --git a/Assets/Oculus/LipSync/Scripts/OVRLipSyncSequence.cs.meta b/Assets/Oculus/LipSync/Scripts/OVRLipSyncSequence.cs.meta new file mode 100644 index 0000000..1dd243c --- /dev/null +++ b/Assets/Oculus/LipSync/Scripts/OVRLipSyncSequence.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 354250b5dc6a14f49b541724e9dd3c37 +timeCreated: 1496772358 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/OculusProjectConfig.asset b/Assets/Oculus/OculusProjectConfig.asset new file mode 100644 index 0000000..172e0c3 --- /dev/null +++ b/Assets/Oculus/OculusProjectConfig.asset @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:e7583a237b0e65c145dad531b08a767c859c1512dd8481e9b9b9bd31b1c23d9f +size 479 diff --git a/Assets/Oculus/OculusProjectConfig.asset.meta b/Assets/Oculus/OculusProjectConfig.asset.meta new file mode 100644 index 0000000..a389b7c --- /dev/null +++ b/Assets/Oculus/OculusProjectConfig.asset.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce416aebb13c7d247a44e27468af98d5 +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 11400000 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform.meta b/Assets/Oculus/Platform.meta new file mode 100644 index 0000000..a75ed1f --- /dev/null +++ b/Assets/Oculus/Platform.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c0b9a74c8d4e94bb48bf58333a921038 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Editor.meta b/Assets/Oculus/Platform/Editor.meta new file mode 100644 index 0000000..eb0eedd --- /dev/null +++ b/Assets/Oculus/Platform/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6120f30a4fbb0a641a13125a1fba707a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Editor/GUIHelper.cs b/Assets/Oculus/Platform/Editor/GUIHelper.cs new file mode 100644 index 0000000..b9349d3 --- /dev/null +++ b/Assets/Oculus/Platform/Editor/GUIHelper.cs @@ -0,0 +1,45 @@ +namespace Oculus.Platform +{ + using UnityEditor; + using UnityEngine; + + class GUIHelper { + public delegate void Worker(); + + static void InOut(Worker begin, Worker body, Worker end) { + try { + begin(); + body(); + } finally { + end(); + } + } + + public static void HInset(int pixels, Worker worker) { + InOut( + () => { + GUILayout.BeginHorizontal(); + GUILayout.Space(pixels); + GUILayout.BeginVertical(); + }, + worker, + () => { + GUILayout.EndVertical(); + GUILayout.EndHorizontal(); + } + ); + } + + public delegate T ControlWorker(); + public static T MakeControlWithLabel(GUIContent label, ControlWorker worker) { + EditorGUILayout.BeginHorizontal(); + EditorGUILayout.LabelField(label); + + var result = worker(); + + EditorGUILayout.EndHorizontal(); + return result; + } + } + +} diff --git a/Assets/Oculus/Platform/Editor/GUIHelper.cs.meta b/Assets/Oculus/Platform/Editor/GUIHelper.cs.meta new file mode 100644 index 0000000..6f0656d --- /dev/null +++ b/Assets/Oculus/Platform/Editor/GUIHelper.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 19bb2c637ba6e9c459e3db36b2ec10c3 +timeCreated: 1523486797 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Editor/OculusPlatformSettingsEditor.cs b/Assets/Oculus/Platform/Editor/OculusPlatformSettingsEditor.cs new file mode 100644 index 0000000..10afbc0 --- /dev/null +++ b/Assets/Oculus/Platform/Editor/OculusPlatformSettingsEditor.cs @@ -0,0 +1,443 @@ +namespace Oculus.Platform +{ + using System; + using System.IO; + using UnityEditor; + using UnityEngine; + using UnityEngine.Networking; + + // This classes implements a UI to edit the PlatformSettings class. + // The UI is accessible from a the menu bar via: Oculus Platform -> Edit Settings + [CustomEditor(typeof(PlatformSettings))] + public class OculusPlatformSettingsEditor : Editor + { + private bool isUnityEditorSettingsExpanded; + private bool isBuildSettingsExpanded; + + private UnityWebRequest getAccessTokenRequest; + + private void OnEnable() + { + isUnityEditorSettingsExpanded = true; + isBuildSettingsExpanded = true; + } + + [UnityEditor.MenuItem("Oculus/Platform/Edit Settings")] + public static void Edit() + { + UnityEditor.Selection.activeObject = PlatformSettings.Instance; + } + + public override void OnInspectorGUI() + { + // + // Application IDs section + // + EditorGUILayout.LabelField("Application ID:"); + GUIContent riftAppIDLabel = new GUIContent("Oculus Rift [?]", "This AppID will be used when building to the Windows target."); + GUIContent mobileAppIDLabel = new GUIContent("Oculus Go/Quest or Gear VR [?]", "This AppID will be used when building to the Android target"); + PlatformSettings.AppID = MakeTextBox(riftAppIDLabel, PlatformSettings.AppID); + PlatformSettings.MobileAppID = MakeTextBox(mobileAppIDLabel, PlatformSettings.MobileAppID); + + if (GUILayout.Button("Create / Find your app on https://dashboard.oculus.com")) + { + UnityEngine.Application.OpenURL("https://dashboard.oculus.com/"); + } + +#if UNITY_ANDROID + if (String.IsNullOrEmpty(PlatformSettings.MobileAppID)) + { + EditorGUILayout.HelpBox("Please enter a valid Oculus Go/Quest or Gear VR App ID.", MessageType.Error); + } + else + { + var msg = "Configured to connect with App ID " + PlatformSettings.MobileAppID; + EditorGUILayout.HelpBox(msg, MessageType.Info); + } +#else + if (String.IsNullOrEmpty(PlatformSettings.AppID)) + { + EditorGUILayout.HelpBox("Please enter a valid Oculus Rift App ID.", MessageType.Error); + } + else + { + var msg = "Configured to connect with App ID " + PlatformSettings.AppID; + EditorGUILayout.HelpBox(msg, MessageType.Info); + } +#endif + EditorGUILayout.Separator(); + + // + // Unity Editor Settings section + // + isUnityEditorSettingsExpanded = EditorGUILayout.Foldout(isUnityEditorSettingsExpanded, "Unity Editor Settings"); + if (isUnityEditorSettingsExpanded) + { + GUIHelper.HInset(6, () => + { + bool HasTestAccessToken = !String.IsNullOrEmpty(StandalonePlatformSettings.OculusPlatformTestUserAccessToken); + if (PlatformSettings.UseStandalonePlatform) + { + if (!HasTestAccessToken && + (String.IsNullOrEmpty(StandalonePlatformSettings.OculusPlatformTestUserEmail) || + String.IsNullOrEmpty(StandalonePlatformSettings.OculusPlatformTestUserPassword))) + { + EditorGUILayout.HelpBox("Please enter a valid user credentials.", MessageType.Error); + } + else + { + var msg = "The Unity editor will use the supplied test user credentials and operate in standalone mode. Some user data will be mocked."; + EditorGUILayout.HelpBox(msg, MessageType.Info); + } + } + else + { + var msg = "The Unity editor will use the user credentials from the Oculus application."; + EditorGUILayout.HelpBox(msg, MessageType.Info); + } + + var useStandaloneLabel = "Use Standalone Platform [?]"; + var useStandaloneHint = "If this is checked your app will use a debug platform with the User info below. " + + "Otherwise your app will connect to the Oculus Platform. This setting only applies to the Unity Editor"; + PlatformSettings.UseStandalonePlatform = + MakeToggle(new GUIContent(useStandaloneLabel, useStandaloneHint), PlatformSettings.UseStandalonePlatform); + + GUI.enabled = PlatformSettings.UseStandalonePlatform; + + if (!HasTestAccessToken) + { + var emailLabel = "Test User Email: "; + var emailHint = "Test users can be configured at " + + "https://dashboard.oculus.com/organizations//testusers " + + "however any valid Oculus account email may be used."; + StandalonePlatformSettings.OculusPlatformTestUserEmail = + MakeTextBox(new GUIContent(emailLabel, emailHint), StandalonePlatformSettings.OculusPlatformTestUserEmail); + + var passwdLabel = "Test User Password: "; + var passwdHint = "Password associated with the email address."; + StandalonePlatformSettings.OculusPlatformTestUserPassword = + MakePasswordBox(new GUIContent(passwdLabel, passwdHint), StandalonePlatformSettings.OculusPlatformTestUserPassword); + + var isLoggingIn = (getAccessTokenRequest != null); + var loginLabel = (!isLoggingIn) ? "Login" : "Logging in..."; + + GUI.enabled = !isLoggingIn; + if (GUILayout.Button(loginLabel)) + { + WWWForm form = new WWWForm(); + form.AddField("email", StandalonePlatformSettings.OculusPlatformTestUserEmail); + form.AddField("password", StandalonePlatformSettings.OculusPlatformTestUserPassword); + + // Start the WWW request to get the access token + getAccessTokenRequest = UnityWebRequest.Post("https://graph.oculus.com/login", form); + getAccessTokenRequest.SetRequestHeader("Authorization", "Bearer OC|1141595335965881|"); + getAccessTokenRequest.SendWebRequest(); + EditorApplication.update += GetAccessToken; + } + GUI.enabled = true; + } + else + { + var loggedInMsg = "Currently using the credentials associated with " + StandalonePlatformSettings.OculusPlatformTestUserEmail; + EditorGUILayout.HelpBox(loggedInMsg, MessageType.Info); + + var logoutLabel = "Clear Credentials"; + + if (GUILayout.Button(logoutLabel)) + { + StandalonePlatformSettings.OculusPlatformTestUserAccessToken = ""; + } + } + + GUI.enabled = true; + }); + } + EditorGUILayout.Separator(); + + // + // Build Settings section + // + isBuildSettingsExpanded = EditorGUILayout.Foldout(isBuildSettingsExpanded, "Build Settings"); + if (isBuildSettingsExpanded) + { + GUIHelper.HInset(6, () => { + if (!PlayerSettings.virtualRealitySupported) + { + EditorGUILayout.HelpBox("VR Support isn't enabled in the Player Settings", MessageType.Warning); + } + else + { + EditorGUILayout.HelpBox("VR Support is enabled", MessageType.Info); + } + + PlayerSettings.virtualRealitySupported = MakeToggle(new GUIContent("Virtual Reality Support"), PlayerSettings.virtualRealitySupported); + PlayerSettings.bundleVersion = MakeTextBox(new GUIContent("Bundle Version"), PlayerSettings.bundleVersion); +#if UNITY_5_3 || UNITY_5_4 || UNITY_5_5 + PlayerSettings.bundleIdentifier = MakeTextBox(new GUIContent("Bundle Identifier"), PlayerSettings.bundleIdentifier); +#else + BuildTargetGroup buildTargetGroup = EditorUserBuildSettings.selectedBuildTargetGroup; + PlayerSettings.SetApplicationIdentifier( + buildTargetGroup, + MakeTextBox( + new GUIContent("Bundle Identifier"), + PlayerSettings.GetApplicationIdentifier(buildTargetGroup))); +#endif + bool canEnableARM64Support = false; +#if UNITY_2018_1_OR_NEWER + canEnableARM64Support = true; +#endif + if (!canEnableARM64Support) + { + var msg = "Update your Unity Editor to 2018.1.x or newer to enable Arm64 support"; + EditorGUILayout.HelpBox(msg, MessageType.Warning); + if (IsArm64PluginPlatformEnabled()) + { + DisablePluginPlatform(PluginPlatform.Android64); + } + } + else + { + if (!IsArm64PluginPlatformEnabled()) + { + EnablePluginPlatform(PluginPlatform.Android64); + } + } + + GUI.enabled = true; + }); + } + EditorGUILayout.Separator(); + } + + // Asyncronously fetch the access token with the given credentials + private void GetAccessToken() + { + if (getAccessTokenRequest != null && getAccessTokenRequest.isDone) + { + // Clear the password + StandalonePlatformSettings.OculusPlatformTestUserPassword = ""; + + if (String.IsNullOrEmpty(getAccessTokenRequest.error)) + { + var Response = JsonUtility.FromJson(getAccessTokenRequest.downloadHandler.text); + StandalonePlatformSettings.OculusPlatformTestUserAccessToken = Response.access_token; + } + + GUI.changed = true; + EditorApplication.update -= GetAccessToken; + getAccessTokenRequest.Dispose(); + getAccessTokenRequest = null; + } + } + + private string MakeTextBox(GUIContent label, string variable) + { + return GUIHelper.MakeControlWithLabel(label, () => { + GUI.changed = false; + var result = EditorGUILayout.TextField(variable); + SetDirtyOnGUIChange(); + return result; + }); + } + + private string MakePasswordBox(GUIContent label, string variable) + { + return GUIHelper.MakeControlWithLabel(label, () => { + GUI.changed = false; + var result = EditorGUILayout.PasswordField(variable); + SetDirtyOnGUIChange(); + return result; + }); + } + + private bool MakeToggle(GUIContent label, bool variable) + { + return GUIHelper.MakeControlWithLabel(label, () => { + GUI.changed = false; + var result = EditorGUILayout.Toggle(variable); + SetDirtyOnGUIChange(); + return result; + }); + } + + private void SetDirtyOnGUIChange() + { + if (GUI.changed) + { + EditorUtility.SetDirty(PlatformSettings.Instance); + GUI.changed = false; + } + } + + // TODO: Merge this with core utilities plugin updater functionality. Piggybacking here to avoid an orphaned delete in the future. + private const string PluginSubPathAndroid32 = @"/Plugins/Android32/libovrplatformloader.so"; + private const string PluginSubPathAndroid64 = @"/Plugins/Android64/libovrplatformloader.so"; + private const string PluginDisabledSuffix = @".disabled"; + + public enum PluginPlatform + { + Android32, + Android64 + } + + private static string GetCurrentProjectPath() + { + return Directory.GetParent(UnityEngine.Application.dataPath).FullName; + } + + private static string GetPlatformRootPath() + { + // use the path to OculusPluginUpdaterStub as a relative path anchor point + var so = ScriptableObject.CreateInstance(typeof(OculusPluginUpdaterStub)); + var script = MonoScript.FromScriptableObject(so); + string assetPath = AssetDatabase.GetAssetPath(script); + string editorDir = Directory.GetParent(assetPath).FullName; + string platformDir = Directory.GetParent(editorDir).FullName; + + return platformDir; + } + + private static string GetPlatformPluginPath(PluginPlatform platform) + { + string path = GetPlatformRootPath(); + switch (platform) + { + case PluginPlatform.Android32: + path += PluginSubPathAndroid32; + break; + case PluginPlatform.Android64: + path += PluginSubPathAndroid64; + break; + default: + throw new ArgumentException("Attempted to enable platform support for unsupported platform: " + platform); + } + + return path; + } + + //[UnityEditor.MenuItem("Oculus/Platform/EnforcePluginPlatformSettings")] + public static void EnforcePluginPlatformSettings() + { + EnforcePluginPlatformSettings(PluginPlatform.Android32); + EnforcePluginPlatformSettings(PluginPlatform.Android64); + } + + public static void EnforcePluginPlatformSettings(PluginPlatform platform) + { + string path = GetPlatformPluginPath(platform); + + if (!Directory.Exists(path) && !File.Exists(path)) + { + path += PluginDisabledSuffix; + } + + if ((Directory.Exists(path)) || (File.Exists(path))) + { + string basePath = GetCurrentProjectPath(); + string relPath = path.Substring(basePath.Length + 1); + + PluginImporter pi = PluginImporter.GetAtPath(relPath) as PluginImporter; + if (pi == null) + { + return; + } + + // Disable support for all platforms, then conditionally enable desired support below + pi.SetCompatibleWithEditor(false); + pi.SetCompatibleWithAnyPlatform(false); + pi.SetCompatibleWithPlatform(BuildTarget.Android, false); + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows, false); + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneWindows64, false); + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux64, false); +#if !UNITY_2019_2_OR_NEWER + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneLinux, false); + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneLinuxUniversal, false); +#endif +#if UNITY_2017_3_OR_NEWER + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSX, false); +#else + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSXUniversal, false); + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSXIntel, false); + pi.SetCompatibleWithPlatform(BuildTarget.StandaloneOSXIntel64, false); +#endif + + switch (platform) + { + case PluginPlatform.Android32: + pi.SetCompatibleWithPlatform(BuildTarget.Android, true); + pi.SetPlatformData(BuildTarget.Android, "CPU", "ARMv7"); + break; + case PluginPlatform.Android64: + pi.SetCompatibleWithPlatform(BuildTarget.Android, true); + pi.SetPlatformData(BuildTarget.Android, "CPU", "ARM64"); + break; + default: + throw new ArgumentException("Attempted to enable platform support for unsupported platform: " + platform); + } + + AssetDatabase.ImportAsset(relPath, ImportAssetOptions.ForceUpdate); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + AssetDatabase.SaveAssets(); + } + } + + public static bool IsArm64PluginPlatformEnabled() + { + string path = GetPlatformPluginPath(PluginPlatform.Android64); + bool pathAlreadyExists = Directory.Exists(path) || File.Exists(path); + return pathAlreadyExists; + } + + public static void EnablePluginPlatform(PluginPlatform platform) + { + string path = GetPlatformPluginPath(platform); + string disabledPath = path + PluginDisabledSuffix; + + bool pathAlreadyExists = Directory.Exists(path) || File.Exists(path); + bool disabledPathDoesNotExist = !Directory.Exists(disabledPath) && !File.Exists(disabledPath); + + if (pathAlreadyExists || disabledPathDoesNotExist) + { + return; + } + + string basePath = GetCurrentProjectPath(); + string relPath = path.Substring(basePath.Length + 1); + string relDisabledPath = relPath + PluginDisabledSuffix; + + AssetDatabase.MoveAsset(relDisabledPath, relPath); + AssetDatabase.ImportAsset(relPath, ImportAssetOptions.ForceUpdate); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + AssetDatabase.SaveAssets(); + + // Force reserialization of platform settings meta data + EnforcePluginPlatformSettings(platform); + } + + public static void DisablePluginPlatform(PluginPlatform platform) + { + string path = GetPlatformPluginPath(platform); + string disabledPath = path + PluginDisabledSuffix; + + bool pathDoesNotExist = !Directory.Exists(path) && !File.Exists(path); + bool disabledPathAlreadyExists = Directory.Exists(disabledPath) || File.Exists(disabledPath); + + if (pathDoesNotExist || disabledPathAlreadyExists) + { + return; + } + + string basePath = GetCurrentProjectPath(); + string relPath = path.Substring(basePath.Length + 1); + string relDisabledPath = relPath + PluginDisabledSuffix; + + AssetDatabase.MoveAsset(relPath, relDisabledPath); + AssetDatabase.ImportAsset(relDisabledPath, ImportAssetOptions.ForceUpdate); + AssetDatabase.SaveAssets(); + AssetDatabase.Refresh(); + AssetDatabase.SaveAssets(); + } + } +} diff --git a/Assets/Oculus/Platform/Editor/OculusPlatformSettingsEditor.cs.meta b/Assets/Oculus/Platform/Editor/OculusPlatformSettingsEditor.cs.meta new file mode 100644 index 0000000..657e7f4 --- /dev/null +++ b/Assets/Oculus/Platform/Editor/OculusPlatformSettingsEditor.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 03780432f190e734dba71a2337880cdb +timeCreated: 1523486796 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Editor/OculusPluginUpdaterStub.cs b/Assets/Oculus/Platform/Editor/OculusPluginUpdaterStub.cs new file mode 100644 index 0000000..e758c85 --- /dev/null +++ b/Assets/Oculus/Platform/Editor/OculusPluginUpdaterStub.cs @@ -0,0 +1,30 @@ +/************************************************************************************ + +Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved. + +Licensed under the Oculus SDK License Version 3.4.1 (the "License"); +you may not use the Oculus SDK except in compliance with the License, +which is provided at the time of installation or download, or which +otherwise accompanies this software in either electronic or hard copy form. + +You may obtain a copy of the License at + +https://developer.oculus.com/licenses/sdk-3.4.1 + +Unless required by applicable law or agreed to in writing, the Oculus SDK +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +************************************************************************************/ + +using UnityEngine; +using System.Collections; + +public class OculusPluginUpdaterStub : ScriptableObject +{ + // Stub helper class to locate script paths through Unity Editor API. + // Required to be a standalone class in a separate file or else MonoScript.FromScriptableObject() returns an empty string path. +} + diff --git a/Assets/Oculus/Platform/Editor/OculusPluginUpdaterStub.cs.meta b/Assets/Oculus/Platform/Editor/OculusPluginUpdaterStub.cs.meta new file mode 100644 index 0000000..d416105 --- /dev/null +++ b/Assets/Oculus/Platform/Editor/OculusPluginUpdaterStub.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: af1b0142a3500574289a5ff8ae25dfa4 +timeCreated: 1543975087 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Editor/OculusStandalonePlatformResponse.cs b/Assets/Oculus/Platform/Editor/OculusStandalonePlatformResponse.cs new file mode 100644 index 0000000..e291079 --- /dev/null +++ b/Assets/Oculus/Platform/Editor/OculusStandalonePlatformResponse.cs @@ -0,0 +1,10 @@ +namespace Oculus.Platform +{ + using System; + + [Serializable] + public sealed class OculusStandalonePlatformResponse + { + public string access_token; + } +} diff --git a/Assets/Oculus/Platform/Editor/OculusStandalonePlatformResponse.cs.meta b/Assets/Oculus/Platform/Editor/OculusStandalonePlatformResponse.cs.meta new file mode 100644 index 0000000..5c937b5 --- /dev/null +++ b/Assets/Oculus/Platform/Editor/OculusStandalonePlatformResponse.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 81f0418e197774a4e8d643b56923cb90 +timeCreated: 1523486799 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins.meta b/Assets/Oculus/Platform/Plugins.meta new file mode 100644 index 0000000..822d8a9 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2eb794bc450e6db438b4f1ce7c7a8cc8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/Android32.meta b/Assets/Oculus/Platform/Plugins/Android32.meta new file mode 100644 index 0000000..3d26534 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/Android32.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9ef20d596fd3a9c4f9e8949a4aa887e4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/Android32/libovrplatformloader.so b/Assets/Oculus/Platform/Plugins/Android32/libovrplatformloader.so new file mode 100644 index 0000000..78b14cb Binary files /dev/null and b/Assets/Oculus/Platform/Plugins/Android32/libovrplatformloader.so differ diff --git a/Assets/Oculus/Platform/Plugins/Android32/libovrplatformloader.so.meta b/Assets/Oculus/Platform/Plugins/Android32/libovrplatformloader.so.meta new file mode 100644 index 0000000..69cbd8c --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/Android32/libovrplatformloader.so.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 71f62bfe84bf80d48b4aecade2b18710 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARMv7 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/Android64.meta b/Assets/Oculus/Platform/Plugins/Android64.meta new file mode 100644 index 0000000..ddb1187 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/Android64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 77efef5fc6f6e4142991fe8f5f6f7caf +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so new file mode 100644 index 0000000..3728435 Binary files /dev/null and b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so differ diff --git a/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.disabled b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.disabled new file mode 100644 index 0000000..fcb2f16 Binary files /dev/null and b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.disabled differ diff --git a/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.disabled.meta b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.disabled.meta new file mode 100644 index 0000000..f5629ed --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.disabled.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: f01358471902e9b48aa4716a0a1956ba +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARM64 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.meta b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.meta new file mode 100644 index 0000000..e4b49bd --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/Android64/libovrplatformloader.so.meta @@ -0,0 +1,30 @@ +fileFormatVersion: 2 +guid: 5e5d140cbf7f1b64188a4a891384c5c9 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + Android: Android + second: + enabled: 1 + settings: + CPU: ARM64 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 0 + settings: + DefaultValueInitialized: true + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX.meta b/Assets/Oculus/Platform/Plugins/MacOSX.meta new file mode 100644 index 0000000..778e5b5 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: d48199d79a52a82469e54984fa1fd735 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle.meta new file mode 100644 index 0000000..6eaed9d --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle.meta @@ -0,0 +1,40 @@ +fileFormatVersion: 2 +guid: 926602cc248723549b2142278d234dab +folderAsset: yes +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + '': OSXIntel + second: + enabled: 1 + settings: {} + - first: + '': OSXIntel64 + second: + enabled: 1 + settings: {} + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + DefaultValueInitialized: true + - first: + Standalone: OSXUniversal + second: + enabled: 1 + settings: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents.meta new file mode 100644 index 0000000..9c4ea13 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2e71fa5de78da0f40846eeccd6585083 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Info.plist b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Info.plist new file mode 100644 index 0000000..72e3999 Binary files /dev/null and b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Info.plist differ diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Info.plist.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Info.plist.meta new file mode 100644 index 0000000..7f1bb92 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Info.plist.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: bd19ab760a88d4147bb139e1772b30bf +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS.meta new file mode 100644 index 0000000..b9c86b4 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 35b3e6353c47e8548b0e63802c61990b +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS/ovrplatform b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS/ovrplatform new file mode 100644 index 0000000..45140df Binary files /dev/null and b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS/ovrplatform differ diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS/ovrplatform.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS/ovrplatform.meta new file mode 100644 index 0000000..f89050b --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/MacOS/ovrplatform.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3dce8f6f8cd6f3b4a99ef7e0708fbe76 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/PkgInfo b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/PkgInfo new file mode 100644 index 0000000..9d5b594 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/PkgInfo @@ -0,0 +1 @@ +APPLWRUN diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/PkgInfo.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/PkgInfo.meta new file mode 100644 index 0000000..7fec343 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/PkgInfo.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 3c62fefb060a105469849eefc4530f73 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources.meta new file mode 100644 index 0000000..b027ee7 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: b0167466e452cb74797f3e2bcbf901fa +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64.meta new file mode 100644 index 0000000..b26f419 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: c3be0abc39616b446920bd3083dc11c4 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64/liboculus_p2p.dylib b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64/liboculus_p2p.dylib new file mode 100644 index 0000000..1d455f4 Binary files /dev/null and b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64/liboculus_p2p.dylib differ diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64/liboculus_p2p.dylib.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64/liboculus_p2p.dylib.meta new file mode 100644 index 0000000..e72b5bd --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/Resources/darwin-x86_64/liboculus_p2p.dylib.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: f615547c377c15c4ea2a0e37bca038c5 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature.meta new file mode 100644 index 0000000..7f5fe5d --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 486a225f3b1b99744933d51c32f1b18a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature/CodeResources b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature/CodeResources new file mode 100644 index 0000000..e248164 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature/CodeResources @@ -0,0 +1,128 @@ + + + + + files + + Resources/darwin-x86_64/liboculus_p2p.dylib + + JKNLD2GjErCVA+jyjwiOflKeNFE= + + + files2 + + Resources/darwin-x86_64/liboculus_p2p.dylib + + hash2 + + 0Dix3PTkS51fqcK03xNszglO51JTVoPTad1LpFlSEzA= + + + + rules + + ^Resources/ + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^version.plist$ + + + rules2 + + .*\.dSYM($|/) + + weight + 11 + + ^(.*/)?\.DS_Store$ + + omit + + weight + 2000 + + ^(Frameworks|SharedFrameworks|PlugIns|Plug-ins|XPCServices|Helpers|MacOS|Library/(Automator|Spotlight|LoginItems))/ + + nested + + weight + 10 + + ^.* + + ^Info\.plist$ + + omit + + weight + 20 + + ^PkgInfo$ + + omit + + weight + 20 + + ^Resources/ + + weight + 20 + + ^Resources/.*\.lproj/ + + optional + + weight + 1000 + + ^Resources/.*\.lproj/locversion.plist$ + + omit + + weight + 1100 + + ^Resources/Base\.lproj/ + + weight + 1010 + + ^[^/]+$ + + nested + + weight + 10 + + ^embedded\.provisionprofile$ + + weight + 20 + + ^version\.plist$ + + weight + 20 + + + + diff --git a/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature/CodeResources.meta b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature/CodeResources.meta new file mode 100644 index 0000000..d4b4f94 --- /dev/null +++ b/Assets/Oculus/Platform/Plugins/MacOSX/ovrplatform.bundle/Contents/_CodeSignature/CodeResources.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: e95fb942c82302a43978166bf0efaf71 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples.meta b/Assets/Oculus/Platform/Samples.meta new file mode 100644 index 0000000..bb324ec --- /dev/null +++ b/Assets/Oculus/Platform/Samples.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 5d452e1c78bde664788e87528a1d5467 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/EntitlementCheck.meta b/Assets/Oculus/Platform/Samples/EntitlementCheck.meta new file mode 100644 index 0000000..94da9c8 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/EntitlementCheck.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 7b99c9c8ba732ce4c8926116f5de5612 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/EntitlementCheck/EntitlementCheck.cs b/Assets/Oculus/Platform/Samples/EntitlementCheck/EntitlementCheck.cs new file mode 100644 index 0000000..45918a7 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/EntitlementCheck/EntitlementCheck.cs @@ -0,0 +1,100 @@ +using System; +using UnityEngine; +using Oculus.Platform; +using Oculus.Platform.Models; + +namespace Oculus.Platform.Samples.EntitlementCheck +{ + public class EntitlementCheck : MonoBehaviour + { + // Implements a default behavior for entitlement check failures by simply exiting the app. + // Set to false if the app wants to provide custom logic to handle entitlement check failures. + // For example, the app can instead display a modal dialog to the user and exit gracefully. + public bool exitAppOnFailure = true; + + // The app can optionally subscribe to these events to do custom entitlement check logic. + public static event Action UserFailedEntitlementCheck; + public static event Action UserPassedEntitlementCheck; + + void Start() + { + try + { + // Init the Oculust Platform SDK and send an entitlement check request. + if (!Oculus.Platform.Core.IsInitialized()) + { + Oculus.Platform.Core.Initialize(); + } + + Entitlements.IsUserEntitledToApplication().OnComplete(EntitlementCheckCallback); + } + catch + { + // Treat any potential initialization exceptions as an entitlement check failure. + HandleEntitlementCheckResult(false); + } + } + + // Called when the Oculus Platform completes the async entitlement check request and a result is available. + void EntitlementCheckCallback(Message msg) + { + // If the user passed the entitlement check, msg.IsError will be false. + // If the user failed the entitlement check, msg.IsError will be true. + HandleEntitlementCheckResult(msg.IsError == false); + } + + void HandleEntitlementCheckResult(bool result) + { + if (result) // User passed entitlement check + { + Debug.Log("Oculus user entitlement check successful."); + + try + { + // Raise the user passed entitlement check event if the app subscribed a handler to it. + if (UserPassedEntitlementCheck != null) + { + UserPassedEntitlementCheck(); + } + } + catch + { + // Suppressing any exceptions to avoid potential exceptions in the app-provided event handler. + Debug.LogError("Suppressed exception in app-provided UserPassedEntitlementCheck() event handler."); + } + } + else // User failed entitlement check + { + try + { + // Raise the user failed entitlement check event if the app subscribed a handler to it. + if (UserFailedEntitlementCheck != null) + { + UserFailedEntitlementCheck(); + } + } + catch + { + // Suppressing any exceptions to avoid potential exceptions in the app-provided event handler. + // Ensures the default entitlement check behavior will still execute, if enabled. + Debug.LogError("Suppressed exception in app-provided UserFailedEntitlementCheck() event handler."); + } + + if (exitAppOnFailure) + { + // Implements a default behavior for an entitlement check failure -- log the failure and exit the app. + Debug.LogError("Oculus user entitlement check failed. Exiting now."); +#if UNITY_EDITOR + UnityEditor.EditorApplication.isPlaying = false; +#else + UnityEngine.Application.Quit(); +#endif + } + else + { + Debug.LogError("Oculus user entitlement check failed."); + } + } + } + } +} diff --git a/Assets/Oculus/Platform/Samples/EntitlementCheck/EntitlementCheck.cs.meta b/Assets/Oculus/Platform/Samples/EntitlementCheck/EntitlementCheck.cs.meta new file mode 100644 index 0000000..deaa7cd --- /dev/null +++ b/Assets/Oculus/Platform/Samples/EntitlementCheck/EntitlementCheck.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: 75ccf1814f335d94ab1902064233299e +timeCreated: 1543369724 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/EntitlementCheck/Main.unity b/Assets/Oculus/Platform/Samples/EntitlementCheck/Main.unity new file mode 100644 index 0000000..288e87f --- /dev/null +++ b/Assets/Oculus/Platform/Samples/EntitlementCheck/Main.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c062925ec8c9c237f406168b314a1de2195883a74272b6e3e78c8bdb01d3201 +size 5739 diff --git a/Assets/Oculus/Platform/Samples/EntitlementCheck/Main.unity.meta b/Assets/Oculus/Platform/Samples/EntitlementCheck/Main.unity.meta new file mode 100644 index 0000000..893a828 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/EntitlementCheck/Main.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9df623f348e176845a764b6c2e269451 +timeCreated: 1543369713 +licenseType: Free +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/NetChat.meta b/Assets/Oculus/Platform/Samples/NetChat.meta new file mode 100644 index 0000000..b9b332b --- /dev/null +++ b/Assets/Oculus/Platform/Samples/NetChat.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: e9c04c9a614256745a2bc3489262c64a +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/NetChat/DataEntry.cs b/Assets/Oculus/Platform/Samples/NetChat/DataEntry.cs new file mode 100644 index 0000000..5ad3b08 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/NetChat/DataEntry.cs @@ -0,0 +1,836 @@ +namespace Oculus.Platform.Samples.NetChat +{ + using UnityEngine; + using UnityEngine.UI; + using System; + using System.IO; + using System.Collections.Generic; + using Oculus.Platform; + using Oculus.Platform.Models; + + enum states + { + NOT_INIT = 0, + IDLE, + REQUEST_FIND, + FINDING_ROOM, + REQUEST_CREATE, + REQUEST_JOIN, + REQUEST_LEAVE, + IN_EMPTY_ROOM, + IN_FULL_ROOM + } + + // Pools are defined on the Oculus developer portal + // + // For this test we have a pool created with the pool key set as 'filter_pool' + // Mode is set to 'Room' + // Skill Pool is set to 'None' + // We are not considering Round Trip Time + // The following Data Settings are set: + // key: map_name, Type: STRING, String options: Small_Map, Big_Map, Really_Big_Map + // key: game_type, Type: STRING, String Options: deathmatch, CTF + // + // We also have the following two queries defined: + // Query Key: map + // Template: Set (String) + // Key: map_name + // Wildcards: map_param_1, map_param_2 + // + // Query Key: game_type + // Template: Set (String) + // Key: game_type_name + // Wildcards: game_type_param + // + // For this test we have a pool created with the pool key set as 'bout_pool' + // Mode is set to 'Bout' + // Skill Pool is set to 'None' + // We are not considering Round Trip Time + // No Data Settings are set: + // + + public static class Constants + { + public const int BUFFER_SIZE = 512; + public const string BOUT_POOL = "bout_pool"; + public const string FILTER_POOL = "filter_pool"; + } + + public class chatPacket + { + public int packetID { get; set; } + public string textString { get; set; } + + public byte[] Serialize() + { + using (MemoryStream m = new MemoryStream()) + { + using (BinaryWriter writer = new BinaryWriter(m)) + { + // Limit our string to BUFFER_SIZE + if (textString.Length > Constants.BUFFER_SIZE) + { + textString = textString.Substring(0, Constants.BUFFER_SIZE-1); + } + writer.Write(packetID); + writer.Write(textString.ToCharArray()); + writer.Write('\0'); + } + return m.ToArray(); + } + } + + public static chatPacket Deserialize(byte[] data) + { + chatPacket result = new chatPacket(); + using (MemoryStream m = new MemoryStream(data)) + { + using (BinaryReader reader = new BinaryReader(m)) + { + result.packetID = reader.ReadInt32(); + result.textString = System.Text.Encoding.Default.GetString(reader.ReadBytes(Constants.BUFFER_SIZE)); + } + } + return result; + } + } + + public class DataEntry : MonoBehaviour { + + public Text dataOutput; + + states currentState; + User localUser; + User remoteUser; + Room currentRoom; + int lastPacketID; + bool ratedMatchStarted; + + // Use this for initialization + void Start () { + currentState = states.NOT_INIT; + localUser = null; + remoteUser = null; + currentRoom = null; + lastPacketID = 0; + ratedMatchStarted = false; + + Core.Initialize(); + + // Setup our room update handler + Rooms.SetUpdateNotificationCallback(updateRoom); + // Setup our match found handler + Matchmaking.SetMatchFoundNotificationCallback(foundMatch); + + checkEntitlement(); + + } + + // Update is called once per frame + void Update() + { + string currentText = GetComponent().text; + + if (Input.GetKey(KeyCode.Return)) + { + if (currentText != "") + { + SubmitCommand(currentText); + } + + GetComponent().text = ""; + } + + processNetPackets(); + // Handle all messages being returned + Request.RunCallbacks(); + } + + void SubmitCommand(string command) + { + string[] commandParams = command.Split('!'); + + if (commandParams.Length > 0) + { + switch (commandParams[0]) + { + case "c": + requestCreateRoom(); + break; + case "d": + requestCreateFilterRoom(); + break; + case "f": + requestFindMatch(); + break; + case "g": + requestFindRoom(); + break; + case "i": + requestFindFilteredRoom(); + break; + case "s": + if (commandParams.Length > 1) + { + sendChat(commandParams[1]); + } + break; + case "l": + requestLeaveRoom(); + break; + case "1": + requestStartRatedMatch(); + break; + case "2": + requestReportResults(); + break; + default: + printOutputLine("Invalid Command"); + break; + } + } + } + + void printOutputLine(String newLine) + { + dataOutput.text = "> " + newLine + System.Environment.NewLine + dataOutput.text; + } + + void checkEntitlement() + { + Entitlements.IsUserEntitledToApplication().OnComplete(getEntitlementCallback); + } + + void getEntitlementCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("You are entitled to use this app."); + Users.GetLoggedInUser().OnComplete(init); + } + else + { + printOutputLine("You are NOT entitled to use this app."); + } + } + + void init(Message msg) + { + if (!msg.IsError) + { + User user = msg.Data; + localUser = user; + + currentState = states.IDLE; + } + else + { + printOutputLine("Received get current user error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + + // Retry getting the current user + Users.GetLoggedInUser().OnComplete(init); + currentState = states.NOT_INIT; + } + } + + void requestCreateRoom() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + case states.IDLE: + printOutputLine("Trying to create a matchmaking room"); + Matchmaking.CreateAndEnqueueRoom(Constants.FILTER_POOL, 8, true, null).OnComplete(createRoomResponse); + currentState = states.REQUEST_CREATE; + break; + case states.REQUEST_FIND: + printOutputLine("You have already made a request to find a room. Please wait for that request to complete."); + break; + case states.FINDING_ROOM: + printOutputLine("You have already currently looking for a room. Please wait for the match to be made."); + break; + case states.REQUEST_JOIN: + printOutputLine("We are currently trying to join a room. Please wait to see if we can join it."); + break; + case states.REQUEST_LEAVE: + printOutputLine("We are currently trying to leave a room. Please wait to see if we can leave it."); + break; + case states.REQUEST_CREATE: + printOutputLine("You have already requested a matchmaking room to be created. Please wait for the room to be made."); + break; + case states.IN_EMPTY_ROOM: + printOutputLine("You have already in a matchmaking room. Please wait for an opponent to join."); + break; + case states.IN_FULL_ROOM: + printOutputLine("You have already in a match."); + break; + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void createRoomResponse(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received create matchmaking room success"); + Room room = msg.Data.Room; + currentRoom = room; + + printOutputLine("RoomID: " + room.ID.ToString()); + currentState = states.IN_EMPTY_ROOM; + } + else + { + printOutputLine("Received create matchmaking room Error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + printOutputLine("You can only create a matchmaking room for pools of mode Room. Make sure you have an appropriate pool setup on the Developer portal.\n"); + currentState = states.IDLE; + } + } + + void requestCreateFilterRoom() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID.\n"); + break; + + case states.IDLE: + printOutputLine("Trying to create a matchmaking room"); + + // We're going to create a room that has the following values set: + // game_type_name = "CTF" + // map_name = "Really_Big_Map" + // + + Matchmaking.CustomQuery roomCustomQuery = new Matchmaking.CustomQuery(); + + roomCustomQuery.criteria = null; + roomCustomQuery.data = new Dictionary(); + + roomCustomQuery.data.Add("game_type_name", "CTF"); + roomCustomQuery.data.Add("map_name", "Really_Big_Map"); + + Matchmaking.CreateAndEnqueueRoom(Constants.FILTER_POOL, 8, true, roomCustomQuery).OnComplete(createRoomResponse); + currentState = states.REQUEST_CREATE; + break; + + case states.REQUEST_FIND: + printOutputLine("You have already made a request to find a room. Please wait for that request to complete.\n"); + break; + case states.FINDING_ROOM: + printOutputLine("You have already currently looking for a room. Please wait for the match to be made.\n"); + break; + case states.REQUEST_JOIN: + printOutputLine("We are currently trying to join a room. Please wait to see if we can join it.\n"); + break; + case states.REQUEST_LEAVE: + printOutputLine("We are currently trying to leave a room. Please wait to see if we can leave it.\n"); + break; + case states.REQUEST_CREATE: + printOutputLine("You have already requested a matchmaking room to be created. Please wait for the room to be made.\n"); + break; + case states.IN_EMPTY_ROOM: + printOutputLine("You have already in a matchmaking room. Please wait for an opponent to join.\n"); + break; + case states.IN_FULL_ROOM: + printOutputLine("You have already in a match.\n"); + break; + default: + printOutputLine("You have hit an unknown state.\n"); + break; + } + } + + void requestFindRoom() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + + case states.IDLE: + printOutputLine("\nTrying to find a matchmaking room\n"); + + Matchmaking.Enqueue(Constants.FILTER_POOL, null).OnComplete(searchingStarted); + currentState = states.REQUEST_FIND; + break; + + case states.REQUEST_FIND: + printOutputLine("You have already made a request to find a room. Please wait for that request to complete."); + break; + + case states.FINDING_ROOM: + printOutputLine("You have already currently looking for a room. Please wait for the match to be made."); + break; + + case states.REQUEST_JOIN: + printOutputLine("We are currently trying to join a room. Please wait to see if we can join it."); + break; + + case states.REQUEST_LEAVE: + printOutputLine("We are currently trying to leave a room. Please wait to see if we can leave it."); + break; + + case states.REQUEST_CREATE: + printOutputLine("You have already requested a matchmaking room to be created. Please wait for the room to be made."); + break; + + case states.IN_EMPTY_ROOM: + printOutputLine("You have already in a matchmaking room. Please wait for an opponent to join."); + break; + + case states.IN_FULL_ROOM: + printOutputLine("You have already in a match."); + break; + + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void requestFindFilteredRoom() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + + case states.IDLE: + printOutputLine("Trying to find a matchmaking room"); + + // Our search filter criterion + // + // We're filtering using two different queries setup on the developer portal + // + // map - query to filter by map. The query allows you to filter with up to two different maps using keys called 'map_1' and 'map_2' + // game_type - query to filter by game type. The query allows you to filter with up to two different game types using keys called 'type_1' and 'type_2' + // + // In the example below we are filtering for matches that are of type CTF and on either Big_Map or Really_Big_Map. + // + + Matchmaking.CustomQuery roomCustomQuery = new Matchmaking.CustomQuery(); + Matchmaking.CustomQuery.Criterion[] queries = new Matchmaking.CustomQuery.Criterion[2]; + + queries[0].key = "map"; + queries[0].importance = MatchmakingCriterionImportance.Required; + queries[0].parameters = new Dictionary(); + queries[0].parameters.Add("map_param_1","Really_Big_Map"); + queries[0].parameters.Add("map_param_2", "Big_Map"); + + queries[1].key = "game_type"; + queries[1].importance = MatchmakingCriterionImportance.Required; + queries[1].parameters = new Dictionary(); + queries[1].parameters.Add("game_type_param", "CTF"); + + roomCustomQuery.criteria = queries; + roomCustomQuery.data = null; + + Matchmaking.Enqueue(Constants.FILTER_POOL, roomCustomQuery); + currentState = states.REQUEST_FIND; + break; + + case states.REQUEST_FIND: + printOutputLine("You have already made a request to find a room. Please wait for that request to complete."); + break; + + case states.FINDING_ROOM: + printOutputLine("You have already currently looking for a room. Please wait for the match to be made."); + break; + + case states.REQUEST_JOIN: + printOutputLine("We are currently trying to join a room. Please wait to see if we can join it."); + break; + + case states.REQUEST_LEAVE: + printOutputLine("We are currently trying to leave a room. Please wait to see if we can leave it."); + break; + + case states.REQUEST_CREATE: + printOutputLine("You have already requested a matchmaking room to be created. Please wait for the room to be made."); + break; + + case states.IN_EMPTY_ROOM: + printOutputLine("You have already in a matchmaking room. Please wait for an opponent to join."); + break; + + case states.IN_FULL_ROOM: + printOutputLine("You have already in a match."); + break; + + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void foundMatch(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received find match success. We are now going to request to join the room."); + Room room = msg.Data; + + Rooms.Join(room.ID, true).OnComplete(joinRoomResponse); + currentState = states.REQUEST_JOIN; + } + else + { + printOutputLine("Received find match error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + currentState = states.IDLE; + } + } + + void joinRoomResponse(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received join room success."); + currentRoom = msg.Data; + + currentState = states.IN_EMPTY_ROOM; + + // Try to pull out remote user's ID if they have already joined + if (currentRoom.UsersOptional != null) + { + foreach (User element in currentRoom.UsersOptional) + { + if (element.ID != localUser.ID) + { + remoteUser = element; + currentState = states.IN_FULL_ROOM; + } + } + } + } + else + { + printOutputLine("Received join room error"); + printOutputLine("It's possible the room filled up before you could join it."); + + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + currentState = states.IDLE; + } + } + + void requestFindMatch() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + case states.IDLE: + printOutputLine("Trying to find a matchmaking room"); + Matchmaking.Enqueue(Constants.BOUT_POOL, null).OnComplete(searchingStarted); + currentState = states.REQUEST_FIND; + break; + case states.REQUEST_FIND: + printOutputLine("You have already made a request to find a room. Please wait for that request to complete."); + break; + case states.FINDING_ROOM: + printOutputLine("You have already currently looking for a room. Please wait for the match to be made."); + break; + case states.REQUEST_JOIN: + printOutputLine("We are currently trying to join a room. Please wait to see if we can join it."); + break; + case states.REQUEST_LEAVE: + printOutputLine("We are currently trying to leave a room. Please wait to see if we can leave it."); + break; + case states.REQUEST_CREATE: + printOutputLine("You have already requested a matchmaking room to be created. Please wait for the room to be made."); + break; + case states.IN_EMPTY_ROOM: + printOutputLine("You have already in a matchmaking room. Please wait for an opponent to join."); + break; + case states.IN_FULL_ROOM: + printOutputLine("You have already in a match."); + break; + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void searchingStarted(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Searching for a match successfully started"); + currentState = states.REQUEST_FIND; + } + else + { + printOutputLine("Searching for a match error"); + + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void updateRoom(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received room update notification"); + Room room = msg.Data; + + if (currentState == states.IN_EMPTY_ROOM) + { + // Check to see if this update is another user joining + if (room.UsersOptional != null) + { + foreach (User element in room.UsersOptional) + { + if (element.ID != localUser.ID) + { + remoteUser = element; + currentState = states.IN_FULL_ROOM; + } + } + } + } + else + { + // Check to see if this update is another user leaving + if (room.UsersOptional != null && room.UsersOptional.Count == 1) + { + printOutputLine("User ID: " + remoteUser.ID.ToString() + "has left"); + remoteUser = null; + currentState = states.IN_EMPTY_ROOM; + } + } + } + else + { + printOutputLine("Received room update error"); + + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void sendChat(string chatMessage) + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + + case states.IDLE: + case states.REQUEST_FIND: + case states.FINDING_ROOM: + case states.REQUEST_JOIN: + case states.REQUEST_CREATE: + case states.REQUEST_LEAVE: + case states.IN_EMPTY_ROOM: + printOutputLine("You need to be in a room with another player to send a message."); + break; + + case states.IN_FULL_ROOM: + { + chatPacket newMessage = new chatPacket(); + + // Create a packet to send with the packet ID and string payload + lastPacketID++; + newMessage.packetID = lastPacketID; + newMessage.textString = chatMessage; + + Oculus.Platform.Net.SendPacket(remoteUser.ID, newMessage.Serialize(), SendPolicy.Reliable); + } + break; + + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void processNetPackets() + { + Packet incomingPacket = Net.ReadPacket(); + + while (incomingPacket != null) + { + byte[] rawBits = new byte[incomingPacket.Size]; + incomingPacket.ReadBytes(rawBits); + + chatPacket newMessage = chatPacket.Deserialize(rawBits); + + printOutputLine("Chat Text: " + newMessage.textString.ToString()); + printOutputLine("Received Packet from UserID: " + incomingPacket.SenderID.ToString()); + printOutputLine("Received Packet ID: " + newMessage.packetID.ToString()); + + // Look to see if there's another packet waiting + incomingPacket = Net.ReadPacket(); + } + } + + void requestLeaveRoom() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + + case states.IDLE: + case states.REQUEST_FIND: + case states.FINDING_ROOM: + case states.REQUEST_JOIN: + case states.REQUEST_CREATE: + printOutputLine("You are currently not in a room to leave."); + break; + + case states.REQUEST_LEAVE: + printOutputLine("We are currently trying to leave a room. Please wait to see if we can leave it."); + break; + + case states.IN_EMPTY_ROOM: + case states.IN_FULL_ROOM: + printOutputLine("Trying to leave room."); + Rooms.Leave(currentRoom.ID).OnComplete(leaveRoomResponse); + break; + + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void leaveRoomResponse(Message msg) + { + if (!msg.IsError) + { + printOutputLine("We were able to leave the room"); + currentRoom = null; + remoteUser = null; + currentState = states.IDLE; + } + else + { + printOutputLine("Leave room error"); + + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + + } + + void requestStartRatedMatch() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + + case states.IDLE: + case states.REQUEST_FIND: + case states.FINDING_ROOM: + case states.REQUEST_JOIN: + case states.REQUEST_CREATE: + case states.REQUEST_LEAVE: + case states.IN_EMPTY_ROOM: + printOutputLine("You need to be in a room with another player to start a rated match."); + break; + + case states.IN_FULL_ROOM: + printOutputLine("Trying to start a rated match. This call should be made once a rated match begins so we will be able to submit results after the game is done."); + + Matchmaking.StartMatch(currentRoom.ID).OnComplete(startRatedMatchResponse); + break; + + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void startRatedMatchResponse(Message msg) + { + if(!msg.IsError) + { + printOutputLine("Started a rated match"); + ratedMatchStarted = true; + } + else + { + Error error = msg.GetError(); + printOutputLine("Received starting rated match failure: " + error.Message); + printOutputLine("Your matchmaking pool needs to have a skill pool associated with it to play rated matches"); + } + } + + void requestReportResults() + { + switch (currentState) + { + case states.NOT_INIT: + printOutputLine("The app has not initialized properly and we don't know your userID."); + break; + + case states.IDLE: + case states.REQUEST_FIND: + case states.FINDING_ROOM: + case states.REQUEST_JOIN: + case states.REQUEST_CREATE: + case states.REQUEST_LEAVE: + printOutputLine("You need to be in a room with another player to report results on a rated match."); + break; + + case states.IN_EMPTY_ROOM: + case states.IN_FULL_ROOM: + if (ratedMatchStarted) + { + printOutputLine("Submitting rated match results."); + + Dictionary results = new Dictionary(); + results.Add(localUser.ID.ToString(), 1); + results.Add(remoteUser.ID.ToString(), 2); + + Matchmaking.ReportResultsInsecure(currentRoom.ID, results).OnComplete(reportResultsResponse); + } + else + { + printOutputLine("You can't report results unless you've already started a rated match"); + } + break; + + default: + printOutputLine("You have hit an unknown state."); + break; + } + } + + void reportResultsResponse(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Rated match results reported. Now attempting to leave room."); + ratedMatchStarted = false; + requestLeaveRoom(); + } + else + { + Error error = msg.GetError(); + printOutputLine("Received reporting rated match failure: " + error.Message); + } + } + } +} diff --git a/Assets/Oculus/Platform/Samples/NetChat/DataEntry.cs.meta b/Assets/Oculus/Platform/Samples/NetChat/DataEntry.cs.meta new file mode 100644 index 0000000..f67aa39 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/NetChat/DataEntry.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: bfbb4b78fb9572d4da744c39224c6f1d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/NetChat/MainScene.unity b/Assets/Oculus/Platform/Samples/NetChat/MainScene.unity new file mode 100644 index 0000000..c4a9fcc --- /dev/null +++ b/Assets/Oculus/Platform/Samples/NetChat/MainScene.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9822d9250169ef9ed45b9f7505dc67b21735091b7aacd010fa96c8f227adfedb +size 25526 diff --git a/Assets/Oculus/Platform/Samples/NetChat/MainScene.unity.meta b/Assets/Oculus/Platform/Samples/NetChat/MainScene.unity.meta new file mode 100644 index 0000000..d5b7613 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/NetChat/MainScene.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 4a5c060329791374cba1196f7ac36ef5 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample.meta b/Assets/Oculus/Platform/Samples/RichPresenceSample.meta new file mode 100644 index 0000000..ed71217 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3f60ad85b3f1072418c4c5bc1f060ab8 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs.meta b/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs.meta new file mode 100644 index 0000000..d1f57d3 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 80340db49600ae247abe4cf880f14c94 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs/Rich Presence Sample.prefab b/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs/Rich Presence Sample.prefab new file mode 100644 index 0000000..f9739cf --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs/Rich Presence Sample.prefab @@ -0,0 +1,401 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_SourcePrefab: {fileID: 0} + m_RootGameObject: {fileID: 1625345527844402} + m_IsPrefabAsset: 1 +--- !u!1 &1029123982390752 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224566574175330634} + - component: {fileID: 222109690043464122} + - component: {fileID: 114889101218588212} + m_Layer: 5 + m_Name: DestinationsTextList + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1183652821387436 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224908873728430796} + - component: {fileID: 223759242779104624} + - component: {fileID: 114398105957111100} + - component: {fileID: 114561163922829960} + m_Layer: 5 + m_Name: Destinations Display + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1250865195685056 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224638719472242136} + - component: {fileID: 223662648536038570} + - component: {fileID: 114472934823343270} + - component: {fileID: 114114474722117790} + m_Layer: 5 + m_Name: Rich Presence Display + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1625345527844402 +GameObject: + m_ObjectHideFlags: 0 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 4888635847475054} + - component: {fileID: 114347612112539610} + m_Layer: 0 + m_Name: Rich Presence Sample + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!1 &1944862617252598 +GameObject: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 6 + m_Component: + - component: {fileID: 224513550524301700} + - component: {fileID: 222075363776180578} + - component: {fileID: 114782670387223048} + m_Layer: 5 + m_Name: TextStatus + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4888635847475054 +Transform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1625345527844402} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 224638719472242136} + - {fileID: 224908873728430796} + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!114 &114114474722117790 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1250865195685056} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &114347612112539610 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1625345527844402} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 7cbd4da28d0350840aeef051399368a5, type: 3} + m_Name: + m_EditorClassIdentifier: + DeeplinkMessageOverride: + IsJoinable: 1 + IsIdle: 0 + CurrentCapacity: 1 + MaxCapacity: 4 + ExtraContext: 1 + InVRConsole: {fileID: 114782670387223048} + DestinationsConsole: {fileID: 114889101218588212} +--- !u!114 &114398105957111100 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1183652821387436} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &114472934823343270 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1250865195685056} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1980459831, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_UiScaleMode: 0 + m_ReferencePixelsPerUnit: 100 + m_ScaleFactor: 1 + m_ReferenceResolution: {x: 800, y: 600} + m_ScreenMatchMode: 0 + m_MatchWidthOrHeight: 0 + m_PhysicalUnit: 3 + m_FallbackScreenDPI: 96 + m_DefaultSpriteDPI: 96 + m_DynamicPixelsPerUnit: 1 +--- !u!114 &114561163922829960 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1183652821387436} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 1301386320, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_IgnoreReversedGraphics: 1 + m_BlockingObjects: 0 + m_BlockingMask: + serializedVersion: 2 + m_Bits: 4294967295 +--- !u!114 &114782670387223048 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1944862617252598} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 55 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 3 + m_MaxSize: 61 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: VR Console +--- !u!114 &114889101218588212 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1029123982390752} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 708705254, guid: f70555f144d8491a825f0804e09c671c, type: 3} + m_Name: + m_EditorClassIdentifier: + m_Material: {fileID: 0} + m_Color: {r: 0.19607843, g: 0.19607843, b: 0.19607843, a: 1} + m_RaycastTarget: 1 + m_OnCullStateChanged: + m_PersistentCalls: + m_Calls: [] + m_TypeName: UnityEngine.UI.MaskableGraphic+CullStateChangedEvent, UnityEngine.UI, + Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + m_FontData: + m_Font: {fileID: 10102, guid: 0000000000000000e000000000000000, type: 0} + m_FontSize: 61 + m_FontStyle: 0 + m_BestFit: 0 + m_MinSize: 3 + m_MaxSize: 61 + m_Alignment: 0 + m_AlignByGeometry: 0 + m_RichText: 1 + m_HorizontalOverflow: 0 + m_VerticalOverflow: 1 + m_LineSpacing: 1 + m_Text: Destinations +--- !u!222 &222075363776180578 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1944862617252598} + m_CullTransparentMesh: 0 +--- !u!222 &222109690043464122 +CanvasRenderer: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1029123982390752} + m_CullTransparentMesh: 0 +--- !u!223 &223662648536038570 +Canvas: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1250865195685056} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!223 &223759242779104624 +Canvas: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1183652821387436} + m_Enabled: 1 + serializedVersion: 3 + m_RenderMode: 2 + m_Camera: {fileID: 0} + m_PlaneDistance: 100 + m_PixelPerfect: 0 + m_ReceivesEvents: 1 + m_OverrideSorting: 0 + m_OverridePixelPerfect: 0 + m_SortingBucketNormalizedSize: 0 + m_AdditionalShaderChannelsFlag: 0 + m_SortingLayerID: 0 + m_SortingOrder: 0 + m_TargetDisplay: 0 +--- !u!224 &224513550524301700 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1944862617252598} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 224638719472242136} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 1000, y: 600} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224566574175330634 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1029123982390752} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: [] + m_Father: {fileID: 224908873728430796} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0.5, y: 0.5} + m_AnchorMax: {x: 0.5, y: 0.5} + m_AnchoredPosition: {x: 0, y: 0} + m_SizeDelta: {x: 800, y: 600} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224638719472242136 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1250865195685056} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 751} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 224513550524301700} + m_Father: {fileID: 4888635847475054} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: -50, y: 168.95} + m_SizeDelta: {x: 1000, y: 800} + m_Pivot: {x: 0.5, y: 0.5} +--- !u!224 &224908873728430796 +RectTransform: + m_ObjectHideFlags: 1 + m_CorrespondingSourceObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1183652821387436} + m_LocalRotation: {x: -0, y: -0.6427876, z: -0, w: 0.7660445} + m_LocalPosition: {x: 0, y: 0, z: 500} + m_LocalScale: {x: 1, y: 1, z: 1} + m_Children: + - {fileID: 224566574175330634} + m_Father: {fileID: 4888635847475054} + m_RootOrder: 1 + m_LocalEulerAnglesHint: {x: 0, y: -80, z: 0} + m_AnchorMin: {x: 0, y: 0} + m_AnchorMax: {x: 0, y: 0} + m_AnchoredPosition: {x: -700, y: 75.59} + m_SizeDelta: {x: 800, y: 800} + m_Pivot: {x: 0.5, y: 0.5} diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs/Rich Presence Sample.prefab.meta b/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs/Rich Presence Sample.prefab.meta new file mode 100644 index 0000000..3c62764 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Prefabs/Rich Presence Sample.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: a7de3e5619aa4f94c86abdaa1aad343b +NativeFormatImporter: + externalObjects: {} + mainObjectFileID: 0 + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes.meta b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes.meta new file mode 100644 index 0000000..11bccbf --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 17338d874d589684694ad63cdf6d7f53 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes/RichPresenceDemo.unity b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes/RichPresenceDemo.unity new file mode 100644 index 0000000..9b39868 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes/RichPresenceDemo.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:94c1cb0a542aecdc071b4450139994bc6416d1667de556fa8882707e7202a95a +size 8369 diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes/RichPresenceDemo.unity.meta b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes/RichPresenceDemo.unity.meta new file mode 100644 index 0000000..fc63e13 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scenes/RichPresenceDemo.unity.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 44e30fce5a7e2fd4db7c4fedc096ccf3 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts.meta b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts.meta new file mode 100644 index 0000000..38281fb --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 3d6a00d015dd9d5498000e32fbf77c05 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts/RichPresenceSample.cs b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts/RichPresenceSample.cs new file mode 100644 index 0000000..9f7e7f4 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts/RichPresenceSample.cs @@ -0,0 +1,395 @@ +// Uncomment this if you have the Touch controller classes in your project +//#define USE_OVRINPUT + +using Oculus.Platform; +using System.Collections.Generic; +using UnityEngine; +using UnityEngine.UI; + +/** + * This class shows a very simple way to integrate setting the Rich Presence + * with a destination and how to respond to a user's app launch details that + * include the destination they wish to travel to. + */ +public class RichPresenceSample : MonoBehaviour +{ + /** + * Sets extra fields on the rich presence + */ + + // Optional message to override the deep-link message set in the developer + // dashboard. This is where you can specify the ID for a room, party, + // matchmaking pool or group server. There should be no whitespaces. + public string DeeplinkMessageOverride; + + // A boolean to indicate whether the destination is joinable. You can check + // the current capacity against the max capacity to determine whether the room + // is joinable. + public bool IsJoinable; + + // A boolean to indicate whether the current user is idling in the app. + public bool IsIdle; + + // The current capacity at that destination. Used for displaying with the + // extra context when it's set to RichPresenceExtraContext.CurrentCapacity + public uint CurrentCapacity; + + // The maximum capacity of the destination. Can be used with current capacity + // to see if a user can join. For example, when used with a room, set the max + // capacity of the destination to the max capacity of the room. + // Used for displaying with the extra context when it's set to + // RichPresenceExtraContext.CurrentCapacity + public uint MaxCapacity; + + // The time the current match starts or started. Used for displaying with the + // extra context when it's set to RichPresenceExtraContext.StartedAgo + public System.DateTime StartTime = System.DateTime.Now; + + // The time the current match ends. Used for displaying with the + // extra context when it's set to RichPresenceExtraContext.EndingIn + public System.DateTime EndTime = System.DateTime.Now.AddHours(2); + + // Extra information to set the user’s presence correctly. This should give + // more insight for people to decided whether or not to join the user. + public RichPresenceExtraContext ExtraContext = RichPresenceExtraContext.LookingForAMatch; + + public Text InVRConsole; + public Text DestinationsConsole; + + private List DestinationAPINames = new List(); + private ulong LoggedInUserID = 0; + + // Start is called before the first frame update + void Start() + { + UpdateConsole("Init Oculus Platform SDK..."); + Core.AsyncInitialize().OnComplete(message => { + if (message.IsError) + { + // Init failed, nothing will work + UpdateConsole(message.GetError().Message); + } + else + { + /** + * Get the deeplink message when the app starts up + */ + UpdateConsole("Init complete!\n" + GetAppLaunchDetails()); + + /** + * Get and cache the Logged in User ID for future queries + */ + Users.GetLoggedInUser().OnComplete(OnLoggedInUser); + + /** + * Get the list of destinations defined for this app from the developer portal + */ + RichPresence.GetDestinations().OnComplete(OnGetDestinations); + + /** + * Listen for future deeplink message changes that might come in + */ + ApplicationLifecycle.SetLaunchIntentChangedNotificationCallback(OnLaunchIntentChangeNotif); + } + }); + } + + /** + * Setting the rich presence + */ + void SetPresence() + { + var options = new RichPresenceOptions(); + + // Only Destination API Name is required + options.SetApiName(DestinationAPINames[DestinationIndex]); + + // Override the deeplink message if you like, otherwise it will use the one found in the destination + if (!string.IsNullOrEmpty(DeeplinkMessageOverride)) + { + options.SetDeeplinkMessageOverride(DeeplinkMessageOverride); + } + + // Set is Joinable to let other players deeplink and join this user via the presence + options.SetIsJoinable(IsJoinable); + + // Set if the user is idle + options.SetIsIdle(IsIdle); + + // Used when displaying the current to max capacity on the user's presence + options.SetCurrentCapacity(CurrentCapacity); + options.SetMaxCapacity(MaxCapacity); + + // Used to display how long since this start / when will this end + options.SetStartTime(StartTime); + options.SetEndTime(EndTime); + + // Used to display extra info like the capacity, start/end times, or looking for a match + options.SetExtraContext(ExtraContext); + UpdateConsole("Setting Rich Presence to " + DestinationAPINames[DestinationIndex] + " ..."); + + // Here we are setting the rich presence then fetching it after we successfully set it + RichPresence.Set(options).OnComplete(message => { + if (message.IsError) + { + UpdateConsole(message.GetError().Message); + } + else + { + // Note that Users.GetLoggedInUser() does not do a server fetch and will + // not get an updated presence status + Users.Get(LoggedInUserID).OnComplete(message2 => + { + if (message2.IsError) + { + UpdateConsole("Success! But rich presence is unknown!"); + } + else + { + UpdateConsole("Rich Presence set to:\n" + message2.Data.Presence + "\n" + message2.Data.PresenceDeeplinkMessage + "\n" + message2.Data.PresenceDestinationApiName); + } + }); + } + }); + } + + /** + * Clearing the rich presence + */ + void ClearPresence() + { + UpdateConsole("Clearing Rich Presence..."); + RichPresence.Clear().OnComplete(message => { + if (message.IsError) + { + UpdateConsole(message.GetError().Message); + } + else + { + // Clearing the rich presence then fetching the user's presence afterwards + Users.Get(LoggedInUserID).OnComplete(message2 => + { + if (message2.IsError) + { + UpdateConsole("Rich Presence cleared! But rich presence is unknown!"); + } + else + { + UpdateConsole("Rich Presence cleared!\n" + message2.Data.Presence + "\n"); + } + }); + } + }); + } + + /** + * Getting the deeplink information off the app launch details. When a user requests + * to travel to a destination from outside your app, their request will be found here + * Get the info to bring the user to the expected destination. + */ + string GetAppLaunchDetails() + { + var launchDetails = ApplicationLifecycle.GetLaunchDetails(); + + // The other users this user expect to see after traveling to the destination + // If there is conflicting data between the inputted users and destination, + // favor using the users. + // For example, if user A & destination 1 was passed in, but user A is now + // in destination 2, it is better to bring the current user to destination 2 + // if possible. + var users = launchDetails.UsersOptional; + var usersCount = (users != null) ? users.Count : 0; + + // The deeplink message, this should give enough info on how to go the + // destination in the app. + var deeplinkMessage = launchDetails.DeeplinkMessage; + + // The API Name of the destination. You can set the user to this after + // navigating to the app + var destinationApiName = launchDetails.DestinationApiName; + + var detailsString = "-Deeplink Message:\n" + deeplinkMessage + "\n-Api Name:\n" + destinationApiName + "\n-Users:\n"; + if (usersCount > 0) + { + foreach(var user in users) + { + detailsString += user.OculusID + "\n"; + } + } else + { + detailsString += "null\n"; + } + detailsString += "\n"; + return detailsString; + } + + // User has interacted with a deeplink outside this app + void OnLaunchIntentChangeNotif(Oculus.Platform.Message message) + { + if (message.IsError) + { + UpdateConsole(message.GetError().Message); + } else + { + UpdateConsole("Updated launch details:\n" + GetAppLaunchDetails()); + } + } + + void OnGetDestinations(Message message) + { + if (message.IsError) + { + UpdateConsole("Could not get the list of destinations!"); + } + else + { + foreach(Oculus.Platform.Models.Destination destination in message.Data) + { + DestinationAPINames.Add(destination.ApiName); + UpdateDestinationsConsole(); + } + } + } + + #region Helper Functions + + private int DestinationIndex = 0; + private bool OnlyPushUpOnce = false; + // Update is called once per frame + void Update() + { + if (PressAButton()) + { + if (DestinationAPINames.Count > 0) + { + SetPresence(); + } + else + { + UpdateConsole("No destinations to set to!"); + return; + } + } + else if (PressBButton()) + { + ClearPresence(); + } + + ScrollThroughDestinations(); + } + + private void ScrollThroughDestinations() + { + if (PressUp()) + { + if (!OnlyPushUpOnce) + { + DestinationIndex--; + if (DestinationIndex < 0) + { + DestinationIndex = DestinationAPINames.Count - 1; + } + OnlyPushUpOnce = true; + UpdateDestinationsConsole(); + } + } + else if (PressDown()) + { + if (!OnlyPushUpOnce) + { + DestinationIndex++; + if (DestinationIndex >= DestinationAPINames.Count) + { + DestinationIndex = 0; + } + OnlyPushUpOnce = true; + UpdateDestinationsConsole(); + } + } + else + { + OnlyPushUpOnce = false; + } + } + + private void UpdateDestinationsConsole() + { + if (DestinationAPINames.Count == 0) + { + DestinationsConsole.text = "Add some destinations to the developer dashboard first!"; + } + string destinations = "Destination API Names:\n"; + for (int i = 0; i < DestinationAPINames.Count; i++) + { + if (i == DestinationIndex) + { + destinations += "==>"; + } + destinations += DestinationAPINames[i] + "\n"; + } + DestinationsConsole.text = destinations; + } + + private void OnLoggedInUser(Message message) + { + if (message.IsError) + { + Debug.LogError("Cannot get logged in user"); + } + else + { + LoggedInUserID = message.Data.ID; + } + } + + private void UpdateConsole(string value) + { + Debug.Log(value); + + InVRConsole.text = + "Scroll Up/Down on Right Thumbstick\n(A) - Set Rich Presence to selected\n(B) - Clear Rich Presence\n\n" + value; + } + + #endregion + + #region I/O Inputs + private bool PressAButton() + { +#if USE_OVRINPUT + return OVRInput.GetUp(OVRInput.Button.One) || Input.GetKeyUp(KeyCode.A); +#else + return Input.GetKeyUp(KeyCode.A); +#endif + } + + private bool PressBButton() + { +#if USE_OVRINPUT + return OVRInput.GetUp(OVRInput.Button.Two) || Input.GetKeyUp(KeyCode.B); +#else + return Input.GetKeyUp(KeyCode.B); +#endif + } + + private bool PressUp() + { +#if USE_OVRINPUT + Vector2 axis = OVRInput.Get(OVRInput.Axis2D.SecondaryThumbstick); + return (axis.y > 0.2 || Input.GetKeyUp(KeyCode.UpArrow)); +#else + return Input.GetKeyUp(KeyCode.UpArrow); +#endif + } + + private bool PressDown() + { +#if USE_OVRINPUT + Vector2 axis = OVRInput.Get(OVRInput.Axis2D.SecondaryThumbstick); + return (axis.y < -0.2 || Input.GetKeyUp(KeyCode.DownArrow)); +#else + return Input.GetKeyUp(KeyCode.DownArrow); +#endif + } + + #endregion +} diff --git a/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts/RichPresenceSample.cs.meta b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts/RichPresenceSample.cs.meta new file mode 100644 index 0000000..61625db --- /dev/null +++ b/Assets/Oculus/Platform/Samples/RichPresenceSample/Scripts/RichPresenceSample.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 7cbd4da28d0350840aeef051399368a5 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/SimplePlatformSample.meta b/Assets/Oculus/Platform/Samples/SimplePlatformSample.meta new file mode 100644 index 0000000..2fa4e2b --- /dev/null +++ b/Assets/Oculus/Platform/Samples/SimplePlatformSample.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 505c528d4b557444b9056e8a9a430b51 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/SimplePlatformSample/DataEntry.cs b/Assets/Oculus/Platform/Samples/SimplePlatformSample/DataEntry.cs new file mode 100644 index 0000000..0b7b4c6 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/SimplePlatformSample/DataEntry.cs @@ -0,0 +1,641 @@ +namespace Oculus.Platform.Samples.SimplePlatformSample +{ + using UnityEngine; + using UnityEngine.UI; + using System; + using System.Collections; + using System.Collections.Generic; + using Oculus.Platform; + using Oculus.Platform.Models; + + public class DataEntry : MonoBehaviour + { + + public Text dataOutput; + + void Start() + { + Core.Initialize(); + checkEntitlement(); + } + + // Update is called once per frame + void Update() + { + string currentText = GetComponent().text; + + if (Input.GetKey(KeyCode.Return)) + { + if (currentText != "") + { + SubmitCommand(currentText); + } + + GetComponent().text = ""; + } + + // Handle all messages being returned + Request.RunCallbacks(); + } + + private void SubmitCommand(string command) + { + string[] commandParams = command.Split(' '); + + if (commandParams.Length > 0) + { + switch (commandParams[0]) + { + case "p": + if (commandParams.Length > 2) + { + createAndJoinPrivateRoom(commandParams[1], commandParams[2]); + } + break; + case "c": + getCurrentRoom(); + break; + case "g": + if (commandParams.Length > 1) + { + getRoom(commandParams[1]); + } + break; + case "j": + if (commandParams.Length > 1) + { + joinRoom(commandParams[1]); + } + break; + case "l": + if (commandParams.Length > 1) + { + leaveRoom(commandParams[1]); + } + break; + case "k": + if (commandParams.Length > 2) + { + kickUser(commandParams[1], commandParams[2]); + } + break; + case "m": + getLoggedInUser(); + break; + case "u": + if (commandParams.Length > 1) + { + getUser(commandParams[1]); + } + break; + case "d": + getLoggedInFriends(); + break; + case "i": + getInvitableUsers(); + break; + case "o": + if (commandParams.Length > 2) + { + inviteUser(commandParams[1], commandParams[2]); + } + break; + case "s": + if (commandParams.Length > 2) + { + setRoomDescription(commandParams[1], commandParams[2]); + } + break; + case "w": + if (commandParams.Length > 3) + { + updateRoomDataStore(commandParams[1], commandParams[2], commandParams[3]); + } + break; + case "n": + getUserNonce(); + break; + case "e": + checkEntitlement(); + break; + case "a": + if (commandParams.Length > 1) + { + getAchievementDefinition(commandParams[1]); + } + break; + case "b": + if (commandParams.Length > 1) + { + getAchievementProgress(commandParams[1]); + } + break; + case "3": + if (commandParams.Length > 1) + { + unlockAchievement(commandParams[1]); + } + break; + case "4": + if (commandParams.Length > 2) + { + addCountAchievement(commandParams[1], commandParams[2]); + } + break; + case "5": + if (commandParams.Length > 2) + { + addFieldsAchievement(commandParams[1], commandParams[2]); + } + break; + case "1": + if (commandParams.Length > 2) + { + writeLeaderboardEntry(commandParams[1], commandParams[2]); + } + break; + case "2": + if (commandParams.Length > 1) + { + getLeaderboardEntries(commandParams[1]); + } + break; + default: + printOutputLine("Invalid Command"); + break; + } + } + } + + void getLeaderboardEntries(string leaderboardName) + { + Leaderboards.GetEntries(leaderboardName, 10, LeaderboardFilterType.None, LeaderboardStartAt.Top).OnComplete(leaderboardGetCallback); + } + + void writeLeaderboardEntry(string leaderboardName, string value) + { + byte[] extraData = new byte[] { 0x54, 0x65, 0x73, 0x74 }; + + Leaderboards.WriteEntry(leaderboardName, Convert.ToInt32(value), extraData, false).OnComplete(leaderboardWriteCallback); + } + + void addFieldsAchievement(string achievementName, string fields) + { + Achievements.AddFields(achievementName, fields).OnComplete(achievementFieldsCallback); + } + + void addCountAchievement(string achievementName, string count) + { + Achievements.AddCount(achievementName, Convert.ToUInt64(count)).OnComplete(achievementCountCallback); + } + + void unlockAchievement(string achievementName) + { + Achievements.Unlock(achievementName).OnComplete(achievementUnlockCallback); + } + + void getAchievementProgress(string achievementName) + { + string[] Names = new string[1]; + Names[0] = achievementName; + + Achievements.GetProgressByName(Names).OnComplete(achievementProgressCallback); + } + + void getAchievementDefinition(string achievementName) + { + string[] Names = new string[1]; + Names[0] = achievementName; + + Achievements.GetDefinitionsByName(Names).OnComplete(achievementDefinitionCallback); + } + + void checkEntitlement() + { + Entitlements.IsUserEntitledToApplication().OnComplete(getEntitlementCallback); + } + + void getUserNonce() + { + printOutputLine("Trying to get user nonce"); + + Users.GetUserProof().OnComplete(userProofCallback); + } + + void createAndJoinPrivateRoom(string joinPolicy, string maxUsers) + { + printOutputLine("Trying to create and join private room"); + Rooms.CreateAndJoinPrivate((RoomJoinPolicy)Convert.ToUInt32(joinPolicy), Convert.ToUInt32(maxUsers)).OnComplete(createAndJoinPrivateRoomCallback); + } + + void getCurrentRoom() + { + printOutputLine("Trying to get current room"); + Rooms.GetCurrent().OnComplete(getCurrentRoomCallback); + } + + void getRoom(string roomID) + { + printOutputLine("Trying to get room " + roomID); + Rooms.Get(Convert.ToUInt64(roomID)).OnComplete(getCurrentRoomCallback); + } + + void joinRoom(string roomID) + { + printOutputLine("Trying to join room " + roomID); + Rooms.Join(Convert.ToUInt64(roomID), true).OnComplete(joinRoomCallback); + } + + void leaveRoom(string roomID) + { + printOutputLine("Trying to leave room " + roomID); + Rooms.Leave(Convert.ToUInt64(roomID)).OnComplete(leaveRoomCallback); + } + + void kickUser(string roomID, string userID) + { + printOutputLine("Trying to kick user " + userID + " from room " + roomID); + Rooms.KickUser(Convert.ToUInt64(roomID), Convert.ToUInt64(userID), 10 /*kick duration */).OnComplete(getCurrentRoomCallback); + } + + void getLoggedInUser() + { + printOutputLine("Trying to get currently logged in user"); + Users.GetLoggedInUser().OnComplete(getUserCallback); + } + + void getUser(string userID) + { + printOutputLine("Trying to get user " + userID); + Users.Get(Convert.ToUInt64(userID)).OnComplete(getUserCallback); + } + + void getLoggedInFriends() + { + printOutputLine("Trying to get friends of logged in user"); + Users.GetLoggedInUserFriends().OnComplete(getFriendsCallback); + } + + void getInvitableUsers() + { + printOutputLine("Trying to get invitable users"); + Rooms.GetInvitableUsers().OnComplete(getInvitableUsersCallback); + } + + void inviteUser(string roomID, string inviteToken) + { + printOutputLine("Trying to invite token " + inviteToken + " to room " + roomID); + Rooms.InviteUser(Convert.ToUInt64(roomID), inviteToken).OnComplete(inviteUserCallback); + } + + void setRoomDescription(string roomID, string description) + { + printOutputLine("Trying to set description " + description + " to room " + roomID); + Rooms.SetDescription(Convert.ToUInt64(roomID), description).OnComplete(getCurrentRoomCallback); + } + + void updateRoomDataStore(string roomID, string key, string value) + { + Dictionary kvPairs = new Dictionary(); + kvPairs.Add(key, value); + + printOutputLine("Trying to set k=" + key + " v=" + value + " for room " + roomID); + Rooms.UpdateDataStore(Convert.ToUInt64(roomID), kvPairs).OnComplete(getCurrentRoomCallback); + } + + void printOutputLine(String newLine) + { + dataOutput.text = "> " + newLine + System.Environment.NewLine + dataOutput.text; + } + + void outputRoomDetails(Room room) + { + printOutputLine("Room ID: " + room.ID + ", AppID: " + room.ApplicationID + ", Description: " + room.Description); + int numUsers = (room.UsersOptional != null) ? room.UsersOptional.Count : 0; + printOutputLine("MaxUsers: " + room.MaxUsers.ToString() + " Users in room: " + numUsers); + if (room.OwnerOptional != null) + { + printOutputLine("Room owner: " + room.OwnerOptional.ID + " " + room.OwnerOptional.OculusID); + } + printOutputLine("Join Policy: " + room.JoinPolicy.ToString()); + printOutputLine("Room Type: " + room.Type.ToString()); + + Message.MessageType.Matchmaking_Enqueue.GetHashCode(); + + } + + void outputUserArray(UserList users) + { + foreach (User user in users) + { + printOutputLine("User: " + user.ID + " " + user.OculusID + " " + user.Presence + " " + user.InviteToken); + } + } + + + // Callbacks + void userProofCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received user nonce generation success"); + UserProof userNonce = msg.Data; + printOutputLine("Nonce: " + userNonce.Value); + } + else + { + printOutputLine("Received user nonce generation error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + + } + + void getEntitlementCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("You are entitled to use this app."); + } + else + { + printOutputLine("You are NOT entitled to use this app."); + } + } + + void leaderboardGetCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Leaderboard entry get success."); + var entries = msg.Data; + + foreach (var entry in entries) + { + printOutputLine(entry.Rank + ". " + entry.User.OculusID + " " + entry.Score + " " + entry.Timestamp); + } + } + else + { + printOutputLine("Received leaderboard get error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void leaderboardWriteCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Leaderboard entry write success."); + var didUpdate = (Message)msg; + + if (didUpdate.Data) + { + printOutputLine("Score updated."); + } + else + { + printOutputLine("Score NOT updated."); + } + } + else + { + printOutputLine("Received leaderboard write error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void achievementFieldsCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Achievement fields added."); + } + else + { + printOutputLine("Received achievement fields add error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void achievementCountCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Achievement count added."); + } + else + { + printOutputLine("Received achievement count add error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void achievementUnlockCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Achievement unlocked"); + } + else + { + printOutputLine("Received achievement unlock error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void achievementProgressCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received achievement progress success"); + AchievementProgressList progressList = msg.GetAchievementProgressList(); + + foreach (var progress in progressList) + { + if (progress.IsUnlocked) + { + printOutputLine("Achievement Unlocked"); + } + else + { + printOutputLine("Achievement Locked"); + } + printOutputLine("Current Bitfield: " + progress.Bitfield.ToString()); + printOutputLine("Current Count: " + progress.Count.ToString()); + } + } + else + { + printOutputLine("Received achievement progress error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void achievementDefinitionCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received achievement definitions success"); + AchievementDefinitionList definitionList = msg.GetAchievementDefinitions(); + + foreach (var definition in definitionList) + { + switch (definition.Type) + { + case AchievementType.Simple: + printOutputLine("Achievement Type: Simple"); + break; + case AchievementType.Bitfield: + printOutputLine("Achievement Type: Bitfield"); + printOutputLine("Bitfield Length: " + definition.BitfieldLength.ToString()); + printOutputLine("Target: " + definition.Target.ToString()); + break; + case AchievementType.Count: + printOutputLine("Achievement Type: Count"); + printOutputLine("Target: " + definition.Target.ToString()); + break; + case AchievementType.Unknown: + default: + printOutputLine("Achievement Type: Unknown"); + break; + } + } + } + else + { + printOutputLine("Received achievement definitions error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void createAndJoinPrivateRoomCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received create and join room success"); + outputRoomDetails(msg.Data); + } + else + { + printOutputLine("Received create and join room error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void getCurrentRoomCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received get room success"); + outputRoomDetails(msg.Data); + } + else + { + printOutputLine("Received get room error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void joinRoomCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received join room success"); + outputRoomDetails(msg.Data); + } + else + { + printOutputLine("Received join room error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void leaveRoomCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received leave room success"); + outputRoomDetails(msg.Data); + } + else + { + printOutputLine("Received leave room error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void getUserCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received get user success"); + User user = msg.Data; + printOutputLine("User: " + user.ID + " " + user.OculusID + " " + user.Presence + " " + user.InviteToken); + } + else + { + printOutputLine("Received get user error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void getFriendsCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received get friends success"); + UserList users = msg.Data; + outputUserArray(users); + } + else + { + printOutputLine("Received get friends error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void getInvitableUsersCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received get invitable users success"); + UserList users = msg.Data; + outputUserArray(users); + } + else + { + printOutputLine("Received get invitable users error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + + void inviteUserCallback(Message msg) + { + if (!msg.IsError) + { + printOutputLine("Received invite user success"); + } + else + { + printOutputLine("Received invite user error"); + Error error = msg.GetError(); + printOutputLine("Error: " + error.Message); + } + } + } +} diff --git a/Assets/Oculus/Platform/Samples/SimplePlatformSample/DataEntry.cs.meta b/Assets/Oculus/Platform/Samples/SimplePlatformSample/DataEntry.cs.meta new file mode 100644 index 0000000..c145542 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/SimplePlatformSample/DataEntry.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: e10d7d54285902b48a88ddf18008a848 +timeCreated: 1446741207 +licenseType: Pro +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/SimplePlatformSample/MainScene.unity b/Assets/Oculus/Platform/Samples/SimplePlatformSample/MainScene.unity new file mode 100644 index 0000000..02ff9c1 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/SimplePlatformSample/MainScene.unity @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d862a7a665becc128377cd36ca33c6d285a2e67c0842dbf8a9283ecdea6273c6 +size 25711 diff --git a/Assets/Oculus/Platform/Samples/SimplePlatformSample/MainScene.unity.meta b/Assets/Oculus/Platform/Samples/SimplePlatformSample/MainScene.unity.meta new file mode 100644 index 0000000..5fb620e --- /dev/null +++ b/Assets/Oculus/Platform/Samples/SimplePlatformSample/MainScene.unity.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 318d73ef645634c49839069272d9e4f4 +timeCreated: 1446741350 +licenseType: Pro +DefaultImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame.meta b/Assets/Oculus/Platform/Samples/VrBoardGame.meta new file mode 100644 index 0000000..46f198b --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 2e9261b3b12733f46a787545edf4df43 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Oculus_IAP.tsv b/Assets/Oculus/Platform/Samples/VrBoardGame/Oculus_IAP.tsv new file mode 100644 index 0000000..3d0cfe1 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Oculus_IAP.tsv @@ -0,0 +1 @@ +SKU Name Description Currency Amount Item Type PowerballPack1 Purchase more Power Balls 1 USD 0.01 Consumable \ No newline at end of file diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Oculus_IAP.tsv.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Oculus_IAP.tsv.meta new file mode 100644 index 0000000..bd32459 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Oculus_IAP.tsv.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0b687b4832314b24db66e56bef4de820 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs.meta new file mode 100644 index 0000000..22f9114 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6198dac30ce5b6f4c9c485a8df034132 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceA.prefab b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceA.prefab new file mode 100644 index 0000000..8aa815d --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceA.prefab @@ -0,0 +1,112 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1000013725221134} + m_IsPrefabParent: 1 +--- !u!1 &1000013725221134 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4000011548025488} + - component: {fileID: 33000011356183730} + - component: {fileID: 65000012561974784} + - component: {fileID: 23000013314552442} + - component: {fileID: 114000011207431316} + m_Layer: 0 + m_Name: PieceA + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4000011548025488 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013725221134} + m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &23000013314552442 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013725221134} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33000011356183730 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013725221134} + m_Mesh: {fileID: 10202, guid: 0000000000000000e000000000000000, type: 0} +--- !u!65 &65000012561974784 +BoxCollider: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013725221134} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Size: {x: 1, y: 1, z: 1} + m_Center: {x: 0, y: 0, z: 0} +--- !u!114 &114000011207431316 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000013725221134} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4c243c46c5f7948488696c53b4fa9786, type: 3} + m_Name: + m_EditorClassIdentifier: + m_type: 0 + m_prefabA: {fileID: 1000013725221134} + m_prefabB: {fileID: 1000011610856386, guid: ff8c3ef67a52afc4a9cf330f025fdec3, type: 2} + m_prefabPower: {fileID: 1000010836483084, guid: 81a73acbe18cf784cb5184bd404c30bc, + type: 2} diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceA.prefab.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceA.prefab.meta new file mode 100644 index 0000000..72121fa --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceA.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 48e6308f93e461340abb975251ae824b +timeCreated: 1480479889 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceB.prefab b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceB.prefab new file mode 100644 index 0000000..21778b9 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceB.prefab @@ -0,0 +1,113 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1000011610856386} + m_IsPrefabParent: 1 +--- !u!1 &1000011610856386 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4000013853064064} + - component: {fileID: 33000012696557308} + - component: {fileID: 136000012754303966} + - component: {fileID: 23000013106303838} + - component: {fileID: 114000011050251136} + m_Layer: 0 + m_Name: PieceB + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4000013853064064 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011610856386} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.2, y: 0.1, z: 0.2} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &23000013106303838 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011610856386} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33000012696557308 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011610856386} + m_Mesh: {fileID: 10206, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &114000011050251136 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011610856386} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4c243c46c5f7948488696c53b4fa9786, type: 3} + m_Name: + m_EditorClassIdentifier: + m_type: 1 + m_prefabA: {fileID: 1000013725221134, guid: 48e6308f93e461340abb975251ae824b, type: 2} + m_prefabB: {fileID: 1000011610856386} + m_prefabPower: {fileID: 1000010836483084, guid: 81a73acbe18cf784cb5184bd404c30bc, + type: 2} +--- !u!136 &136000012754303966 +CapsuleCollider: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000011610856386} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + m_Radius: 0.5 + m_Height: 2 + m_Direction: 1 + m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceB.prefab.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceB.prefab.meta new file mode 100644 index 0000000..27e2f3e --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PieceB.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ff8c3ef67a52afc4a9cf330f025fdec3 +timeCreated: 1480479894 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PowerBall.prefab b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PowerBall.prefab new file mode 100644 index 0000000..d32b33b --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PowerBall.prefab @@ -0,0 +1,111 @@ +%YAML 1.1 +%TAG !u! tag:unity3d.com,2011: +--- !u!1001 &100100000 +Prefab: + m_ObjectHideFlags: 1 + serializedVersion: 2 + m_Modification: + m_TransformParent: {fileID: 0} + m_Modifications: [] + m_RemovedComponents: [] + m_ParentPrefab: {fileID: 0} + m_RootGameObject: {fileID: 1000010836483084} + m_IsPrefabParent: 1 +--- !u!1 &1000010836483084 +GameObject: + m_ObjectHideFlags: 0 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + serializedVersion: 5 + m_Component: + - component: {fileID: 4000013490292564} + - component: {fileID: 33000012739098690} + - component: {fileID: 135000010301361876} + - component: {fileID: 23000010370066952} + - component: {fileID: 114000013731705678} + m_Layer: 0 + m_Name: PowerBall + m_TagString: Untagged + m_Icon: {fileID: 0} + m_NavMeshLayer: 0 + m_StaticEditorFlags: 0 + m_IsActive: 1 +--- !u!4 &4000013490292564 +Transform: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010836483084} + m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} + m_LocalPosition: {x: 0, y: 0, z: 0} + m_LocalScale: {x: 0.2, y: 0.2, z: 0.2} + m_Children: [] + m_Father: {fileID: 0} + m_RootOrder: 0 + m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0} +--- !u!23 &23000010370066952 +MeshRenderer: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010836483084} + m_Enabled: 1 + m_CastShadows: 1 + m_ReceiveShadows: 1 + m_MotionVectors: 1 + m_LightProbeUsage: 1 + m_ReflectionProbeUsage: 1 + m_Materials: + - {fileID: 10303, guid: 0000000000000000f000000000000000, type: 0} + m_StaticBatchInfo: + firstSubMesh: 0 + subMeshCount: 0 + m_StaticBatchRoot: {fileID: 0} + m_ProbeAnchor: {fileID: 0} + m_LightProbeVolumeOverride: {fileID: 0} + m_ScaleInLightmap: 1 + m_PreserveUVs: 1 + m_IgnoreNormalsForChartDetection: 0 + m_ImportantGI: 0 + m_SelectedEditorRenderState: 3 + m_MinimumChartSize: 4 + m_AutoUVMaxDistance: 0.5 + m_AutoUVMaxAngle: 89 + m_LightmapParameters: {fileID: 0} + m_SortingLayerID: 0 + m_SortingLayer: 0 + m_SortingOrder: 0 +--- !u!33 &33000012739098690 +MeshFilter: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010836483084} + m_Mesh: {fileID: 10207, guid: 0000000000000000e000000000000000, type: 0} +--- !u!114 &114000013731705678 +MonoBehaviour: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010836483084} + m_Enabled: 1 + m_EditorHideFlags: 0 + m_Script: {fileID: 11500000, guid: 4c243c46c5f7948488696c53b4fa9786, type: 3} + m_Name: + m_EditorClassIdentifier: + m_type: 2 + m_prefabA: {fileID: 1000013725221134, guid: 48e6308f93e461340abb975251ae824b, type: 2} + m_prefabB: {fileID: 1000011610856386, guid: ff8c3ef67a52afc4a9cf330f025fdec3, type: 2} + m_prefabPower: {fileID: 1000010836483084} +--- !u!135 &135000010301361876 +SphereCollider: + m_ObjectHideFlags: 1 + m_PrefabParentObject: {fileID: 0} + m_PrefabInternal: {fileID: 100100000} + m_GameObject: {fileID: 1000010836483084} + m_Material: {fileID: 0} + m_IsTrigger: 0 + m_Enabled: 1 + serializedVersion: 2 + m_Radius: 0.5 + m_Center: {x: 0, y: 0, z: 0} diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PowerBall.prefab.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PowerBall.prefab.meta new file mode 100644 index 0000000..c43520a --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Prefabs/PowerBall.prefab.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 81a73acbe18cf784cb5184bd404c30bc +timeCreated: 1480479897 +licenseType: Free +NativeFormatImporter: + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Readme.md b/Assets/Oculus/Platform/Samples/VrBoardGame/Readme.md new file mode 100644 index 0000000..2aab267 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Readme.md @@ -0,0 +1,64 @@ +# Overview + +This example demonstrates using the Oculus In-App-Purchase API and skill based matchmaking. +The setting is a simple boardgame (which you are encourage to chage to your creative idea!) +on a 3x3 grid with two pieces and one special 'power-piece' that can be purchased with +IAP through the Oculus Store. After an Online match is completed the ranking is sent to +the Matchmaking Service so that following match selections will take into account a user's +skill level. + +# Application Setup + +1. Open the Project in Unity 5.4.1p1 or later +2. Import the OculusPlatform Unity package + - Unity: Main Menu -> Assets -> Import Package -> Custom Package + - SDK Location: Unity/OculusPlatform.unitypackage + +## Rift +1. Create your Rift application on the Oculus Developer Dashboard +2. Copy the Application ID into the Project (Main Menu -> Oculus Platform -> Edit Settings -> Oculus Rift App Id) + +## GearVR +1. Create the GearVR application on the Oculus Developer Dashboard +2. Move the GearVR application into the Rift application's App Grouping +3. Copy the Application ID into the Project (Main Menu -> Oculus Platform -> Edit Settings -> Gear VR App Id) +4. Copy the OSIG files for the GearVR devices you are testing to Assets\Plugins\Android\Assets + +# Configure Matchmaking + +1. On the Oculus Dashboard, navigate to the Matchmaking section for your App Grouping +2. Change the option box from 'Pools' to 'Skill Pools' +3. Click Create Pool +4. Set the 'Skill Pool Key' to ''VR_BOARD_GAME'' +5. Select ''Medium'' for the 'Luck Factor' +6. Enter ''0'' for the 'Draw Probability +7. Click 'Save & Deploy' +8. Change the option box 'Skill Pools' to 'Pools' +9. Click Create Pool +10. Set the 'Pool Key' to ''VR_BOARD_GAME_POOL'' +11. Set the Mode to Quickmatch +12. Enter ''2'' for both the Min and Max Users +13. Select ''VR_BOARD_GAME'' for the 'Skill Pool' +14. Leave 'Advanced Quickmatch' set to ''No'' +15. Leave 'Should Consider Ping Time?' at the default setting of ''No'' +16. Click 'Save & Deploy' + +# Configure IAP + +1. On the Oculus Dashboard, make sure the Payment Info is setup for your Organization +2. Navigate to the IAP tab under your App Grouping +3. Select the Upload TSV button and choose the Oculus_IAP.tsv in the project root directory. + +# Upload your builds + +Build executables from Unity and upload them to your Application Dashboard +* Rift + 1. Add the executable and data folder to a zip file + 2. Upload the zip to the Alpha channel on your Dashboard + 3. Set the executable name you chose in the zip file + 4. Add Friends you are testing with as Subscribed Users for the Alpha channel +* GearVR + 1. Create an android keystore (if you don't have one) so Unity can sign the build. (Player Settings -> Publishing Settings) + 2. Upload the apk to the Alpha channel on your Dashboard + 3. Each apk you upload needs a new build number (Player Settings -> Other Settings) + 4. Add Friends you are testing with as Subscribed Users for the Alpha channel diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Readme.md.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Readme.md.meta new file mode 100644 index 0000000..e1f6719 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Readme.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 0975c71f0ce832c489580f5059a6118a +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts.meta new file mode 100644 index 0000000..a04632b --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6dd4d72c9c45c0146abb9e5322fadc16 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/BoardPosition.cs b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/BoardPosition.cs new file mode 100644 index 0000000..5fdbd01 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/BoardPosition.cs @@ -0,0 +1,15 @@ +namespace Oculus.Platform.Samples.VrBoardGame +{ + using UnityEngine; + using System.Collections; + + // This behaviour is attached to GameObjects whose collision mesh + // describes a specific position on the GameBoard. The collision + // mesh doesn't need to fully cover the board position, but enough + // for eye raycasts to detect that the user is looking there. + public class BoardPosition : MonoBehaviour { + + [SerializeField] [Range(0,2)] public int x = 0; + [SerializeField] [Range(0,2)] public int y = 0; + } +} diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/BoardPosition.cs.meta b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/BoardPosition.cs.meta new file mode 100644 index 0000000..2c6d084 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/BoardPosition.cs.meta @@ -0,0 +1,12 @@ +fileFormatVersion: 2 +guid: d9244e220b0fee34c98de6ed84ee6cdd +timeCreated: 1480276073 +licenseType: Free +MonoImporter: + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/EyeCamera.cs b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/EyeCamera.cs new file mode 100644 index 0000000..47c63d6 --- /dev/null +++ b/Assets/Oculus/Platform/Samples/VrBoardGame/Scripts/EyeCamera.cs @@ -0,0 +1,99 @@ +namespace Oculus.Platform.Samples.VrBoardGame +{ + using UnityEngine; + using UnityEngine.UI; + using UnityEngine.EventSystems; + + // This is a helper class for selecting objects that the user is looking at. + // It will select UI objects that have an attach 3d collision volume and helps + // the GameController locate GamePieces and GamePositions. + public class EyeCamera : MonoBehaviour + { + // the EventSystem used by the UI elements + [SerializeField] private EventSystem m_eventSystem = null; + + // the GameController to notify + [SerializeField] private GameController m_gameController = null; + + // a tine ball in the distance to debug where the user is looking + [SerializeField] private SphereCollider m_gazeTracker = null; + + // the current Button, if any, being looked at + private Button m_currentButton; + + // the current GamePiece, if any, being looked at + private GamePiece m_currentPiece; + + // the current BoardPosition, if any, being looked at + private BoardPosition m_boardPosition; + + void Update() + { + RaycastHit hit; + Button button = null; + GamePiece piece = null; + BoardPosition pos = null; + + // do a forward raycast to see if we hit a selectable object + bool hitSomething = Physics.Raycast(transform.position, transform.forward, out hit, 50f); + if (hitSomething) { + button = hit.collider.GetComponent