mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-09 16:30:16 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into edit-button-to-select-in-pal
This commit is contained in:
commit
0670a4689f
23 changed files with 402 additions and 94 deletions
|
@ -32,6 +32,7 @@
|
||||||
#include "AudioMixerClientData.h"
|
#include "AudioMixerClientData.h"
|
||||||
#include "AvatarAudioStream.h"
|
#include "AvatarAudioStream.h"
|
||||||
#include "InjectedAudioStream.h"
|
#include "InjectedAudioStream.h"
|
||||||
|
#include "AudioHelpers.h"
|
||||||
|
|
||||||
#include "AudioMixerSlave.h"
|
#include "AudioMixerSlave.h"
|
||||||
|
|
||||||
|
@ -406,63 +407,6 @@ void AudioMixerSlave::addStreamToMix(AudioMixerClientData& listenerNodeData, con
|
||||||
AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
const int IEEE754_MANT_BITS = 23;
|
|
||||||
const int IEEE754_EXPN_BIAS = 127;
|
|
||||||
|
|
||||||
//
|
|
||||||
// for x > 0.0f, returns log2(x)
|
|
||||||
// for x <= 0.0f, returns large negative value
|
|
||||||
//
|
|
||||||
// abs |error| < 8e-3, smooth (exact for x=2^N) for NPOLY=3
|
|
||||||
// abs |error| < 2e-4, smooth (exact for x=2^N) for NPOLY=5
|
|
||||||
// rel |error| < 0.4 from precision loss very close to 1.0f
|
|
||||||
//
|
|
||||||
static inline float fastlog2(float x) {
|
|
||||||
|
|
||||||
union { float f; int32_t i; } mant, bits = { x };
|
|
||||||
|
|
||||||
// split into mantissa and exponent
|
|
||||||
mant.i = (bits.i & ((1 << IEEE754_MANT_BITS) - 1)) | (IEEE754_EXPN_BIAS << IEEE754_MANT_BITS);
|
|
||||||
int32_t expn = (bits.i >> IEEE754_MANT_BITS) - IEEE754_EXPN_BIAS;
|
|
||||||
|
|
||||||
mant.f -= 1.0f;
|
|
||||||
|
|
||||||
// polynomial for log2(1+x) over x=[0,1]
|
|
||||||
//x = (-0.346555386f * mant.f + 1.346555386f) * mant.f;
|
|
||||||
x = (((-0.0821307180f * mant.f + 0.321188984f) * mant.f - 0.677784014f) * mant.f + 1.43872575f) * mant.f;
|
|
||||||
|
|
||||||
return x + expn;
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
|
||||||
// for -126 <= x < 128, returns exp2(x)
|
|
||||||
//
|
|
||||||
// rel |error| < 3e-3, smooth (exact for x=N) for NPOLY=3
|
|
||||||
// rel |error| < 9e-6, smooth (exact for x=N) for NPOLY=5
|
|
||||||
//
|
|
||||||
static inline float fastexp2(float x) {
|
|
||||||
|
|
||||||
union { float f; int32_t i; } xi;
|
|
||||||
|
|
||||||
// bias such that x > 0
|
|
||||||
x += IEEE754_EXPN_BIAS;
|
|
||||||
//x = MAX(x, 1.0f);
|
|
||||||
//x = MIN(x, 254.9999f);
|
|
||||||
|
|
||||||
// split into integer and fraction
|
|
||||||
xi.i = (int32_t)x;
|
|
||||||
x -= xi.i;
|
|
||||||
|
|
||||||
// construct exp2(xi) as a float
|
|
||||||
xi.i <<= IEEE754_MANT_BITS;
|
|
||||||
|
|
||||||
// polynomial for exp2(x) over x=[0,1]
|
|
||||||
//x = (0.339766028f * x + 0.660233972f) * x + 1.0f;
|
|
||||||
x = (((0.0135557472f * x + 0.0520323690f) * x + 0.241379763f) * x + 0.693032121f) * x + 1.0f;
|
|
||||||
|
|
||||||
return x * xi.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
float AudioMixerSlave::gainForSource(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd,
|
float AudioMixerSlave::gainForSource(const AvatarAudioStream& listeningNodeStream, const PositionalAudioStream& streamToAdd,
|
||||||
const glm::vec3& relativePosition, bool isEcho) {
|
const glm::vec3& relativePosition, bool isEcho) {
|
||||||
float gain = 1.0f;
|
float gain = 1.0f;
|
||||||
|
@ -514,7 +458,7 @@ float AudioMixerSlave::gainForSource(const AvatarAudioStream& listeningNodeStrea
|
||||||
g = (g > 1.0f) ? 1.0f : g;
|
g = (g > 1.0f) ? 1.0f : g;
|
||||||
|
|
||||||
// calculate the distance coefficient using the distance to this node
|
// calculate the distance coefficient using the distance to this node
|
||||||
float distanceCoefficient = fastexp2(fastlog2(g) * fastlog2(distanceBetween/ATTENUATION_BEGINS_AT_DISTANCE));
|
float distanceCoefficient = fastExp2f(fastLog2f(g) * fastLog2f(distanceBetween/ATTENUATION_BEGINS_AT_DISTANCE));
|
||||||
|
|
||||||
// multiply the current attenuation coefficient by the distance coefficient
|
// multiply the current attenuation coefficient by the distance coefficient
|
||||||
gain *= distanceCoefficient;
|
gain *= distanceCoefficient;
|
||||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 119 KiB After Width: | Height: | Size: 123 KiB |
Binary file not shown.
Binary file not shown.
|
@ -79,6 +79,10 @@ Item {
|
||||||
StatText {
|
StatText {
|
||||||
text: "Avatar Simrate: " + root.avatarSimrate
|
text: "Avatar Simrate: " + root.avatarSimrate
|
||||||
}
|
}
|
||||||
|
StatText {
|
||||||
|
text: "Missed Frame Count: " + root.appdropped;
|
||||||
|
visible: root.appdropped > 0;
|
||||||
|
}
|
||||||
StatText {
|
StatText {
|
||||||
text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount
|
text: "Packets In/Out: " + root.packetInCount + "/" + root.packetOutCount
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,7 @@ Item {
|
||||||
border.width: 2
|
border.width: 2
|
||||||
// "ADMIN" text
|
// "ADMIN" text
|
||||||
RalewaySemiBold {
|
RalewaySemiBold {
|
||||||
|
id: adminTabText
|
||||||
text: "ADMIN"
|
text: "ADMIN"
|
||||||
// Text size
|
// Text size
|
||||||
size: hifi.fontSizes.tableHeading + 2
|
size: hifi.fontSizes.tableHeading + 2
|
||||||
|
@ -325,7 +326,7 @@ Item {
|
||||||
visible: iAmAdmin
|
visible: iAmAdmin
|
||||||
color: hifi.colors.lightGrayText
|
color: hifi.colors.lightGrayText
|
||||||
}
|
}
|
||||||
// This Rectangle refers to the [?] popup button
|
// This Rectangle refers to the [?] popup button next to "NAMES"
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: hifi.colors.tableBackgroundLight
|
color: hifi.colors.tableBackgroundLight
|
||||||
width: 20
|
width: 20
|
||||||
|
@ -353,7 +354,36 @@ Item {
|
||||||
onExited: helpText.color = hifi.colors.darkGray
|
onExited: helpText.color = hifi.colors.darkGray
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Explanitory popup upon clicking "[?]"
|
// This Rectangle refers to the [?] popup button next to "ADMIN"
|
||||||
|
Rectangle {
|
||||||
|
visible: iAmAdmin
|
||||||
|
color: adminTab.color
|
||||||
|
width: 20
|
||||||
|
height: 28
|
||||||
|
anchors.right: adminTab.right
|
||||||
|
anchors.rightMargin: 31
|
||||||
|
anchors.top: adminTab.top
|
||||||
|
anchors.topMargin: 2
|
||||||
|
RalewayRegular {
|
||||||
|
id: adminHelpText
|
||||||
|
text: "[?]"
|
||||||
|
size: hifi.fontSizes.tableHeading + 2
|
||||||
|
font.capitalization: Font.AllUppercase
|
||||||
|
color: hifi.colors.redHighlight
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
verticalAlignment: Text.AlignVCenter
|
||||||
|
anchors.fill: parent
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
hoverEnabled: true
|
||||||
|
onClicked: adminPopup.visible = true
|
||||||
|
onEntered: adminHelpText.color = "#94132e"
|
||||||
|
onExited: adminHelpText.color = hifi.colors.redHighlight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Explanitory popup upon clicking "[?]" next to "NAMES"
|
||||||
Item {
|
Item {
|
||||||
visible: false
|
visible: false
|
||||||
id: namesPopup
|
id: namesPopup
|
||||||
|
@ -392,6 +422,44 @@ Item {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Explanitory popup upon clicking "[?]" next to "ADMIN"
|
||||||
|
Item {
|
||||||
|
visible: false
|
||||||
|
id: adminPopup
|
||||||
|
anchors.fill: pal
|
||||||
|
Rectangle {
|
||||||
|
anchors.fill: parent
|
||||||
|
color: "black"
|
||||||
|
opacity: 0.5
|
||||||
|
radius: hifi.dimensions.borderRadius
|
||||||
|
}
|
||||||
|
Rectangle {
|
||||||
|
width: Math.max(parent.width * 0.75, 400)
|
||||||
|
height: adminPopupText.contentHeight*1.5
|
||||||
|
anchors.centerIn: parent
|
||||||
|
radius: hifi.dimensions.borderRadius
|
||||||
|
color: "white"
|
||||||
|
FiraSansSemiBold {
|
||||||
|
id: adminPopupText
|
||||||
|
text: 'Silencing a user mutes their microphone. Silenced users can unmute themselves by clicking the "UNMUTE" button on their HUD.\n\n' +
|
||||||
|
"Banning a user will remove them from this domain and prevent them from returning. You can un-ban users from your domain's settings page."
|
||||||
|
size: hifi.fontSizes.textFieldInput
|
||||||
|
color: hifi.colors.darkGray
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
anchors.fill: parent
|
||||||
|
anchors.leftMargin: 15
|
||||||
|
anchors.rightMargin: 15
|
||||||
|
wrapMode: Text.WordWrap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
acceptedButtons: Qt.LeftButton
|
||||||
|
onClicked: {
|
||||||
|
adminPopup.visible = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
function findSessionIndex(sessionId, optionalData) { // no findIndex in .qml
|
||||||
var data = optionalData || userModelData, length = data.length;
|
var data = optionalData || userModelData, length = data.length;
|
||||||
|
|
|
@ -95,7 +95,7 @@ Item {
|
||||||
readonly property color tableRowDarkEven: "#1c1c1c" // Equivalent to "#a6181818" over #404040 background
|
readonly property color tableRowDarkEven: "#1c1c1c" // Equivalent to "#a6181818" over #404040 background
|
||||||
readonly property color tableBackgroundLight: tableRowLightEven
|
readonly property color tableBackgroundLight: tableRowLightEven
|
||||||
readonly property color tableBackgroundDark: tableRowDarkEven
|
readonly property color tableBackgroundDark: tableRowDarkEven
|
||||||
readonly property color tableScrollHandleLight: tableRowLightOdd
|
readonly property color tableScrollHandleLight: "#8F8F8F"
|
||||||
readonly property color tableScrollHandleDark: "#707070"
|
readonly property color tableScrollHandleDark: "#707070"
|
||||||
readonly property color tableScrollBackgroundLight: tableRowLightEven
|
readonly property color tableScrollBackgroundLight: tableRowLightEven
|
||||||
readonly property color tableScrollBackgroundDark: "#323232"
|
readonly property color tableScrollBackgroundDark: "#323232"
|
||||||
|
|
|
@ -1137,6 +1137,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
||||||
_settingsTimer.moveToThread(&_settingsThread);
|
_settingsTimer.moveToThread(&_settingsThread);
|
||||||
_settingsTimer.setSingleShot(false);
|
_settingsTimer.setSingleShot(false);
|
||||||
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable
|
_settingsTimer.setInterval(SAVE_SETTINGS_INTERVAL); // 10s, Qt::CoarseTimer acceptable
|
||||||
|
_settingsThread.setPriority(QThread::LowestPriority);
|
||||||
_settingsThread.start();
|
_settingsThread.start();
|
||||||
|
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::FirstPerson)) {
|
||||||
|
|
|
@ -125,6 +125,8 @@ void Stats::updateStats(bool force) {
|
||||||
STAT_UPDATE(framerate, qApp->getFps());
|
STAT_UPDATE(framerate, qApp->getFps());
|
||||||
if (qApp->getActiveDisplayPlugin()) {
|
if (qApp->getActiveDisplayPlugin()) {
|
||||||
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
auto displayPlugin = qApp->getActiveDisplayPlugin();
|
||||||
|
auto stats = displayPlugin->getHardwareStats();
|
||||||
|
STAT_UPDATE(appdropped, stats["app_dropped_frame_count"].toInt());
|
||||||
STAT_UPDATE(renderrate, displayPlugin->renderRate());
|
STAT_UPDATE(renderrate, displayPlugin->renderRate());
|
||||||
STAT_UPDATE(presentrate, displayPlugin->presentRate());
|
STAT_UPDATE(presentrate, displayPlugin->presentRate());
|
||||||
STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate());
|
STAT_UPDATE(presentnewrate, displayPlugin->newFramePresentRate());
|
||||||
|
|
|
@ -39,6 +39,8 @@ class Stats : public QQuickItem {
|
||||||
// How often the display device reprojecting old frames
|
// How often the display device reprojecting old frames
|
||||||
STATS_PROPERTY(float, stutterrate, 0)
|
STATS_PROPERTY(float, stutterrate, 0)
|
||||||
|
|
||||||
|
STATS_PROPERTY(int, appdropped, 0)
|
||||||
|
|
||||||
STATS_PROPERTY(float, presentnewrate, 0)
|
STATS_PROPERTY(float, presentnewrate, 0)
|
||||||
STATS_PROPERTY(float, presentdroprate, 0)
|
STATS_PROPERTY(float, presentdroprate, 0)
|
||||||
STATS_PROPERTY(int, simrate, 0)
|
STATS_PROPERTY(int, simrate, 0)
|
||||||
|
@ -135,6 +137,7 @@ public slots:
|
||||||
void forceUpdateStats() { updateStats(true); }
|
void forceUpdateStats() { updateStats(true); }
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void appdroppedChanged();
|
||||||
void framerateChanged();
|
void framerateChanged();
|
||||||
void expandedChanged();
|
void expandedChanged();
|
||||||
void timingExpandedChanged();
|
void timingExpandedChanged();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "AudioLogging.h"
|
#include "AudioLogging.h"
|
||||||
#include "SoundCache.h"
|
#include "SoundCache.h"
|
||||||
#include "AudioSRC.h"
|
#include "AudioSRC.h"
|
||||||
|
#include "AudioHelpers.h"
|
||||||
|
|
||||||
int audioInjectorPtrMetaTypeId = qRegisterMetaType<AudioInjector*>();
|
int audioInjectorPtrMetaTypeId = qRegisterMetaType<AudioInjector*>();
|
||||||
|
|
||||||
|
@ -187,7 +188,7 @@ bool AudioInjector::injectLocally() {
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uchar MAX_INJECTOR_VOLUME = 0xFF;
|
const uchar MAX_INJECTOR_VOLUME = packFloatGainToByte(1.0f);
|
||||||
static const int64_t NEXT_FRAME_DELTA_ERROR_OR_FINISHED = -1;
|
static const int64_t NEXT_FRAME_DELTA_ERROR_OR_FINISHED = -1;
|
||||||
static const int64_t NEXT_FRAME_DELTA_IMMEDIATELY = 0;
|
static const int64_t NEXT_FRAME_DELTA_IMMEDIATELY = 0;
|
||||||
|
|
||||||
|
@ -333,7 +334,7 @@ int64_t AudioInjector::injectNextFrame() {
|
||||||
_currentPacket->writePrimitive(_options.position);
|
_currentPacket->writePrimitive(_options.position);
|
||||||
_currentPacket->writePrimitive(_options.orientation);
|
_currentPacket->writePrimitive(_options.orientation);
|
||||||
|
|
||||||
quint8 volume = MAX_INJECTOR_VOLUME * _options.volume;
|
quint8 volume = packFloatGainToByte(_options.volume);
|
||||||
_currentPacket->seek(volumeOptionOffset);
|
_currentPacket->seek(volumeOptionOffset);
|
||||||
_currentPacket->writePrimitive(volume);
|
_currentPacket->writePrimitive(volume);
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ public:
|
||||||
AudioFOA& getLocalFOA() { return _localFOA; }
|
AudioFOA& getLocalFOA() { return _localFOA; }
|
||||||
|
|
||||||
bool isLocalOnly() const { return _options.localOnly; }
|
bool isLocalOnly() const { return _options.localOnly; }
|
||||||
float getVolume() const { return glm::clamp(_options.volume, 0.0f, 1.0f); }
|
float getVolume() const { return _options.volume; }
|
||||||
glm::vec3 getPosition() const { return _options.position; }
|
glm::vec3 getPosition() const { return _options.position; }
|
||||||
glm::quat getOrientation() const { return _options.orientation; }
|
glm::quat getOrientation() const { return _options.orientation; }
|
||||||
bool isStereo() const { return _options.stereo; }
|
bool isStereo() const { return _options.stereo; }
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include <UUID.h>
|
#include <UUID.h>
|
||||||
|
|
||||||
#include "InjectedAudioStream.h"
|
#include "InjectedAudioStream.h"
|
||||||
|
#include "AudioHelpers.h"
|
||||||
|
|
||||||
InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, bool isStereo, int numStaticJitterFrames) :
|
InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, bool isStereo, int numStaticJitterFrames) :
|
||||||
PositionalAudioStream(PositionalAudioStream::Injector, isStereo, numStaticJitterFrames),
|
PositionalAudioStream(PositionalAudioStream::Injector, isStereo, numStaticJitterFrames),
|
||||||
|
@ -25,8 +26,6 @@ InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, bool isS
|
||||||
_radius(0.0f),
|
_radius(0.0f),
|
||||||
_attenuationRatio(0) {}
|
_attenuationRatio(0) {}
|
||||||
|
|
||||||
const uchar MAX_INJECTOR_VOLUME = 255;
|
|
||||||
|
|
||||||
int InjectedAudioStream::parseStreamProperties(PacketType type,
|
int InjectedAudioStream::parseStreamProperties(PacketType type,
|
||||||
const QByteArray& packetAfterSeqNum,
|
const QByteArray& packetAfterSeqNum,
|
||||||
int& numAudioSamples) {
|
int& numAudioSamples) {
|
||||||
|
@ -62,7 +61,7 @@ int InjectedAudioStream::parseStreamProperties(PacketType type,
|
||||||
|
|
||||||
quint8 attenuationByte = 0;
|
quint8 attenuationByte = 0;
|
||||||
packetStream >> attenuationByte;
|
packetStream >> attenuationByte;
|
||||||
_attenuationRatio = attenuationByte / (float)MAX_INJECTOR_VOLUME;
|
_attenuationRatio = unpackFloatGainFromByte(attenuationByte);
|
||||||
|
|
||||||
packetStream >> _ignorePenumbra;
|
packetStream >> _ignorePenumbra;
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
||||||
case PacketType::MicrophoneAudioNoEcho:
|
case PacketType::MicrophoneAudioNoEcho:
|
||||||
case PacketType::MicrophoneAudioWithEcho:
|
case PacketType::MicrophoneAudioWithEcho:
|
||||||
case PacketType::AudioStreamStats:
|
case PacketType::AudioStreamStats:
|
||||||
return static_cast<PacketVersion>(AudioVersion::SpaceBubbleChanges);
|
return static_cast<PacketVersion>(AudioVersion::HighDynamicRangeVolume);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return 17;
|
return 17;
|
||||||
|
|
|
@ -245,6 +245,7 @@ enum class AudioVersion : PacketVersion {
|
||||||
TerminatingStreamStats,
|
TerminatingStreamStats,
|
||||||
SpaceBubbleChanges,
|
SpaceBubbleChanges,
|
||||||
HasPersonalMute,
|
HasPersonalMute,
|
||||||
|
HighDynamicRangeVolume,
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_PacketHeaders_h
|
#endif // hifi_PacketHeaders_h
|
||||||
|
|
94
libraries/shared/src/AudioHelpers.h
Normal file
94
libraries/shared/src/AudioHelpers.h
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
//
|
||||||
|
// AudioHelpers.h
|
||||||
|
// libraries/shared/src
|
||||||
|
//
|
||||||
|
// Created by Ken Cooke on 1/4/17.
|
||||||
|
// Copyright 2017 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef hifi_AudioHelpers_h
|
||||||
|
#define hifi_AudioHelpers_h
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
const int IEEE754_MANT_BITS = 23;
|
||||||
|
const int IEEE754_EXPN_BIAS = 127;
|
||||||
|
|
||||||
|
//
|
||||||
|
// for x > 0.0f, returns log2(x)
|
||||||
|
// for x <= 0.0f, returns large negative value
|
||||||
|
//
|
||||||
|
// abs |error| < 2e-4, smooth (exact for x=2^N)
|
||||||
|
// rel |error| < 0.4 from precision loss very close to 1.0f
|
||||||
|
//
|
||||||
|
static inline float fastLog2f(float x) {
|
||||||
|
|
||||||
|
union { float f; int32_t i; } mant, bits = { x };
|
||||||
|
|
||||||
|
// split into mantissa and exponent
|
||||||
|
mant.i = (bits.i & ((1 << IEEE754_MANT_BITS) - 1)) | (IEEE754_EXPN_BIAS << IEEE754_MANT_BITS);
|
||||||
|
int32_t expn = (bits.i >> IEEE754_MANT_BITS) - IEEE754_EXPN_BIAS;
|
||||||
|
|
||||||
|
mant.f -= 1.0f;
|
||||||
|
|
||||||
|
// polynomial for log2(1+x) over x=[0,1]
|
||||||
|
x = (((-0.0821307180f * mant.f + 0.321188984f) * mant.f - 0.677784014f) * mant.f + 1.43872575f) * mant.f;
|
||||||
|
|
||||||
|
return x + expn;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// for -127 <= x < 128, returns exp2(x)
|
||||||
|
// otherwise, returns undefined
|
||||||
|
//
|
||||||
|
// rel |error| < 9e-6, smooth (exact for x=N)
|
||||||
|
//
|
||||||
|
static inline float fastExp2f(float x) {
|
||||||
|
|
||||||
|
union { float f; int32_t i; } xi;
|
||||||
|
|
||||||
|
// bias such that x > 0
|
||||||
|
x += IEEE754_EXPN_BIAS;
|
||||||
|
|
||||||
|
// split into integer and fraction
|
||||||
|
xi.i = (int32_t)x;
|
||||||
|
x -= xi.i;
|
||||||
|
|
||||||
|
// construct exp2(xi) as a float
|
||||||
|
xi.i <<= IEEE754_MANT_BITS;
|
||||||
|
|
||||||
|
// polynomial for exp2(x) over x=[0,1]
|
||||||
|
x = (((0.0135557472f * x + 0.0520323690f) * x + 0.241379763f) * x + 0.693032121f) * x + 1.0f;
|
||||||
|
|
||||||
|
return x * xi.f;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// Quantize a non-negative gain value to the nearest 0.5dB, and pack to a byte.
|
||||||
|
//
|
||||||
|
// Values above +30dB are clamped to +30dB
|
||||||
|
// Values below -97dB are clamped to -inf
|
||||||
|
// Value of 1.0 (+0dB) is reconstructed exactly
|
||||||
|
//
|
||||||
|
const float GAIN_CONVERSION_RATIO = 2.0f * 6.02059991f; // scale log2 to 0.5dB
|
||||||
|
const float GAIN_CONVERSION_OFFSET = 255 - 60.0f; // translate +30dB to max
|
||||||
|
|
||||||
|
static inline uint8_t packFloatGainToByte(float gain) {
|
||||||
|
|
||||||
|
float f = fastLog2f(gain) * GAIN_CONVERSION_RATIO + GAIN_CONVERSION_OFFSET;
|
||||||
|
int32_t i = (int32_t)(f + 0.5f); // quantize
|
||||||
|
|
||||||
|
uint8_t byte = (i < 0) ? 0 : ((i > 255) ? 255 : i); // clamp
|
||||||
|
return byte;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline float unpackFloatGainFromByte(uint8_t byte) {
|
||||||
|
|
||||||
|
float gain = (byte == 0) ? 0.0f : fastExp2f((byte - GAIN_CONVERSION_OFFSET) * (1.0f/GAIN_CONVERSION_RATIO));
|
||||||
|
return gain;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // hifi_AudioHelpers_h
|
|
@ -74,7 +74,9 @@ void Settings::endGroup() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Settings::setValue(const QString& name, const QVariant& value) {
|
void Settings::setValue(const QString& name, const QVariant& value) {
|
||||||
_manager->setValue(name, value);
|
if (_manager->value(name) != value) {
|
||||||
|
_manager->setValue(name, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant Settings::value(const QString& name, const QVariant& defaultValue) const {
|
QVariant Settings::value(const QString& name, const QVariant& defaultValue) const {
|
||||||
|
|
|
@ -195,6 +195,8 @@ var STATE_OVERLAY_TOUCHING = 8;
|
||||||
var holdEnabled = true;
|
var holdEnabled = true;
|
||||||
var nearGrabEnabled = true;
|
var nearGrabEnabled = true;
|
||||||
var farGrabEnabled = true;
|
var farGrabEnabled = true;
|
||||||
|
var myAvatarScalingEnabled = true;
|
||||||
|
var objectScalingEnabled = true;
|
||||||
|
|
||||||
// "collidesWith" is specified by comma-separated list of group names
|
// "collidesWith" is specified by comma-separated list of group names
|
||||||
// the possible group names are: static, dynamic, kinematic, myAvatar, otherAvatar
|
// the possible group names are: static, dynamic, kinematic, myAvatar, otherAvatar
|
||||||
|
@ -2312,6 +2314,10 @@ function MyController(hand) {
|
||||||
};
|
};
|
||||||
|
|
||||||
this.maybeScale = function(props) {
|
this.maybeScale = function(props) {
|
||||||
|
if (!objectScalingEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.shouldScale) {
|
if (!this.shouldScale) {
|
||||||
// If both secondary triggers squeezed, and the non-holding hand is empty, start scaling
|
// If both secondary triggers squeezed, and the non-holding hand is empty, start scaling
|
||||||
if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed() && this.getOtherHandController().state === STATE_OFF) {
|
if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed() && this.getOtherHandController().state === STATE_OFF) {
|
||||||
|
@ -2331,6 +2337,10 @@ function MyController(hand) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.maybeScaleMyAvatar = function() {
|
this.maybeScaleMyAvatar = function() {
|
||||||
|
if (!myAvatarScalingEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (!this.shouldScale) {
|
if (!this.shouldScale) {
|
||||||
// If both secondary triggers squeezed, start scaling
|
// If both secondary triggers squeezed, start scaling
|
||||||
if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed()) {
|
if (this.secondarySqueezed() && this.getOtherHandController().secondarySqueezed()) {
|
||||||
|
@ -3016,6 +3026,14 @@ var handleHandMessages = function(channel, message, sender) {
|
||||||
print("farGrabEnabled: ", data.farGrabEnabled);
|
print("farGrabEnabled: ", data.farGrabEnabled);
|
||||||
farGrabEnabled = data.farGrabEnabled;
|
farGrabEnabled = data.farGrabEnabled;
|
||||||
}
|
}
|
||||||
|
if (data.myAvatarScalingEnabled !== undefined) {
|
||||||
|
print("myAvatarScalingEnabled: ", data.myAvatarScalingEnabled);
|
||||||
|
myAvatarScalingEnabled = data.myAvatarScalingEnabled;
|
||||||
|
}
|
||||||
|
if (data.objectScalingEnabled !== undefined) {
|
||||||
|
print("objectScalingEnabled: ", data.objectScalingEnabled);
|
||||||
|
objectScalingEnabled = data.objectScalingEnabled;
|
||||||
|
}
|
||||||
} else if (channel === 'Hifi-Hand-Grab') {
|
} else if (channel === 'Hifi-Hand-Grab') {
|
||||||
try {
|
try {
|
||||||
data = JSON.parse(message);
|
data = JSON.parse(message);
|
||||||
|
|
|
@ -74,6 +74,9 @@ TOUCH_CONTROLLER_CONFIGURATION_LEFT = {
|
||||||
teleport: {
|
teleport: {
|
||||||
defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Teleport.png"
|
defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Teleport.png"
|
||||||
},
|
},
|
||||||
|
both_triggers: {
|
||||||
|
defaultTextureURL: BASE_URL + "Oculus-Labels-L.fbx/Oculus-Labels-L.fbm/Grip-Trigger.png"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -212,7 +215,7 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = {
|
||||||
modelURL: BASE_URL + "Oculus-Labels-R.fbx",
|
modelURL: BASE_URL + "Oculus-Labels-R.fbx",
|
||||||
naturalPosition: { x: 0.009739525616168976, y: -0.0017818436026573181, z: 0.016794726252555847 },
|
naturalPosition: { x: 0.009739525616168976, y: -0.0017818436026573181, z: 0.016794726252555847 },
|
||||||
|
|
||||||
textureName: "Texture",
|
textureName: "blank",
|
||||||
defaultTextureLayer: "blank",
|
defaultTextureLayer: "blank",
|
||||||
textureLayers: {
|
textureLayers: {
|
||||||
blank: {
|
blank: {
|
||||||
|
@ -230,6 +233,9 @@ TOUCH_CONTROLLER_CONFIGURATION_RIGHT = {
|
||||||
teleport: {
|
teleport: {
|
||||||
defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Teleport.png"
|
defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Teleport.png"
|
||||||
},
|
},
|
||||||
|
both_triggers: {
|
||||||
|
defaultTextureURL: BASE_URL + "Oculus-Labels-R.fbx/Oculus-Labels-R.fbm/Grip-Trigger.png"
|
||||||
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
130
scripts/tutorials/entity_scripts/springAway.js
Normal file
130
scripts/tutorials/entity_scripts/springAway.js
Normal file
|
@ -0,0 +1,130 @@
|
||||||
|
// springAway.js
|
||||||
|
//
|
||||||
|
// If you attach this entity script to an object, the object will spring away from
|
||||||
|
// your avatar's hands. Useful for making a beachball or basketball, because you
|
||||||
|
// can bounce it on your hands.
|
||||||
|
//
|
||||||
|
// You can change the force applied by the script by setting userData to contain
|
||||||
|
// a value 'strength', which will otherwise default to DEFAULT_STRENGTH
|
||||||
|
//
|
||||||
|
// Note that the use of dimensions.x as the size of the entity means that it
|
||||||
|
// needs to be spherical for this to look correct.
|
||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
|
||||||
|
var UPDATE_INTERVAL_MSECS = 1000/45; // Update the spring/object at 45Hz
|
||||||
|
var SETTINGS_INTERVAL_MSECS = 1000; // Periodically check user data for updates
|
||||||
|
var TOO_FAR = 5.0; // If the object
|
||||||
|
var DEFAULT_STRENGTH = 3.0; // How strong/stiff is the spring?
|
||||||
|
|
||||||
|
|
||||||
|
var entity;
|
||||||
|
var props;
|
||||||
|
var checkTimer = false;
|
||||||
|
var settingsTimer = false;
|
||||||
|
var strength = DEFAULT_STRENGTH;
|
||||||
|
var _this;
|
||||||
|
|
||||||
|
var WANT_DEBUG = false;
|
||||||
|
function debugPrint(string) {
|
||||||
|
if (WANT_DEBUG) {
|
||||||
|
print(string);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function howFarAway(position) {
|
||||||
|
return Vec3.distance(MyAvatar.position, position);
|
||||||
|
}
|
||||||
|
|
||||||
|
function springForce(position, center, radius) {
|
||||||
|
//
|
||||||
|
// Return a vector corresponding to a normalized spring force ranging from 1 at
|
||||||
|
// exact center to zero at distance radius from center.
|
||||||
|
//
|
||||||
|
var distance = Vec3.distance(position, center);
|
||||||
|
return Vec3.multiply(1.0 - distance / radius, Vec3.normalize(Vec3.subtract(center, position)));
|
||||||
|
}
|
||||||
|
|
||||||
|
function fingerPosition(which) {
|
||||||
|
//
|
||||||
|
// Get the worldspace position of either the tip of the index finger (jointName "RightHandIndex3", etc), or
|
||||||
|
// fall back to the controller position if that doesn't exist.
|
||||||
|
//
|
||||||
|
var joint = MyAvatar.getJointPosition(which === "RIGHT" ? "RightHandIndex3" : "LeftHandIndex3");
|
||||||
|
if (Vec3.length(joint) > 0) {
|
||||||
|
return joint;
|
||||||
|
} else {
|
||||||
|
return Vec3.sum(MyAvatar.position,
|
||||||
|
Vec3.multiplyQbyV(MyAvatar.orientation,
|
||||||
|
Controller.getPoseValue(which === "RIGHT" ? Controller.Standard.RightHand : Controller.Standard.LeftHand).translation));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.preload = function(entityID) {
|
||||||
|
// Load the sound and range from the entity userData fields, and note the position of the entity.
|
||||||
|
debugPrint("springAway preload");
|
||||||
|
entity = entityID;
|
||||||
|
_this = this;
|
||||||
|
checkTimer = Script.setInterval(this.maybePush, UPDATE_INTERVAL_MSECS);
|
||||||
|
settingsTimer = Script.setInterval(this.checkSettings, SETTINGS_INTERVAL_MSECS);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.maybePush = function() {
|
||||||
|
props = Entities.getEntityProperties(entity, [ "position", "dimensions", "velocity" ]);
|
||||||
|
|
||||||
|
// First, check if the entity is far enough away to not need to do anything with it
|
||||||
|
|
||||||
|
if (howFarAway(props.position) - props.dimensions.x / 2 > TOO_FAR) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var rightFingerPosition = fingerPosition("RIGHT");
|
||||||
|
var leftFingerPosition = fingerPosition("LEFT");
|
||||||
|
|
||||||
|
var addVelocity = { x: 0, y: 0, z: 0 };
|
||||||
|
|
||||||
|
|
||||||
|
if (Vec3.distance(leftFingerPosition, props.position) < props.dimensions.x / 2) {
|
||||||
|
addVelocity = Vec3.sum(addVelocity, Vec3.multiply(springForce(leftFingerPosition, props.position, props.dimensions.x), strength));
|
||||||
|
}
|
||||||
|
if (Vec3.distance(rightFingerPosition, props.position) < props.dimensions.x / 2) {
|
||||||
|
addVelocity = Vec3.sum(addVelocity, Vec3.multiply(springForce(rightFingerPosition, props.position, props.dimensions.x), strength));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Vec3.length(addVelocity) > 0) {
|
||||||
|
Entities.editEntity(entity, {
|
||||||
|
velocity: Vec3.sum(props.velocity, addVelocity)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.checkSettings = function() {
|
||||||
|
var dataProps = Entities.getEntityProperties(entity, [ "userData" ]);
|
||||||
|
if (dataProps.userData) {
|
||||||
|
var data = JSON.parse(dataProps.userData);
|
||||||
|
if (data.strength) {
|
||||||
|
if (!(strength === data.strength)) {
|
||||||
|
debugPrint("Read new spring strength: " + data.strength);
|
||||||
|
}
|
||||||
|
strength = data.strength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.unload = function(entityID) {
|
||||||
|
debugPrint("springAway unload");
|
||||||
|
if (checkTimer) {
|
||||||
|
Script.clearInterval(checkTimer);
|
||||||
|
}
|
||||||
|
if (settingsTimer) {
|
||||||
|
Script.clearInterval(settingsTimer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
})
|
|
@ -42,7 +42,7 @@ const appIcon = path.join(__dirname, '../resources/console.png');
|
||||||
const DELETE_LOG_FILES_OLDER_THAN_X_SECONDS = 60 * 60 * 24 * 7; // 7 Days
|
const DELETE_LOG_FILES_OLDER_THAN_X_SECONDS = 60 * 60 * 24 * 7; // 7 Days
|
||||||
const LOG_FILE_REGEX = /(domain-server|ac-monitor|ac)-.*-std(out|err).txt/;
|
const LOG_FILE_REGEX = /(domain-server|ac-monitor|ac)-.*-std(out|err).txt/;
|
||||||
|
|
||||||
const HOME_CONTENT_URL = "http://cachefly.highfidelity.com/home-tutorial-release-5572.tar.gz";
|
const HOME_CONTENT_URL = "http://cdn.highfidelity.com/content-sets/home-tutorial-28.tar.gz";
|
||||||
|
|
||||||
function getBuildInfo() {
|
function getBuildInfo() {
|
||||||
var buildInfoPath = null;
|
var buildInfoPath = null;
|
||||||
|
|
|
@ -58,6 +58,9 @@ function info() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const CONTROLLER_TOUCH = 'touch';
|
||||||
|
const CONTROLLER_VIVE = 'vive';
|
||||||
|
|
||||||
var NEAR_BOX_SPAWN_NAME = "tutorial/nearGrab/box_spawn";
|
var NEAR_BOX_SPAWN_NAME = "tutorial/nearGrab/box_spawn";
|
||||||
var FAR_BOX_SPAWN_NAME = "tutorial/farGrab/box_spawn";
|
var FAR_BOX_SPAWN_NAME = "tutorial/farGrab/box_spawn";
|
||||||
var GUN_SPAWN_NAME = "tutorial/gun_spawn";
|
var GUN_SPAWN_NAME = "tutorial/gun_spawn";
|
||||||
|
@ -323,7 +326,7 @@ function hideEntitiesWithTag(tag) {
|
||||||
//});
|
//});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the entity properties for an entity with a given name if it is in our
|
* Return the entity properties for an entity with a given name if it is in our
|
||||||
* cached list of entities. Otherwise, return undefined.
|
* cached list of entities. Otherwise, return undefined.
|
||||||
*/
|
*/
|
||||||
|
@ -371,6 +374,8 @@ function disableEverything() {
|
||||||
nearGrabEnabled: true,
|
nearGrabEnabled: true,
|
||||||
holdEnabled: false,
|
holdEnabled: false,
|
||||||
farGrabEnabled: false,
|
farGrabEnabled: false,
|
||||||
|
myAvatarScalingEnabled: false,
|
||||||
|
objectScalingEnabled: false,
|
||||||
}));
|
}));
|
||||||
setControllerPartLayer('touchpad', 'blank');
|
setControllerPartLayer('touchpad', 'blank');
|
||||||
setControllerPartLayer('trigger', 'blank');
|
setControllerPartLayer('trigger', 'blank');
|
||||||
|
@ -399,6 +404,8 @@ function reenableEverything() {
|
||||||
nearGrabEnabled: true,
|
nearGrabEnabled: true,
|
||||||
holdEnabled: true,
|
holdEnabled: true,
|
||||||
farGrabEnabled: true,
|
farGrabEnabled: true,
|
||||||
|
myAvatarScalingEnabled: true,
|
||||||
|
objectScalingEnabled: true,
|
||||||
}));
|
}));
|
||||||
setControllerPartLayer('touchpad', 'blank');
|
setControllerPartLayer('touchpad', 'blank');
|
||||||
setControllerPartLayer('trigger', 'blank');
|
setControllerPartLayer('trigger', 'blank');
|
||||||
|
@ -516,12 +523,14 @@ stepOrient.prototype = {
|
||||||
// STEP: Near Grab //
|
// STEP: Near Grab //
|
||||||
// //
|
// //
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
var stepNearGrab = function() {
|
var stepNearGrab = function(tutorialManager) {
|
||||||
this.name = 'nearGrab';
|
this.name = 'nearGrab';
|
||||||
this.tag = "nearGrab";
|
this.tags = ["bothGrab", "nearGrab", "nearGrab-" + tutorialManager.controllerName];
|
||||||
this.tempTag = "nearGrab-temporary";
|
this.tempTag = "nearGrab-temporary";
|
||||||
this.birdIDs = [];
|
this.birdIDs = [];
|
||||||
|
|
||||||
|
this.controllerName = tutorialManager.controllerName;
|
||||||
|
|
||||||
Messages.subscribe("Entity-Exploded");
|
Messages.subscribe("Entity-Exploded");
|
||||||
Messages.messageReceived.connect(this.onMessage.bind(this));
|
Messages.messageReceived.connect(this.onMessage.bind(this));
|
||||||
}
|
}
|
||||||
|
@ -530,12 +539,17 @@ stepNearGrab.prototype = {
|
||||||
this.finished = false;
|
this.finished = false;
|
||||||
this.onFinish = onFinish;
|
this.onFinish = onFinish;
|
||||||
|
|
||||||
setControllerPartLayer('tips', 'trigger');
|
if (this.controllerName === CONTROLLER_TOUCH) {
|
||||||
setControllerPartLayer('trigger', 'highlight');
|
setControllerPartLayer('tips', 'both_triggers');
|
||||||
|
setControllerPartLayer('trigger', 'highlight');
|
||||||
|
setControllerPartLayer('grip', 'highlight');
|
||||||
|
} else {
|
||||||
|
setControllerPartLayer('tips', 'trigger');
|
||||||
|
setControllerPartLayer('trigger', 'highlight');
|
||||||
|
}
|
||||||
|
|
||||||
// Spawn content set
|
// Show content set
|
||||||
showEntitiesWithTag(this.tag, { visible: true });
|
showEntitiesWithTags(this.tags);
|
||||||
showEntitiesWithTag('bothGrab', { visible: true });
|
|
||||||
|
|
||||||
var boxSpawnPosition = getEntityWithName(NEAR_BOX_SPAWN_NAME).position;
|
var boxSpawnPosition = getEntityWithName(NEAR_BOX_SPAWN_NAME).position;
|
||||||
function createBlock(fireworkNumber) {
|
function createBlock(fireworkNumber) {
|
||||||
|
@ -573,8 +587,8 @@ stepNearGrab.prototype = {
|
||||||
this.finished = true;
|
this.finished = true;
|
||||||
setControllerPartLayer('tips', 'blank');
|
setControllerPartLayer('tips', 'blank');
|
||||||
setControllerPartLayer('trigger', 'normal');
|
setControllerPartLayer('trigger', 'normal');
|
||||||
hideEntitiesWithTag(this.tag, { visible: false});
|
setControllerPartLayer('grip', 'normal');
|
||||||
hideEntitiesWithTag('bothGrab', { visible: false});
|
hideEntitiesWithTags(this.tags);
|
||||||
deleteEntitiesWithTag(this.tempTag);
|
deleteEntitiesWithTag(this.tempTag);
|
||||||
if (this.positionWatcher) {
|
if (this.positionWatcher) {
|
||||||
this.positionWatcher.destroy();
|
this.positionWatcher.destroy();
|
||||||
|
@ -696,6 +710,7 @@ PositionWatcher.prototype = {
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
var stepEquip = function(tutorialManager) {
|
var stepEquip = function(tutorialManager) {
|
||||||
const controllerName = tutorialManager.controllerName;
|
const controllerName = tutorialManager.controllerName;
|
||||||
|
this.controllerName = controllerName;
|
||||||
|
|
||||||
this.name = 'equip';
|
this.name = 'equip';
|
||||||
|
|
||||||
|
@ -714,8 +729,13 @@ var stepEquip = function(tutorialManager) {
|
||||||
}
|
}
|
||||||
stepEquip.prototype = {
|
stepEquip.prototype = {
|
||||||
start: function(onFinish) {
|
start: function(onFinish) {
|
||||||
setControllerPartLayer('tips', 'trigger');
|
if (this.controllerName === CONTROLLER_TOUCH) {
|
||||||
setControllerPartLayer('trigger', 'highlight');
|
setControllerPartLayer('tips', 'grip');
|
||||||
|
setControllerPartLayer('grip', 'highlight');
|
||||||
|
} else {
|
||||||
|
setControllerPartLayer('tips', 'trigger');
|
||||||
|
setControllerPartLayer('trigger', 'highlight');
|
||||||
|
}
|
||||||
|
|
||||||
Messages.sendLocalMessage('Hifi-Grab-Disable', JSON.stringify({
|
Messages.sendLocalMessage('Hifi-Grab-Disable', JSON.stringify({
|
||||||
holdEnabled: true,
|
holdEnabled: true,
|
||||||
|
|
|
@ -52,6 +52,16 @@ TUTORIAL_TAG_TO_ENTITY_IDS_MAP = {
|
||||||
"tag": "farGrab"
|
"tag": "farGrab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"nearGrab-vive": {
|
||||||
|
"{88221a22-b710-4d35-852b-5257b0aa77dc}": {
|
||||||
|
"tag": "nearGrab-vive"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nearGrab-touch": {
|
||||||
|
"{7c0f2fde-6c5c-459b-bf82-421979cebf2e}": {
|
||||||
|
"tag": "nearGrab-touch"
|
||||||
|
}
|
||||||
|
},
|
||||||
"nearGrab": {
|
"nearGrab": {
|
||||||
"{55c861ef-60ca-4722-a6c5-9c6967966ec5}": {
|
"{55c861ef-60ca-4722-a6c5-9c6967966ec5}": {
|
||||||
"tag": "nearGrab"
|
"tag": "nearGrab"
|
||||||
|
@ -59,9 +69,6 @@ TUTORIAL_TAG_TO_ENTITY_IDS_MAP = {
|
||||||
"{644d655b-ae66-43b1-9bab-a44b9a8ad632}": {
|
"{644d655b-ae66-43b1-9bab-a44b9a8ad632}": {
|
||||||
"tag": "nearGrab"
|
"tag": "nearGrab"
|
||||||
},
|
},
|
||||||
"{88221a22-b710-4d35-852b-5257b0aa77dc}": {
|
|
||||||
"tag": "nearGrab"
|
|
||||||
},
|
|
||||||
"{8bf0baa1-88d0-448a-a782-100d4413bd82}": {
|
"{8bf0baa1-88d0-448a-a782-100d4413bd82}": {
|
||||||
"tag": "nearGrab"
|
"tag": "nearGrab"
|
||||||
},
|
},
|
||||||
|
@ -70,13 +77,20 @@ TUTORIAL_TAG_TO_ENTITY_IDS_MAP = {
|
||||||
"tag": "nearGrab"
|
"tag": "nearGrab"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"equip-part1-touch": {
|
||||||
|
"{470f0634-8be7-4b52-a8bd-5183d489fcb6}": {
|
||||||
|
"tag": "equip-part1-touch"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"equip-part1-vive": {
|
||||||
|
"{97ced5e7-fc81-40f9-a9e8-f85b4b30f24c}": {
|
||||||
|
"tag": "equip-part1-vive"
|
||||||
|
}
|
||||||
|
},
|
||||||
"equip-part1": {
|
"equip-part1": {
|
||||||
"{d73822ca-0a34-4cf4-a530-3258ac459a14}": {
|
"{d73822ca-0a34-4cf4-a530-3258ac459a14}": {
|
||||||
"tag": "equip-part1"
|
"tag": "equip-part1"
|
||||||
},
|
},
|
||||||
"{97ced5e7-fc81-40f9-a9e8-f85b4b30f24c}": {
|
|
||||||
"tag": "equip-part1"
|
|
||||||
},
|
|
||||||
"{8572d991-5777-45df-97bf-7243d7b12f81}": {
|
"{8572d991-5777-45df-97bf-7243d7b12f81}": {
|
||||||
"tag": "equip-part1"
|
"tag": "equip-part1"
|
||||||
},
|
},
|
||||||
|
@ -102,16 +116,17 @@ TUTORIAL_TAG_TO_ENTITY_IDS_MAP = {
|
||||||
"equip-part2-vive": {
|
"equip-part2-vive": {
|
||||||
"{b5d17eda-90ab-40cf-b973-efcecb2e992e}": {
|
"{b5d17eda-90ab-40cf-b973-efcecb2e992e}": {
|
||||||
"tag": "equip-part2-vive"
|
"tag": "equip-part2-vive"
|
||||||
|
},
|
||||||
|
"{6307cd16-dd1d-4988-a339-578178436b45}": {
|
||||||
|
"tag": "equip-part2-vive"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"equip-part2-touch": {
|
"equip-part2-touch": {
|
||||||
"{69195139-e020-4739-bb2c-50faebc6860a}": {
|
"{69195139-e020-4739-bb2c-50faebc6860a}": {
|
||||||
"tag": "equip-part2-touch"
|
"tag": "equip-part2-touch"
|
||||||
}
|
},
|
||||||
},
|
"{9b0a99ae-221b-4e59-ba3c-d8e64a083774}": {
|
||||||
"equip-part2": {
|
"tag": "equip-part2-touch"
|
||||||
"{6307cd16-dd1d-4988-a339-578178436b45}": {
|
|
||||||
"tag": "equip-part2"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bothGrab": {
|
"bothGrab": {
|
||||||
|
|
Loading…
Reference in a new issue