mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
Merge remote-tracking branch 'upstream/master' into smarter_textures
This commit is contained in:
commit
3bef5ad528
47 changed files with 612 additions and 1353 deletions
|
@ -241,6 +241,7 @@ void AudioMixer::sendStatsPacket() {
|
|||
|
||||
statsObject["avg_streams_per_frame"] = (float)_stats.sumStreams / (float)_numStatFrames;
|
||||
statsObject["avg_listeners_per_frame"] = (float)_stats.sumListeners / (float)_numStatFrames;
|
||||
statsObject["avg_listeners_(silent)_per_frame"] = (float)_stats.sumListenersSilent / (float)_numStatFrames;
|
||||
|
||||
statsObject["silent_packets_per_frame"] = (float)_numSilentPackets / (float)_numStatFrames;
|
||||
|
||||
|
|
|
@ -106,6 +106,7 @@ void AudioMixerSlave::mix(const SharedNodePointer& node) {
|
|||
|
||||
sendMixPacket(node, *data, encodedBuffer);
|
||||
} else {
|
||||
++stats.sumListenersSilent;
|
||||
sendSilentPacket(node, *data);
|
||||
}
|
||||
|
||||
|
@ -221,17 +222,19 @@ bool AudioMixerSlave::prepareMix(const SharedNodePointer& listener) {
|
|||
stats.mixTime += mixTime.count();
|
||||
#endif
|
||||
|
||||
// use the per listener AudioLimiter to render the mixed data...
|
||||
listenerData->audioLimiter.render(_mixSamples, _bufferSamples, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||
|
||||
// check for silent audio after the peak limiter has converted the samples
|
||||
// check for silent audio before limiting
|
||||
// limiting uses a dither and can only guarantee abs(sample) <= 1
|
||||
bool hasAudio = false;
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; ++i) {
|
||||
if (_bufferSamples[i] != 0) {
|
||||
if (_mixSamples[i] != 0.0f) {
|
||||
hasAudio = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// use the per listener AudioLimiter to render the mixed data
|
||||
listenerData->audioLimiter.render(_mixSamples, _bufferSamples, AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||
|
||||
return hasAudio;
|
||||
}
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
void AudioMixerStats::reset() {
|
||||
sumStreams = 0;
|
||||
sumListeners = 0;
|
||||
sumListenersSilent = 0;
|
||||
totalMixes = 0;
|
||||
hrtfRenders = 0;
|
||||
hrtfSilentRenders = 0;
|
||||
|
@ -28,6 +29,7 @@ void AudioMixerStats::reset() {
|
|||
void AudioMixerStats::accumulate(const AudioMixerStats& otherStats) {
|
||||
sumStreams += otherStats.sumStreams;
|
||||
sumListeners += otherStats.sumListeners;
|
||||
sumListenersSilent += otherStats.sumListenersSilent;
|
||||
totalMixes += otherStats.totalMixes;
|
||||
hrtfRenders += otherStats.hrtfRenders;
|
||||
hrtfSilentRenders += otherStats.hrtfSilentRenders;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
struct AudioMixerStats {
|
||||
int sumStreams { 0 };
|
||||
int sumListeners { 0 };
|
||||
int sumListenersSilent { 0 };
|
||||
|
||||
int totalMixes { 0 };
|
||||
|
||||
|
|
|
@ -37,7 +37,6 @@ const QString AVATAR_MIXER_LOGGING_NAME = "avatar-mixer";
|
|||
|
||||
// FIXME - what we'd actually like to do is send to users at ~50% of their present rate down to 30hz. Assume 90 for now.
|
||||
const int AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND = 45;
|
||||
const unsigned int AVATAR_DATA_SEND_INTERVAL_MSECS = (1.0f / (float) AVATAR_MIXER_BROADCAST_FRAMES_PER_SECOND) * 1000;
|
||||
|
||||
AvatarMixer::AvatarMixer(ReceivedMessage& message) :
|
||||
ThreadedAssignment(message)
|
||||
|
|
46
interface/resources/icons/tablet-icons/scope-auto.svg
Normal file
46
interface/resources/icons/tablet-icons/scope-auto.svg
Normal file
|
@ -0,0 +1,46 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g id="Layer_2">
|
||||
</g>
|
||||
<g>
|
||||
<path class="st0" d="M25.3,23.7c-0.6,0-1.2,0.2-1.6,0.7S23,25.4,23,26c0,0.6,0.2,1.1,0.7,1.6c0.5,0.5,1,0.7,1.6,0.7
|
||||
c0.6,0,1.2-0.2,1.6-0.7c0.5-0.5,0.7-1,0.7-1.6c0-0.6-0.2-1.2-0.7-1.6C26.5,23.9,26,23.7,25.3,23.7z"/>
|
||||
<path class="st0" d="M25.3,17.2c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C34.4,21.2,30.3,17.2,25.3,17.2z M31.5,26c0,0.3-0.1,0.6-0.3,0.8
|
||||
c-0.2,0.2-0.5,0.3-0.8,0.3c-0.2,0-0.3,0-0.5-0.1c-0.1,0-0.3,0-0.5-0.1c-0.2,0.6-0.3,1.1-0.6,1.4c0.2,0.1,0.3,0.2,0.4,0.3h0.1
|
||||
c0.2,0.1,0.4,0.2,0.4,0.2c0.5,0.5,0.5,1.1,0,1.6c-0.2,0.2-0.5,0.3-0.8,0.3c-0.3,0-0.6-0.1-0.8-0.3c0,0-0.1-0.2-0.2-0.4
|
||||
c0,0,0-0.1-0.1-0.1c-0.1-0.1-0.2-0.2-0.2-0.4c-0.4,0.3-0.9,0.5-1.4,0.6c0.1,0.2,0.1,0.4,0.1,0.5c0.1,0.2,0.1,0.3,0.1,0.5
|
||||
c0,0.3-0.1,0.6-0.3,0.8c-0.2,0.2-0.5,0.3-0.8,0.3c-0.3,0-0.6-0.1-0.8-0.3c-0.2-0.2-0.3-0.5-0.3-0.8c0-0.2,0-0.3,0.1-0.5
|
||||
c0-0.1,0-0.3,0.1-0.5c-0.5-0.1-1-0.3-1.4-0.6c-0.1,0.2-0.2,0.3-0.2,0.4L22.8,30c0,0.1-0.1,0.2-0.2,0.4c-0.2,0.2-0.5,0.3-0.8,0.3
|
||||
c-0.3,0-0.6-0.1-0.8-0.3c-0.5-0.5-0.5-1.1,0-1.6c0.1-0.1,0.2-0.2,0.5-0.2c0-0.1,0.2-0.2,0.4-0.3c-0.2-0.3-0.4-0.8-0.6-1.4
|
||||
C21.1,27,20.9,27,20.7,27V27c-0.1,0.1-0.2,0.1-0.5,0.1c-0.3,0-0.6-0.1-0.8-0.3c-0.2-0.2-0.3-0.5-0.3-0.8c0-0.3,0.1-0.6,0.3-0.8
|
||||
c0.2-0.2,0.5-0.3,0.8-0.3c0.2,0,0.3,0,0.5,0.1c0.1,0,0.3,0,0.5,0.1c0.1-0.5,0.3-1,0.6-1.4c-0.1,0-0.2-0.1-0.4-0.2h-0.1
|
||||
c-0.2-0.1-0.3-0.2-0.4-0.3c-0.5-0.5-0.5-1,0-1.5c0.5-0.5,1.1-0.5,1.6,0c0.1,0.1,0.2,0.2,0.2,0.4c0.1,0.1,0.2,0.2,0.3,0.5
|
||||
c0.4-0.3,0.9-0.5,1.4-0.6c-0.1-0.2-0.1-0.3-0.1-0.5v-0.1c-0.1-0.2-0.1-0.3-0.1-0.5c0-0.3,0.1-0.6,0.3-0.8c0.2-0.2,0.5-0.3,0.8-0.3
|
||||
c0.3,0,0.6,0.1,0.8,0.3c0.2,0.2,0.3,0.5,0.3,0.8c0,0.2,0,0.3-0.1,0.5v0.1c0,0.2,0,0.3-0.1,0.5c0.4,0.1,0.9,0.3,1.4,0.6
|
||||
c0-0.2,0.1-0.3,0.2-0.5c0-0.1,0.1-0.2,0.3-0.4c0.2-0.2,0.4-0.3,0.8-0.3c0.3,0,0.6,0.1,0.8,0.3c0.5,0.5,0.5,1.1,0,1.6
|
||||
c-0.2,0.2-0.3,0.2-0.4,0.3c-0.1,0.1-0.2,0.2-0.5,0.2c0.3,0.5,0.5,1,0.6,1.4c0.2-0.1,0.3-0.1,0.5-0.1H30c0.2-0.1,0.3-0.1,0.5-0.1
|
||||
c0.3,0,0.6,0.1,0.8,0.3C31.4,25.5,31.5,25.7,31.5,26L31.5,26z"/>
|
||||
</g>
|
||||
<path class="st0" d="M22.3,15.4v-2.6c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2v3.5C20.7,15.9,21.5,15.6,22.3,15.4z"/>
|
||||
<path class="st0" d="M25.3,15c0.4,0,0.8,0,1.1,0.1V8.6c0-0.6-0.5-1.2-1.2-1.2S24.1,8,24.1,8.6V15C24.5,15,24.9,15,25.3,15z"/>
|
||||
<path class="st0" d="M30.6,16.3V3.6c0-0.6-0.5-1.2-1.2-1.2S28.3,3,28.3,3.6v11.7C29.1,15.6,29.9,15.9,30.6,16.3z"/>
|
||||
<path class="st0" d="M48,24.9h-0.6v-2.1c0-0.6-0.5-1.2-1.2-1.2S45,22.2,45,22.9v2.1h-1.8V12c0-0.6-0.5-1.2-1.2-1.2s-1.2,0.5-1.2,1.2
|
||||
v12.9H39v-9.6c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2V36c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2v-8.7h1.8v12.9
|
||||
c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2V27.3H45v2.9c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-2.9H48c0.6,0,1.2-0.5,1.2-1.2
|
||||
S48.6,24.9,48,24.9z"/>
|
||||
<path class="st0" d="M13.9,12c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2v12.9H9.7v-4.6c0-0.6-0.5-1.2-1.2-1.2
|
||||
c-0.6,0-1.2,0.5-1.2,1.2v4.6H5.5v-2.1c0-0.6-0.5-1.2-1.2-1.2s-1.2,0.5-1.2,1.2v2.1H2.6c-0.6,0-1.2,0.5-1.2,1.2s0.5,1.2,1.2,1.2h0.6
|
||||
v2.1c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-2.1h1.8v6.2c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2v-6.2h1.8v12.1
|
||||
c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2V12z"/>
|
||||
<path class="st0" d="M28.3,37v9.8c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2V36.1C29.9,36.5,29.1,36.8,28.3,37z"/>
|
||||
<path class="st0" d="M25.3,37.5c-0.4,0-0.8,0-1.2-0.1v4.5c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-4.5
|
||||
C26.1,37.4,25.7,37.5,25.3,37.5z"/>
|
||||
<path class="st0" d="M19.9,36.1v3.3c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2V37C21.5,36.8,20.7,36.5,19.9,36.1z"/>
|
||||
<rect x="12" y="24.6" class="st0" width="6.9" height="3"/>
|
||||
<rect x="32.9" y="24.6" class="st0" width="5.1" height="3"/>
|
||||
</svg>
|
After Width: | Height: | Size: 4 KiB |
30
interface/resources/icons/tablet-icons/scope-pause.svg
Normal file
30
interface/resources/icons/tablet-icons/scope-pause.svg
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g id="Layer_2">
|
||||
</g>
|
||||
<path class="st0" d="M22.3,15.4v-2.6c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2v3.5C20.7,15.9,21.5,15.6,22.3,15.4z"/>
|
||||
<path class="st0" d="M25.3,15c0.4,0,0.8,0,1.1,0.1V8.6c0-0.6-0.5-1.2-1.2-1.2S24.1,8,24.1,8.6V15C24.5,15,24.9,15,25.3,15z"/>
|
||||
<path class="st0" d="M30.6,16.3V3.6c0-0.6-0.5-1.2-1.2-1.2S28.3,3,28.3,3.6v11.7C29.1,15.6,29.9,15.9,30.6,16.3z"/>
|
||||
<path class="st0" d="M48,24.9h-0.6v-2.1c0-0.6-0.5-1.2-1.2-1.2S45,22.2,45,22.9v2.1h-1.8V12c0-0.6-0.5-1.2-1.2-1.2s-1.2,0.5-1.2,1.2
|
||||
v12.9H39v-9.6c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2V36c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2v-8.7h1.8v12.9
|
||||
c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2V27.3H45v2.9c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-2.9H48c0.6,0,1.2-0.5,1.2-1.2
|
||||
S48.6,24.9,48,24.9z"/>
|
||||
<path class="st0" d="M13.9,12c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2v12.9H9.7v-4.6c0-0.6-0.5-1.2-1.2-1.2
|
||||
c-0.6,0-1.2,0.5-1.2,1.2v4.6H5.5v-2.1c0-0.6-0.5-1.2-1.2-1.2s-1.2,0.5-1.2,1.2v2.1H2.6c-0.6,0-1.2,0.5-1.2,1.2s0.5,1.2,1.2,1.2h0.6
|
||||
v2.1c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-2.1h1.8v6.2c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2v-6.2h1.8v12.1
|
||||
c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2V12z"/>
|
||||
<path class="st0" d="M28.3,37v9.8c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2V36.1C29.9,36.5,29.1,36.8,28.3,37z"/>
|
||||
<path class="st0" d="M25.3,37.5c-0.4,0-0.8,0-1.2-0.1v4.5c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-4.5
|
||||
C26.1,37.4,25.7,37.5,25.3,37.5z"/>
|
||||
<path class="st0" d="M19.9,36.1v3.3c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2V37C21.5,36.8,20.7,36.5,19.9,36.1z"/>
|
||||
<rect x="12" y="24.6" class="st0" width="7.3" height="3"/>
|
||||
<rect x="32.9" y="24.6" class="st0" width="5.3" height="3"/>
|
||||
<path class="st0" d="M25.3,17c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C34.4,21,30.3,17,25.3,17z M24.1,29.7c0,0.5-0.6,1-1.4,1
|
||||
s-1.4-0.4-1.4-1v-7.3c0-0.5,0.6-1,1.4-1s1.4,0.4,1.4,1V29.7z M29.3,29.7c0,0.5-0.6,1-1.4,1c-0.8,0-1.4-0.4-1.4-1v-7.3
|
||||
c0-0.5,0.6-1,1.4-1c0.8,0,1.4,0.4,1.4,1V29.7z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
30
interface/resources/icons/tablet-icons/scope-play.svg
Normal file
30
interface/resources/icons/tablet-icons/scope-play.svg
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
||||
viewBox="0 0 50 50" style="enable-background:new 0 0 50 50;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<g id="Layer_2">
|
||||
</g>
|
||||
<path class="st0" d="M22.3,15.4v-2.6c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2v3.5C20.7,15.9,21.5,15.6,22.3,15.4z"/>
|
||||
<path class="st0" d="M25.3,15c0.4,0,0.8,0,1.1,0.1V8.6c0-0.6-0.5-1.2-1.2-1.2S24.1,8,24.1,8.6V15C24.5,15,24.9,15,25.3,15z"/>
|
||||
<path class="st0" d="M30.6,16.3V3.6c0-0.6-0.5-1.2-1.2-1.2S28.3,3,28.3,3.6v11.7C29.1,15.6,29.9,15.9,30.6,16.3z"/>
|
||||
<path class="st0" d="M48,24.9h-0.6v-2.1c0-0.6-0.5-1.2-1.2-1.2S45,22.2,45,22.9v2.1h-1.8V12c0-0.6-0.5-1.2-1.2-1.2s-1.2,0.5-1.2,1.2
|
||||
v12.9H39v-9.6c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2V36c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2v-8.7h1.8v12.9
|
||||
c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2V27.3H45v2.9c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-2.9H48c0.6,0,1.2-0.5,1.2-1.2
|
||||
S48.6,24.9,48,24.9z"/>
|
||||
<path class="st0" d="M13.9,12c0-0.6-0.5-1.2-1.2-1.2c-0.6,0-1.2,0.5-1.2,1.2v12.9H9.7v-4.6c0-0.6-0.5-1.2-1.2-1.2
|
||||
c-0.6,0-1.2,0.5-1.2,1.2v4.6H5.5v-2.1c0-0.6-0.5-1.2-1.2-1.2s-1.2,0.5-1.2,1.2v2.1H2.6c-0.6,0-1.2,0.5-1.2,1.2s0.5,1.2,1.2,1.2h0.6
|
||||
v2.1c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-2.1h1.8v6.2c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2v-6.2h1.8v12.1
|
||||
c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2V12z"/>
|
||||
<path class="st0" d="M28.3,37v9.8c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2V36.1C29.9,36.5,29.1,36.8,28.3,37z"/>
|
||||
<path class="st0" d="M25.3,37.5c-0.4,0-0.8,0-1.2-0.1v4.5c0,0.6,0.5,1.2,1.2,1.2s1.2-0.5,1.2-1.2v-4.5
|
||||
C26.1,37.4,25.7,37.5,25.3,37.5z"/>
|
||||
<path class="st0" d="M19.9,36.1v3.3c0,0.6,0.5,1.2,1.2,1.2c0.6,0,1.2-0.5,1.2-1.2V37C21.5,36.8,20.7,36.5,19.9,36.1z"/>
|
||||
<path class="st0" d="M25.3,17.2c-5,0-9,4-9,9c0,5,4,9,9,9s9-4,9-9C34.4,21.2,30.3,17.2,25.3,17.2z M30.3,26.1l-6,5.4
|
||||
c-0.1,0.1-0.2,0.1-0.4,0.1c-0.1,0-0.3,0-0.3-0.1c-0.3-0.1-0.5-0.4-0.5-0.5V20.9c0-0.1,0.2-0.4,0.4-0.5c0.1,0,0.2-0.1,0.3-0.1
|
||||
c0.2,0,0.3,0,0.4,0.1l6,4.8c0.1,0.1,0.2,0.3,0.2,0.4C30.5,25.8,30.4,26,30.3,26.1z"/>
|
||||
<rect x="12" y="24.6" class="st0" width="7.3" height="3"/>
|
||||
<rect x="32.9" y="24.6" class="st0" width="7.3" height="3"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.3 KiB |
|
@ -181,6 +181,31 @@ Item {
|
|||
root.avatarMixerOutPps + "pps, " +
|
||||
root.myAvatarSendRate.toFixed(2) + "hz";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio Mixer In: " + root.audioMixerInKbps + " kbps, " +
|
||||
root.audioMixerInPps + "pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio In Audio: " + root.audioAudioInboundPPS + " pps, " +
|
||||
"Silent: " + root.audioSilentInboundPPS + " pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio Mixer Out: " + root.audioMixerOutKbps + " kbps, " +
|
||||
root.audioMixerOutPps + "pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio Out Mic: " + root.audioMicOutboundPPS + " pps, " +
|
||||
"Silent: " + root.audioSilentOutboundPPS + " pps";
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Audio Codec: " + root.audioCodec + " Noise Gate: " +
|
||||
root.audioNoiseGate;
|
||||
}
|
||||
StatText {
|
||||
visible: root.expanded;
|
||||
text: "Downloads: " + root.downloads + "/" + root.downloadLimit +
|
||||
|
|
|
@ -1182,6 +1182,10 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
// set the local loopback interface for local sounds
|
||||
AudioInjector::setLocalAudioInterface(audioIO.data());
|
||||
AudioScriptingInterface::getInstance().setLocalAudioInterface(audioIO.data());
|
||||
connect(audioIO.data(), &AudioClient::noiseGateOpened, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::noiseGateOpened);
|
||||
connect(audioIO.data(), &AudioClient::noiseGateClosed, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::noiseGateClosed);
|
||||
connect(audioIO.data(), &AudioClient::inputReceived, &AudioScriptingInterface::getInstance(), &AudioScriptingInterface::inputReceived);
|
||||
|
||||
|
||||
this->installEventFilter(this);
|
||||
|
||||
|
@ -1947,6 +1951,8 @@ void Application::initializeUi() {
|
|||
rootContext->setContextProperty("ApplicationInterface", this);
|
||||
rootContext->setContextProperty("Audio", &AudioScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
rootContext->setContextProperty("AudioScope", DependencyManager::get<AudioScope>().data());
|
||||
|
||||
rootContext->setContextProperty("Controller", DependencyManager::get<controller::ScriptingInterface>().data());
|
||||
rootContext->setContextProperty("Entities", DependencyManager::get<EntityScriptingInterface>().data());
|
||||
_fileDownload = new FileScriptingInterface(engine);
|
||||
|
@ -3174,7 +3180,23 @@ void Application::mousePressEvent(QMouseEvent* event) {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::mouseDoublePressEvent(QMouseEvent* event) const {
|
||||
void Application::mouseDoublePressEvent(QMouseEvent* event) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto eventPosition = getApplicationCompositor().getMouseEventPosition(event);
|
||||
QPointF transformedPos = offscreenUi->mapToVirtualScreen(eventPosition, _glWidget);
|
||||
QMouseEvent mappedEvent(event->type(),
|
||||
transformedPos,
|
||||
event->screenPos(), event->button(),
|
||||
event->buttons(), event->modifiers());
|
||||
|
||||
if (!_aboutToQuit) {
|
||||
getOverlays().mouseDoublePressEvent(&mappedEvent);
|
||||
if (!_controllerScriptingInterface->areEntityClicksCaptured()) {
|
||||
getEntities()->mouseDoublePressEvent(&mappedEvent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if one of our scripts have asked to capture this event, then stop processing it
|
||||
if (_controllerScriptingInterface->isMouseCaptured()) {
|
||||
return;
|
||||
|
@ -5521,6 +5543,7 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("Settings", SettingsScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get<AudioScope>().data());
|
||||
|
||||
// Caches
|
||||
scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||
|
|
|
@ -494,7 +494,7 @@ private:
|
|||
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseDoublePressEvent(QMouseEvent* event) const;
|
||||
void mouseDoublePressEvent(QMouseEvent* event);
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
|
||||
void touchBeginEvent(QTouchEvent* event);
|
||||
|
|
|
@ -52,12 +52,14 @@ AudioScope::AudioScope() :
|
|||
connect(audioIO.data(), &AudioClient::inputReceived, this, &AudioScope::addInputToScope);
|
||||
}
|
||||
|
||||
void AudioScope::toggle() {
|
||||
_isEnabled = !_isEnabled;
|
||||
if (_isEnabled) {
|
||||
allocateScope();
|
||||
} else {
|
||||
freeScope();
|
||||
void AudioScope::setVisible(bool visible) {
|
||||
if (_isEnabled != visible) {
|
||||
_isEnabled = visible;
|
||||
if (_isEnabled) {
|
||||
allocateScope();
|
||||
} else {
|
||||
freeScope();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,14 @@ public:
|
|||
void render(RenderArgs* renderArgs, int width, int height);
|
||||
|
||||
public slots:
|
||||
void toggle();
|
||||
void toggle() { setVisible(!_isEnabled); }
|
||||
void setVisible(bool visible);
|
||||
bool getVisible() const { return _isEnabled; }
|
||||
|
||||
void togglePause() { _isPaused = !_isPaused; }
|
||||
void setPause(bool paused) { _isPaused = paused; }
|
||||
bool getPause() { return _isPaused; }
|
||||
|
||||
void selectAudioScopeFiveFrames();
|
||||
void selectAudioScopeTwentyFrames();
|
||||
void selectAudioScopeFiftyFrames();
|
||||
|
@ -74,7 +80,6 @@ private:
|
|||
int _inputID;
|
||||
int _outputLeftID;
|
||||
int _outputRightD;
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_AudioScope_h
|
||||
|
|
|
@ -81,6 +81,10 @@ void HMDScriptingInterface::closeTablet() {
|
|||
_showTablet = false;
|
||||
}
|
||||
|
||||
void HMDScriptingInterface::openTablet() {
|
||||
_showTablet = true;
|
||||
}
|
||||
|
||||
QScriptValue HMDScriptingInterface::getHUDLookAtPosition2D(QScriptContext* context, QScriptEngine* engine) {
|
||||
glm::vec3 hudIntersection;
|
||||
auto instance = DependencyManager::get<HMDScriptingInterface>();
|
||||
|
|
|
@ -76,6 +76,8 @@ public:
|
|||
|
||||
Q_INVOKABLE void closeTablet();
|
||||
|
||||
Q_INVOKABLE void openTablet();
|
||||
|
||||
signals:
|
||||
bool shouldShowHandControllersChanged();
|
||||
|
||||
|
|
|
@ -200,15 +200,16 @@ void Stats::updateStats(bool force) {
|
|||
STAT_UPDATE(avatarMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AvatarMixer)));
|
||||
STAT_UPDATE(avatarMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AvatarMixer)));
|
||||
STAT_UPDATE(avatarMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AvatarMixer)));
|
||||
STAT_UPDATE(myAvatarSendRate, avatarManager->getMyAvatarSendRate());
|
||||
} else {
|
||||
STAT_UPDATE(avatarMixerInKbps, -1);
|
||||
STAT_UPDATE(avatarMixerInPps, -1);
|
||||
STAT_UPDATE(avatarMixerOutKbps, -1);
|
||||
STAT_UPDATE(avatarMixerOutPps, -1);
|
||||
STAT_UPDATE(myAvatarSendRate, avatarManager->getMyAvatarSendRate());
|
||||
}
|
||||
STAT_UPDATE(myAvatarSendRate, avatarManager->getMyAvatarSendRate());
|
||||
|
||||
SharedNodePointer audioMixerNode = nodeList->soloNodeOfType(NodeType::AudioMixer);
|
||||
auto audioClient = DependencyManager::get<AudioClient>();
|
||||
if (audioMixerNode || force) {
|
||||
STAT_UPDATE(audioMixerKbps, roundf(
|
||||
bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer) +
|
||||
|
@ -216,10 +217,30 @@ void Stats::updateStats(bool force) {
|
|||
STAT_UPDATE(audioMixerPps, roundf(
|
||||
bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer) +
|
||||
bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
||||
|
||||
STAT_UPDATE(audioMixerInKbps, roundf(bandwidthRecorder->getAverageInputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerInPps, roundf(bandwidthRecorder->getAverageInputPacketsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerOutKbps, roundf(bandwidthRecorder->getAverageOutputKilobitsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMixerOutPps, roundf(bandwidthRecorder->getAverageOutputPacketsPerSecond(NodeType::AudioMixer)));
|
||||
STAT_UPDATE(audioMicOutboundPPS, audioClient->getMicAudioOutboundPPS());
|
||||
STAT_UPDATE(audioSilentOutboundPPS, audioClient->getSilentOutboundPPS());
|
||||
STAT_UPDATE(audioAudioInboundPPS, audioClient->getAudioInboundPPS());
|
||||
STAT_UPDATE(audioSilentInboundPPS, audioClient->getSilentInboundPPS());
|
||||
} else {
|
||||
STAT_UPDATE(audioMixerKbps, -1);
|
||||
STAT_UPDATE(audioMixerPps, -1);
|
||||
STAT_UPDATE(audioMixerInKbps, -1);
|
||||
STAT_UPDATE(audioMixerInPps, -1);
|
||||
STAT_UPDATE(audioMixerOutKbps, -1);
|
||||
STAT_UPDATE(audioMixerOutPps, -1);
|
||||
STAT_UPDATE(audioMicOutboundPPS, -1);
|
||||
STAT_UPDATE(audioSilentOutboundPPS, -1);
|
||||
STAT_UPDATE(audioAudioInboundPPS, -1);
|
||||
STAT_UPDATE(audioSilentInboundPPS, -1);
|
||||
}
|
||||
STAT_UPDATE(audioCodec, audioClient->getSelectedAudioFormat());
|
||||
STAT_UPDATE(audioNoiseGate, audioClient->getNoiseGateOpen() ? "Open" : "Closed");
|
||||
|
||||
|
||||
auto loadingRequests = ResourceCache::getLoadingRequests();
|
||||
STAT_UPDATE(downloads, loadingRequests.size());
|
||||
|
|
|
@ -70,8 +70,20 @@ class Stats : public QQuickItem {
|
|||
STATS_PROPERTY(int, avatarMixerOutKbps, 0)
|
||||
STATS_PROPERTY(int, avatarMixerOutPps, 0)
|
||||
STATS_PROPERTY(float, myAvatarSendRate, 0)
|
||||
|
||||
STATS_PROPERTY(int, audioMixerInKbps, 0)
|
||||
STATS_PROPERTY(int, audioMixerInPps, 0)
|
||||
STATS_PROPERTY(int, audioMixerOutKbps, 0)
|
||||
STATS_PROPERTY(int, audioMixerOutPps, 0)
|
||||
STATS_PROPERTY(int, audioMixerKbps, 0)
|
||||
STATS_PROPERTY(int, audioMixerPps, 0)
|
||||
STATS_PROPERTY(int, audioMicOutboundPPS, 0)
|
||||
STATS_PROPERTY(int, audioSilentOutboundPPS, 0)
|
||||
STATS_PROPERTY(int, audioAudioInboundPPS, 0)
|
||||
STATS_PROPERTY(int, audioSilentInboundPPS, 0)
|
||||
STATS_PROPERTY(QString, audioCodec, QString())
|
||||
STATS_PROPERTY(QString, audioNoiseGate, QString())
|
||||
|
||||
STATS_PROPERTY(int, downloads, 0)
|
||||
STATS_PROPERTY(int, downloadLimit, 0)
|
||||
STATS_PROPERTY(int, downloadsPending, 0)
|
||||
|
@ -182,8 +194,19 @@ signals:
|
|||
void avatarMixerOutKbpsChanged();
|
||||
void avatarMixerOutPpsChanged();
|
||||
void myAvatarSendRateChanged();
|
||||
void audioMixerInKbpsChanged();
|
||||
void audioMixerInPpsChanged();
|
||||
void audioMixerOutKbpsChanged();
|
||||
void audioMixerOutPpsChanged();
|
||||
void audioMixerKbpsChanged();
|
||||
void audioMixerPpsChanged();
|
||||
void audioMicOutboundPPSChanged();
|
||||
void audioSilentOutboundPPSChanged();
|
||||
void audioAudioInboundPPSChanged();
|
||||
void audioSilentInboundPPSChanged();
|
||||
void audioCodecChanged();
|
||||
void audioNoiseGateChanged();
|
||||
|
||||
void downloadsChanged();
|
||||
void downloadLimitChanged();
|
||||
void downloadsPendingChanged();
|
||||
|
|
|
@ -258,8 +258,3 @@ QVariant Line3DOverlay::getProperty(const QString& property) {
|
|||
Line3DOverlay* Line3DOverlay::createClone() const {
|
||||
return new Line3DOverlay(this);
|
||||
}
|
||||
|
||||
|
||||
void Line3DOverlay::locationChanged(bool tellPhysics) {
|
||||
// do nothing
|
||||
}
|
||||
|
|
|
@ -48,8 +48,6 @@ public:
|
|||
|
||||
virtual Line3DOverlay* createClone() const override;
|
||||
|
||||
virtual void locationChanged(bool tellPhysics = true) override;
|
||||
|
||||
glm::vec3 getDirection() const { return _direction; }
|
||||
float getLength() const { return _length; }
|
||||
glm::vec3 getLocalStart() const { return getLocalPosition(); }
|
||||
|
|
|
@ -769,6 +769,26 @@ bool Overlays::mousePressEvent(QMouseEvent* event) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Overlays::mouseDoublePressEvent(QMouseEvent* event) {
|
||||
PerformanceTimer perfTimer("Overlays::mouseDoublePressEvent");
|
||||
|
||||
PickRay ray = qApp->computePickRay(event->x(), event->y());
|
||||
RayToOverlayIntersectionResult rayPickResult = findRayIntersectionForMouseEvent(ray);
|
||||
if (rayPickResult.intersects) {
|
||||
_currentClickingOnOverlayID = rayPickResult.overlayID;
|
||||
|
||||
// Only Web overlays can have focus.
|
||||
auto thisOverlay = std::dynamic_pointer_cast<Web3DOverlay>(getOverlay(_currentClickingOnOverlayID));
|
||||
if (thisOverlay) {
|
||||
auto pointerEvent = calculatePointerEvent(thisOverlay, ray, rayPickResult, event, PointerEvent::Press);
|
||||
emit mouseDoublePressOnOverlay(_currentClickingOnOverlayID, pointerEvent);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
emit mouseDoublePressOffOverlay();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Overlays::mouseReleaseEvent(QMouseEvent* event) {
|
||||
PerformanceTimer perfTimer("Overlays::mouseReleaseEvent");
|
||||
|
||||
|
|
|
@ -101,6 +101,7 @@ public:
|
|||
OverlayID addOverlay(Overlay::Pointer overlay);
|
||||
|
||||
bool mousePressEvent(QMouseEvent* event);
|
||||
bool mouseDoublePressEvent(QMouseEvent* event);
|
||||
bool mouseReleaseEvent(QMouseEvent* event);
|
||||
bool mouseMoveEvent(QMouseEvent* event);
|
||||
|
||||
|
@ -300,9 +301,11 @@ signals:
|
|||
void panelDeleted(OverlayID id);
|
||||
|
||||
void mousePressOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||
void mouseDoublePressOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||
void mouseReleaseOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||
void mouseMoveOnOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||
void mousePressOffOverlay();
|
||||
void mouseDoublePressOffOverlay();
|
||||
|
||||
void hoverEnterOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||
void hoverOverOverlay(OverlayID overlayID, const PointerEvent& event);
|
||||
|
|
|
@ -1310,17 +1310,18 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
|||
if (!_animSkeleton) {
|
||||
return;
|
||||
}
|
||||
if (jointDataVec.size() != (int)_internalPoseSet._relativePoses.size()) {
|
||||
// animations haven't fully loaded yet.
|
||||
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
int numJoints = jointDataVec.size();
|
||||
const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses();
|
||||
if (numJoints != (int)absoluteDefaultPoses.size()) {
|
||||
// jointData is incompatible
|
||||
return;
|
||||
}
|
||||
|
||||
// make a vector of rotations in absolute-geometry-frame
|
||||
const AnimPoseVec& absoluteDefaultPoses = _animSkeleton->getAbsoluteDefaultPoses();
|
||||
std::vector<glm::quat> rotations;
|
||||
rotations.reserve(absoluteDefaultPoses.size());
|
||||
rotations.reserve(numJoints);
|
||||
const glm::quat rigToGeometryRot(glmExtractRotation(_rigToGeometryTransform));
|
||||
for (int i = 0; i < jointDataVec.size(); i++) {
|
||||
for (int i = 0; i < numJoints; i++) {
|
||||
const JointData& data = jointDataVec.at(i);
|
||||
if (data.rotationSet) {
|
||||
// JointData rotations are in absolute rig-frame so we rotate them to absolute geometry-frame
|
||||
|
@ -1334,8 +1335,11 @@ void Rig::copyJointsFromJointData(const QVector<JointData>& jointDataVec) {
|
|||
_animSkeleton->convertAbsoluteRotationsToRelative(rotations);
|
||||
|
||||
// store new relative poses
|
||||
if (numJoints != (int)_internalPoseSet._relativePoses.size()) {
|
||||
_internalPoseSet._relativePoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
}
|
||||
const AnimPoseVec& relativeDefaultPoses = _animSkeleton->getRelativeDefaultPoses();
|
||||
for (int i = 0; i < jointDataVec.size(); i++) {
|
||||
for (int i = 0; i < numJoints; i++) {
|
||||
const JointData& data = jointDataVec.at(i);
|
||||
_internalPoseSet._relativePoses[i].scale() = Vectors::ONE;
|
||||
_internalPoseSet._relativePoses[i].rot() = rotations[i];
|
||||
|
|
|
@ -608,6 +608,13 @@ void AudioClient::handleAudioEnvironmentDataPacket(QSharedPointer<ReceivedMessag
|
|||
}
|
||||
|
||||
void AudioClient::handleAudioDataPacket(QSharedPointer<ReceivedMessage> message) {
|
||||
|
||||
if (message->getType() == PacketType::SilentAudioFrame) {
|
||||
_silentInbound.increment();
|
||||
} else {
|
||||
_audioInbound.increment();
|
||||
}
|
||||
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->flagTimeForConnectionStep(LimitedNodeList::ConnectionStep::ReceiveFirstAudioPacket);
|
||||
|
||||
|
@ -1024,6 +1031,7 @@ void AudioClient::handleAudioInput() {
|
|||
if (_inputGate.clippedInLastFrame()) {
|
||||
_timeSinceLastClip = 0.0f;
|
||||
}
|
||||
|
||||
} else {
|
||||
float loudness = 0.0f;
|
||||
|
||||
|
@ -1041,6 +1049,13 @@ void AudioClient::handleAudioInput() {
|
|||
|
||||
emit inputReceived({ reinterpret_cast<char*>(networkAudioSamples), numNetworkBytes });
|
||||
|
||||
if (_inputGate.openedInLastFrame()) {
|
||||
emit noiseGateOpened();
|
||||
}
|
||||
if (_inputGate.closedInLastFrame()) {
|
||||
emit noiseGateClosed();
|
||||
}
|
||||
|
||||
} else {
|
||||
// our input loudness is 0, since we're muted
|
||||
_lastInputLoudness = 0;
|
||||
|
@ -1052,9 +1067,18 @@ void AudioClient::handleAudioInput() {
|
|||
auto packetType = _shouldEchoToServer ?
|
||||
PacketType::MicrophoneAudioWithEcho : PacketType::MicrophoneAudioNoEcho;
|
||||
|
||||
if (_lastInputLoudness == 0) {
|
||||
// if the _inputGate closed in this last frame, then we don't actually want
|
||||
// to send a silent packet, instead, we want to go ahead and encode and send
|
||||
// the output from the input gate (eventually, this could be crossfaded)
|
||||
// and allow the codec to properly encode down to silent/zero. If we still
|
||||
// have _lastInputLoudness of 0 in our NEXT frame, we will send a silent packet
|
||||
if (_lastInputLoudness == 0 && !_inputGate.closedInLastFrame()) {
|
||||
packetType = PacketType::SilentAudioFrame;
|
||||
_silentOutbound.increment();
|
||||
} else {
|
||||
_micAudioOutbound.increment();
|
||||
}
|
||||
|
||||
Transform audioTransform;
|
||||
audioTransform.setTranslation(_positionGetter());
|
||||
audioTransform.setRotation(_orientationGetter());
|
||||
|
@ -1079,6 +1103,7 @@ void AudioClient::handleAudioInput() {
|
|||
}
|
||||
}
|
||||
|
||||
// FIXME - should this go through the noise gate and honor mute and echo?
|
||||
void AudioClient::handleRecordedAudioInput(const QByteArray& audio) {
|
||||
Transform audioTransform;
|
||||
audioTransform.setTranslation(_positionGetter());
|
||||
|
@ -1091,6 +1116,8 @@ void AudioClient::handleRecordedAudioInput(const QByteArray& audio) {
|
|||
encodedBuffer = audio;
|
||||
}
|
||||
|
||||
_micAudioOutbound.increment();
|
||||
|
||||
// FIXME check a flag to see if we should echo audio?
|
||||
emitAudioPacket(encodedBuffer.data(), encodedBuffer.size(), _outgoingAvatarAudioSequenceNumber,
|
||||
audioTransform, avatarBoundingBoxCorner, avatarBoundingBoxScale,
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
#include <AudioLimiter.h>
|
||||
#include <AudioConstants.h>
|
||||
|
||||
#include <shared/RateCounter.h>
|
||||
|
||||
#include <plugins/CodecPlugin.h>
|
||||
|
||||
#include "AudioIOStats.h"
|
||||
|
@ -121,6 +123,13 @@ public:
|
|||
void negotiateAudioFormat();
|
||||
void selectAudioFormat(const QString& selectedCodecName);
|
||||
|
||||
Q_INVOKABLE QString getSelectedAudioFormat() const { return _selectedCodecName; }
|
||||
Q_INVOKABLE bool getNoiseGateOpen() const { return _inputGate.isOpen(); }
|
||||
Q_INVOKABLE float getSilentOutboundPPS() const { return _silentOutbound.rate(); }
|
||||
Q_INVOKABLE float getMicAudioOutboundPPS() const { return _micAudioOutbound.rate(); }
|
||||
Q_INVOKABLE float getSilentInboundPPS() const { return _silentInbound.rate(); }
|
||||
Q_INVOKABLE float getAudioInboundPPS() const { return _audioInbound.rate(); }
|
||||
|
||||
const MixedProcessedAudioStream& getReceivedAudioStream() const { return _receivedAudioStream; }
|
||||
MixedProcessedAudioStream& getReceivedAudioStream() { return _receivedAudioStream; }
|
||||
|
||||
|
@ -218,6 +227,8 @@ signals:
|
|||
void inputReceived(const QByteArray& inputSamples);
|
||||
void outputBytesToNetwork(int numBytes);
|
||||
void inputBytesFromNetwork(int numBytes);
|
||||
void noiseGateOpened();
|
||||
void noiseGateClosed();
|
||||
|
||||
void changeDevice(const QAudioDeviceInfo& outputDeviceInfo);
|
||||
void deviceChanged();
|
||||
|
@ -382,6 +393,11 @@ private:
|
|||
Encoder* _encoder { nullptr }; // for outbound mic stream
|
||||
|
||||
QThread* _checkDevicesThread { nullptr };
|
||||
|
||||
RateCounter<> _silentOutbound;
|
||||
RateCounter<> _micAudioOutbound;
|
||||
RateCounter<> _silentInbound;
|
||||
RateCounter<> _audioInbound;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ void AudioNoiseGate::removeDCOffset(int16_t* samples, int numSamples) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) {
|
||||
//
|
||||
// Impose Noise Gate
|
||||
|
@ -77,8 +76,7 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) {
|
|||
// NOISE_GATE_FRAMES_TO_AVERAGE: How many audio frames should we average together to compute noise floor.
|
||||
// More means better rejection but also can reject continuous things like singing.
|
||||
// NUMBER_OF_NOISE_SAMPLE_FRAMES: How often should we re-evaluate the noise floor?
|
||||
|
||||
|
||||
|
||||
float loudness = 0;
|
||||
int thisSample = 0;
|
||||
int samplesOverNoiseGate = 0;
|
||||
|
@ -142,16 +140,38 @@ void AudioNoiseGate::gateSamples(int16_t* samples, int numSamples) {
|
|||
_sampleCounter = 0;
|
||||
|
||||
}
|
||||
|
||||
_closedInLastFrame = false;
|
||||
_openedInLastFrame = false;
|
||||
|
||||
if (samplesOverNoiseGate > NOISE_GATE_WIDTH) {
|
||||
_openedInLastFrame = !_isOpen;
|
||||
_isOpen = true;
|
||||
_framesToClose = NOISE_GATE_CLOSE_FRAME_DELAY;
|
||||
} else {
|
||||
if (--_framesToClose == 0) {
|
||||
_closedInLastFrame = _isOpen;
|
||||
_isOpen = false;
|
||||
}
|
||||
}
|
||||
if (!_isOpen) {
|
||||
memset(samples, 0, numSamples * sizeof(int16_t));
|
||||
if (_closedInLastFrame) {
|
||||
// would be nice to do a little crossfade to silence
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
float fadedSample = (1.0f - (float)i / (float)numSamples) * (float)samples[i];
|
||||
samples[i] = (int16_t)fadedSample;
|
||||
}
|
||||
} else {
|
||||
memset(samples, 0, numSamples * sizeof(int16_t));
|
||||
}
|
||||
_lastLoudness = 0;
|
||||
}
|
||||
|
||||
if (_openedInLastFrame) {
|
||||
// would be nice to do a little crossfade from silence
|
||||
for (int i = 0; i < numSamples; i++) {
|
||||
float fadedSample = ((float)i / (float)numSamples) * (float)samples[i];
|
||||
samples[i] = (int16_t)fadedSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,9 @@ public:
|
|||
void removeDCOffset(int16_t* samples, int numSamples);
|
||||
|
||||
bool clippedInLastFrame() const { return _didClipInLastFrame; }
|
||||
bool closedInLastFrame() const { return _closedInLastFrame; }
|
||||
bool openedInLastFrame() const { return _openedInLastFrame; }
|
||||
bool isOpen() const { return _isOpen; }
|
||||
float getMeasuredFloor() const { return _measuredFloor; }
|
||||
float getLastLoudness() const { return _lastLoudness; }
|
||||
|
||||
|
@ -40,6 +43,8 @@ private:
|
|||
float _sampleFrames[NUMBER_OF_NOISE_SAMPLE_FRAMES];
|
||||
int _sampleCounter;
|
||||
bool _isOpen;
|
||||
bool _closedInLastFrame { false };
|
||||
bool _openedInLastFrame { false };
|
||||
int _framesToClose;
|
||||
};
|
||||
|
||||
|
|
|
@ -136,9 +136,10 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
break;
|
||||
}
|
||||
case SequenceNumberStats::Early: {
|
||||
// Packet is early; write droppable silent samples for each of the skipped packets.
|
||||
// NOTE: we assume that each dropped packet contains the same number of samples
|
||||
// as the packet we just received.
|
||||
// Packet is early. Treat the packets as if all the packets between the last
|
||||
// OnTime packet and this packet were lost. If we're using a codec this will
|
||||
// also result in allowing the codec to interpolate lost data. Then
|
||||
// fall through to the "on time" logic to actually handle this packet
|
||||
int packetsDropped = arrivalInfo._seqDiffFromExpected;
|
||||
lostAudioData(packetsDropped);
|
||||
|
||||
|
@ -147,7 +148,8 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
case SequenceNumberStats::OnTime: {
|
||||
// Packet is on time; parse its data to the ringbuffer
|
||||
if (message.getType() == PacketType::SilentAudioFrame) {
|
||||
// FIXME - Some codecs need to know about these silent frames... and can produce better output
|
||||
// If we recieved a SilentAudioFrame from our sender, we might want to drop
|
||||
// some of the samples in order to catch up to our desired jitter buffer size.
|
||||
writeDroppableSilentFrames(networkFrames);
|
||||
} else {
|
||||
// note: PCM and no codec are identical
|
||||
|
@ -158,7 +160,12 @@ int InboundAudioStream::parseData(ReceivedMessage& message) {
|
|||
parseAudioData(message.getType(), afterProperties);
|
||||
} else {
|
||||
qDebug(audio) << "Codec mismatch: expected" << _selectedCodecName << "got" << codecInPacket << "writing silence";
|
||||
writeDroppableSilentFrames(networkFrames);
|
||||
|
||||
// Since the data in the stream is using a codec that we aren't prepared for,
|
||||
// we need to let the codec know that we don't have data for it, this will
|
||||
// allow the codec to interpolate missing data and produce a fade to silence.
|
||||
lostAudioData(1);
|
||||
|
||||
// inform others of the mismatch
|
||||
auto sendingNode = DependencyManager::get<NodeList>()->nodeWithUUID(message.getSourceID());
|
||||
emit mismatchedAudioCodec(sendingNode, _selectedCodecName, codecInPacket);
|
||||
|
@ -240,6 +247,25 @@ int InboundAudioStream::parseAudioData(PacketType type, const QByteArray& packet
|
|||
|
||||
int InboundAudioStream::writeDroppableSilentFrames(int silentFrames) {
|
||||
|
||||
// We can't guarentee that all clients have faded the stream down
|
||||
// to silence and encoded that silence before sending us a
|
||||
// SilentAudioFrame. If the encoder has truncated the stream it will
|
||||
// leave the decoder holding some unknown loud state. To handle this
|
||||
// case we will call the decoder's lostFrame() method, which indicates
|
||||
// that it should interpolate from its last known state down toward
|
||||
// silence.
|
||||
if (_decoder) {
|
||||
// FIXME - We could potentially use the output from the codec, in which
|
||||
// case we might get a cleaner fade toward silence. NOTE: The below logic
|
||||
// attempts to catch up in the event that the jitter buffers have grown.
|
||||
// The better long term fix is to use the output from the decode, detect
|
||||
// when it actually reaches silence, and then delete the silent portions
|
||||
// of the jitter buffers. Or petentially do a cross fade from the decode
|
||||
// output to silence.
|
||||
QByteArray decodedBuffer;
|
||||
_decoder->lostFrame(decodedBuffer);
|
||||
}
|
||||
|
||||
// calculate how many silent frames we should drop.
|
||||
int silentSamples = silentFrames * _numChannels;
|
||||
int samplesPerFrame = _ringBuffer.getNumFrameSamples();
|
||||
|
|
|
@ -2000,6 +2000,11 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
}
|
||||
}
|
||||
|
||||
auto currentBasis = getRecordingBasis();
|
||||
if (!currentBasis) {
|
||||
currentBasis = std::make_shared<Transform>(Transform::fromJson(json[JSON_AVATAR_BASIS]));
|
||||
}
|
||||
|
||||
if (json.contains(JSON_AVATAR_RELATIVE)) {
|
||||
// During playback you can either have the recording basis set to the avatar current state
|
||||
// meaning that all playback is relative to this avatars starting position, or
|
||||
|
@ -2008,15 +2013,14 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
// The first is more useful for playing back recordings on your own avatar, while
|
||||
// the latter is more useful for playing back other avatars within your scene.
|
||||
|
||||
auto currentBasis = getRecordingBasis();
|
||||
if (!currentBasis) {
|
||||
currentBasis = std::make_shared<Transform>(Transform::fromJson(json[JSON_AVATAR_BASIS]));
|
||||
}
|
||||
|
||||
auto relativeTransform = Transform::fromJson(json[JSON_AVATAR_RELATIVE]);
|
||||
auto worldTransform = currentBasis->worldTransform(relativeTransform);
|
||||
setPosition(worldTransform.getTranslation());
|
||||
setOrientation(worldTransform.getRotation());
|
||||
} else {
|
||||
// We still set the position in the case that there is no movement.
|
||||
setPosition(currentBasis->getTranslation());
|
||||
setOrientation(currentBasis->getRotation());
|
||||
}
|
||||
|
||||
if (json.contains(JSON_AVATAR_SCALE)) {
|
||||
|
|
|
@ -735,6 +735,52 @@ void EntityTreeRenderer::mousePressEvent(QMouseEvent* event) {
|
|||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mouseDoublePressEvent(QMouseEvent* event) {
|
||||
// If we don't have a tree, or we're in the process of shutting down, then don't
|
||||
// process these events.
|
||||
if (!_tree || _shuttingDown) {
|
||||
return;
|
||||
}
|
||||
PerformanceTimer perfTimer("EntityTreeRenderer::mouseDoublePressEvent");
|
||||
PickRay ray = _viewState->computePickRay(event->x(), event->y());
|
||||
|
||||
bool precisionPicking = !_dontDoPrecisionPicking;
|
||||
RayToEntityIntersectionResult rayPickResult = findRayIntersectionWorker(ray, Octree::Lock, precisionPicking);
|
||||
if (rayPickResult.intersects) {
|
||||
//qCDebug(entitiesrenderer) << "mouseDoublePressEvent over entity:" << rayPickResult.entityID;
|
||||
|
||||
QString urlString = rayPickResult.properties.getHref();
|
||||
QUrl url = QUrl(urlString, QUrl::StrictMode);
|
||||
if (url.isValid() && !url.isEmpty()){
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(urlString);
|
||||
}
|
||||
|
||||
glm::vec2 pos2D = projectOntoEntityXYPlane(rayPickResult.entity, ray, rayPickResult);
|
||||
PointerEvent pointerEvent(PointerEvent::Press, MOUSE_POINTER_ID,
|
||||
pos2D, rayPickResult.intersection,
|
||||
rayPickResult.surfaceNormal, ray.direction,
|
||||
toPointerButton(*event), toPointerButtons(*event));
|
||||
|
||||
emit mouseDoublePressOnEntity(rayPickResult.entityID, pointerEvent);
|
||||
|
||||
if (_entitiesScriptEngine) {
|
||||
_entitiesScriptEngine->callEntityScriptMethod(rayPickResult.entityID, "mouseDoublePressOnEntity", pointerEvent);
|
||||
}
|
||||
|
||||
_currentClickingOnEntityID = rayPickResult.entityID;
|
||||
emit clickDownOnEntity(_currentClickingOnEntityID, pointerEvent);
|
||||
if (_entitiesScriptEngine) {
|
||||
_entitiesScriptEngine->callEntityScriptMethod(_currentClickingOnEntityID, "doubleclickOnEntity", pointerEvent);
|
||||
}
|
||||
|
||||
_lastPointerEvent = pointerEvent;
|
||||
_lastPointerEventValid = true;
|
||||
|
||||
} else {
|
||||
emit mouseDoublePressOffEntity();
|
||||
}
|
||||
}
|
||||
|
||||
void EntityTreeRenderer::mouseReleaseEvent(QMouseEvent* event) {
|
||||
// If we don't have a tree, or we're in the process of shutting down, then don't
|
||||
// process these events.
|
||||
|
|
|
@ -90,6 +90,7 @@ public:
|
|||
// event handles which may generate entity related events
|
||||
void mouseReleaseEvent(QMouseEvent* event);
|
||||
void mousePressEvent(QMouseEvent* event);
|
||||
void mouseDoublePressEvent(QMouseEvent* event);
|
||||
void mouseMoveEvent(QMouseEvent* event);
|
||||
|
||||
/// connect our signals to anEntityScriptingInterface for firing of events related clicking,
|
||||
|
@ -103,9 +104,11 @@ public:
|
|||
|
||||
signals:
|
||||
void mousePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||
void mouseDoublePressOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||
void mouseMoveOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||
void mouseReleaseOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||
void mousePressOffEntity();
|
||||
void mouseDoublePressOffEntity();
|
||||
|
||||
void clickDownOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||
void holdingClickOnEntity(const EntityItemID& entityItemID, const PointerEvent& event);
|
||||
|
|
|
@ -32,10 +32,13 @@ protected:
|
|||
Q_INVOKABLE void setStereoInput(bool stereo);
|
||||
|
||||
signals:
|
||||
void mutedByMixer();
|
||||
void environmentMuted();
|
||||
void receivedFirstPacket();
|
||||
void disconnected();
|
||||
void mutedByMixer(); /// the client has been muted by the mixer
|
||||
void environmentMuted(); /// the entire environment has been muted by the mixer
|
||||
void receivedFirstPacket(); /// the client has received its first packet from the audio mixer
|
||||
void disconnected(); /// the client has been disconnected from the audio mixer
|
||||
void noiseGateOpened(); /// the noise gate has opened
|
||||
void noiseGateClosed(); /// the noise gate has closed
|
||||
void inputReceived(const QByteArray& inputSamples); /// a frame of mic input audio has been received and processed
|
||||
|
||||
private:
|
||||
AudioScriptingInterface();
|
||||
|
|
|
@ -47,6 +47,9 @@ QScriptValue PointerEvent::toScriptValue(QScriptEngine* engine, const PointerEve
|
|||
case Press:
|
||||
obj.setProperty("type", "Press");
|
||||
break;
|
||||
case DoublePress:
|
||||
obj.setProperty("type", "DoublePress");
|
||||
break;
|
||||
case Release:
|
||||
obj.setProperty("type", "Release");
|
||||
break;
|
||||
|
@ -128,6 +131,8 @@ void PointerEvent::fromScriptValue(const QScriptValue& object, PointerEvent& eve
|
|||
QString typeStr = type.isString() ? type.toString() : "Move";
|
||||
if (typeStr == "Press") {
|
||||
event._type = Press;
|
||||
} else if (typeStr == "DoublePress") {
|
||||
event._type = DoublePress;
|
||||
} else if (typeStr == "Release") {
|
||||
event._type = Release;
|
||||
} else {
|
||||
|
|
|
@ -26,9 +26,10 @@ public:
|
|||
};
|
||||
|
||||
enum EventType {
|
||||
Press, // A button has just been pressed
|
||||
Release, // A button has just been released
|
||||
Move // The pointer has just moved
|
||||
Press, // A button has just been pressed
|
||||
DoublePress, // A button has just been double pressed
|
||||
Release, // A button has just been released
|
||||
Move // The pointer has just moved
|
||||
};
|
||||
|
||||
PointerEvent();
|
||||
|
|
|
@ -24,29 +24,34 @@ public:
|
|||
RateCounter() { _rate = 0; } // avoid use of std::atomic copy ctor
|
||||
|
||||
void increment(size_t count = 1) {
|
||||
auto now = usecTimestampNow();
|
||||
float currentIntervalMs = (now - _start) / (float) USECS_PER_MSEC;
|
||||
if (currentIntervalMs > (float) INTERVAL) {
|
||||
float currentCount = _count;
|
||||
float intervalSeconds = currentIntervalMs / (float) MSECS_PER_SECOND;
|
||||
_rate = roundf(currentCount / intervalSeconds * _scale) / _scale;
|
||||
_start = now;
|
||||
_count = 0;
|
||||
};
|
||||
checkRate();
|
||||
_count += count;
|
||||
}
|
||||
|
||||
float rate() const { return _rate; }
|
||||
float rate() const { checkRate(); return _rate; }
|
||||
|
||||
uint8_t precision() const { return PRECISION; }
|
||||
|
||||
uint32_t interval() const { return INTERVAL; }
|
||||
|
||||
private:
|
||||
uint64_t _start { usecTimestampNow() };
|
||||
size_t _count { 0 };
|
||||
mutable uint64_t _start { usecTimestampNow() };
|
||||
mutable size_t _count { 0 };
|
||||
const float _scale { powf(10, PRECISION) };
|
||||
std::atomic<float> _rate;
|
||||
mutable std::atomic<float> _rate;
|
||||
|
||||
void checkRate() const {
|
||||
auto now = usecTimestampNow();
|
||||
float currentIntervalMs = (now - _start) / (float)USECS_PER_MSEC;
|
||||
if (currentIntervalMs > (float)INTERVAL) {
|
||||
float currentCount = _count;
|
||||
float intervalSeconds = currentIntervalMs / (float)MSECS_PER_SECOND;
|
||||
_rate = roundf(currentCount / intervalSeconds * _scale) / _scale;
|
||||
_start = now;
|
||||
_count = 0;
|
||||
};
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
19
script-archive/entityScripts/doubleClickExample.js
Normal file
19
script-archive/entityScripts/doubleClickExample.js
Normal file
|
@ -0,0 +1,19 @@
|
|||
(function() {
|
||||
var _this;
|
||||
function DoubleClickExample() {
|
||||
_this = this;
|
||||
return;
|
||||
}
|
||||
|
||||
DoubleClickExample.prototype = {
|
||||
clickDownOnEntity: function() {
|
||||
print("clickDownOnEntity");
|
||||
},
|
||||
|
||||
doubleclickOnEntity: function() {
|
||||
print("doubleclickOnEntity");
|
||||
}
|
||||
|
||||
};
|
||||
return new DoubleClickExample();
|
||||
});
|
|
@ -72,6 +72,9 @@ tablet.screenChanged.connect(onScreenChanged);
|
|||
AudioDevice.muteToggled.connect(onMuteToggled);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onAudioScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
AudioDevice.muteToggled.disconnect(onMuteToggled);
|
||||
|
|
95
scripts/system/audioScope.js
Normal file
95
scripts/system/audioScope.js
Normal file
|
@ -0,0 +1,95 @@
|
|||
"use strict";
|
||||
//
|
||||
// audioScope.js
|
||||
// scripts/system/
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 3/10/2016
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
/* global Script, Tablet, AudioScope, Audio */
|
||||
|
||||
(function () { // BEGIN LOCAL_SCOPE
|
||||
|
||||
var scopeVisibile = AudioScope.getVisible();
|
||||
var scopePaused = AudioScope.getPause();
|
||||
var autoPause = false;
|
||||
|
||||
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
||||
var showScopeButton = tablet.addButton({
|
||||
icon: "icons/tablet-icons/scope.svg",
|
||||
text: "Audio Scope",
|
||||
isActive: scopeVisibile
|
||||
});
|
||||
|
||||
var scopePauseImage = "icons/tablet-icons/scope-pause.svg";
|
||||
var scopePlayImage = "icons/tablet-icons/scope-play.svg";
|
||||
|
||||
var pauseScopeButton = tablet.addButton({
|
||||
icon: scopePaused ? scopePlayImage : scopePauseImage,
|
||||
text: scopePaused ? "Unpause" : "Pause",
|
||||
isActive: scopePaused
|
||||
});
|
||||
|
||||
var autoPauseScopeButton = tablet.addButton({
|
||||
icon: "icons/tablet-icons/scope-auto.svg",
|
||||
text: "Auto Pause",
|
||||
isActive: autoPause
|
||||
});
|
||||
|
||||
function setScopePause(paused) {
|
||||
scopePaused = paused;
|
||||
pauseScopeButton.editProperties({
|
||||
isActive: scopePaused,
|
||||
icon: scopePaused ? scopePlayImage : scopePauseImage,
|
||||
text: scopePaused ? "Unpause" : "Pause"
|
||||
});
|
||||
AudioScope.setPause(scopePaused);
|
||||
}
|
||||
|
||||
showScopeButton.clicked.connect(function () {
|
||||
// toggle button active state
|
||||
scopeVisibile = !scopeVisibile;
|
||||
showScopeButton.editProperties({
|
||||
isActive: scopeVisibile
|
||||
});
|
||||
|
||||
AudioScope.setVisible(scopeVisibile);
|
||||
});
|
||||
|
||||
pauseScopeButton.clicked.connect(function () {
|
||||
// toggle button active state
|
||||
setScopePause(!scopePaused);
|
||||
});
|
||||
|
||||
autoPauseScopeButton.clicked.connect(function () {
|
||||
// toggle button active state
|
||||
autoPause = !autoPause;
|
||||
autoPauseScopeButton.editProperties({
|
||||
isActive: autoPause,
|
||||
text: autoPause ? "Auto Pause" : "Manual"
|
||||
});
|
||||
});
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
tablet.removeButton(showScopeButton);
|
||||
tablet.removeButton(pauseScopeButton);
|
||||
tablet.removeButton(autoPauseScopeButton);
|
||||
});
|
||||
|
||||
Audio.noiseGateOpened.connect(function(){
|
||||
if (autoPause) {
|
||||
setScopePause(false);
|
||||
}
|
||||
});
|
||||
|
||||
Audio.noiseGateClosed.connect(function(){
|
||||
// noise gate closed
|
||||
if (autoPause) {
|
||||
setScopePause(true);
|
||||
}
|
||||
});
|
||||
|
||||
}()); // END LOCAL_SCOPE
|
|
@ -18,13 +18,14 @@ var button;
|
|||
var buttonName = "GOTO";
|
||||
var toolBar = null;
|
||||
var tablet = null;
|
||||
|
||||
var onGotoScreen = false;
|
||||
function onAddressBarShown(visible) {
|
||||
button.editProperties({isActive: visible});
|
||||
}
|
||||
|
||||
function onClicked(){
|
||||
DialogsManager.toggleAddressBar();
|
||||
onGotoScreen = !onGotoScreen;
|
||||
}
|
||||
|
||||
if (Settings.getValue("HUDUIEnabled")) {
|
||||
|
@ -49,6 +50,9 @@ button.clicked.connect(onClicked);
|
|||
DialogsManager.addressBarShown.connect(onAddressBarShown);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onGotoScreen) {
|
||||
DialogsManager.toggleAddressBar();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
if (tablet) {
|
||||
tablet.removeButton(button);
|
||||
|
|
|
@ -48,6 +48,9 @@
|
|||
}, POLL_RATE);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (enabled) {
|
||||
Menu.closeInfoView('InfoView_html/help.html');
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
Script.clearInterval(interval);
|
||||
if (tablet) {
|
||||
|
|
|
@ -45,6 +45,7 @@ var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
|
|||
var desktopOnlyViews = ['Mirror', 'Independent Mode', 'Entity Mode'];
|
||||
|
||||
function onHmdChanged(isHmd) {
|
||||
HMD.closeTablet();
|
||||
if (isHmd) {
|
||||
button.editProperties({
|
||||
icon: "icons/tablet-icons/switch-desk-i.svg",
|
||||
|
|
|
@ -121,6 +121,7 @@ function onClick() {
|
|||
if (onMarketplaceScreen) {
|
||||
// for toolbar-mode: go back to home screen, this will close the window.
|
||||
tablet.gotoHomeScreen();
|
||||
onMarketplaceScreen = false;
|
||||
} else {
|
||||
var entity = HMD.tabletID;
|
||||
Entities.editEntity(entity, {textures: JSON.stringify({"tex.close": HOME_BUTTON_TEXTURE})});
|
||||
|
@ -140,6 +141,9 @@ tablet.screenChanged.connect(onScreenChanged);
|
|||
Entities.canWriteAssetsChanged.connect(onCanWriteAssetsChanged);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onMarketplaceScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
tablet.removeButton(marketplaceButton);
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
Entities.canWriteAssetsChanged.disconnect(onCanWriteAssetsChanged);
|
||||
|
|
|
@ -48,6 +48,9 @@ var HOME_BUTTON_TEXTURE = "http://hifi-content.s3.amazonaws.com/alan/dev/tablet-
|
|||
tablet.screenChanged.connect(onScreenChanged);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
if (onMenuScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.removeButton(button);
|
||||
tablet.screenChanged.disconnect(onScreenChanged);
|
||||
|
|
|
@ -696,6 +696,9 @@ function clearLocalQMLDataAndClosePAL() {
|
|||
}
|
||||
|
||||
function shutdown() {
|
||||
if (onPalScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onTabletButtonClicked);
|
||||
tablet.removeButton(button);
|
||||
tablet.screenChanged.disconnect(onTabletScreenChanged);
|
||||
|
|
|
@ -191,12 +191,12 @@ function resetButtons(pathStillSnapshot, pathAnimatedSnapshot, notify) {
|
|||
if (clearOverlayWhenMoving) {
|
||||
MyAvatar.setClearOverlayWhenMoving(true); // not until after the share dialog
|
||||
}
|
||||
HMD.openTablet();
|
||||
}
|
||||
|
||||
function processingGif() {
|
||||
// show hud
|
||||
Reticle.visible = reticleVisible;
|
||||
|
||||
button.clicked.disconnect(onClicked);
|
||||
buttonConnected = false;
|
||||
// show overlays if they were on
|
||||
|
@ -211,8 +211,10 @@ Window.snapshotShared.connect(snapshotShared);
|
|||
Window.processingGif.connect(processingGif);
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
button.clicked.disconnect(onClicked);
|
||||
buttonConnected = false;
|
||||
if (buttonConnected) {
|
||||
button.clicked.disconnect(onClicked);
|
||||
buttonConnected = false;
|
||||
}
|
||||
if (tablet) {
|
||||
tablet.removeButton(button);
|
||||
}
|
||||
|
|
|
@ -131,7 +131,9 @@
|
|||
}
|
||||
|
||||
Script.scriptEnding.connect(function () {
|
||||
Entities.deleteEntity(HMD.tabletID);
|
||||
var tabletID = HMD.tabletID;
|
||||
Entities.deleteEntity(tabletID);
|
||||
Overlays.deleteOverlay(tabletID)
|
||||
HMD.tabletID = null;
|
||||
HMD.homeButtonID = null;
|
||||
HMD.tabletScreenID = null;
|
||||
|
|
|
@ -115,6 +115,9 @@
|
|||
tablet.screenChanged.connect(onScreenChanged);
|
||||
|
||||
function cleanup() {
|
||||
if (onUsersScreen) {
|
||||
tablet.gotoHomeScreen();
|
||||
}
|
||||
button.clicked.disconnect(onClicked);
|
||||
tablet.removeButton(button);
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue