generated from VR-Sexe/Unity3DTemplate
Remove Oculus
This commit is contained in:
parent
cc4b569ab3
commit
deab42bad3
@ -65,7 +65,7 @@ Material:
|
|||||||
- _Cutoff: 0.5
|
- _Cutoff: 0.5
|
||||||
- _DetailNormalMapScale: 1
|
- _DetailNormalMapScale: 1
|
||||||
- _DstBlend: 10
|
- _DstBlend: 10
|
||||||
- _GlossMapScale: 0.846
|
- _GlossMapScale: 0.5
|
||||||
- _Glossiness: 0.737
|
- _Glossiness: 0.737
|
||||||
- _GlossyReflections: 1
|
- _GlossyReflections: 1
|
||||||
- _Metallic: 0
|
- _Metallic: 0
|
||||||
@ -78,6 +78,6 @@ Material:
|
|||||||
- _UVSec: 0
|
- _UVSec: 0
|
||||||
- _ZWrite: 0
|
- _ZWrite: 0
|
||||||
m_Colors:
|
m_Colors:
|
||||||
- _Color: {r: 0, g: 0.5, b: 1, a: 0.12941177}
|
- _Color: {r: 0, g: 0.5, b: 1, a: 0}
|
||||||
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
|
||||||
m_BuildTextureStacks: []
|
m_BuildTextureStacks: []
|
||||||
|
|||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5ee9cf450aed91a4eb42599f74a5fbc7
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 29ab7e927676ef74a93aeedf4146f1ac
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1470780399
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 180c8a539f95cce428f820b0ba392c1f
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1468506676
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav
(Stored with Git LFS)
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01.wav
(Stored with Git LFS)
Binary file not shown.
@ -1,22 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 485ac48a563e2bf44bb4de7ead5a1f68
|
|
||||||
timeCreated: 1461716881
|
|
||||||
licenseType: Store
|
|
||||||
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:
|
|
||||||
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav
(Stored with Git LFS)
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_close_01a.wav
(Stored with Git LFS)
Binary file not shown.
@ -1,22 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: d3994560fb567c34a821fd9355c10eef
|
|
||||||
timeCreated: 1461716882
|
|
||||||
licenseType: Store
|
|
||||||
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:
|
|
||||||
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav
(Stored with Git LFS)
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01.wav
(Stored with Git LFS)
Binary file not shown.
@ -1,22 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 7000b4d67a1320940b363f3cf891dfff
|
|
||||||
timeCreated: 1461716881
|
|
||||||
licenseType: Store
|
|
||||||
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:
|
|
||||||
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav
(Stored with Git LFS)
BIN
Assets/Oculus/AudioManager/Audio/TestSounds/metal_sliding_door_open_01a.wav
(Stored with Git LFS)
Binary file not shown.
@ -1,22 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 8198ccc08475a764daaf226b841a55f1
|
|
||||||
timeCreated: 1461716882
|
|
||||||
licenseType: Store
|
|
||||||
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:
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Oculus.AudioManager",
|
|
||||||
"references": [
|
|
||||||
"Oculus.Spatializer"
|
|
||||||
],
|
|
||||||
"includePlatforms": [],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [
|
|
||||||
{
|
|
||||||
"name": "com.unity.xr.management",
|
|
||||||
"expression": "",
|
|
||||||
"define": "USING_XR_MANAGEMENT"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "com.unity.xr.oculus",
|
|
||||||
"expression": "",
|
|
||||||
"define": "USING_XR_SDK_OCULUS"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 21b850ac1b5452b46a20c637f002dbf9
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6d597fe114807b54a99033a3dae9ce0d
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1470780399
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 7ee6cbebddf12044c95f9d6eb6e40823
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1470780399
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,36 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: cfae243ecd01edd49bd439c56a8b18cf
|
|
||||||
timeCreated: 1468506975
|
|
||||||
licenseType: Store
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,484 +0,0 @@
|
|||||||
%YAML 1.1
|
|
||||||
%TAG !u! tag:unity3d.com,2011:
|
|
||||||
--- !u!29 &1
|
|
||||||
OcclusionCullingSettings:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 2
|
|
||||||
m_OcclusionBakeSettings:
|
|
||||||
smallestOccluder: 5
|
|
||||||
smallestHole: 0.25
|
|
||||||
backfaceThreshold: 100
|
|
||||||
m_SceneGUID: 00000000000000000000000000000000
|
|
||||||
m_OcclusionCullingData: {fileID: 0}
|
|
||||||
--- !u!104 &2
|
|
||||||
RenderSettings:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 9
|
|
||||||
m_Fog: 0
|
|
||||||
m_FogColor: {r: 0.5, g: 0.5, b: 0.5, a: 1}
|
|
||||||
m_FogMode: 3
|
|
||||||
m_FogDensity: 0.01
|
|
||||||
m_LinearFogStart: 0
|
|
||||||
m_LinearFogEnd: 300
|
|
||||||
m_AmbientSkyColor: {r: 0.212, g: 0.227, b: 0.259, a: 1}
|
|
||||||
m_AmbientEquatorColor: {r: 0.114, g: 0.125, b: 0.133, a: 1}
|
|
||||||
m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
|
|
||||||
m_AmbientIntensity: 1
|
|
||||||
m_AmbientMode: 3
|
|
||||||
m_SubtractiveShadowColor: {r: 0.42, g: 0.478, b: 0.627, a: 1}
|
|
||||||
m_SkyboxMaterial: {fileID: 0}
|
|
||||||
m_HaloStrength: 0.5
|
|
||||||
m_FlareStrength: 1
|
|
||||||
m_FlareFadeSpeed: 3
|
|
||||||
m_HaloTexture: {fileID: 0}
|
|
||||||
m_SpotCookie: {fileID: 10001, guid: 0000000000000000e000000000000000, type: 0}
|
|
||||||
m_DefaultReflectionMode: 0
|
|
||||||
m_DefaultReflectionResolution: 128
|
|
||||||
m_ReflectionBounces: 1
|
|
||||||
m_ReflectionIntensity: 1
|
|
||||||
m_CustomReflection: {fileID: 0}
|
|
||||||
m_Sun: {fileID: 0}
|
|
||||||
m_IndirectSpecularColor: {r: 0, g: 0, b: 0, a: 1}
|
|
||||||
m_UseRadianceAmbientProbe: 0
|
|
||||||
--- !u!157 &3
|
|
||||||
LightmapSettings:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
serializedVersion: 11
|
|
||||||
m_GIWorkflowMode: 1
|
|
||||||
m_GISettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_BounceScale: 1
|
|
||||||
m_IndirectOutputScale: 1
|
|
||||||
m_AlbedoBoost: 1
|
|
||||||
m_EnvironmentLightingMode: 0
|
|
||||||
m_EnableBakedLightmaps: 0
|
|
||||||
m_EnableRealtimeLightmaps: 0
|
|
||||||
m_LightmapEditorSettings:
|
|
||||||
serializedVersion: 12
|
|
||||||
m_Resolution: 2
|
|
||||||
m_BakeResolution: 40
|
|
||||||
m_AtlasSize: 1024
|
|
||||||
m_AO: 0
|
|
||||||
m_AOMaxDistance: 1
|
|
||||||
m_CompAOExponent: 0
|
|
||||||
m_CompAOExponentDirect: 0
|
|
||||||
m_ExtractAmbientOcclusion: 0
|
|
||||||
m_Padding: 2
|
|
||||||
m_LightmapParameters: {fileID: 0}
|
|
||||||
m_LightmapsBakeMode: 1
|
|
||||||
m_TextureCompression: 1
|
|
||||||
m_FinalGather: 0
|
|
||||||
m_FinalGatherFiltering: 1
|
|
||||||
m_FinalGatherRayCount: 1024
|
|
||||||
m_ReflectionCompression: 2
|
|
||||||
m_MixedBakeMode: 1
|
|
||||||
m_BakeBackend: 0
|
|
||||||
m_PVRSampling: 1
|
|
||||||
m_PVRDirectSampleCount: 32
|
|
||||||
m_PVRSampleCount: 512
|
|
||||||
m_PVRBounces: 2
|
|
||||||
m_PVREnvironmentSampleCount: 512
|
|
||||||
m_PVREnvironmentReferencePointCount: 2048
|
|
||||||
m_PVRFilteringMode: 0
|
|
||||||
m_PVRDenoiserTypeDirect: 0
|
|
||||||
m_PVRDenoiserTypeIndirect: 0
|
|
||||||
m_PVRDenoiserTypeAO: 0
|
|
||||||
m_PVRFilterTypeDirect: 0
|
|
||||||
m_PVRFilterTypeIndirect: 0
|
|
||||||
m_PVRFilterTypeAO: 0
|
|
||||||
m_PVREnvironmentMIS: 0
|
|
||||||
m_PVRCulling: 1
|
|
||||||
m_PVRFilteringGaussRadiusDirect: 1
|
|
||||||
m_PVRFilteringGaussRadiusIndirect: 5
|
|
||||||
m_PVRFilteringGaussRadiusAO: 2
|
|
||||||
m_PVRFilteringAtrousPositionSigmaDirect: 0.5
|
|
||||||
m_PVRFilteringAtrousPositionSigmaIndirect: 2
|
|
||||||
m_PVRFilteringAtrousPositionSigmaAO: 1
|
|
||||||
m_ExportTrainingData: 0
|
|
||||||
m_TrainingDataDestination: TrainingData
|
|
||||||
m_LightProbeSampleCountMultiplier: 4
|
|
||||||
m_LightingDataAsset: {fileID: 0}
|
|
||||||
m_UseShadowmask: 0
|
|
||||||
--- !u!196 &4
|
|
||||||
NavMeshSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_BuildSettings:
|
|
||||||
serializedVersion: 2
|
|
||||||
agentTypeID: 0
|
|
||||||
agentRadius: 0.5
|
|
||||||
agentHeight: 2
|
|
||||||
agentSlope: 45
|
|
||||||
agentClimb: 0.4
|
|
||||||
ledgeDropHeight: 0
|
|
||||||
maxJumpAcrossDistance: 0
|
|
||||||
minRegionArea: 2
|
|
||||||
manualCellSize: 0
|
|
||||||
cellSize: 0.16666667
|
|
||||||
manualTileSize: 0
|
|
||||||
tileSize: 256
|
|
||||||
accuratePlacement: 0
|
|
||||||
debug:
|
|
||||||
m_Flags: 0
|
|
||||||
m_NavMeshData: {fileID: 0}
|
|
||||||
--- !u!1 &767466533
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 767466535}
|
|
||||||
- component: {fileID: 767466534}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: AudioManager
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!114 &767466534
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 767466533}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: 6d1d30b41806244fca035fdae2896fb7, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
makePersistent: 1
|
|
||||||
enableSpatializedAudio: 1
|
|
||||||
enableSpatializedFastOverride: 0
|
|
||||||
audioMixer: {fileID: 0}
|
|
||||||
defaultMixerGroup: {fileID: 24300001, guid: 323417d454569d94fa01d511f6eb44d9, type: 2}
|
|
||||||
reservedMixerGroup: {fileID: 0}
|
|
||||||
voiceChatMixerGroup: {fileID: 0}
|
|
||||||
verboseLogging: 0
|
|
||||||
maxSoundEmitters: 32
|
|
||||||
volumeSoundFX: 1
|
|
||||||
soundFxFadeSecs: 1
|
|
||||||
audioMinFallOffDistance: 1
|
|
||||||
audioMaxFallOffDistance: 25
|
|
||||||
soundGroupings:
|
|
||||||
- name: Test Group
|
|
||||||
soundList:
|
|
||||||
- name: TestSound1
|
|
||||||
playback: 0
|
|
||||||
volume: 1
|
|
||||||
pitchVariance: {x: 0.95, y: 1.05}
|
|
||||||
falloffDistance: {x: 1, y: 25}
|
|
||||||
falloffCurve: 2
|
|
||||||
volumeFalloffCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1.0044228
|
|
||||||
inSlope: -1.9459304
|
|
||||||
outSlope: -1.9459304
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0.27001944
|
|
||||||
value: 0.24837627
|
|
||||||
inSlope: -1.3226271
|
|
||||||
outSlope: -1.3226271
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0.99744946
|
|
||||||
value: -0.0020017216
|
|
||||||
inSlope: -0.42040923
|
|
||||||
outSlope: -0.42040923
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 0
|
|
||||||
reverbZoneMix:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1.0044228
|
|
||||||
inSlope: -1.9459304
|
|
||||||
outSlope: -1.9459304
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0.36357749
|
|
||||||
value: 0.4567863
|
|
||||||
inSlope: -1.3226271
|
|
||||||
outSlope: -1.3226271
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0.99594045
|
|
||||||
value: 0.19572063
|
|
||||||
inSlope: -0.107312
|
|
||||||
outSlope: -0.107312
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 0
|
|
||||||
spread: 0
|
|
||||||
pctChanceToPlay: 1
|
|
||||||
priority: 0
|
|
||||||
delay: {x: 0, y: 0}
|
|
||||||
looping: 0
|
|
||||||
ospProps:
|
|
||||||
enableSpatialization: 1
|
|
||||||
useFastOverride: 1
|
|
||||||
gain: 0
|
|
||||||
enableInvSquare: 1
|
|
||||||
volumetric: 0
|
|
||||||
invSquareFalloff: {x: 1, y: 250}
|
|
||||||
soundClips:
|
|
||||||
- {fileID: 8300000, guid: 7000b4d67a1320940b363f3cf891dfff, type: 3}
|
|
||||||
- {fileID: 8300000, guid: 8198ccc08475a764daaf226b841a55f1, type: 3}
|
|
||||||
visibilityToggle: 0
|
|
||||||
- name: TestSound2
|
|
||||||
playback: 0
|
|
||||||
volume: 1
|
|
||||||
pitchVariance: {x: 0.79999995, y: 1.25}
|
|
||||||
falloffDistance: {x: 1, y: 25}
|
|
||||||
falloffCurve: 1
|
|
||||||
volumeFalloffCurve:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 1
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
reverbZoneMix:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Curve:
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 0
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
- serializedVersion: 3
|
|
||||||
time: 1
|
|
||||||
value: 1
|
|
||||||
inSlope: 0
|
|
||||||
outSlope: 0
|
|
||||||
tangentMode: 0
|
|
||||||
weightedMode: 0
|
|
||||||
inWeight: 0.33333334
|
|
||||||
outWeight: 0.33333334
|
|
||||||
m_PreInfinity: 2
|
|
||||||
m_PostInfinity: 2
|
|
||||||
m_RotationOrder: 4
|
|
||||||
spread: 0
|
|
||||||
pctChanceToPlay: 1
|
|
||||||
priority: 0
|
|
||||||
delay: {x: 0, y: 0}
|
|
||||||
looping: 0
|
|
||||||
ospProps:
|
|
||||||
enableSpatialization: 1
|
|
||||||
useFastOverride: 0
|
|
||||||
gain: 0
|
|
||||||
enableInvSquare: 0
|
|
||||||
volumetric: 0
|
|
||||||
invSquareFalloff: {x: 1, y: 25}
|
|
||||||
soundClips:
|
|
||||||
- {fileID: 8300000, guid: 485ac48a563e2bf44bb4de7ead5a1f68, type: 3}
|
|
||||||
- {fileID: 8300000, guid: d3994560fb567c34a821fd9355c10eef, type: 3}
|
|
||||||
visibilityToggle: 0
|
|
||||||
mixerGroup: {fileID: 24300001, guid: 1dd706bb85d8aef4e83a6229dbd62c36, type: 2}
|
|
||||||
maxPlayingSounds: 0
|
|
||||||
preloadAudio: 0
|
|
||||||
volumeOverride: 1
|
|
||||||
playingSoundCount: 0
|
|
||||||
--- !u!4 &767466535
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 767466533}
|
|
||||||
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: 1
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!1 &1050355579
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 1050355581}
|
|
||||||
- component: {fileID: 1050355580}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: TestScript
|
|
||||||
m_TagString: Untagged
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!114 &1050355580
|
|
||||||
MonoBehaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1050355579}
|
|
||||||
m_Enabled: 1
|
|
||||||
m_EditorHideFlags: 0
|
|
||||||
m_Script: {fileID: 11500000, guid: cfae243ecd01edd49bd439c56a8b18cf, type: 3}
|
|
||||||
m_Name:
|
|
||||||
m_EditorClassIdentifier:
|
|
||||||
testSound1:
|
|
||||||
soundFXName: TestSound1
|
|
||||||
testSound2:
|
|
||||||
soundFXName: TestSound2
|
|
||||||
--- !u!4 &1050355581
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 1050355579}
|
|
||||||
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: 2
|
|
||||||
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
|
|
||||||
--- !u!1 &2106254871
|
|
||||||
GameObject:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
serializedVersion: 6
|
|
||||||
m_Component:
|
|
||||||
- component: {fileID: 2106254876}
|
|
||||||
- component: {fileID: 2106254875}
|
|
||||||
- component: {fileID: 2106254873}
|
|
||||||
- component: {fileID: 2106254872}
|
|
||||||
m_Layer: 0
|
|
||||||
m_Name: Main Camera
|
|
||||||
m_TagString: MainCamera
|
|
||||||
m_Icon: {fileID: 0}
|
|
||||||
m_NavMeshLayer: 0
|
|
||||||
m_StaticEditorFlags: 0
|
|
||||||
m_IsActive: 1
|
|
||||||
--- !u!81 &2106254872
|
|
||||||
AudioListener:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2106254871}
|
|
||||||
m_Enabled: 1
|
|
||||||
--- !u!124 &2106254873
|
|
||||||
Behaviour:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2106254871}
|
|
||||||
m_Enabled: 1
|
|
||||||
--- !u!20 &2106254875
|
|
||||||
Camera:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2106254871}
|
|
||||||
m_Enabled: 1
|
|
||||||
serializedVersion: 2
|
|
||||||
m_ClearFlags: 1
|
|
||||||
m_BackGroundColor: {r: 0.19215687, g: 0.3019608, b: 0.4745098, a: 0.019607844}
|
|
||||||
m_projectionMatrixMode: 1
|
|
||||||
m_GateFitMode: 2
|
|
||||||
m_FOVAxisMode: 0
|
|
||||||
m_SensorSize: {x: 36, y: 24}
|
|
||||||
m_LensShift: {x: 0, y: 0}
|
|
||||||
m_FocalLength: 50
|
|
||||||
m_NormalizedViewPortRect:
|
|
||||||
serializedVersion: 2
|
|
||||||
x: 0
|
|
||||||
y: 0
|
|
||||||
width: 1
|
|
||||||
height: 1
|
|
||||||
near clip plane: 0.3
|
|
||||||
far clip plane: 1000
|
|
||||||
field of view: 60
|
|
||||||
orthographic: 1
|
|
||||||
orthographic size: 5
|
|
||||||
m_Depth: -1
|
|
||||||
m_CullingMask:
|
|
||||||
serializedVersion: 2
|
|
||||||
m_Bits: 4294967295
|
|
||||||
m_RenderingPath: -1
|
|
||||||
m_TargetTexture: {fileID: 0}
|
|
||||||
m_TargetDisplay: 0
|
|
||||||
m_TargetEye: 3
|
|
||||||
m_HDR: 0
|
|
||||||
m_AllowMSAA: 1
|
|
||||||
m_AllowDynamicResolution: 0
|
|
||||||
m_ForceIntoRT: 0
|
|
||||||
m_OcclusionCulling: 1
|
|
||||||
m_StereoConvergence: 10
|
|
||||||
m_StereoSeparation: 0.022
|
|
||||||
--- !u!4 &2106254876
|
|
||||||
Transform:
|
|
||||||
m_ObjectHideFlags: 0
|
|
||||||
m_CorrespondingSourceObject: {fileID: 0}
|
|
||||||
m_PrefabInstance: {fileID: 0}
|
|
||||||
m_PrefabAsset: {fileID: 0}
|
|
||||||
m_GameObject: {fileID: 2106254871}
|
|
||||||
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
|
|
||||||
m_LocalPosition: {x: 0, y: 0, z: -10}
|
|
||||||
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}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 600e5d49b0a68254286400e32c53addc
|
|
||||||
timeCreated: 1468506358
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 25be027379f7fce4d97ba2bcaf313019
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1470780399
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b8c0d722519c64144a78f8fc99cd40b5
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1468505670
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,118 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c11944691f6b9cf44a391c95cb3f7dea
|
|
||||||
timeCreated: 1455050294
|
|
||||||
licenseType: Store
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,429 +0,0 @@
|
|||||||
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<string,SoundFX> soundFXCache = null;
|
|
||||||
|
|
||||||
static private AudioManager theAudioManager = null;
|
|
||||||
static private FastList<string> names = new FastList<string>();
|
|
||||||
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<string,SoundFX>( 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<AudioManager>() == null ) ) {
|
|
||||||
if ( !hideWarnings ) {
|
|
||||||
Debug.LogError( "[ERROR] AudioManager object missing from hierarchy!" );
|
|
||||||
hideWarnings = true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
} else {
|
|
||||||
audioManagerObject.GetComponent<AudioManager>().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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6d1d30b41806244fca035fdae2896fb7
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,798 +0,0 @@
|
|||||||
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<SoundEmitter> playingEmitters = new FastList<SoundEmitter>();
|
|
||||||
private FastList<SoundEmitter> nextFreeEmitters = new FastList<SoundEmitter>();
|
|
||||||
|
|
||||||
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 ) } );
|
|
||||||
|
|
||||||
// Calculate the maximum number of emitters that can be running at one time.
|
|
||||||
static private int CalculateMaxEmittersSize() {
|
|
||||||
return theAudioManager.maxSoundEmitters + (int)EmitterChannel.Any;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify if this index is valid
|
|
||||||
static private bool ValidateEmitterIndex(int index) {
|
|
||||||
return index > -1 && index < CalculateMaxEmittersSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------
|
|
||||||
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<AudioListener>() 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[CalculateMaxEmittersSize()];
|
|
||||||
|
|
||||||
// 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 < CalculateMaxEmittersSize(); 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<SoundEmitter>();
|
|
||||||
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 "<color=green>" + count.ToString() + "</color>";
|
|
||||||
} else if ( t < 0.7 ) {
|
|
||||||
return "<color=yellow>" + count.ToString() + "</color>";
|
|
||||||
} else {
|
|
||||||
return "<color=red>" + count.ToString() + "</color>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------
|
|
||||||
FmtFree()
|
|
||||||
-----------------------
|
|
||||||
*/
|
|
||||||
string FmtFree( int count ) {
|
|
||||||
float t = count / (float)theAudioManager.maxSoundEmitters;
|
|
||||||
if ( t < 0.2f ) {
|
|
||||||
return "<color=red>" + count.ToString() + "</color>";
|
|
||||||
} else if ( t < 0.3 ) {
|
|
||||||
return "<color=yellow>" + count.ToString() + "</color>";
|
|
||||||
} else {
|
|
||||||
return "<color=green>" + count.ToString() + "</color>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------
|
|
||||||
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 ( ValidateEmitterIndex(emitterIdx) ) {
|
|
||||||
theAudioManager.soundEmitters[emitterIdx].SetOnFinished( onFinished );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------
|
|
||||||
SetOnFinished()
|
|
||||||
-----------------------
|
|
||||||
*/
|
|
||||||
public static void SetOnFinished( int emitterIdx, System.Action<object> onFinished, object obj ) {
|
|
||||||
if ( ValidateEmitterIndex(emitterIdx) ) {
|
|
||||||
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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 41cb0f893e9a44e83b09a66c55bd7856
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 02213405caaf04aeea7876974c06fa5a
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
@ -1,46 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 48902580b26e3554d992bad48087eee5
|
|
||||||
timeCreated: 1471010515
|
|
||||||
licenseType: Store
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,631 +0,0 @@
|
|||||||
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<SoundGroup> soundGroups = new FastList<SoundGroup>();
|
|
||||||
private FastList<ItemRect> groups = new FastList<ItemRect>();
|
|
||||||
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<SoundFX> origSoundList = new List<SoundFX>( audioManager.soundGroupings[origGroup].soundList );
|
|
||||||
SoundFX temp = origSoundList[origIndex];
|
|
||||||
List<SoundFX> moveToSoundList = new List<SoundFX>( 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<SoundFX> soundList = new List<SoundFX>( 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<SoundFX> soundList = new List<SoundFX>( 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<SoundFX> soundList = new List<SoundFX>( audioManager.soundGroupings[selectedGroup].soundList );
|
|
||||||
soundList.RemoveAt( deleteSoundIdx );
|
|
||||||
audioManager.soundGroupings[selectedGroup].soundList = soundList.ToArray();
|
|
||||||
MarkDirty();
|
|
||||||
deleteSoundIdx = -1;
|
|
||||||
}
|
|
||||||
// duplicate a sound
|
|
||||||
if ( dupeSoundIdx > -1 ) {
|
|
||||||
List<SoundFX> soundList = new List<SoundFX>( audioManager.soundGroupings[selectedGroup].soundList );
|
|
||||||
SoundFX origSoundFX = soundList[dupeSoundIdx];
|
|
||||||
// clone this soundFX
|
|
||||||
string json = JsonUtility.ToJson( origSoundFX );
|
|
||||||
SoundFX soundFX = JsonUtility.FromJson<SoundFX>( 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<ItemRect> items = new FastList<ItemRect>();
|
|
||||||
|
|
||||||
/*
|
|
||||||
-----------------------
|
|
||||||
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 = "<b><size=11>" + text + "</size></b>";
|
|
||||||
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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9f04a80514947486d9793cab0005447f
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,70 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 225aed143a64c4a6a93f3a07656ac5cd
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 82a91f30f2305c14dbfd2cc3c289dc59
|
|
||||||
timeCreated: 1472247018
|
|
||||||
licenseType: Store
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,66 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 9fc79251b168140d68851f1e8c283514
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Oculus.AudioManager.Audio.Editor",
|
|
||||||
"rootNamespace": "",
|
|
||||||
"references": [
|
|
||||||
"Oculus.AudioManager"
|
|
||||||
],
|
|
||||||
"includePlatforms": [
|
|
||||||
"Editor"
|
|
||||||
],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e2367297a6c431949a05cf8078ad917d
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,67 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e791ce392b6937f47b1f7c90c6b402db
|
|
||||||
timeCreated: 1468857307
|
|
||||||
licenseType: Store
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,62 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6204bcaba636340b48858c9f10ab9016
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,26 +0,0 @@
|
|||||||
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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 15126f023faf44286a08bdb5bdbdb6e7
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,433 +0,0 @@
|
|||||||
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<object> 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<AudioSource>();
|
|
||||||
if ( audioSource == null ) {
|
|
||||||
audioSource = gameObject.AddComponent<AudioSource>();
|
|
||||||
}
|
|
||||||
// is the spatialized audio enabled?
|
|
||||||
if ( AudioManager.enableSpatialization && !disableSpatialization ) {
|
|
||||||
osp = GetComponent<ONSPAudioSource>();
|
|
||||||
if ( osp == null ) {
|
|
||||||
osp = gameObject.AddComponent<ONSPAudioSource>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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<object> 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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ecd24e91b27c645fc95f6c42115c13cc
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,311 +0,0 @@
|
|||||||
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<object> 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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b0a1e5e7b5cff46a187b02100f0e4a3c
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,144 +0,0 @@
|
|||||||
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<object> 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
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 48176edab546a48de9b146105d7c5f47
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 02268a883a27b9c4abac4ee978caec4d
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1468506022
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: b43e7f73d4ffc2545a17b938f63e6bc0
|
|
||||||
folderAsset: yes
|
|
||||||
timeCreated: 1468507225
|
|
||||||
licenseType: Store
|
|
||||||
DefaultImporter:
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,77 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f244e745a5bf8412d9d81d43dff35cf5
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Oculus.AudioManager.Utils.Editor",
|
|
||||||
"rootNamespace": "",
|
|
||||||
"references": [
|
|
||||||
"Oculus.AudioManager"
|
|
||||||
],
|
|
||||||
"includePlatforms": [
|
|
||||||
"Editor"
|
|
||||||
],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": false,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4e79697c263b8554db87efff0e7046ba
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,283 +0,0 @@
|
|||||||
using UnityEngine;
|
|
||||||
using System;
|
|
||||||
using System.Collections;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
public class FastList<T> {
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Comparison function should return -1 if left is less than right, 1 if left is greater than right, and 0 if they match.
|
|
||||||
/// </summary>
|
|
||||||
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<T> 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<T> GetEnumerator() {
|
|
||||||
if (array != null) {
|
|
||||||
for (int i = 0; i < size; i++) {
|
|
||||||
yield return array[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public T Find(Predicate<T> 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5ad95fb7eea735748bd34c963525ea21
|
|
||||||
timeCreated: 1432749689
|
|
||||||
licenseType: Store
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,35 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 4616bbe65d311471f8d71174295f4986
|
|
||||||
MonoImporter:
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 55135e1bc8a58a94eb578cf012e2b9cd
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e628d552f8b252d44815ffae12fd3976
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,540 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEngine;
|
|
||||||
using UnityEngine.Assertions;
|
|
||||||
using UnityEditor;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.Editor
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// A utility class for building custom editors with less work required.
|
|
||||||
/// </summary>
|
|
||||||
public class EditorBase : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
|
|
||||||
#region API
|
|
||||||
|
|
||||||
protected virtual void OnEnable() { }
|
|
||||||
|
|
||||||
protected virtual void OnDisable() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// You must put all of the editor specifications into OnInit
|
|
||||||
/// </summary>
|
|
||||||
protected virtual void OnInit() { }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit with one or more property names to hide them from the inspector.
|
|
||||||
///
|
|
||||||
/// This is preferable to using [HideInInspector] because it still allows the property to
|
|
||||||
/// be viewed when using the Inspector debug mode.
|
|
||||||
/// </summary>
|
|
||||||
protected void Hide(params string[] properties)
|
|
||||||
{
|
|
||||||
Assert.IsTrue(properties.Length > 0, "Should always hide at least one property.");
|
|
||||||
if (!ValidateProperties(properties))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_hiddenProperties.UnionWith(properties);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit with one or more property names to defer drawing them until after all
|
|
||||||
/// non-deferred properties have been drawn. All deferred properties will be drawn in the order
|
|
||||||
/// they are passed in to calls to Defer.
|
|
||||||
/// </summary>
|
|
||||||
protected void Defer(params string[] properties)
|
|
||||||
{
|
|
||||||
Assert.IsTrue(properties.Length > 0, "Should always defer at least one property.");
|
|
||||||
if (!ValidateProperties(properties))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var property in properties)
|
|
||||||
{
|
|
||||||
if (_deferredProperties.Contains(property))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
_deferredProperties.Add(property);
|
|
||||||
_deferredActions.Add(() =>
|
|
||||||
{
|
|
||||||
DrawProperty(serializedObject.FindProperty(property));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit with a single property name and a custom property drawer. Equivalent
|
|
||||||
/// to calling Draw and then Defer for the property.
|
|
||||||
/// </summary>
|
|
||||||
protected void Defer(string property, Action<SerializedProperty> customDrawer)
|
|
||||||
{
|
|
||||||
Draw(property, customDrawer);
|
|
||||||
Defer(property);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit with a single delegate to have it be called after all other non-deferred
|
|
||||||
/// properties have been drawn.
|
|
||||||
/// </summary>
|
|
||||||
protected void Defer(Action deferredAction)
|
|
||||||
{
|
|
||||||
_deferredActions.Add(deferredAction);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit to specify a custom drawer for a single property. Whenever the property is drawn,
|
|
||||||
/// it will use the provided property drawer instead of the default one.
|
|
||||||
/// </summary>
|
|
||||||
protected void Draw(string property, Action<SerializedProperty> drawer)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(property))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_customDrawers.Add(property, drawer);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit to specify a custom drawer for a single property. Include an extra property that gets
|
|
||||||
/// lumped in with the primary property. The extra property is not drawn normally, and is instead grouped in
|
|
||||||
/// with the primary property. Can be used in situations where a collection of properties need to be drawn together.
|
|
||||||
/// </summary>
|
|
||||||
protected void Draw(string property,
|
|
||||||
string withExtra0,
|
|
||||||
Action<SerializedProperty, SerializedProperty> drawer)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(property, withExtra0))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Hide(withExtra0);
|
|
||||||
Draw(property, p =>
|
|
||||||
{
|
|
||||||
drawer(p,
|
|
||||||
serializedObject.FindProperty(withExtra0));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Draw(string property,
|
|
||||||
string withExtra0,
|
|
||||||
string withExtra1,
|
|
||||||
Action<SerializedProperty, SerializedProperty, SerializedProperty> drawer)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(property, withExtra0, withExtra1))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Hide(withExtra0);
|
|
||||||
Hide(withExtra1);
|
|
||||||
Draw(property, p =>
|
|
||||||
{
|
|
||||||
drawer(p,
|
|
||||||
serializedObject.FindProperty(withExtra0),
|
|
||||||
serializedObject.FindProperty(withExtra1));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Draw(string property,
|
|
||||||
string withExtra0,
|
|
||||||
string withExtra1,
|
|
||||||
string withExtra2,
|
|
||||||
Action<SerializedProperty, SerializedProperty, SerializedProperty, SerializedProperty>
|
|
||||||
drawer)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(property, withExtra0, withExtra1, withExtra2))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Hide(withExtra0);
|
|
||||||
Hide(withExtra1);
|
|
||||||
Hide(withExtra2);
|
|
||||||
Draw(property, p =>
|
|
||||||
{
|
|
||||||
drawer(p,
|
|
||||||
serializedObject.FindProperty(withExtra0),
|
|
||||||
serializedObject.FindProperty(withExtra1),
|
|
||||||
serializedObject.FindProperty(withExtra2));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Draw(string property,
|
|
||||||
string withExtra0,
|
|
||||||
string withExtra1,
|
|
||||||
string withExtra2,
|
|
||||||
string withExtra3,
|
|
||||||
Action<SerializedProperty, SerializedProperty, SerializedProperty, SerializedProperty,
|
|
||||||
SerializedProperty> drawer)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(property, withExtra0, withExtra1, withExtra2, withExtra3))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Hide(withExtra0);
|
|
||||||
Hide(withExtra1);
|
|
||||||
Hide(withExtra2);
|
|
||||||
Hide(withExtra3);
|
|
||||||
Draw(property, p =>
|
|
||||||
{
|
|
||||||
drawer(p,
|
|
||||||
serializedObject.FindProperty(withExtra0),
|
|
||||||
serializedObject.FindProperty(withExtra1),
|
|
||||||
serializedObject.FindProperty(withExtra2),
|
|
||||||
serializedObject.FindProperty(withExtra3));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Conditional(string boolPropName, bool showIf, params string[] toHide)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(boolPropName) || !ValidateProperties(toHide))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var boolProp = serializedObject.FindProperty(boolPropName);
|
|
||||||
if (boolProp.propertyType != SerializedPropertyType.Boolean)
|
|
||||||
{
|
|
||||||
Debug.LogError(
|
|
||||||
$"Must provide a Boolean property to this Conditional method, but the property {boolPropName} had a type of {boolProp.propertyType}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Func<bool>> conditions;
|
|
||||||
foreach (var prop in toHide)
|
|
||||||
{
|
|
||||||
if (!_propertyDrawConditions.TryGetValue(prop, out conditions))
|
|
||||||
{
|
|
||||||
conditions = new List<Func<bool>>();
|
|
||||||
_propertyDrawConditions[prop] = conditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
conditions.Add(() =>
|
|
||||||
{
|
|
||||||
if (boolProp.hasMultipleDifferentValues)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return boolProp.boolValue == showIf;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void Conditional<T>(string enumPropName, T showIf, params string[] toHide)
|
|
||||||
where T : Enum
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(enumPropName) || !ValidateProperties(toHide))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var enumProp = serializedObject.FindProperty(enumPropName);
|
|
||||||
if (enumProp.propertyType != SerializedPropertyType.Enum)
|
|
||||||
{
|
|
||||||
Debug.LogError(
|
|
||||||
$"Must provide a Boolean property to this Conditional method, but the property {enumPropName} had a type of {enumProp.propertyType}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Func<bool>> conditions;
|
|
||||||
foreach (var prop in toHide)
|
|
||||||
{
|
|
||||||
if (!_propertyDrawConditions.TryGetValue(prop, out conditions))
|
|
||||||
{
|
|
||||||
conditions = new List<Func<bool>>();
|
|
||||||
_propertyDrawConditions[prop] = conditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
conditions.Add(() =>
|
|
||||||
{
|
|
||||||
if (enumProp.hasMultipleDifferentValues)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return enumProp.intValue == showIf.GetHashCode();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit to specify a custom decorator for a single property. Before a property is drawn,
|
|
||||||
/// all of the decorators will be drawn first.
|
|
||||||
/// </summary>
|
|
||||||
protected void Decorate(string property, Action<SerializedProperty> decorator)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(property))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Action<SerializedProperty>> decorators;
|
|
||||||
if (!_customDecorators.TryGetValue(property, out decorators))
|
|
||||||
{
|
|
||||||
decorators = new List<Action<SerializedProperty>>();
|
|
||||||
_customDecorators[property] = decorators;
|
|
||||||
}
|
|
||||||
|
|
||||||
decorators.Add(decorator);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Call in OnInit to specify a custom grouping behaviour for a range of properties. Specify the first
|
|
||||||
/// and last property (inclusive) and the action to take BEFORE the first property is drawn, and the action
|
|
||||||
/// to take AFTER the last property is drawn.
|
|
||||||
/// </summary>
|
|
||||||
protected void Group(string firstProperty, string lastProperty, Action beginGroup,
|
|
||||||
Action endGroup)
|
|
||||||
{
|
|
||||||
if (!ValidateProperties(firstProperty) || !ValidateProperties(lastProperty))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_groupBegins.Add(firstProperty, beginGroup);
|
|
||||||
_groupEnds.Add(lastProperty, endGroup);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// A utility version of the more generic Group method.
|
|
||||||
/// Call in OnInit to specify a range of properties that should be grouped within a styled vertical
|
|
||||||
/// layout group.
|
|
||||||
/// </summary>
|
|
||||||
protected void Group(string firstProperty, string lastProperty, GUIStyle style)
|
|
||||||
{
|
|
||||||
if (style == null)
|
|
||||||
{
|
|
||||||
Debug.LogError(
|
|
||||||
"Cannot provide a null style to EditorBase.Group. If you are acquiring a " +
|
|
||||||
"Style from the EditorStyles class, try calling Group from with on OnInit instead " +
|
|
||||||
"of from within OnEnable.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Group(firstProperty,
|
|
||||||
lastProperty,
|
|
||||||
() => EditorGUILayout.BeginVertical(style),
|
|
||||||
() => EditorGUILayout.EndVertical());
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Groups the given properties into a foldout with a given name.
|
|
||||||
/// </summary>
|
|
||||||
protected void Foldout(string firstProperty, string lastProperty, string foldoutName,
|
|
||||||
bool showByDefault = false)
|
|
||||||
{
|
|
||||||
Group(firstProperty,
|
|
||||||
lastProperty,
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
bool shouldShow;
|
|
||||||
if (!_foldouts.TryGetValue(foldoutName, out shouldShow))
|
|
||||||
{
|
|
||||||
shouldShow = showByDefault;
|
|
||||||
}
|
|
||||||
|
|
||||||
shouldShow = EditorGUILayout.Foldout(shouldShow, foldoutName);
|
|
||||||
|
|
||||||
_foldouts[foldoutName] = shouldShow;
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
|
|
||||||
_currentStates.Push(shouldShow);
|
|
||||||
},
|
|
||||||
() =>
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
_currentStates.Pop();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
protected virtual void OnBeforeInspector() { }
|
|
||||||
protected virtual void OnAfterInspector(bool anyPropertiesModified) { }
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region IMPLEMENTATION
|
|
||||||
|
|
||||||
[NonSerialized]
|
|
||||||
private bool _hasInitBeenCalled = false;
|
|
||||||
|
|
||||||
private HashSet<string> _hiddenProperties = new HashSet<string>();
|
|
||||||
private HashSet<string> _deferredProperties = new HashSet<string>();
|
|
||||||
private List<Action> _deferredActions = new List<Action>();
|
|
||||||
|
|
||||||
private Dictionary<string, bool> _foldouts = new Dictionary<string, bool>();
|
|
||||||
private Stack<bool> _currentStates = new Stack<bool>();
|
|
||||||
|
|
||||||
private Dictionary<string, Action<SerializedProperty>> _customDrawers =
|
|
||||||
new Dictionary<string, Action<SerializedProperty>>();
|
|
||||||
|
|
||||||
private Dictionary<string, List<Action<SerializedProperty>>> _customDecorators =
|
|
||||||
new Dictionary<string, List<Action<SerializedProperty>>>();
|
|
||||||
|
|
||||||
private Dictionary<string, Action> _groupBegins = new Dictionary<string, Action>();
|
|
||||||
private Dictionary<string, Action> _groupEnds = new Dictionary<string, Action>();
|
|
||||||
|
|
||||||
private Dictionary<string, List<Func<bool>>> _propertyDrawConditions =
|
|
||||||
new Dictionary<string, List<Func<bool>>>();
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
if (!_hasInitBeenCalled)
|
|
||||||
{
|
|
||||||
OnInit();
|
|
||||||
_hasInitBeenCalled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
SerializedProperty it = serializedObject.GetIterator();
|
|
||||||
it.NextVisible(enterChildren: true);
|
|
||||||
|
|
||||||
//Draw script header
|
|
||||||
EditorGUI.BeginDisabledGroup(true);
|
|
||||||
EditorGUILayout.PropertyField(it);
|
|
||||||
EditorGUI.EndDisabledGroup();
|
|
||||||
|
|
||||||
OnBeforeInspector();
|
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
|
|
||||||
while (it.NextVisible(enterChildren: false))
|
|
||||||
{
|
|
||||||
//Don't draw deferred properties in this pass, we will draw them after everything else
|
|
||||||
if (_deferredProperties.Contains(it.name))
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
DrawProperty(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var deferredAction in _deferredActions)
|
|
||||||
{
|
|
||||||
deferredAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool anyModified = EditorGUI.EndChangeCheck();
|
|
||||||
|
|
||||||
OnAfterInspector(anyModified);
|
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawProperty(SerializedProperty property)
|
|
||||||
{
|
|
||||||
Action groupBeginAction;
|
|
||||||
if (_groupBegins.TryGetValue(property.name, out groupBeginAction))
|
|
||||||
{
|
|
||||||
groupBeginAction();
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
//Don't draw if we are in a property that is currently hidden by a foldout
|
|
||||||
if (_currentStates.Any(s => s == false))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Don't draw hidden properties
|
|
||||||
if (_hiddenProperties.Contains(property.name))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
List<Func<bool>> conditions;
|
|
||||||
if (_propertyDrawConditions.TryGetValue(property.name, out conditions))
|
|
||||||
{
|
|
||||||
foreach (var condition in conditions)
|
|
||||||
{
|
|
||||||
if (!condition())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//First draw all decorators for the property
|
|
||||||
List<Action<SerializedProperty>> decorators;
|
|
||||||
if (_customDecorators.TryGetValue(property.name, out decorators))
|
|
||||||
{
|
|
||||||
foreach (var decorator in decorators)
|
|
||||||
{
|
|
||||||
decorator(property);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Then draw the property itself, using a custom drawer if needed
|
|
||||||
Action<SerializedProperty> customDrawer;
|
|
||||||
if (_customDrawers.TryGetValue(property.name, out customDrawer))
|
|
||||||
{
|
|
||||||
customDrawer(property);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
EditorGUILayout.PropertyField(property, includeChildren: true);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
Action groupEndAction;
|
|
||||||
if (_groupEnds.TryGetValue(property.name, out groupEndAction))
|
|
||||||
{
|
|
||||||
groupEndAction();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private bool ValidateProperties(params string[] properties)
|
|
||||||
{
|
|
||||||
foreach (var property in properties)
|
|
||||||
{
|
|
||||||
if (serializedObject.FindProperty(property) == null)
|
|
||||||
{
|
|
||||||
Debug.LogWarning(
|
|
||||||
$"Could not find property {property}, maybe it was deleted or renamed?");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 79ba2d579e9d1f14593db01074139346
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: c93e89dd55b481b4aa6ed62d6c8227bd
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Editor;
|
|
||||||
using Oculus.Interaction.Input;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.GrabAPI
|
|
||||||
{
|
|
||||||
[CustomPropertyDrawer(typeof(GrabbingRule))]
|
|
||||||
public class GrabbingRuleEditor : PropertyDrawer
|
|
||||||
{
|
|
||||||
private static Dictionary<string, bool> _unfolds = new Dictionary<string, bool>();
|
|
||||||
|
|
||||||
private static readonly string[] FINGER_PROPERTY_NAMES = new string[]
|
|
||||||
{
|
|
||||||
"_thumbRequirement",
|
|
||||||
"_indexRequirement",
|
|
||||||
"_middleRequirement",
|
|
||||||
"_ringRequirement",
|
|
||||||
"_pinkyRequirement",
|
|
||||||
};
|
|
||||||
|
|
||||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
InitializeUnfold(property);
|
|
||||||
if (_unfolds[property.propertyPath])
|
|
||||||
{
|
|
||||||
return EditorConstants.ROW_HEIGHT * (Constants.NUM_FINGERS + 2);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return EditorConstants.ROW_HEIGHT * 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginProperty(position, label, property);
|
|
||||||
|
|
||||||
InitializeUnfold(property);
|
|
||||||
Rect rowRect = new Rect(position.x, position.y, position.width, EditorConstants.ROW_HEIGHT);
|
|
||||||
_unfolds[property.propertyPath] = EditorGUI.Foldout(rowRect, _unfolds[property.propertyPath], label, true);
|
|
||||||
|
|
||||||
if (_unfolds[property.propertyPath])
|
|
||||||
{
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
for (int i = 0; i < Constants.NUM_FINGERS; i++)
|
|
||||||
{
|
|
||||||
rowRect.y += EditorConstants.ROW_HEIGHT;
|
|
||||||
SerializedProperty finger = property.FindPropertyRelative(FINGER_PROPERTY_NAMES[i]);
|
|
||||||
HandFinger fingerID = (HandFinger)i;
|
|
||||||
FingerRequirement current = (FingerRequirement)finger.intValue;
|
|
||||||
FingerRequirement selected = (FingerRequirement)EditorGUI.EnumPopup(rowRect, $"{fingerID}: ", current);
|
|
||||||
finger.intValue = (int)selected;
|
|
||||||
}
|
|
||||||
|
|
||||||
rowRect.y += EditorConstants.ROW_HEIGHT;
|
|
||||||
DrawFlagProperty<FingerUnselectMode>(property, rowRect, "Unselect Mode", "_unselectMode", false);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
EditorGUI.EndProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void InitializeUnfold(SerializedProperty property)
|
|
||||||
{
|
|
||||||
if (!_unfolds.ContainsKey(property.propertyPath))
|
|
||||||
{
|
|
||||||
_unfolds.Add(property.propertyPath, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawFlagProperty<TEnum>(SerializedProperty parentProperty, Rect position, string title, string fieldName, bool isFlags) where TEnum : Enum
|
|
||||||
{
|
|
||||||
SerializedProperty fieldProperty = parentProperty.FindPropertyRelative(fieldName);
|
|
||||||
TEnum value = (TEnum)Enum.ToObject(typeof(TEnum), fieldProperty.intValue);
|
|
||||||
Enum selectedValue = isFlags ?
|
|
||||||
EditorGUI.EnumFlagsField(position, title, value)
|
|
||||||
: EditorGUI.EnumPopup(position, title, value);
|
|
||||||
fieldProperty.intValue = (int)Enum.ToObject(typeof(TEnum), selectedValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 17f32e95fcaa23e45a5ac1297f201be2
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: f0d69d4b88de08343adc54816c3220a1
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using Oculus.Interaction.HandGrab.Visuals;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.HandGrab.Editor
|
|
||||||
{
|
|
||||||
public class HandGhostProviderUtils
|
|
||||||
{
|
|
||||||
public static bool TryGetDefaultProvider(out HandGhostProvider provider)
|
|
||||||
{
|
|
||||||
provider = null;
|
|
||||||
HandGhostProvider[] providers = Resources.FindObjectsOfTypeAll<HandGhostProvider>();
|
|
||||||
if (providers != null && providers.Length > 0)
|
|
||||||
{
|
|
||||||
provider = providers[0];
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] assets = AssetDatabase.FindAssets($"t:{nameof(HandGhostProvider)}");
|
|
||||||
if (assets != null && assets.Length > 0)
|
|
||||||
{
|
|
||||||
string pathPath = AssetDatabase.GUIDToAssetPath(assets[0]);
|
|
||||||
provider = AssetDatabase.LoadAssetAtPath<HandGhostProvider>(pathPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return provider != null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 62c8971cfb0b66040a9845cfc622ed6a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.HandGrab.Editor
|
|
||||||
{
|
|
||||||
[CanEditMultipleObjects]
|
|
||||||
[CustomEditor(typeof(HandGrabInteractable))]
|
|
||||||
public class HandGrabInteractableEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private HandGrabInteractable _interactable;
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_interactable = target as HandGrabInteractable;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
base.OnInspectorGUI();
|
|
||||||
|
|
||||||
DrawGrabPosesMenu();
|
|
||||||
GUILayout.Space(20f);
|
|
||||||
DrawGenerationMenu();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawGrabPosesMenu()
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Refresh HandGrab Pose"))
|
|
||||||
{
|
|
||||||
_interactable.HandGrabPoses.Clear();
|
|
||||||
HandGrabPose[] handGrabPoses = _interactable.GetComponentsInChildren<HandGrabPose>();
|
|
||||||
_interactable.HandGrabPoses.AddRange(handGrabPoses);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUILayout.Button("Add HandGrab Pose"))
|
|
||||||
{
|
|
||||||
if (_interactable.HandGrabPoses.Count > 0)
|
|
||||||
{
|
|
||||||
AddHandGrabPose(_interactable.HandGrabPoses[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
AddHandGrabPose();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUILayout.Button("Replicate Default Scaled HandGrab Pose"))
|
|
||||||
{
|
|
||||||
if (_interactable.HandGrabPoses.Count > 0)
|
|
||||||
{
|
|
||||||
AddHandGrabPose(_interactable.HandGrabPoses[0], 0.8f);
|
|
||||||
AddHandGrabPose(_interactable.HandGrabPoses[0], 1.2f);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.LogError("You have to provide a default HandGrabPose first!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddHandGrabPose(HandGrabPose copy = null, float? scale = null)
|
|
||||||
{
|
|
||||||
HandGrabPose point = _interactable.CreatePoint();
|
|
||||||
if (copy != null)
|
|
||||||
{
|
|
||||||
HandGrabPoseEditor.CloneHandGrabPose(copy, point);
|
|
||||||
if (scale.HasValue)
|
|
||||||
{
|
|
||||||
HandGrabPoseData scaledData = point.SaveData();
|
|
||||||
scaledData.scale = scale.Value;
|
|
||||||
point.LoadData(scaledData, copy.RelativeTo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_interactable.HandGrabPoses.Add(point);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawGenerationMenu()
|
|
||||||
{
|
|
||||||
if (GUILayout.Button("Create Mirrored HandGrabInteractable"))
|
|
||||||
{
|
|
||||||
HandGrabInteractable mirrorInteractable =
|
|
||||||
HandGrabInteractable.Create(_interactable.RelativeTo,
|
|
||||||
$"{_interactable.gameObject.name}_mirror");
|
|
||||||
|
|
||||||
HandGrabInteractableData data = _interactable.SaveData();
|
|
||||||
data.poses = null;
|
|
||||||
mirrorInteractable.LoadData(data);
|
|
||||||
|
|
||||||
foreach (HandGrabPose point in _interactable.HandGrabPoses)
|
|
||||||
{
|
|
||||||
HandGrabPose mirrorPoint = mirrorInteractable.CreatePoint();
|
|
||||||
HandGrabPoseEditor.Mirror(point, mirrorPoint);
|
|
||||||
mirrorPoint.transform.SetParent(mirrorInteractable.transform);
|
|
||||||
mirrorInteractable.HandGrabPoses.Add(mirrorPoint);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: e5ce7770848930447885c9abba8bb99a
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,291 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Editor;
|
|
||||||
using Oculus.Interaction.HandGrab.Visuals;
|
|
||||||
using Oculus.Interaction.Input;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.HandGrab.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(HandGrabPose))]
|
|
||||||
public class HandGrabPoseEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private HandGrabPose _handGrabPose;
|
|
||||||
|
|
||||||
private HandGhostProvider _ghostVisualsProvider;
|
|
||||||
private HandGhost _handGhost;
|
|
||||||
private Handedness _lastHandedness;
|
|
||||||
|
|
||||||
private int _editMode = 0;
|
|
||||||
private SerializedProperty _handPoseProperty;
|
|
||||||
|
|
||||||
private const float GIZMO_SCALE = 0.005f;
|
|
||||||
private static readonly string[] EDIT_MODES = new string[] { "Edit fingers", "Follow Surface" };
|
|
||||||
|
|
||||||
private void Awake()
|
|
||||||
{
|
|
||||||
_handGrabPose = target as HandGrabPose;
|
|
||||||
_handPoseProperty = serializedObject.FindProperty("_handPose");
|
|
||||||
AssignMissingGhostProvider();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnDestroy()
|
|
||||||
{
|
|
||||||
DestroyGhost();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
base.OnInspectorGUI();
|
|
||||||
|
|
||||||
if (_handGrabPose.HandPose != null
|
|
||||||
&& _handPoseProperty != null)
|
|
||||||
{
|
|
||||||
EditorGUILayout.PropertyField(_handPoseProperty);
|
|
||||||
EditorGUILayout.Space();
|
|
||||||
DrawGhostMenu(_handGrabPose.HandPose, false);
|
|
||||||
}
|
|
||||||
else if (_handGhost != null)
|
|
||||||
{
|
|
||||||
DestroyGhost();
|
|
||||||
}
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawGhostMenu(HandPose handPose, bool forceCreate)
|
|
||||||
{
|
|
||||||
GUIStyle boldStyle = new GUIStyle(GUI.skin.label) { fontStyle = FontStyle.Bold };
|
|
||||||
EditorGUILayout.LabelField("Interactive Edition", boldStyle);
|
|
||||||
|
|
||||||
HandGhostProvider provider = EditorGUILayout.ObjectField("Ghost Provider", _ghostVisualsProvider, typeof(HandGhostProvider), false) as HandGhostProvider;
|
|
||||||
if (forceCreate
|
|
||||||
|| provider != _ghostVisualsProvider
|
|
||||||
|| _handGhost == null
|
|
||||||
|| _lastHandedness != handPose.Handedness)
|
|
||||||
{
|
|
||||||
RegenerateGhost(provider);
|
|
||||||
}
|
|
||||||
_lastHandedness = handPose.Handedness;
|
|
||||||
|
|
||||||
if (_handGrabPose.SnapSurface == null)
|
|
||||||
{
|
|
||||||
_editMode = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_editMode = GUILayout.Toolbar(_editMode, EDIT_MODES);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSceneGUI()
|
|
||||||
{
|
|
||||||
if (SceneView.currentDrawingSceneView == null
|
|
||||||
|| _handGhost == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_editMode == 0)
|
|
||||||
{
|
|
||||||
GhostEditFingers();
|
|
||||||
}
|
|
||||||
else if (_editMode == 1)
|
|
||||||
{
|
|
||||||
GhostFollowSurface();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#region generation
|
|
||||||
/// <summary>
|
|
||||||
/// Generates a new HandGrabPoseData that mirrors the provided one. Left hand becomes right hand and vice-versa.
|
|
||||||
/// The mirror axis is defined by the surface of the snap point, if any, if none a best-guess is provided
|
|
||||||
/// but note that it can then moved manually in the editor.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="originalPoint">The point to mirror</param>
|
|
||||||
/// <param name="originalPoint">The target HandGrabPose to set as mirrored of the originalPoint</param>
|
|
||||||
public static void Mirror(HandGrabPose originalPoint, HandGrabPose mirrorPoint)
|
|
||||||
{
|
|
||||||
HandPose handPose = originalPoint.HandPose;
|
|
||||||
|
|
||||||
Handedness oppositeHandedness = handPose.Handedness == Handedness.Left ? Handedness.Right : Handedness.Left;
|
|
||||||
|
|
||||||
HandGrabPoseData mirrorData = originalPoint.SaveData();
|
|
||||||
mirrorData.handPose.Handedness = oppositeHandedness;
|
|
||||||
|
|
||||||
if (originalPoint.SnapSurface != null)
|
|
||||||
{
|
|
||||||
mirrorData.gripPose = originalPoint.SnapSurface.MirrorPose(mirrorData.gripPose);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mirrorData.gripPose = mirrorData.gripPose.MirrorPoseRotation(Vector3.forward, Vector3.up);
|
|
||||||
Vector3 translation = Vector3.Project(mirrorData.gripPose.position, Vector3.right);
|
|
||||||
mirrorData.gripPose.position = mirrorData.gripPose.position - 2f * translation;
|
|
||||||
}
|
|
||||||
|
|
||||||
mirrorPoint.LoadData(mirrorData, originalPoint.RelativeTo);
|
|
||||||
if (originalPoint.SnapSurface != null)
|
|
||||||
{
|
|
||||||
Grab.GrabSurfaces.IGrabSurface mirroredSurface = originalPoint.SnapSurface.CreateMirroredSurface(mirrorPoint.gameObject);
|
|
||||||
mirrorPoint.InjectOptionalSurface(mirroredSurface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void CloneHandGrabPose(HandGrabPose originalPoint, HandGrabPose targetPoint)
|
|
||||||
{
|
|
||||||
HandGrabPoseData mirrorData = originalPoint.SaveData();
|
|
||||||
targetPoint.LoadData(mirrorData, originalPoint.RelativeTo);
|
|
||||||
if (originalPoint.SnapSurface != null)
|
|
||||||
{
|
|
||||||
Grab.GrabSurfaces.IGrabSurface mirroredSurface = originalPoint.SnapSurface.CreateDuplicatedSurface(targetPoint.gameObject);
|
|
||||||
targetPoint.InjectOptionalSurface(mirroredSurface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region ghost
|
|
||||||
|
|
||||||
private void AssignMissingGhostProvider()
|
|
||||||
{
|
|
||||||
if (_ghostVisualsProvider != null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandGhostProviderUtils.TryGetDefaultProvider(out _ghostVisualsProvider);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegenerateGhost(HandGhostProvider provider)
|
|
||||||
{
|
|
||||||
_ghostVisualsProvider = provider;
|
|
||||||
DestroyGhost();
|
|
||||||
CreateGhost();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void CreateGhost()
|
|
||||||
{
|
|
||||||
if (_ghostVisualsProvider == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandGhost ghostPrototype = _ghostVisualsProvider.GetHand(_handGrabPose.HandPose.Handedness);
|
|
||||||
_handGhost = GameObject.Instantiate(ghostPrototype, _handGrabPose.transform);
|
|
||||||
_handGhost.gameObject.hideFlags = HideFlags.HideAndDontSave;
|
|
||||||
_handGhost.SetPose(_handGrabPose);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DestroyGhost()
|
|
||||||
{
|
|
||||||
if (_handGhost == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
GameObject.DestroyImmediate(_handGhost.gameObject);
|
|
||||||
_handGhost = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GhostFollowSurface()
|
|
||||||
{
|
|
||||||
if (_handGhost == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pose ghostTargetPose = _handGrabPose.RelativeGrip;
|
|
||||||
|
|
||||||
if (_handGrabPose.SnapSurface != null)
|
|
||||||
{
|
|
||||||
Vector3 mousePosition = Event.current.mousePosition;
|
|
||||||
Ray ray = HandleUtility.GUIPointToWorldRay(mousePosition);
|
|
||||||
Pose recorderPose = _handGrabPose.transform.GetPose();
|
|
||||||
if (_handGrabPose.SnapSurface.CalculateBestPoseAtSurface(ray, recorderPose, out Pose target))
|
|
||||||
{
|
|
||||||
_handGrabPose.RelativeTo.Delta(target, ref ghostTargetPose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_handGhost.SetRootPose(ghostTargetPose, _handGrabPose.RelativeTo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void GhostEditFingers()
|
|
||||||
{
|
|
||||||
HandPuppet puppet = _handGhost.GetComponent<HandPuppet>();
|
|
||||||
if (puppet != null && puppet.JointMaps != null)
|
|
||||||
{
|
|
||||||
DrawBonesRotator(puppet.JointMaps);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawBonesRotator(List<HandJointMap> bones)
|
|
||||||
{
|
|
||||||
bool changed = false;
|
|
||||||
for (int i = 0; i < FingersMetadata.HAND_JOINT_IDS.Length; i++)
|
|
||||||
{
|
|
||||||
HandJointId joint = FingersMetadata.HAND_JOINT_IDS[i];
|
|
||||||
HandFinger finger = FingersMetadata.JOINT_TO_FINGER[(int)joint];
|
|
||||||
|
|
||||||
if (_handGrabPose.HandPose.FingersFreedom[(int)finger] == JointFreedom.Free)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
HandJointMap jointMap = bones.Find(b => b.id == joint);
|
|
||||||
if (jointMap == null)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform transform = jointMap.transform;
|
|
||||||
transform.localRotation = jointMap.RotationOffset * _handGrabPose.HandPose.JointRotations[i];
|
|
||||||
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
Quaternion rotation = Handles.Disc(transform.rotation, transform.position,
|
|
||||||
transform.forward, GIZMO_SCALE, false, 0);
|
|
||||||
|
|
||||||
if (FingersMetadata.HAND_JOINT_CAN_SPREAD[i])
|
|
||||||
{
|
|
||||||
Handles.color = EditorConstants.SECONDARY_COLOR;
|
|
||||||
rotation = Handles.Disc(rotation, transform.position,
|
|
||||||
transform.up, GIZMO_SCALE, false, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
transform.rotation = rotation;
|
|
||||||
Quaternion finalRot = jointMap.TrackedRotation;
|
|
||||||
if (_handGrabPose.HandPose.JointRotations[i] != finalRot)
|
|
||||||
{
|
|
||||||
Undo.RecordObject(_handGrabPose, "Bone Rotation");
|
|
||||||
_handGrabPose.HandPose.JointRotations[i] = finalRot;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changed)
|
|
||||||
{
|
|
||||||
EditorUtility.SetDirty(_handGrabPose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 92b8a050249b4ea47b9da8fe38ed12a1
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Editor;
|
|
||||||
using Oculus.Interaction.Input;
|
|
||||||
using System;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.HandGrab.Editor
|
|
||||||
{
|
|
||||||
[CustomPropertyDrawer(typeof(HandPose))]
|
|
||||||
public class HandPoseEditor : PropertyDrawer
|
|
||||||
{
|
|
||||||
private bool _foldedFreedom = true;
|
|
||||||
private bool _foldedRotations = false;
|
|
||||||
|
|
||||||
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
float multiplier = 4;
|
|
||||||
|
|
||||||
if (_foldedFreedom)
|
|
||||||
{
|
|
||||||
multiplier += Constants.NUM_FINGERS;
|
|
||||||
}
|
|
||||||
if (_foldedRotations)
|
|
||||||
{
|
|
||||||
multiplier += FingersMetadata.HAND_JOINT_IDS.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
return EditorConstants.ROW_HEIGHT * multiplier;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginProperty(position, label, property);
|
|
||||||
Rect labelPos = EditorGUI.PrefixLabel(position, GUIUtility.GetControlID(FocusType.Passive), label);
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
|
|
||||||
Rect rowRect = new Rect(position.x, labelPos.y + EditorConstants.ROW_HEIGHT, position.width, EditorConstants.ROW_HEIGHT);
|
|
||||||
DrawFlagProperty<Handedness>(property, rowRect, "Handedness:", "_handedness", false);
|
|
||||||
rowRect.y += EditorConstants.ROW_HEIGHT;
|
|
||||||
rowRect = DrawFingersFreedomMenu(property, rowRect);
|
|
||||||
rowRect = DrawJointAngles(property, rowRect);
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
EditorGUI.EndProperty();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Rect DrawFingersFreedomMenu(SerializedProperty property, Rect position)
|
|
||||||
{
|
|
||||||
_foldedFreedom = EditorGUI.Foldout(position, _foldedFreedom, "Fingers Freedom", true);
|
|
||||||
position.y += EditorConstants.ROW_HEIGHT;
|
|
||||||
if (_foldedFreedom)
|
|
||||||
{
|
|
||||||
SerializedProperty fingersFreedom = property.FindPropertyRelative("_fingersFreedom");
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
for (int i = 0; i < Constants.NUM_FINGERS; i++)
|
|
||||||
{
|
|
||||||
SerializedProperty finger = fingersFreedom.GetArrayElementAtIndex(i);
|
|
||||||
HandFinger fingerID = (HandFinger)i;
|
|
||||||
JointFreedom current = (JointFreedom)finger.intValue;
|
|
||||||
JointFreedom selected = (JointFreedom)EditorGUI.EnumPopup(position, $"{fingerID}", current);
|
|
||||||
finger.intValue = (int)selected;
|
|
||||||
position.y += EditorConstants.ROW_HEIGHT;
|
|
||||||
}
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Rect DrawJointAngles(SerializedProperty property, Rect position)
|
|
||||||
{
|
|
||||||
_foldedRotations = EditorGUI.Foldout(position, _foldedRotations, "Joint Angles", true);
|
|
||||||
position.y += EditorConstants.ROW_HEIGHT;
|
|
||||||
if (_foldedRotations)
|
|
||||||
{
|
|
||||||
SerializedProperty jointRotations = property.FindPropertyRelative("_jointRotations");
|
|
||||||
EditorGUI.indentLevel++;
|
|
||||||
for (int i = 0; i < FingersMetadata.HAND_JOINT_IDS.Length; i++)
|
|
||||||
{
|
|
||||||
SerializedProperty finger = jointRotations.GetArrayElementAtIndex(i);
|
|
||||||
HandJointId jointID = FingersMetadata.HAND_JOINT_IDS[i];
|
|
||||||
Vector3 current = finger.quaternionValue.eulerAngles;
|
|
||||||
Vector3 rotation = EditorGUI.Vector3Field(position, $"{jointID}", current);
|
|
||||||
finger.quaternionValue = Quaternion.Euler(rotation);
|
|
||||||
position.y += EditorConstants.ROW_HEIGHT;
|
|
||||||
}
|
|
||||||
EditorGUI.indentLevel--;
|
|
||||||
}
|
|
||||||
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawFlagProperty<TEnum>(SerializedProperty parentProperty, Rect position, string title, string fieldName, bool isFlags) where TEnum : Enum
|
|
||||||
{
|
|
||||||
SerializedProperty fieldProperty = parentProperty.FindPropertyRelative(fieldName);
|
|
||||||
TEnum value = (TEnum)Enum.ToObject(typeof(TEnum), fieldProperty.intValue);
|
|
||||||
Enum selectedValue = isFlags ?
|
|
||||||
EditorGUI.EnumFlagsField(position, title, value)
|
|
||||||
: EditorGUI.EnumPopup(position, title, value);
|
|
||||||
fieldProperty.intValue = (int)Enum.ToObject(typeof(TEnum), selectedValue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 25b4f8dbe894a92489fe06cc956a42e0
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,83 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 System.Collections.Generic;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.HandGrab.Editor
|
|
||||||
{
|
|
||||||
public class HandWristOffsetUndoWizard : ScriptableWizard
|
|
||||||
{
|
|
||||||
[SerializeField]
|
|
||||||
private HandWristOffset _wristOffset;
|
|
||||||
|
|
||||||
[SerializeField]
|
|
||||||
private HandGrabPose _grabPose;
|
|
||||||
|
|
||||||
[MenuItem("Oculus/Interaction/HandWristOffset Undo Wizard")]
|
|
||||||
private static void CreateWizard()
|
|
||||||
{
|
|
||||||
ScriptableWizard.DisplayWizard<HandWristOffsetUndoWizard>("HandWristOffset Undo Wizard", "Close", "Undo Offset");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWizardCreate()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnWizardOtherButton()
|
|
||||||
{
|
|
||||||
List<HandGrabPose> children = new List<HandGrabPose>(_grabPose.GetComponentsInChildren<HandGrabPose>());
|
|
||||||
children.Remove(_grabPose);
|
|
||||||
foreach (HandGrabPose childPoint in children)
|
|
||||||
{
|
|
||||||
if (childPoint == _grabPose)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
childPoint.transform.SetParent(_grabPose.transform.parent, true);
|
|
||||||
UndoOffset(childPoint);
|
|
||||||
}
|
|
||||||
|
|
||||||
UndoOffset(_grabPose);
|
|
||||||
|
|
||||||
foreach (HandGrabPose childPoint in children)
|
|
||||||
{
|
|
||||||
childPoint.transform.SetParent(_grabPose.transform, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UndoOffset(HandGrabPose grabPose)
|
|
||||||
{
|
|
||||||
Pose offset = Pose.identity;
|
|
||||||
_wristOffset.GetOffset(ref offset, grabPose.HandPose.Handedness, grabPose.transform.localScale.x);
|
|
||||||
offset.Invert();
|
|
||||||
|
|
||||||
Undo.RecordObject(grabPose.transform, "Transform Changed");
|
|
||||||
Pose pose = grabPose.transform.GetPose(Space.Self);
|
|
||||||
pose.Premultiply(offset);
|
|
||||||
grabPose.transform.SetPose(pose, Space.Self);
|
|
||||||
EditorUtility.SetDirty(grabPose.transform);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 070da65b3b3353149bcd22ecad3b01ef
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: eef729dcc033d3e419718da8e409c0f3
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,278 +0,0 @@
|
|||||||
/************************************************************************************
|
|
||||||
Copyright : Copyright (c) Facebook Technologies, LLC and its affiliates. All rights reserved.
|
|
||||||
|
|
||||||
Your use of this SDK or tool is subject to the Oculus SDK License Agreement, available at
|
|
||||||
https://developer.oculus.com/licenses/oculussdk/
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, the Utilities 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 Oculus.Interaction.Editor;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.Grab.GrabSurfaces.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(BezierGrabSurface))]
|
|
||||||
[CanEditMultipleObjects]
|
|
||||||
public class BezierGrabSurfaceEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private BezierGrabSurface _surface;
|
|
||||||
private SerializedProperty _relativeToProperty;
|
|
||||||
|
|
||||||
private bool IsSelectedIndexValid => _selectedIndex >= 0 && _selectedIndex < _surface.ControlPoints.Count;
|
|
||||||
|
|
||||||
private int _selectedIndex = -1;
|
|
||||||
private const float PICK_SIZE = 0.1f;
|
|
||||||
private const float AXIS_SIZE = 0.5f;
|
|
||||||
private const int CURVE_STEPS = 50;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_surface = (target as BezierGrabSurface);
|
|
||||||
_relativeToProperty = serializedObject.FindProperty("_relativeTo");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
base.OnInspectorGUI();
|
|
||||||
|
|
||||||
if (GUILayout.Button("Add ControlPoint At Start"))
|
|
||||||
{
|
|
||||||
AddControlPoint(true);
|
|
||||||
}
|
|
||||||
if (GUILayout.Button("Add ControlPoint At End"))
|
|
||||||
{
|
|
||||||
AddControlPoint(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!IsSelectedIndexValid)
|
|
||||||
{
|
|
||||||
_selectedIndex = -1;
|
|
||||||
GUILayout.Label($"No Selected Point");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
GUILayout.Label($"Selected Point: {_selectedIndex}");
|
|
||||||
if (GUILayout.Button("Align Selected Tangent"))
|
|
||||||
{
|
|
||||||
AlignTangent(_selectedIndex);
|
|
||||||
}
|
|
||||||
if (GUILayout.Button("Smooth Selected Tangent"))
|
|
||||||
{
|
|
||||||
SmoothTangent(_selectedIndex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void OnSceneGUI()
|
|
||||||
{
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
|
|
||||||
Transform relative = _relativeToProperty.objectReferenceValue as Transform ?? _surface.transform;
|
|
||||||
Pose relativePose = relative.GetPose();
|
|
||||||
DrawEndsCaps(_surface.ControlPoints, relativePose);
|
|
||||||
if (Event.current.type == EventType.Repaint)
|
|
||||||
{
|
|
||||||
DrawCurve(_surface.ControlPoints, relativePose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AddControlPoint(bool addFirst)
|
|
||||||
{
|
|
||||||
BezierControlPoint controlPoint = BezierControlPoint.DEFAULT;
|
|
||||||
if (_surface.ControlPoints.Count == 1)
|
|
||||||
{
|
|
||||||
controlPoint = _surface.ControlPoints[0];
|
|
||||||
controlPoint.pose.position += Vector3.forward;
|
|
||||||
}
|
|
||||||
else if (_surface.ControlPoints.Count > 1)
|
|
||||||
{
|
|
||||||
BezierControlPoint firstControlPoint;
|
|
||||||
BezierControlPoint secondControlPoint;
|
|
||||||
if (addFirst)
|
|
||||||
{
|
|
||||||
firstControlPoint = _surface.ControlPoints[1];
|
|
||||||
secondControlPoint = _surface.ControlPoints[0];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
firstControlPoint = _surface.ControlPoints[_surface.ControlPoints.Count - 2];
|
|
||||||
secondControlPoint = _surface.ControlPoints[_surface.ControlPoints.Count - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
controlPoint.pose.position = 2 * secondControlPoint.pose.position - firstControlPoint.pose.position;
|
|
||||||
controlPoint.pose.rotation = secondControlPoint.pose.rotation;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addFirst)
|
|
||||||
{
|
|
||||||
_surface.ControlPoints.Insert(0, controlPoint);
|
|
||||||
_selectedIndex = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_surface.ControlPoints.Add(controlPoint);
|
|
||||||
_selectedIndex = _surface.ControlPoints.Count - 1;
|
|
||||||
}
|
|
||||||
AlignTangent(_selectedIndex);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AlignTangent(int index)
|
|
||||||
{
|
|
||||||
BezierControlPoint controlPoint = _surface.ControlPoints[index];
|
|
||||||
BezierControlPoint nextControlPoint = _surface.ControlPoints[(index + 1) % _surface.ControlPoints.Count];
|
|
||||||
|
|
||||||
controlPoint.tangentPoint = (nextControlPoint.pose.position - controlPoint.pose.position) * 0.5f;
|
|
||||||
_surface.ControlPoints[index] = controlPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void SmoothTangent(int index)
|
|
||||||
{
|
|
||||||
BezierControlPoint controlPoint = _surface.ControlPoints[index];
|
|
||||||
BezierControlPoint prevControlPoint = _surface.ControlPoints[(index + _surface.ControlPoints.Count - 1) % _surface.ControlPoints.Count];
|
|
||||||
|
|
||||||
Vector3 prevTangent = prevControlPoint.pose.position + prevControlPoint.tangentPoint;
|
|
||||||
controlPoint.tangentPoint = (controlPoint.pose.position - prevTangent) * 0.5f;
|
|
||||||
_surface.ControlPoints[index] = controlPoint;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawEndsCaps(List<BezierControlPoint> controlPoints, in Pose relativePose)
|
|
||||||
{
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
for (int i = 0; i < controlPoints.Count; i++)
|
|
||||||
{
|
|
||||||
DrawControlPoint(i, relativePose);
|
|
||||||
}
|
|
||||||
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR_DISABLED;
|
|
||||||
if (IsSelectedIndexValid)
|
|
||||||
{
|
|
||||||
DrawControlPointHandles(_selectedIndex, relativePose);
|
|
||||||
DrawTangentLine(_selectedIndex, relativePose);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawCurve(List<BezierControlPoint> controlPoints, in Pose relativePose)
|
|
||||||
{
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
for (int i = 0; i < controlPoints.Count && controlPoints.Count > 1; i++)
|
|
||||||
{
|
|
||||||
BezierControlPoint fromControlPoint = _surface.ControlPoints[i];
|
|
||||||
Pose from = fromControlPoint.WorldSpacePose(relativePose);
|
|
||||||
|
|
||||||
BezierControlPoint toControlPoint = _surface.ControlPoints[(i + 1) % controlPoints.Count];
|
|
||||||
if (toControlPoint.disconnected)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
Pose to = toControlPoint.WorldSpacePose(relativePose);
|
|
||||||
Vector3 tangent = from.position + relativePose.rotation * fromControlPoint.tangentPoint;
|
|
||||||
DrawBezier(from.position, tangent, to.position, CURVE_STEPS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawBezier(Vector3 start, Vector3 middle, Vector3 end, int steps)
|
|
||||||
{
|
|
||||||
Vector3 from = start;
|
|
||||||
Vector3 to;
|
|
||||||
float t;
|
|
||||||
for (int i = 1; i < steps; i++)
|
|
||||||
{
|
|
||||||
t = i / (steps - 1f);
|
|
||||||
to = BezierGrabSurface.EvaluateBezier(start, middle, end, t);
|
|
||||||
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
Handles.DrawLine(from, to, EditorConstants.LINE_THICKNESS);
|
|
||||||
#else
|
|
||||||
Handles.DrawLine(from, to);
|
|
||||||
#endif
|
|
||||||
from = to;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawTangentLine(int index, in Pose relativePose)
|
|
||||||
{
|
|
||||||
BezierControlPoint controlPoint = _surface.ControlPoints[index];
|
|
||||||
Pose pose = controlPoint.WorldSpacePose(relativePose);
|
|
||||||
Vector3 center = pose.position;
|
|
||||||
Vector3 tangent = pose.position + relativePose.rotation * controlPoint.tangentPoint;
|
|
||||||
|
|
||||||
#if UNITY_2020_2_OR_NEWER
|
|
||||||
Handles.DrawLine(center, tangent, EditorConstants.LINE_THICKNESS);
|
|
||||||
#else
|
|
||||||
Handles.DrawLine(center, tangent);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawControlPoint(int index, in Pose relativePose)
|
|
||||||
{
|
|
||||||
BezierControlPoint controlPoint = _surface.ControlPoints[index];
|
|
||||||
Pose pose = controlPoint.WorldSpacePose(relativePose);
|
|
||||||
float handleSize = HandleUtility.GetHandleSize(pose.position);
|
|
||||||
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
if (Handles.Button(pose.position, pose.rotation, handleSize * PICK_SIZE, handleSize * PICK_SIZE, Handles.DotHandleCap))
|
|
||||||
{
|
|
||||||
_selectedIndex = index;
|
|
||||||
}
|
|
||||||
|
|
||||||
Handles.color = Color.red;
|
|
||||||
Handles.DrawLine(pose.position, pose.position + pose.right * handleSize * AXIS_SIZE);
|
|
||||||
Handles.color = Color.green;
|
|
||||||
Handles.DrawLine(pose.position, pose.position + pose.up * handleSize * AXIS_SIZE);
|
|
||||||
Handles.color = Color.blue;
|
|
||||||
Handles.DrawLine(pose.position, pose.position + pose.forward * handleSize * AXIS_SIZE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawControlPointHandles(int index, in Pose relativePose)
|
|
||||||
{
|
|
||||||
BezierControlPoint controlPoint = _surface.ControlPoints[index];
|
|
||||||
Pose pose = controlPoint.WorldSpacePose(relativePose);
|
|
||||||
if (Tools.current == Tool.Move)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
Quaternion pointRotation = Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : pose.rotation;
|
|
||||||
pose.position = Handles.PositionHandle(pose.position, pointRotation);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(_surface, "Change ControlPoint Position");
|
|
||||||
controlPoint.pose.position = Quaternion.Inverse(relativePose.rotation) * (pose.position - relativePose.position);
|
|
||||||
_surface.ControlPoints[index] = controlPoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (Tools.current == Tool.Rotate)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
pose.rotation = Handles.RotationHandle(pose.rotation, pose.position);
|
|
||||||
pose.rotation.Normalize();
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(_surface, "Change ControlPoint Rotation");
|
|
||||||
controlPoint.pose.rotation = (Quaternion.Inverse(relativePose.rotation) * pose.rotation);
|
|
||||||
_surface.ControlPoints[index] = controlPoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector3 tangent = pose.position + relativePose.rotation * controlPoint.tangentPoint;
|
|
||||||
Quaternion tangentRotation = Tools.pivotRotation == PivotRotation.Global ? Quaternion.identity : relativePose.rotation;
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
tangent = Handles.PositionHandle(tangent, tangentRotation);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(_surface, "Change ControlPoint Tangent");
|
|
||||||
controlPoint.tangentPoint = Quaternion.Inverse(relativePose.rotation) * (tangent - pose.position);
|
|
||||||
_surface.ControlPoints[index] = controlPoint;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 718688abdc60caa4984fe98623ff42dd
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Editor;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.IMGUI.Controls;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.Grab.GrabSurfaces.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(BoxGrabSurface))]
|
|
||||||
[CanEditMultipleObjects]
|
|
||||||
public class BoxGrabSurfaceEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private BoxBoundsHandle _boxHandle = new BoxBoundsHandle();
|
|
||||||
private BoxGrabSurface _surface;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_boxHandle.handleColor = EditorConstants.PRIMARY_COLOR;
|
|
||||||
_boxHandle.wireframeColor = EditorConstants.PRIMARY_COLOR_DISABLED;
|
|
||||||
_boxHandle.axes = PrimitiveBoundsHandle.Axes.X | PrimitiveBoundsHandle.Axes.Z;
|
|
||||||
|
|
||||||
_surface = (target as BoxGrabSurface);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSceneGUI()
|
|
||||||
{
|
|
||||||
DrawRotator(_surface);
|
|
||||||
DrawBoxEditor(_surface);
|
|
||||||
DrawSlider(_surface);
|
|
||||||
|
|
||||||
if (Event.current.type == EventType.Repaint)
|
|
||||||
{
|
|
||||||
DrawSnapLines(_surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSnapLines(BoxGrabSurface surface)
|
|
||||||
{
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
|
|
||||||
Vector3 rightAxis = surface.Rotation * Vector3.right;
|
|
||||||
Vector3 forwardAxis = surface.Rotation * Vector3.forward;
|
|
||||||
Vector3 forwardOffset = forwardAxis * surface.Size.z;
|
|
||||||
|
|
||||||
Vector3 bottomLeft = surface.transform.position - rightAxis * surface.Size.x * (1f - surface.WidthOffset);
|
|
||||||
Vector3 bottomRight = surface.transform.position + rightAxis * surface.Size.x * (surface.WidthOffset);
|
|
||||||
Vector3 topLeft = bottomLeft + forwardOffset;
|
|
||||||
Vector3 topRight = bottomRight + forwardOffset;
|
|
||||||
|
|
||||||
Handles.DrawLine(bottomLeft + rightAxis * surface.SnapOffset.y, bottomRight + rightAxis * surface.SnapOffset.x);
|
|
||||||
Handles.DrawLine(topLeft - rightAxis * surface.SnapOffset.x, topRight - rightAxis * surface.SnapOffset.y);
|
|
||||||
Handles.DrawLine(bottomLeft - forwardAxis * surface.SnapOffset.z, topLeft - forwardAxis * surface.SnapOffset.w);
|
|
||||||
Handles.DrawLine(bottomRight + forwardAxis * surface.SnapOffset.w, topRight + forwardAxis * surface.SnapOffset.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSlider(BoxGrabSurface surface)
|
|
||||||
{
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
Vector3 rightDir = surface.Rotation * Vector3.right;
|
|
||||||
Vector3 forwardDir = surface.Rotation * Vector3.forward;
|
|
||||||
Vector3 bottomRight = surface.transform.position
|
|
||||||
+ rightDir * surface.Size.x * (surface.WidthOffset);
|
|
||||||
Vector3 bottomLeft = surface.transform.position
|
|
||||||
- rightDir * surface.Size.x * (1f - surface.WidthOffset);
|
|
||||||
Vector3 topRight = bottomRight + forwardDir * surface.Size.z;
|
|
||||||
|
|
||||||
Vector3 rightHandle = DrawOffsetHandle(bottomRight + rightDir * surface.SnapOffset.x, rightDir);
|
|
||||||
Vector3 leftHandle = DrawOffsetHandle(bottomLeft + rightDir * surface.SnapOffset.y, -rightDir);
|
|
||||||
Vector3 topHandle = DrawOffsetHandle(topRight + forwardDir * surface.SnapOffset.z, forwardDir);
|
|
||||||
Vector3 bottomHandle = DrawOffsetHandle(bottomRight + forwardDir * surface.SnapOffset.w, -forwardDir);
|
|
||||||
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(surface, "Change Offset Box");
|
|
||||||
Vector4 offset = surface.SnapOffset;
|
|
||||||
offset.x = DistanceToHandle(bottomRight, rightHandle, rightDir);
|
|
||||||
offset.y = DistanceToHandle(bottomLeft, leftHandle, rightDir);
|
|
||||||
offset.z = DistanceToHandle(topRight, topHandle, forwardDir);
|
|
||||||
offset.w = DistanceToHandle(bottomRight, bottomHandle, forwardDir);
|
|
||||||
surface.SnapOffset = offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Vector3 DrawOffsetHandle(Vector3 point, Vector3 dir)
|
|
||||||
{
|
|
||||||
float size = HandleUtility.GetHandleSize(point) * 0.2f;
|
|
||||||
return Handles.Slider(point, dir, size, Handles.ConeHandleCap, 0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float DistanceToHandle(Vector3 origin, Vector3 handlePoint, Vector3 dir)
|
|
||||||
{
|
|
||||||
float distance = Vector3.Distance(origin, handlePoint);
|
|
||||||
if (Vector3.Dot(handlePoint - origin, dir) < 0f)
|
|
||||||
{
|
|
||||||
distance = -distance;
|
|
||||||
}
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawRotator(BoxGrabSurface surface)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
Quaternion rotation = Handles.RotationHandle(surface.Rotation, surface.transform.position);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(surface, "Change Rotation Box");
|
|
||||||
surface.Rotation = rotation;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawBoxEditor(BoxGrabSurface surface)
|
|
||||||
{
|
|
||||||
Quaternion rot = surface.Rotation;
|
|
||||||
Vector3 size = surface.Size;
|
|
||||||
|
|
||||||
Vector3 snapP = surface.transform.position;
|
|
||||||
|
|
||||||
_boxHandle.size = size;
|
|
||||||
float widthPos = Mathf.Lerp(-size.x * 0.5f, size.x * 0.5f, surface.WidthOffset);
|
|
||||||
_boxHandle.center = new Vector3(widthPos, 0f, size.z * 0.5f);
|
|
||||||
|
|
||||||
Matrix4x4 handleMatrix = Matrix4x4.TRS(
|
|
||||||
snapP,
|
|
||||||
rot,
|
|
||||||
Vector3.one
|
|
||||||
);
|
|
||||||
|
|
||||||
using (new Handles.DrawingScope(handleMatrix))
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
_boxHandle.DrawHandle();
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(surface, "Change Box Properties");
|
|
||||||
|
|
||||||
surface.Size = _boxHandle.size;
|
|
||||||
float width = _boxHandle.size.x;
|
|
||||||
surface.WidthOffset = width != 0f ? (_boxHandle.center.x + width * 0.5f) / width : 0f;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: baf3d860debef0947b62cdebdd94cb74
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,154 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Editor;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.IMGUI.Controls;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.Grab.GrabSurfaces.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(CylinderGrabSurface))]
|
|
||||||
[CanEditMultipleObjects]
|
|
||||||
public class CylinderGrabSurfaceEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private const float DRAW_SURFACE_ANGULAR_RESOLUTION = 5f;
|
|
||||||
|
|
||||||
private ArcHandle _arcEndHandle = new ArcHandle();
|
|
||||||
private ArcHandle _arcStartHandle = new ArcHandle();
|
|
||||||
|
|
||||||
private Vector3[] _surfaceEdges;
|
|
||||||
|
|
||||||
private CylinderGrabSurface _surface;
|
|
||||||
private SerializedProperty _relativeToProperty;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_arcStartHandle.SetColorWithRadiusHandle(EditorConstants.PRIMARY_COLOR_DISABLED, 0f);
|
|
||||||
_arcEndHandle.SetColorWithRadiusHandle(EditorConstants.PRIMARY_COLOR, 0f);
|
|
||||||
_surface = (target as CylinderGrabSurface);
|
|
||||||
_relativeToProperty = serializedObject.FindProperty("_relativeTo");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSceneGUI()
|
|
||||||
{
|
|
||||||
DrawEndsCaps(_surface);
|
|
||||||
|
|
||||||
float oldArcStart = _surface.ArcOffset;
|
|
||||||
float newArcStart = DrawArcEditor(_surface, _arcStartHandle,
|
|
||||||
oldArcStart, Quaternion.LookRotation(_surface.OriginalDir, _surface.Direction));
|
|
||||||
|
|
||||||
_surface.ArcOffset = newArcStart;
|
|
||||||
_surface.ArcLength -= newArcStart - oldArcStart;
|
|
||||||
|
|
||||||
_surface.ArcLength = DrawArcEditor(_surface, _arcEndHandle,
|
|
||||||
_surface.ArcLength, Quaternion.LookRotation(_surface.StartArcDir, _surface.Direction));
|
|
||||||
|
|
||||||
if (Event.current.type == EventType.Repaint)
|
|
||||||
{
|
|
||||||
DrawSurfaceVolume(_surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawEndsCaps(CylinderGrabSurface surface)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
Transform relative = _relativeToProperty.objectReferenceValue as Transform ?? surface.transform;
|
|
||||||
Quaternion handleRotation = relative.rotation;
|
|
||||||
|
|
||||||
Vector3 startPosition = Handles.PositionHandle(surface.StartPoint, handleRotation);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(surface, "Change Start Cylinder Position");
|
|
||||||
surface.StartPoint = startPosition;
|
|
||||||
}
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
Vector3 endPosition = Handles.PositionHandle(surface.EndPoint, handleRotation);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(surface, "Change Start Cylinder Position");
|
|
||||||
surface.EndPoint = endPosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSurfaceVolume(CylinderGrabSurface surface)
|
|
||||||
{
|
|
||||||
Vector3 start = surface.StartPoint;
|
|
||||||
Vector3 end = surface.EndPoint;
|
|
||||||
float radius = surface.Radius;
|
|
||||||
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
Handles.DrawWireArc(end,
|
|
||||||
surface.Direction,
|
|
||||||
surface.StartArcDir,
|
|
||||||
surface.ArcLength,
|
|
||||||
radius);
|
|
||||||
|
|
||||||
Handles.DrawLine(start, end);
|
|
||||||
Handles.DrawLine(start, start + surface.StartArcDir * radius);
|
|
||||||
Handles.DrawLine(start, start + surface.EndArcDir * radius);
|
|
||||||
Handles.DrawLine(end, end + surface.StartArcDir * radius);
|
|
||||||
Handles.DrawLine(end, end + surface.EndArcDir * radius);
|
|
||||||
|
|
||||||
int edgePoints = Mathf.CeilToInt((2 * surface.ArcLength) / DRAW_SURFACE_ANGULAR_RESOLUTION) + 3;
|
|
||||||
if (_surfaceEdges == null
|
|
||||||
|| _surfaceEdges.Length != edgePoints)
|
|
||||||
{
|
|
||||||
_surfaceEdges = new Vector3[edgePoints];
|
|
||||||
}
|
|
||||||
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR_DISABLED;
|
|
||||||
int i = 0;
|
|
||||||
for (float angle = 0f; angle < surface.ArcLength; angle += DRAW_SURFACE_ANGULAR_RESOLUTION)
|
|
||||||
{
|
|
||||||
Vector3 direction = Quaternion.AngleAxis(angle, surface.Direction) * surface.StartArcDir;
|
|
||||||
_surfaceEdges[i++] = start + direction * radius;
|
|
||||||
_surfaceEdges[i++] = end + direction * radius;
|
|
||||||
}
|
|
||||||
_surfaceEdges[i++] = start + surface.EndArcDir * radius;
|
|
||||||
_surfaceEdges[i++] = end + surface.EndArcDir * radius;
|
|
||||||
Handles.DrawPolyLine(_surfaceEdges);
|
|
||||||
}
|
|
||||||
|
|
||||||
private float DrawArcEditor(CylinderGrabSurface surface, ArcHandle handle, float inputAngle, Quaternion rotation)
|
|
||||||
{
|
|
||||||
handle.radius = surface.Radius;
|
|
||||||
handle.angle = inputAngle;
|
|
||||||
|
|
||||||
Matrix4x4 handleMatrix = Matrix4x4.TRS(
|
|
||||||
surface.StartPoint,
|
|
||||||
rotation,
|
|
||||||
Vector3.one
|
|
||||||
);
|
|
||||||
|
|
||||||
using (new Handles.DrawingScope(handleMatrix))
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
handle.DrawHandle();
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(surface, "Change Cylinder Properties");
|
|
||||||
return handle.angle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return inputAngle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 69099ed7427360a4ab3734573c188647
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,86 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Editor;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.IMGUI.Controls;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.Grab.GrabSurfaces.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(SphereGrabSurface))]
|
|
||||||
[CanEditMultipleObjects]
|
|
||||||
public class SphereGrabSurfaceEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private SphereBoundsHandle _sphereHandle = new SphereBoundsHandle();
|
|
||||||
private SphereGrabSurface _surface;
|
|
||||||
private SerializedProperty _relativeToProperty;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_sphereHandle.SetColor(EditorConstants.PRIMARY_COLOR);
|
|
||||||
_sphereHandle.midpointHandleDrawFunction = null;
|
|
||||||
|
|
||||||
_surface = (target as SphereGrabSurface);
|
|
||||||
_relativeToProperty = serializedObject.FindProperty("_relativeTo");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void OnSceneGUI()
|
|
||||||
{
|
|
||||||
DrawCentre(_surface);
|
|
||||||
Handles.color = Color.white;
|
|
||||||
DrawSphereEditor(_surface);
|
|
||||||
|
|
||||||
if (Event.current.type == EventType.Repaint)
|
|
||||||
{
|
|
||||||
DrawSurfaceVolume(_surface);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawCentre(SphereGrabSurface surface)
|
|
||||||
{
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
Transform relative = _relativeToProperty.objectReferenceValue as Transform ?? surface.transform;
|
|
||||||
Quaternion handleRotation = relative.rotation;
|
|
||||||
Vector3 centrePosition = Handles.PositionHandle(surface.Centre, handleRotation);
|
|
||||||
if (EditorGUI.EndChangeCheck())
|
|
||||||
{
|
|
||||||
Undo.RecordObject(surface, "Change Centre Sphere Position");
|
|
||||||
surface.Centre = centrePosition;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void DrawSurfaceVolume(SphereGrabSurface surface)
|
|
||||||
{
|
|
||||||
Handles.color = EditorConstants.PRIMARY_COLOR;
|
|
||||||
Vector3 startLine = surface.Centre;
|
|
||||||
Vector3 endLine = startLine + surface.Rotation * Vector3.forward * surface.Radius;
|
|
||||||
Handles.DrawDottedLine(startLine, endLine, 5);
|
|
||||||
}
|
|
||||||
private void DrawSphereEditor(SphereGrabSurface surface)
|
|
||||||
{
|
|
||||||
_sphereHandle.radius = surface.Radius;
|
|
||||||
_sphereHandle.center = surface.Centre;
|
|
||||||
|
|
||||||
EditorGUI.BeginChangeCheck();
|
|
||||||
_sphereHandle.DrawHandle();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: ee7657a153e652d448fa1b7775ca7f8c
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 5760a4e866e11cb46a5adff4e32acc44
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Input;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEngine;
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.HandGrab.Visuals.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(HandPuppet))]
|
|
||||||
public class HandPuppetEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
DrawDefaultInspector();
|
|
||||||
|
|
||||||
HandPuppet puppet = target as HandPuppet;
|
|
||||||
if (GUILayout.Button("Auto-Assign Bones"))
|
|
||||||
{
|
|
||||||
SkinnedMeshRenderer skinnedHand = puppet.GetComponentInChildren<SkinnedMeshRenderer>();
|
|
||||||
if (skinnedHand != null)
|
|
||||||
{
|
|
||||||
SetPrivateValue(puppet, "_jointMaps", AutoAsignBones(skinnedHand));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private List<HandJointMap> AutoAsignBones(SkinnedMeshRenderer skinnedHand)
|
|
||||||
{
|
|
||||||
List<HandJointMap> maps = new List<HandJointMap>();
|
|
||||||
Transform root = skinnedHand.rootBone;
|
|
||||||
Regex regEx = new Regex(@"Hand(\w*)(\d)");
|
|
||||||
foreach (var bone in FingersMetadata.HAND_JOINT_IDS)
|
|
||||||
{
|
|
||||||
Match match = regEx.Match(bone.ToString());
|
|
||||||
if (match != Match.Empty)
|
|
||||||
{
|
|
||||||
string boneName = match.Groups[1].Value.ToLower();
|
|
||||||
string boneNumber = match.Groups[2].Value;
|
|
||||||
Transform skinnedBone = RecursiveSearchForChildrenContainingPattern(root, "col", boneName, boneNumber);
|
|
||||||
if (skinnedBone != null)
|
|
||||||
{
|
|
||||||
maps.Add(new HandJointMap()
|
|
||||||
{
|
|
||||||
id = bone,
|
|
||||||
transform = skinnedBone,
|
|
||||||
rotationOffset = Vector3.zero
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return maps;
|
|
||||||
}
|
|
||||||
|
|
||||||
private Transform RecursiveSearchForChildrenContainingPattern(Transform root, string ignorePattern, params string[] args)
|
|
||||||
{
|
|
||||||
if (root == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < root.childCount; i++)
|
|
||||||
{
|
|
||||||
Transform child = root.GetChild(i);
|
|
||||||
string childName = child.name.ToLower();
|
|
||||||
|
|
||||||
bool shouldCheck = string.IsNullOrEmpty(ignorePattern)|| !childName.Contains(ignorePattern);
|
|
||||||
if (shouldCheck)
|
|
||||||
{
|
|
||||||
bool containsAllArgs = args.All(a => childName.Contains(a));
|
|
||||||
Transform result = containsAllArgs ? child
|
|
||||||
: RecursiveSearchForChildrenContainingPattern(child, ignorePattern, args);
|
|
||||||
if (result != null)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetPrivateValue(object instance, string fieldName, object value)
|
|
||||||
{
|
|
||||||
FieldInfo fieldData = GetPrivateField(instance, fieldName);
|
|
||||||
fieldData.SetValue(instance, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static FieldInfo GetPrivateField(object instance, string fieldName)
|
|
||||||
{
|
|
||||||
Type type = instance.GetType();
|
|
||||||
FieldInfo fieldData = null;
|
|
||||||
while (type != null && fieldData == null)
|
|
||||||
{
|
|
||||||
fieldData = type.GetField(fieldName, BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
type = type.BaseType;
|
|
||||||
}
|
|
||||||
return fieldData;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: fb714303644f5c343bd2c80559c02856
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 6d1754bb0e390e44e906221c5091ed9a
|
|
||||||
folderAsset: yes
|
|
||||||
DefaultImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Input;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.SceneManagement;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.Hands.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(FromHandPrefabDataSource))]
|
|
||||||
public class FromHandPrefabDataSourceEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private SerializedProperty _handednessProperty;
|
|
||||||
|
|
||||||
private int HandednessIdx => _handednessProperty.enumValueIndex;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_handednessProperty = serializedObject.FindProperty("_handedness");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
DrawPropertiesExcluding(serializedObject);
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
|
|
||||||
FromHandPrefabDataSource source = (FromHandPrefabDataSource)target;
|
|
||||||
InitializeSkeleton(source);
|
|
||||||
|
|
||||||
if (GUILayout.Button("Auto Map Joints"))
|
|
||||||
{
|
|
||||||
AutoMapJoints(source);
|
|
||||||
EditorUtility.SetDirty(source);
|
|
||||||
EditorSceneManager.MarkSceneDirty(source.gameObject.scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField("Joints", EditorStyles.boldLabel);
|
|
||||||
HandJointId start = HandJointId.HandStart;
|
|
||||||
HandJointId end = HandJointId.HandEnd;
|
|
||||||
|
|
||||||
for (int i = (int)start; i < (int)end; ++i)
|
|
||||||
{
|
|
||||||
string jointName = HandJointLabelFromJointId((HandJointId)i);
|
|
||||||
source.JointTransforms[i] = (Transform)EditorGUILayout.ObjectField(jointName,
|
|
||||||
source.JointTransforms[i], typeof(Transform), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly string[] _fbxHandSidePrefix = { "l_", "r_" };
|
|
||||||
private static readonly string _fbxHandBonePrefix = "b_";
|
|
||||||
|
|
||||||
private static readonly string[] _fbxHandBoneNames =
|
|
||||||
{
|
|
||||||
"wrist",
|
|
||||||
"forearm_stub",
|
|
||||||
"thumb0",
|
|
||||||
"thumb1",
|
|
||||||
"thumb2",
|
|
||||||
"thumb3",
|
|
||||||
"index1",
|
|
||||||
"index2",
|
|
||||||
"index3",
|
|
||||||
"middle1",
|
|
||||||
"middle2",
|
|
||||||
"middle3",
|
|
||||||
"ring1",
|
|
||||||
"ring2",
|
|
||||||
"ring3",
|
|
||||||
"pinky0",
|
|
||||||
"pinky1",
|
|
||||||
"pinky2",
|
|
||||||
"pinky3"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly string[] _fbxHandFingerNames =
|
|
||||||
{
|
|
||||||
"thumb",
|
|
||||||
"index",
|
|
||||||
"middle",
|
|
||||||
"ring",
|
|
||||||
"pinky"
|
|
||||||
};
|
|
||||||
|
|
||||||
private void InitializeSkeleton(FromHandPrefabDataSource source)
|
|
||||||
{
|
|
||||||
if (source.JointTransforms.Count == 0)
|
|
||||||
{
|
|
||||||
for (int i = (int)HandJointId.HandStart; i < (int)HandJointId.HandEnd; ++i)
|
|
||||||
{
|
|
||||||
source.JointTransforms.Add(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AutoMapJoints(FromHandPrefabDataSource source)
|
|
||||||
{
|
|
||||||
Transform rootTransform = source.transform;
|
|
||||||
|
|
||||||
for (int i = (int)HandJointId.HandStart; i < (int)HandJointId.HandEnd; ++i)
|
|
||||||
{
|
|
||||||
string fbxBoneName = FbxBoneNameFromHandJointId((HandJointId)i);
|
|
||||||
Transform t = rootTransform.FindChildRecursive(fbxBoneName);
|
|
||||||
source.JointTransforms[i] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string FbxBoneNameFromHandJointId(HandJointId handJointId)
|
|
||||||
{
|
|
||||||
if (handJointId >= HandJointId.HandThumbTip && handJointId <= HandJointId.HandPinkyTip)
|
|
||||||
{
|
|
||||||
return _fbxHandSidePrefix[(int)HandednessIdx] + _fbxHandFingerNames[(int)handJointId - (int)HandJointId.HandThumbTip] + "_finger_tip_marker";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _fbxHandBonePrefix + _fbxHandSidePrefix[(int)HandednessIdx] + _fbxHandBoneNames[(int)handJointId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// force aliased enum values to the more appropriate value
|
|
||||||
private static string HandJointLabelFromJointId(HandJointId handJointId)
|
|
||||||
{
|
|
||||||
switch (handJointId)
|
|
||||||
{
|
|
||||||
case HandJointId.HandWristRoot:
|
|
||||||
return "HandWristRoot";
|
|
||||||
case HandJointId.HandForearmStub:
|
|
||||||
return "HandForearmStub";
|
|
||||||
case HandJointId.HandThumb0:
|
|
||||||
return "HandThumb0";
|
|
||||||
case HandJointId.HandThumb1:
|
|
||||||
return "HandThumb1";
|
|
||||||
case HandJointId.HandThumb2:
|
|
||||||
return "HandThumb2";
|
|
||||||
case HandJointId.HandThumb3:
|
|
||||||
return "HandThumb3";
|
|
||||||
case HandJointId.HandIndex1:
|
|
||||||
return "HandIndex1";
|
|
||||||
case HandJointId.HandIndex2:
|
|
||||||
return "HandIndex2";
|
|
||||||
case HandJointId.HandIndex3:
|
|
||||||
return "HandIndex3";
|
|
||||||
case HandJointId.HandMiddle1:
|
|
||||||
return "HandMiddle1";
|
|
||||||
case HandJointId.HandMiddle2:
|
|
||||||
return "HandMiddle2";
|
|
||||||
case HandJointId.HandMiddle3:
|
|
||||||
return "HandMiddle3";
|
|
||||||
case HandJointId.HandRing1:
|
|
||||||
return "HandRing1";
|
|
||||||
case HandJointId.HandRing2:
|
|
||||||
return "HandRing2";
|
|
||||||
case HandJointId.HandRing3:
|
|
||||||
return "HandRing3";
|
|
||||||
case HandJointId.HandPinky0:
|
|
||||||
return "HandPinky0";
|
|
||||||
case HandJointId.HandPinky1:
|
|
||||||
return "HandPinky1";
|
|
||||||
case HandJointId.HandPinky2:
|
|
||||||
return "HandPinky2";
|
|
||||||
case HandJointId.HandPinky3:
|
|
||||||
return "HandPinky3";
|
|
||||||
case HandJointId.HandThumbTip:
|
|
||||||
return "HandThumbTip";
|
|
||||||
case HandJointId.HandIndexTip:
|
|
||||||
return "HandIndexTip";
|
|
||||||
case HandJointId.HandMiddleTip:
|
|
||||||
return "HandMiddleTip";
|
|
||||||
case HandJointId.HandRingTip:
|
|
||||||
return "HandRingTip";
|
|
||||||
case HandJointId.HandPinkyTip:
|
|
||||||
return "HandPinkyTip";
|
|
||||||
default:
|
|
||||||
return "HandUnknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 7b1127eced26c0748b86cc88310b1711
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,213 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Licensed under the Oculus SDK License Agreement (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/oculussdk/
|
|
||||||
*
|
|
||||||
* 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 Oculus.Interaction.Input;
|
|
||||||
using UnityEditor;
|
|
||||||
using UnityEditor.SceneManagement;
|
|
||||||
using UnityEngine;
|
|
||||||
|
|
||||||
namespace Oculus.Interaction.Hands.Editor
|
|
||||||
{
|
|
||||||
[CustomEditor(typeof(HandVisual))]
|
|
||||||
public class HandVisualEditor : UnityEditor.Editor
|
|
||||||
{
|
|
||||||
private SerializedProperty _handProperty;
|
|
||||||
private SerializedProperty _rootProperty;
|
|
||||||
|
|
||||||
private IHand Hand => _handProperty.objectReferenceValue as IHand;
|
|
||||||
|
|
||||||
private void OnEnable()
|
|
||||||
{
|
|
||||||
_handProperty = serializedObject.FindProperty("_hand");
|
|
||||||
_rootProperty = serializedObject.FindProperty("_root");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void OnInspectorGUI()
|
|
||||||
{
|
|
||||||
DrawPropertiesExcluding(serializedObject);
|
|
||||||
serializedObject.ApplyModifiedProperties();
|
|
||||||
|
|
||||||
HandVisual visual = (HandVisual)target;
|
|
||||||
InitializeSkeleton(visual);
|
|
||||||
|
|
||||||
if (Hand == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (GUILayout.Button("Auto Map Joints"))
|
|
||||||
{
|
|
||||||
AutoMapJoints(visual);
|
|
||||||
EditorUtility.SetDirty(visual);
|
|
||||||
EditorSceneManager.MarkSceneDirty(visual.gameObject.scene);
|
|
||||||
}
|
|
||||||
|
|
||||||
EditorGUILayout.LabelField("Joints", EditorStyles.boldLabel);
|
|
||||||
HandJointId start = HandJointId.HandStart;
|
|
||||||
HandJointId end = HandJointId.HandEnd;
|
|
||||||
|
|
||||||
for (int i = (int)start; i < (int)end; ++i)
|
|
||||||
{
|
|
||||||
string jointName = HandJointLabelFromJointId((HandJointId)i);
|
|
||||||
visual.Joints[i] = (Transform)EditorGUILayout.ObjectField(jointName,
|
|
||||||
visual.Joints[i], typeof(Transform), true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static readonly string[] _fbxHandSidePrefix = { "l_", "r_" };
|
|
||||||
private static readonly string _fbxHandBonePrefix = "b_";
|
|
||||||
|
|
||||||
private static readonly string[] _fbxHandBoneNames =
|
|
||||||
{
|
|
||||||
"wrist",
|
|
||||||
"forearm_stub",
|
|
||||||
"thumb0",
|
|
||||||
"thumb1",
|
|
||||||
"thumb2",
|
|
||||||
"thumb3",
|
|
||||||
"index1",
|
|
||||||
"index2",
|
|
||||||
"index3",
|
|
||||||
"middle1",
|
|
||||||
"middle2",
|
|
||||||
"middle3",
|
|
||||||
"ring1",
|
|
||||||
"ring2",
|
|
||||||
"ring3",
|
|
||||||
"pinky0",
|
|
||||||
"pinky1",
|
|
||||||
"pinky2",
|
|
||||||
"pinky3"
|
|
||||||
};
|
|
||||||
|
|
||||||
private static readonly string[] _fbxHandFingerNames =
|
|
||||||
{
|
|
||||||
"thumb",
|
|
||||||
"index",
|
|
||||||
"middle",
|
|
||||||
"ring",
|
|
||||||
"pinky"
|
|
||||||
};
|
|
||||||
|
|
||||||
private void InitializeSkeleton(HandVisual visual)
|
|
||||||
{
|
|
||||||
if (visual.Joints.Count == 0)
|
|
||||||
{
|
|
||||||
for (int i = (int)HandJointId.HandStart; i < (int)HandJointId.HandEnd; ++i)
|
|
||||||
{
|
|
||||||
visual.Joints.Add(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void AutoMapJoints(HandVisual visual)
|
|
||||||
{
|
|
||||||
if (Hand == null)
|
|
||||||
{
|
|
||||||
InitializeSkeleton(visual);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Transform rootTransform = visual.transform;
|
|
||||||
if (_rootProperty.objectReferenceValue != null)
|
|
||||||
{
|
|
||||||
rootTransform = _rootProperty.objectReferenceValue as Transform;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = (int)HandJointId.HandStart; i < (int)HandJointId.HandEnd; ++i)
|
|
||||||
{
|
|
||||||
string fbxBoneName = FbxBoneNameFromHandJointId(visual, (HandJointId)i);
|
|
||||||
Transform t = rootTransform.FindChildRecursive(fbxBoneName);
|
|
||||||
visual.Joints[i] = t;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private string FbxBoneNameFromHandJointId(HandVisual visual, HandJointId handJointId)
|
|
||||||
{
|
|
||||||
if (handJointId >= HandJointId.HandThumbTip && handJointId <= HandJointId.HandPinkyTip)
|
|
||||||
{
|
|
||||||
return _fbxHandSidePrefix[(int)Hand.Handedness] + _fbxHandFingerNames[(int)handJointId - (int)HandJointId.HandThumbTip] + "_finger_tip_marker";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return _fbxHandBonePrefix + _fbxHandSidePrefix[(int)Hand.Handedness] + _fbxHandBoneNames[(int)handJointId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// force aliased enum values to the more appropriate value
|
|
||||||
private static string HandJointLabelFromJointId(HandJointId handJointId)
|
|
||||||
{
|
|
||||||
switch (handJointId)
|
|
||||||
{
|
|
||||||
case HandJointId.HandWristRoot:
|
|
||||||
return "HandWristRoot";
|
|
||||||
case HandJointId.HandForearmStub:
|
|
||||||
return "HandForearmStub";
|
|
||||||
case HandJointId.HandThumb0:
|
|
||||||
return "HandThumb0";
|
|
||||||
case HandJointId.HandThumb1:
|
|
||||||
return "HandThumb1";
|
|
||||||
case HandJointId.HandThumb2:
|
|
||||||
return "HandThumb2";
|
|
||||||
case HandJointId.HandThumb3:
|
|
||||||
return "HandThumb3";
|
|
||||||
case HandJointId.HandIndex1:
|
|
||||||
return "HandIndex1";
|
|
||||||
case HandJointId.HandIndex2:
|
|
||||||
return "HandIndex2";
|
|
||||||
case HandJointId.HandIndex3:
|
|
||||||
return "HandIndex3";
|
|
||||||
case HandJointId.HandMiddle1:
|
|
||||||
return "HandMiddle1";
|
|
||||||
case HandJointId.HandMiddle2:
|
|
||||||
return "HandMiddle2";
|
|
||||||
case HandJointId.HandMiddle3:
|
|
||||||
return "HandMiddle3";
|
|
||||||
case HandJointId.HandRing1:
|
|
||||||
return "HandRing1";
|
|
||||||
case HandJointId.HandRing2:
|
|
||||||
return "HandRing2";
|
|
||||||
case HandJointId.HandRing3:
|
|
||||||
return "HandRing3";
|
|
||||||
case HandJointId.HandPinky0:
|
|
||||||
return "HandPinky0";
|
|
||||||
case HandJointId.HandPinky1:
|
|
||||||
return "HandPinky1";
|
|
||||||
case HandJointId.HandPinky2:
|
|
||||||
return "HandPinky2";
|
|
||||||
case HandJointId.HandPinky3:
|
|
||||||
return "HandPinky3";
|
|
||||||
case HandJointId.HandThumbTip:
|
|
||||||
return "HandThumbTip";
|
|
||||||
case HandJointId.HandIndexTip:
|
|
||||||
return "HandIndexTip";
|
|
||||||
case HandJointId.HandMiddleTip:
|
|
||||||
return "HandMiddleTip";
|
|
||||||
case HandJointId.HandRingTip:
|
|
||||||
return "HandRingTip";
|
|
||||||
case HandJointId.HandPinkyTip:
|
|
||||||
return "HandPinkyTip";
|
|
||||||
default:
|
|
||||||
return "HandUnknown";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 037bf294d05876e4c8dd96432f39faaa
|
|
||||||
MonoImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
serializedVersion: 2
|
|
||||||
defaultReferences: []
|
|
||||||
executionOrder: 0
|
|
||||||
icon: {instanceID: 0}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "Oculus.Interaction.Editor",
|
|
||||||
"rootNamespace": "",
|
|
||||||
"references": [
|
|
||||||
"GUID:2a230cb87a1d3ba4a98bdc0ddae76e6c"
|
|
||||||
],
|
|
||||||
"includePlatforms": [
|
|
||||||
"Editor"
|
|
||||||
],
|
|
||||||
"excludePlatforms": [],
|
|
||||||
"allowUnsafeCode": true,
|
|
||||||
"overrideReferences": false,
|
|
||||||
"precompiledReferences": [],
|
|
||||||
"autoReferenced": true,
|
|
||||||
"defineConstraints": [],
|
|
||||||
"versionDefines": [],
|
|
||||||
"noEngineReferences": false
|
|
||||||
}
|
|
||||||
@ -1,7 +0,0 @@
|
|||||||
fileFormatVersion: 2
|
|
||||||
guid: 48af58ae5328ff048acacd924604a804
|
|
||||||
AssemblyDefinitionImporter:
|
|
||||||
externalObjects: {}
|
|
||||||
userData:
|
|
||||||
assetBundleName:
|
|
||||||
assetBundleVariant:
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user