From 617f0488834f97674a914b7e25a7d13d99146c95 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 22 Sep 2015 13:40:33 +0200 Subject: [PATCH 1/4] Added JS interface to change audio listening position / orientation in Interface - MyAvatar.audioListenerMode change using: MyAvatar.FROM_HEAD , MyAvatar.FROM_CAMERA , MyAvatar.CUSTOM - MyAvatar.customListenPosition and MyAvatar.customListenOrientation are for manual listening positions --- interface/src/Application.cpp | 2 ++ interface/src/Application.h | 4 +-- interface/src/avatar/MyAvatar.cpp | 35 +++++++++++++++++++++- interface/src/avatar/MyAvatar.h | 34 +++++++++++++++++++++ libraries/shared/src/RegisteredMetaTypes.h | 8 ++--- 5 files changed, 76 insertions(+), 7 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ee98ce4c25..84d66fc285 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4024,6 +4024,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri // hook our avatar and avatar hash map object into this script engine scriptEngine->registerGlobalObject("MyAvatar", _myAvatar); + qScriptRegisterMetaType(scriptEngine, maAudioListenModeToScriptValue, maAudioListenModeFromScriptValue); + scriptEngine->registerGlobalObject("AvatarList", DependencyManager::get().data()); scriptEngine->registerGlobalObject("Camera", &_myCamera); diff --git a/interface/src/Application.h b/interface/src/Application.h index 0a591bf500..5ea890fc2d 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -142,8 +142,8 @@ public: static Application* getInstance() { return qApp; } // TODO: replace fully by qApp static const glm::vec3& getPositionForPath() { return getInstance()->_myAvatar->getPosition(); } static glm::quat getOrientationForPath() { return getInstance()->_myAvatar->getOrientation(); } - static glm::vec3 getPositionForAudio() { return getInstance()->_myAvatar->getHead()->getPosition(); } - static glm::quat getOrientationForAudio() { return getInstance()->_myAvatar->getHead()->getFinalOrientationInWorldFrame(); } + static glm::vec3 getPositionForAudio() { return getInstance()->_myAvatar->getPositionForAudio(); } + static glm::quat getOrientationForAudio() { return getInstance()->_myAvatar->getOrientationForAudio(); } static void initPlugins(); static void shutdownPlugins(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index ae483988e3..21b718e404 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -108,7 +108,8 @@ MyAvatar::MyAvatar(RigPointer rig) : _goToPosition(), _goToOrientation(), _rig(rig), - _prevShouldDrawHead(true) + _prevShouldDrawHead(true), + _audioListenerMode(FROM_HEAD) { for (int i = 0; i < MAX_DRIVE_KEYS; i++) { _driveKeys[i] = 0.0f; @@ -1806,3 +1807,35 @@ glm::mat4 MyAvatar::deriveBodyFromHMDSensor() const { // avatar facing is determined solely by hmd orientation. return createMatFromQuatAndPos(hmdOrientationYawOnly, bodyPos); } + +glm::vec3 MyAvatar::getPositionForAudio() { + switch (_audioListenerMode) { + case AudioListenerMode::FROM_HEAD: + return getHead()->getPosition(); + case AudioListenerMode::FROM_CAMERA: + return Application::getInstance()->getCamera()->getPosition(); + case AudioListenerMode::CUSTOM: + return _customListenPosition; + } + return vec3(); +} + +glm::quat MyAvatar::getOrientationForAudio() { + switch (_audioListenerMode) { + case AudioListenerMode::FROM_HEAD: + return getHead()->getFinalOrientationInWorldFrame(); + case AudioListenerMode::FROM_CAMERA: + return Application::getInstance()->getCamera()->getOrientation(); + case AudioListenerMode::CUSTOM: + return _customListenOrientation; + } + return quat(); +} + +QScriptValue maAudioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode) { + return audioListenerMode; +} + +void maAudioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode) { + audioListenerMode = (AudioListenerMode)object.toUInt16(); +} diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 6989ea3969..3dfcde735b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -26,6 +26,14 @@ enum eyeContactTarget { MOUTH }; +enum AudioListenerMode { + FROM_HEAD = 0, + FROM_CAMERA, + CUSTOM +}; +Q_DECLARE_METATYPE(AudioListenerMode); + + class MyAvatar : public Avatar { Q_OBJECT Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) @@ -33,12 +41,21 @@ class MyAvatar : public Avatar { Q_PROPERTY(float motorTimescale READ getScriptedMotorTimescale WRITE setScriptedMotorTimescale) Q_PROPERTY(QString motorReferenceFrame READ getScriptedMotorFrame WRITE setScriptedMotorFrame) Q_PROPERTY(QString collisionSoundURL READ getCollisionSoundURL WRITE setCollisionSoundURL) + Q_PROPERTY(AudioListenerMode audioListenerMode READ getAudioListenerMode WRITE setAudioListenerMode) + Q_PROPERTY(glm::vec3 customListenPosition READ getCustomListenPosition WRITE setCustomListenPosition) + Q_PROPERTY(glm::quat customListenOrientation READ getCustomListenOrientation WRITE setCustomListenOrientation) + Q_PROPERTY(AudioListenerMode FROM_HEAD READ getAudioListenerModeHead) + Q_PROPERTY(AudioListenerMode FROM_CAMERA READ getAudioListenerModeCamera) + Q_PROPERTY(AudioListenerMode CUSTOM READ getAudioListenerModeCustom) //TODO: make gravity feature work Q_PROPERTY(glm::vec3 gravity READ getGravity WRITE setGravity) public: MyAvatar(RigPointer rig); ~MyAvatar(); + AudioListenerMode getAudioListenerModeHead() const { return FROM_HEAD; } + AudioListenerMode getAudioListenerModeCamera() const { return FROM_CAMERA; } + AudioListenerMode getAudioListenerModeCustom() const { return CUSTOM; } void reset(); void update(float deltaTime); @@ -153,6 +170,13 @@ public: void doUpdateBillboard(); void destroyAnimGraph(); + AudioListenerMode getAudioListenerMode() { return _audioListenerMode; } + void setAudioListenerMode(AudioListenerMode audioListenerMode) { _audioListenerMode = audioListenerMode; } + glm::vec3 getCustomListenPosition() { return _customListenPosition; } + void setCustomListenPosition(glm::vec3 customListenPosition) { _customListenPosition = customListenPosition; } + glm::quat getCustomListenOrientation() { return _customListenOrientation; } + void setCustomListenOrientation(glm::quat customListenOrientation) { _customListenOrientation = customListenOrientation; } + public slots: void increaseSize(); void decreaseSize(); @@ -200,6 +224,9 @@ public slots: void setEnableDebugDrawAnimPose(bool isEnabled); void setEnableMeshVisible(bool isEnabled); + glm::vec3 getPositionForAudio(); + glm::quat getOrientationForAudio(); + signals: void transformChanged(); void newCollisionSoundURL(const QUrl& url); @@ -325,6 +352,13 @@ private: bool _enableDebugDrawBindPose = false; bool _enableDebugDrawAnimPose = false; AnimSkeleton::ConstPointer _debugDrawSkeleton = nullptr; + + AudioListenerMode _audioListenerMode; + glm::vec3 _customListenPosition; + glm::quat _customListenOrientation; }; +QScriptValue maAudioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); +void maAudioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode); + #endif // hifi_MyAvatar_h diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 31f1da8a40..c419741c3b 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -59,7 +59,7 @@ void qURLFromScriptValue(const QScriptValue& object, QUrl& url); QScriptValue qVectorVec3ToScriptValue(QScriptEngine* engine, const QVector& vector); void qVectorVec3FromScriptValue(const QScriptValue& array, QVector& vector); -QVector qVectorVec3FromScriptValue( const QScriptValue& array); +QVector qVectorVec3FromScriptValue(const QScriptValue& array); QScriptValue qVectorFloatToScriptValue(QScriptEngine* engine, const QVector& vector); void qVectorFloatFromScriptValue(const QScriptValue& array, QVector& vector); @@ -77,10 +77,10 @@ QScriptValue pickRayToScriptValue(QScriptEngine* engine, const PickRay& pickRay) void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay); enum ContactEventType { - CONTACT_EVENT_TYPE_START, + CONTACT_EVENT_TYPE_START, CONTACT_EVENT_TYPE_CONTINUE, - CONTACT_EVENT_TYPE_END -}; + CONTACT_EVENT_TYPE_END +}; class Collision { public: From 81932fe1d7976216a07a01990b81fcbcfb551f75 Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 22 Sep 2015 15:38:53 +0200 Subject: [PATCH 2/4] - added MyAvatar.audioListenerModeChanged signal , for registering changes. - updated the developerMenuItems.js script to include AudioListenerMode menu options under Developer > Audio --- .../utilities/tools/developerMenuItems.js | 49 +++++++++++++++---- interface/src/avatar/MyAvatar.cpp | 7 +++ interface/src/avatar/MyAvatar.h | 3 +- 3 files changed, 48 insertions(+), 11 deletions(-) diff --git a/examples/utilities/tools/developerMenuItems.js b/examples/utilities/tools/developerMenuItems.js index ace2b032e2..3439d85b3b 100644 --- a/examples/utilities/tools/developerMenuItems.js +++ b/examples/utilities/tools/developerMenuItems.js @@ -13,6 +13,7 @@ var createdRenderMenu = false; var createdGeneratedAudioMenu = false; +var createdAudioListenerModeMenu = false; var createdStereoInputMenuItem = false; var DEVELOPER_MENU = "Developer"; @@ -29,6 +30,15 @@ var AUDIO_SOURCE_INJECT = "Generated Audio"; var AUDIO_SOURCE_MENU = AUDIO_MENU + " > Generated Audio Source"; var AUDIO_SOURCE_PINK_NOISE = "Pink Noise"; var AUDIO_SOURCE_SINE_440 = "Sine 440hz"; +var AUDIO_LISTENER_MODE_MENU = AUDIO_MENU + " > Audio Listener Mode" +var AUDIO_LISTENER_MODE_FROM_HEAD = "Audio from head"; +var AUDIO_LISTENER_MODE_FROM_CAMERA = "Audio from camera"; +var AUDIO_LISTENER_MODE_CUSTOM = "Audio from custom position"; +var AUDIO_LISTENER_OPTIONS = [ + AUDIO_LISTENER_MODE_FROM_HEAD, + AUDIO_LISTENER_MODE_FROM_CAMERA, + AUDIO_LISTENER_MODE_CUSTOM +]; var AUDIO_STEREO_INPUT = "Stereo Input"; @@ -67,7 +77,6 @@ function setupMenus() { Menu.addMenuItem({ menuName: RENDER_MENU, menuItemName: AVATARS_ITEM, isCheckable: true, isChecked: Scene.shouldRenderAvatars }) } - if (!Menu.menuExists(AUDIO_MENU)) { Menu.addMenu(AUDIO_MENU); } @@ -80,6 +89,14 @@ function setupMenus() { Audio.selectPinkNoise(); createdGeneratedAudioMenu = true; } + + if (!Menu.menuExists(AUDIO_LISTENER_MODE_MENU)) { + Menu.addMenu(AUDIO_LISTENER_MODE_MENU); + Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_FROM_HEAD, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.FROM_HEAD) }); + Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_FROM_CAMERA, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.FROM_CAMERA) }); + Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_CUSTOM, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.CUSTOM) }); + } + if (!Menu.menuItemExists(AUDIO_MENU, AUDIO_STEREO_INPUT)) { Menu.addMenuItem({ menuName: AUDIO_MENU, menuItemName: AUDIO_STEREO_INPUT, isCheckable: true, isChecked: false }); createdStereoInputMenuItem = true; @@ -99,15 +116,23 @@ Menu.menuItemEvent.connect(function (menuItem) { Scene.shouldRenderAvatars = Menu.isOptionChecked(AVATARS_ITEM); } else if (menuItem == AUDIO_SOURCE_INJECT && !createdGeneratedAudioMenu) { Audio.injectGeneratedNoise(Menu.isOptionChecked(AUDIO_SOURCE_INJECT)); - } else if (menuItem == AUDIO_SOURCE_PINK_NOISE && !createdGeneratedAudioMenu) { - Audio.selectPinkNoise(); - Menu.setIsOptionChecked(AUDIO_SOURCE_SINE_440, false); - } else if (menuItem == AUDIO_SOURCE_SINE_440 && !createdGeneratedAudioMenu) { - Audio.selectSine440(); - Menu.setIsOptionChecked(AUDIO_SOURCE_PINK_NOISE, false); - } else if (menuItem == AUDIO_STEREO_INPUT) { - Audio.setStereoInput(Menu.isOptionChecked(AUDIO_STEREO_INPUT)) - } + } else if (menuItem == AUDIO_SOURCE_PINK_NOISE && !createdGeneratedAudioMenu) { + Audio.selectPinkNoise(); + Menu.setIsOptionChecked(AUDIO_SOURCE_SINE_440, false); + } else if (menuItem == AUDIO_SOURCE_SINE_440 && !createdGeneratedAudioMenu) { + Audio.selectSine440(); + Menu.setIsOptionChecked(AUDIO_SOURCE_PINK_NOISE, false); + } else if (menuItem == AUDIO_STEREO_INPUT) { + Audio.setStereoInput(Menu.isOptionChecked(AUDIO_STEREO_INPUT)) + } else if (AUDIO_LISTENER_OPTIONS.indexOf(menuItem) !== -1) { + MyAvatar.audioListenerMode = AUDIO_LISTENER_OPTIONS.indexOf(menuItem); + } +}); + +MyAvatar.audioListenerModeChanged(function() { + for (var i = 0; i < AUDIO_LISTENER_OPTIONS.length; i++) { + Menu.setIsOptionChecked(AUDIO_LISTENER_OPTIONS[i], (MyAvatar.audioListenerMode === i)); + } }); Scene.shouldRenderAvatarsChanged.connect(function(shouldRenderAvatars) { @@ -134,6 +159,10 @@ function scriptEnding() { Menu.removeMenu(AUDIO_SOURCE_MENU); } + if (createdAudioListenerModeMenu) { + Menu.removeMenu(AUDIO_LISTENER_MODE_MENU); + } + if (createdStereoInputMenuItem) { Menu.removeMenuItem(AUDIO_MENU, AUDIO_STEREO_INPUT); } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 21b718e404..2b695f3fe2 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1832,6 +1832,13 @@ glm::quat MyAvatar::getOrientationForAudio() { return quat(); } +void MyAvatar::setAudioListenerMode(AudioListenerMode audioListenerMode) { + if (_audioListenerMode != audioListenerMode) { + _audioListenerMode = audioListenerMode; + emit audioListenerModeChanged(); + } +} + QScriptValue maAudioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode) { return audioListenerMode; } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 3dfcde735b..d916977ad5 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -171,7 +171,7 @@ public: void destroyAnimGraph(); AudioListenerMode getAudioListenerMode() { return _audioListenerMode; } - void setAudioListenerMode(AudioListenerMode audioListenerMode) { _audioListenerMode = audioListenerMode; } + void setAudioListenerMode(AudioListenerMode audioListenerMode); glm::vec3 getCustomListenPosition() { return _customListenPosition; } void setCustomListenPosition(glm::vec3 customListenPosition) { _customListenPosition = customListenPosition; } glm::quat getCustomListenOrientation() { return _customListenOrientation; } @@ -228,6 +228,7 @@ public slots: glm::quat getOrientationForAudio(); signals: + void audioListenerModeChanged(); void transformChanged(); void newCollisionSoundURL(const QUrl& url); void collisionWithEntity(const Collision& collision); From dfb9034b4e18f9b4b22b9a201c6c8749bb1a4f5c Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 22 Sep 2015 15:45:57 +0200 Subject: [PATCH 3/4] - delete new AudioListenerMode menu on script ending - style fix (function naming) --- examples/utilities/tools/developerMenuItems.js | 1 + interface/src/Application.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 4 ++-- interface/src/avatar/MyAvatar.h | 4 ++-- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/utilities/tools/developerMenuItems.js b/examples/utilities/tools/developerMenuItems.js index 3439d85b3b..3fe3a10be7 100644 --- a/examples/utilities/tools/developerMenuItems.js +++ b/examples/utilities/tools/developerMenuItems.js @@ -95,6 +95,7 @@ function setupMenus() { Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_FROM_HEAD, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.FROM_HEAD) }); Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_FROM_CAMERA, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.FROM_CAMERA) }); Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_CUSTOM, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.CUSTOM) }); + createdAudioListenerModeMenu = true; } if (!Menu.menuItemExists(AUDIO_MENU, AUDIO_STEREO_INPUT)) { diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 84d66fc285..32198c5524 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4024,7 +4024,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri // hook our avatar and avatar hash map object into this script engine scriptEngine->registerGlobalObject("MyAvatar", _myAvatar); - qScriptRegisterMetaType(scriptEngine, maAudioListenModeToScriptValue, maAudioListenModeFromScriptValue); + qScriptRegisterMetaType(scriptEngine, audioListenModeToScriptValue, audioListenModeFromScriptValue); scriptEngine->registerGlobalObject("AvatarList", DependencyManager::get().data()); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 2b695f3fe2..a80cb456ef 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1839,10 +1839,10 @@ void MyAvatar::setAudioListenerMode(AudioListenerMode audioListenerMode) { } } -QScriptValue maAudioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode) { +QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode) { return audioListenerMode; } -void maAudioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode) { +void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode) { audioListenerMode = (AudioListenerMode)object.toUInt16(); } diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index d916977ad5..3452a68c47 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -359,7 +359,7 @@ private: glm::quat _customListenOrientation; }; -QScriptValue maAudioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); -void maAudioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode); +QScriptValue audioListenModeToScriptValue(QScriptEngine* engine, const AudioListenerMode& audioListenerMode); +void audioListenModeFromScriptValue(const QScriptValue& object, AudioListenerMode& audioListenerMode); #endif // hifi_MyAvatar_h From 4d26eb5258e5988d1ebf859c3a67ec137a6a0aad Mon Sep 17 00:00:00 2001 From: Thijs Wenker Date: Tue, 22 Sep 2015 16:20:58 +0200 Subject: [PATCH 4/4] - added some comments - replaced repetitious code with loop - fixed the audioListenerModeChanged signal (forgot connect call) --- examples/utilities/tools/developerMenuItems.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/examples/utilities/tools/developerMenuItems.js b/examples/utilities/tools/developerMenuItems.js index 3fe3a10be7..ef8be8aaa9 100644 --- a/examples/utilities/tools/developerMenuItems.js +++ b/examples/utilities/tools/developerMenuItems.js @@ -34,9 +34,14 @@ var AUDIO_LISTENER_MODE_MENU = AUDIO_MENU + " > Audio Listener Mode" var AUDIO_LISTENER_MODE_FROM_HEAD = "Audio from head"; var AUDIO_LISTENER_MODE_FROM_CAMERA = "Audio from camera"; var AUDIO_LISTENER_MODE_CUSTOM = "Audio from custom position"; + +// be sure that the audio listener options are in the right order (same as the enumerator) var AUDIO_LISTENER_OPTIONS = [ + // MyAvatar.FROM_HEAD (0) AUDIO_LISTENER_MODE_FROM_HEAD, + // MyAvatar.FROM_CAMERA (1) AUDIO_LISTENER_MODE_FROM_CAMERA, + // MyAvatar.CUSTOM (2) AUDIO_LISTENER_MODE_CUSTOM ]; var AUDIO_STEREO_INPUT = "Stereo Input"; @@ -92,9 +97,9 @@ function setupMenus() { if (!Menu.menuExists(AUDIO_LISTENER_MODE_MENU)) { Menu.addMenu(AUDIO_LISTENER_MODE_MENU); - Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_FROM_HEAD, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.FROM_HEAD) }); - Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_FROM_CAMERA, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.FROM_CAMERA) }); - Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_MODE_CUSTOM, isCheckable: true, isChecked: (MyAvatar.audioListenerMode === MyAvatar.CUSTOM) }); + for (var i = 0; i < AUDIO_LISTENER_OPTIONS.length; i++) { + Menu.addMenuItem({ menuName: AUDIO_LISTENER_MODE_MENU, menuItemName: AUDIO_LISTENER_OPTIONS[i], isCheckable: true, isChecked: (MyAvatar.audioListenerMode === i) }); + } createdAudioListenerModeMenu = true; } @@ -130,10 +135,10 @@ Menu.menuItemEvent.connect(function (menuItem) { } }); -MyAvatar.audioListenerModeChanged(function() { +MyAvatar.audioListenerModeChanged.connect(function() { for (var i = 0; i < AUDIO_LISTENER_OPTIONS.length; i++) { Menu.setIsOptionChecked(AUDIO_LISTENER_OPTIONS[i], (MyAvatar.audioListenerMode === i)); - } + } }); Scene.shouldRenderAvatarsChanged.connect(function(shouldRenderAvatars) {