mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 06:05:31 +02:00
Merge remote-tracking branch 'upstream/master' into animationBlendChanges
This commit is contained in:
commit
91b9865f27
17 changed files with 337 additions and 62 deletions
|
@ -162,7 +162,19 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCrea
|
|||
jvmArgs.version = JNI_VERSION_1_6; // choose your JNI version
|
||||
jvmArgs.name = NULL; // you might want to give the java thread a name
|
||||
jvmArgs.group = NULL; // you might want to assign the java thread to a ThreadGroup
|
||||
jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&myNewEnv), &jvmArgs);
|
||||
|
||||
int attachedHere = 0; // know if detaching at the end is necessary
|
||||
jint res = jvm->GetEnv((void**)&myNewEnv, JNI_VERSION_1_6); // checks if current env needs attaching or it is already attached
|
||||
if (JNI_OK != res) {
|
||||
qDebug() << "[JCRASH] GetEnv env not attached yet, attaching now..";
|
||||
res = jvm->AttachCurrentThread(reinterpret_cast<JNIEnv **>(&myNewEnv), &jvmArgs);
|
||||
if (JNI_OK != res) {
|
||||
qDebug() << "[JCRASH] Failed to AttachCurrentThread, ErrorCode = " << res;
|
||||
return;
|
||||
} else {
|
||||
attachedHere = 1;
|
||||
}
|
||||
}
|
||||
|
||||
QAndroidJniObject string = QAndroidJniObject::fromString(a);
|
||||
jboolean jBackToScene = (jboolean) backToScene;
|
||||
|
@ -175,7 +187,9 @@ JNIEXPORT void Java_io_highfidelity_hifiinterface_InterfaceActivity_nativeOnCrea
|
|||
myNewEnv->CallObjectMethod(hashmap, mapClassPut, QAndroidJniObject::fromString("url").object<jstring>(), jArg.object<jstring>());
|
||||
}
|
||||
__interfaceActivity.callMethod<void>("openAndroidActivity", "(Ljava/lang/String;ZLjava/util/HashMap;)V", string.object<jstring>(), jBackToScene, hashmap);
|
||||
jvm->DetachCurrentThread();
|
||||
if (attachedHere) {
|
||||
jvm->DetachCurrentThread();
|
||||
}
|
||||
});
|
||||
|
||||
QObject::connect(&AndroidHelper::instance(), &AndroidHelper::hapticFeedbackRequested, [](int duration) {
|
||||
|
|
|
@ -1223,7 +1223,7 @@
|
|||
"name": "max_avatar_height",
|
||||
"type": "double",
|
||||
"label": "Maximum Avatar Height (meters)",
|
||||
"help": "Limits the scale of avatars in your domain. Cannot be greater than 1755.",
|
||||
"help": "Limits the height of avatars in your domain. Cannot be greater than 1755.",
|
||||
"placeholder": 5.2,
|
||||
"default": 5.2
|
||||
},
|
||||
|
|
|
@ -58,7 +58,11 @@ $(document).ready(function(){
|
|||
}
|
||||
|
||||
Settings.handlePostSettings = function(formJSON) {
|
||||
|
||||
|
||||
if (!verifyAvatarHeights()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if we've set the basic http password
|
||||
if (formJSON["security"]) {
|
||||
|
||||
|
@ -207,7 +211,7 @@ $(document).ready(function(){
|
|||
swal({
|
||||
title: '',
|
||||
type: 'error',
|
||||
text: "There was a problem retreiving domain information from High Fidelity API.",
|
||||
text: "There was a problem retrieving domain information from High Fidelity API.",
|
||||
confirmButtonText: 'Try again',
|
||||
showCancelButton: true,
|
||||
closeOnConfirm: false
|
||||
|
@ -288,7 +292,7 @@ $(document).ready(function(){
|
|||
swal({
|
||||
title: 'Create new domain ID',
|
||||
type: 'input',
|
||||
text: 'Enter a label this machine.</br></br>This will help you identify which domain ID belongs to which machine.</br></br>',
|
||||
text: 'Enter a label for this machine.</br></br>This will help you identify which domain ID belongs to which machine.</br></br>',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: "Create",
|
||||
closeOnConfirm: false,
|
||||
|
@ -669,7 +673,7 @@ $(document).ready(function(){
|
|||
var spinner = createDomainSpinner();
|
||||
$('#' + Settings.PLACES_TABLE_ID).after($(spinner));
|
||||
|
||||
var errorEl = createDomainLoadingError("There was an error retreiving your places.");
|
||||
var errorEl = createDomainLoadingError("There was an error retrieving your places.");
|
||||
$("#" + Settings.PLACES_TABLE_ID).after(errorEl);
|
||||
|
||||
// do we have a domain ID?
|
||||
|
@ -1091,4 +1095,43 @@ $(document).ready(function(){
|
|||
|
||||
$('#settings_backup .panel-body').html(html);
|
||||
}
|
||||
|
||||
function verifyAvatarHeights() {
|
||||
var errorString = '';
|
||||
var minAllowedHeight = 0.009;
|
||||
var maxAllowedHeight = 1755;
|
||||
var alertCss = { backgroundColor: '#ffa0a0' };
|
||||
var minHeightElement = $('input[name="avatars.min_avatar_height"]');
|
||||
var maxHeightElement = $('input[name="avatars.max_avatar_height"]');
|
||||
|
||||
var minHeight = Number(minHeightElement.val());
|
||||
var maxHeight = Number(maxHeightElement.val());
|
||||
|
||||
if (maxHeight < minHeight) {
|
||||
errorString = 'Maximum avatar height must not be less than minimum avatar height<br>';
|
||||
minHeightElement.css(alertCss);
|
||||
maxHeightElement.css(alertCss);
|
||||
};
|
||||
if (minHeight < minAllowedHeight) {
|
||||
errorString += 'Minimum avatar height must not be less than ' + minAllowedHeight + '<br>';
|
||||
minHeightElement.css(alertCss);
|
||||
}
|
||||
if (maxHeight > maxAllowedHeight) {
|
||||
errorString += 'Maximum avatar height must not be greater than ' + maxAllowedHeight + '<br>';
|
||||
maxHeightElement.css(alertCss);
|
||||
}
|
||||
|
||||
if (errorString.length > 0) {
|
||||
swal({
|
||||
type: 'error',
|
||||
title: '',
|
||||
text: errorString,
|
||||
html: true
|
||||
});
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
|
|
|
@ -299,7 +299,7 @@ Item {
|
|||
anchors.fill: stackView
|
||||
id: controllerPrefereneces
|
||||
objectName: "TabletControllerPreferences"
|
||||
showCategories: ["VR Movement", "Game Controller", "Sixense Controllers", "Perception Neuron", "Leap Motion"]
|
||||
showCategories: [( (HMD.active) ? "VR Movement" : "Movement"), "Game Controller", "Sixense Controllers", "Perception Neuron", "Leap Motion"]
|
||||
categoryProperties: {
|
||||
"VR Movement" : {
|
||||
"User real-world height (meters)" : { "anchors.right" : "undefined" },
|
||||
|
|
|
@ -3650,6 +3650,10 @@ bool Application::event(QEvent* event) {
|
|||
|
||||
bool Application::eventFilter(QObject* object, QEvent* event) {
|
||||
|
||||
if (_aboutToQuit) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::Leave) {
|
||||
getApplicationCompositor().handleLeaveEvent();
|
||||
}
|
||||
|
@ -4839,6 +4843,13 @@ void Application::loadSettings() {
|
|||
}
|
||||
|
||||
isFirstPerson = (qApp->isHMDMode());
|
||||
|
||||
// Flying should be disabled by default in HMD mode on first run, and it
|
||||
// should be enabled by default in desktop mode.
|
||||
|
||||
auto myAvatar = getMyAvatar();
|
||||
myAvatar->setFlyingEnabled(!isFirstPerson);
|
||||
|
||||
} else {
|
||||
// if this is not the first run, the camera will be initialized differently depending on user settings
|
||||
|
||||
|
|
|
@ -144,9 +144,19 @@ void AvatarBookmarks::removeBookmark(const QString& bookmarkName) {
|
|||
emit bookmarkDeleted(bookmarkName);
|
||||
}
|
||||
|
||||
bool isWearableEntity(const EntityItemPointer& entity) {
|
||||
return entity->isVisible() && entity->getParentJointIndex() != INVALID_JOINT_INDEX &&
|
||||
(entity->getParentID() == DependencyManager::get<NodeList>()->getSessionUUID() || entity->getParentID() == DependencyManager::get<AvatarManager>()->getMyAvatar()->getSelfID());
|
||||
}
|
||||
|
||||
void AvatarBookmarks::updateAvatarEntities(const QVariantList &avatarEntities) {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
myAvatar->removeAvatarEntities();
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
myAvatar->removeAvatarEntities([&](const QUuid& entityID) {
|
||||
auto entity = entityTree->findEntityByID(entityID);
|
||||
return entity && isWearableEntity(entity);
|
||||
});
|
||||
|
||||
addAvatarEntities(avatarEntities);
|
||||
}
|
||||
|
@ -163,7 +173,12 @@ void AvatarBookmarks::loadBookmark(const QString& bookmarkName) {
|
|||
QVariantMap bookmark = bookmarkEntry.value().toMap();
|
||||
if (!bookmark.empty()) {
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
myAvatar->removeAvatarEntities();
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
myAvatar->removeAvatarEntities([&](const QUuid& entityID) {
|
||||
auto entity = entityTree->findEntityByID(entityID);
|
||||
return entity && isWearableEntity(entity);
|
||||
});
|
||||
const QString& avatarUrl = bookmark.value(ENTRY_AVATAR_URL, "").toString();
|
||||
myAvatar->useFullAvatarURL(avatarUrl);
|
||||
qCDebug(interfaceapp) << "Avatar On " << avatarUrl;
|
||||
|
@ -233,6 +248,27 @@ QVariantMap AvatarBookmarks::getAvatarDataToBookmark() {
|
|||
bookmark.insert(ENTRY_AVATAR_URL, avatarUrl);
|
||||
bookmark.insert(ENTRY_AVATAR_SCALE, avatarScale);
|
||||
bookmark.insert(ENTRY_AVATAR_ATTACHMENTS, myAvatar->getAttachmentsVariant());
|
||||
bookmark.insert(ENTRY_AVATAR_ENTITIES, myAvatar->getAvatarEntitiesVariant());
|
||||
|
||||
QScriptEngine scriptEngine;
|
||||
QVariantList wearableEntities;
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
auto avatarEntities = myAvatar->getAvatarEntityData();
|
||||
for (auto entityID : avatarEntities.keys()) {
|
||||
auto entity = entityTree->findEntityByID(entityID);
|
||||
if (!entity || !isWearableEntity(entity)) {
|
||||
continue;
|
||||
}
|
||||
QVariantMap avatarEntityData;
|
||||
EncodeBitstreamParams params;
|
||||
auto desiredProperties = entity->getEntityProperties(params);
|
||||
desiredProperties += PROP_LOCAL_POSITION;
|
||||
desiredProperties += PROP_LOCAL_ROTATION;
|
||||
EntityItemProperties entityProperties = entity->getProperties(desiredProperties);
|
||||
QScriptValue scriptProperties = EntityItemPropertiesToScriptValue(&scriptEngine, entityProperties);
|
||||
avatarEntityData["properties"] = scriptProperties.toVariant();
|
||||
wearableEntities.append(QVariant(avatarEntityData));
|
||||
}
|
||||
bookmark.insert(ENTRY_AVATAR_ENTITIES, wearableEntities);
|
||||
return bookmark;
|
||||
}
|
||||
|
|
|
@ -275,6 +275,13 @@ Menu::Menu() {
|
|||
QString("hifi/tablet/TabletGraphicsPreferences.qml"), "GraphicsPreferencesDialog");
|
||||
});
|
||||
|
||||
// Settings > Attachments...
|
||||
action = addActionToQMenuAndActionHash(settingsMenu, MenuOption::Attachments);
|
||||
connect(action, &QAction::triggered, [] {
|
||||
qApp->showDialog(QString("hifi/dialogs/AttachmentsDialog.qml"),
|
||||
QString("hifi/tablet/TabletAttachmentsDialog.qml"), "AttachmentsDialog");
|
||||
});
|
||||
|
||||
// Settings > Developer Menu
|
||||
addCheckableActionToQMenuAndActionHash(settingsMenu, "Developer Menu", 0, false, this, SLOT(toggleDeveloperMenus()));
|
||||
|
||||
|
|
|
@ -1281,7 +1281,8 @@ void MyAvatar::loadData() {
|
|||
settings.remove("avatarEntityData");
|
||||
}
|
||||
setAvatarEntityDataChanged(true);
|
||||
setFlyingEnabled(settings.value("enabledFlying").toBool());
|
||||
Setting::Handle<bool> firstRunVal { Settings::firstRun, true };
|
||||
setFlyingEnabled(firstRunVal.get() ? getFlyingEnabled() : settings.value("enabledFlying").toBool());
|
||||
setDisplayName(settings.value("displayName").toString());
|
||||
setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString());
|
||||
setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool());
|
||||
|
@ -1607,14 +1608,16 @@ void MyAvatar::setSkeletonModelURL(const QUrl& skeletonModelURL) {
|
|||
emit skeletonModelURLChanged();
|
||||
}
|
||||
|
||||
void MyAvatar::removeAvatarEntities() {
|
||||
void MyAvatar::removeAvatarEntities(const std::function<bool(const QUuid& entityID)>& condition) {
|
||||
auto treeRenderer = DependencyManager::get<EntityTreeRenderer>();
|
||||
EntityTreePointer entityTree = treeRenderer ? treeRenderer->getTree() : nullptr;
|
||||
if (entityTree) {
|
||||
entityTree->withWriteLock([&] {
|
||||
AvatarEntityMap avatarEntities = getAvatarEntityData();
|
||||
for (auto entityID : avatarEntities.keys()) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
if (!condition || condition(entityID)) {
|
||||
entityTree->deleteEntity(entityID, true, true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include "MyCharacterController.h"
|
||||
#include "RingBufferHistory.h"
|
||||
#include <ThreadSafeValueCache.h>
|
||||
#include <EntityItem.h>
|
||||
|
||||
class AvatarActionHold;
|
||||
class ModelItemID;
|
||||
|
@ -926,7 +927,7 @@ public:
|
|||
* @returns {object[]}
|
||||
*/
|
||||
Q_INVOKABLE QVariantList getAvatarEntitiesVariant();
|
||||
void removeAvatarEntities();
|
||||
void removeAvatarEntities(const std::function<bool(const QUuid& entityID)>& condition = {});
|
||||
|
||||
/**jsdoc
|
||||
* @function MyAvatar.isFlying
|
||||
|
|
|
@ -266,20 +266,15 @@ void setupPreferences() {
|
|||
preferences->addPreference(new SliderPreference(FACE_TRACKING, "Eye Deflection", getter, setter));
|
||||
}
|
||||
|
||||
static const QString MOVEMENT{ "VR Movement" };
|
||||
static const QString MOVEMENT{ "Movement" };
|
||||
{
|
||||
|
||||
static const QString movementsControlChannel = QStringLiteral("Hifi-Advanced-Movement-Disabler");
|
||||
auto getter = [=]()->bool { return myAvatar->useAdvancedMovementControls(); };
|
||||
auto setter = [=](bool value) { myAvatar->setUseAdvancedMovementControls(value); };
|
||||
preferences->addPreference(new CheckPreference(MOVEMENT,
|
||||
QStringLiteral("Advanced movement for hand controllers"),
|
||||
getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); };
|
||||
auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); };
|
||||
preferences->addPreference(new CheckPreference(MOVEMENT, "Flying & jumping", getter, setter));
|
||||
QStringLiteral("Advanced movement for hand controllers"),
|
||||
getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->int { return myAvatar->getSnapTurn() ? 0 : 1; };
|
||||
|
@ -307,6 +302,47 @@ void setupPreferences() {
|
|||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
static const QString VR_MOVEMENT{ "VR Movement" };
|
||||
{
|
||||
|
||||
static const QString movementsControlChannel = QStringLiteral("Hifi-Advanced-Movement-Disabler");
|
||||
auto getter = [=]()->bool { return myAvatar->useAdvancedMovementControls(); };
|
||||
auto setter = [=](bool value) { myAvatar->setUseAdvancedMovementControls(value); };
|
||||
preferences->addPreference(new CheckPreference(VR_MOVEMENT,
|
||||
QStringLiteral("Advanced movement for hand controllers"),
|
||||
getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); };
|
||||
auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); };
|
||||
preferences->addPreference(new CheckPreference(VR_MOVEMENT, "Flying & jumping", getter, setter));
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->int { return myAvatar->getSnapTurn() ? 0 : 1; };
|
||||
auto setter = [=](int value) { myAvatar->setSnapTurn(value == 0); };
|
||||
auto preference = new RadioButtonsPreference(VR_MOVEMENT, "Snap turn / Smooth turn", getter, setter);
|
||||
QStringList items;
|
||||
items << "Snap turn" << "Smooth turn";
|
||||
preference->setItems(items);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto getter = [=]()->float { return myAvatar->getUserHeight(); };
|
||||
auto setter = [=](float value) { myAvatar->setUserHeight(value); };
|
||||
auto preference = new SpinnerPreference(VR_MOVEMENT, "User real-world height (meters)", getter, setter);
|
||||
preference->setMin(1.0f);
|
||||
preference->setMax(2.2f);
|
||||
preference->setDecimals(3);
|
||||
preference->setStep(0.001f);
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
{
|
||||
auto preference = new ButtonPreference(VR_MOVEMENT, "RESET SENSORS", [] {
|
||||
qApp->resetSensors();
|
||||
});
|
||||
preferences->addPreference(preference);
|
||||
}
|
||||
|
||||
static const QString AVATAR_CAMERA{ "Mouse Sensitivity" };
|
||||
{
|
||||
auto getter = [=]()->float { return myAvatar->getPitchSpeed(); };
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
set(TARGET_NAME audio-client)
|
||||
setup_hifi_library(Network Multimedia)
|
||||
if (ANDROID)
|
||||
set(PLATFORM_QT_COMPONENTS AndroidExtras)
|
||||
endif ()
|
||||
setup_hifi_library(Network Multimedia ${PLATFORM_QT_COMPONENTS})
|
||||
link_hifi_libraries(audio plugins)
|
||||
include_hifi_library_headers(shared)
|
||||
include_hifi_library_headers(networking)
|
||||
|
|
|
@ -52,6 +52,10 @@
|
|||
#include "AudioLogging.h"
|
||||
#include "AudioHelpers.h"
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
#include <QtAndroidExtras/QAndroidJniObject>
|
||||
#endif
|
||||
|
||||
const int AudioClient::MIN_BUFFER_FRAMES = 1;
|
||||
|
||||
const int AudioClient::MAX_BUFFER_FRAMES = 20;
|
||||
|
@ -60,7 +64,7 @@ static const int RECEIVED_AUDIO_STREAM_CAPACITY_FRAMES = 100;
|
|||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
static const int CHECK_INPUT_READS_MSECS = 2000;
|
||||
static const int MIN_READS_TO_CONSIDER_INPUT_ALIVE = 100;
|
||||
static const int MIN_READS_TO_CONSIDER_INPUT_ALIVE = 10;
|
||||
#endif
|
||||
|
||||
static const auto DEFAULT_POSITION_GETTER = []{ return Vectors::ZERO; };
|
||||
|
@ -235,7 +239,7 @@ AudioClient::AudioClient() :
|
|||
|
||||
// start a thread to detect any device changes
|
||||
_checkDevicesTimer = new QTimer(this);
|
||||
connect(_checkDevicesTimer, &QTimer::timeout, [this] {
|
||||
connect(_checkDevicesTimer, &QTimer::timeout, this, [this] {
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkDevices(); });
|
||||
});
|
||||
const unsigned long DEVICE_CHECK_INTERVAL_MSECS = 2 * 1000;
|
||||
|
@ -243,7 +247,7 @@ AudioClient::AudioClient() :
|
|||
|
||||
// start a thread to detect peak value changes
|
||||
_checkPeakValuesTimer = new QTimer(this);
|
||||
connect(_checkPeakValuesTimer, &QTimer::timeout, [this] {
|
||||
connect(_checkPeakValuesTimer, &QTimer::timeout, this, [this] {
|
||||
QtConcurrent::run(QThreadPool::globalInstance(), [this] { checkPeakValues(); });
|
||||
});
|
||||
const unsigned long PEAK_VALUES_CHECK_INTERVAL_MSECS = 50;
|
||||
|
@ -482,6 +486,15 @@ bool nativeFormatForAudioDevice(const QAudioDeviceInfo& audioDevice,
|
|||
audioFormat.setSampleType(QAudioFormat::SignedInt);
|
||||
audioFormat.setByteOrder(QAudioFormat::LittleEndian);
|
||||
|
||||
#if defined(Q_OS_ANDROID)
|
||||
// Using the HW sample rate (AUDIO_INPUT_FLAG_FAST) in some samsung phones causes a low volume at input stream
|
||||
// Changing the sample rate forces a resampling that (in samsung) amplifies +18 dB
|
||||
QAndroidJniObject brand = QAndroidJniObject::getStaticObjectField<jstring>("android/os/Build", "BRAND");
|
||||
if (audioDevice == QAudioDeviceInfo::defaultInputDevice() && brand.toString().contains("samsung", Qt::CaseInsensitive)) {
|
||||
audioFormat.setSampleRate(24000);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!audioDevice.isFormatSupported(audioFormat)) {
|
||||
qCWarning(audioclient) << "The native format is" << audioFormat << "but isFormatSupported() failed.";
|
||||
return false;
|
||||
|
@ -635,9 +648,7 @@ void AudioClient::start() {
|
|||
qCDebug(audioclient) << "The closest format available is" << outputDeviceInfo.nearestFormat(_desiredOutputFormat);
|
||||
}
|
||||
#if defined(Q_OS_ANDROID)
|
||||
connect(&_checkInputTimer, &QTimer::timeout, [this] {
|
||||
checkInputTimeout();
|
||||
});
|
||||
connect(&_checkInputTimer, &QTimer::timeout, this, &AudioClient::checkInputTimeout);
|
||||
_checkInputTimer.start(CHECK_INPUT_READS_MSECS);
|
||||
#endif
|
||||
}
|
||||
|
@ -651,6 +662,7 @@ void AudioClient::stop() {
|
|||
switchOutputToAudioDevice(QAudioDeviceInfo(), true);
|
||||
#if defined(Q_OS_ANDROID)
|
||||
_checkInputTimer.stop();
|
||||
disconnect(&_checkInputTimer, &QTimer::timeout, 0, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -1558,9 +1570,7 @@ bool AudioClient::switchInputToAudioDevice(const QAudioDeviceInfo inputDeviceInf
|
|||
#if defined(Q_OS_ANDROID)
|
||||
if (_audioInput) {
|
||||
_shouldRestartInputSetup = true;
|
||||
connect(_audioInput, &QAudioInput::stateChanged, [this](QAudio::State state) {
|
||||
audioInputStateChanged(state);
|
||||
});
|
||||
connect(_audioInput, &QAudioInput::stateChanged, this, &AudioClient::audioInputStateChanged);
|
||||
}
|
||||
#endif
|
||||
_inputDevice = _audioInput->start();
|
||||
|
@ -1764,7 +1774,7 @@ bool AudioClient::switchOutputToAudioDevice(const QAudioDeviceInfo outputDeviceI
|
|||
_outputScratchBuffer = new int16_t[_outputPeriod];
|
||||
|
||||
// size local output mix buffer based on resampled network frame size
|
||||
int networkPeriod = _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO);
|
||||
int networkPeriod = _localToOutputResampler ? _localToOutputResampler->getMaxOutput(AudioConstants::NETWORK_FRAME_SAMPLES_STEREO) : AudioConstants::NETWORK_FRAME_SAMPLES_STEREO;
|
||||
_localOutputMixBuffer = new float[networkPeriod];
|
||||
|
||||
// local period should be at least twice the output period,
|
||||
|
|
|
@ -185,7 +185,7 @@ private:
|
|||
#if defined(Q_OS_ANDROID)
|
||||
Setting::Handle<bool> _ignoreRadiusEnabled { "IgnoreRadiusEnabled", false };
|
||||
#else
|
||||
Setting::Handle<bool> _ignoreRadiusEnabled { "IgnoreRadiusEnabled", true };
|
||||
Setting::Handle<bool> _ignoreRadiusEnabled { "IgnoreRadiusEnabled", false }; // False, until such time as it is made to work better.
|
||||
#endif
|
||||
|
||||
#if (PR_BUILD || DEV_BUILD)
|
||||
|
|
|
@ -229,7 +229,7 @@ qint64 Socket::writeDatagram(const QByteArray& datagram, const HifiSockAddr& soc
|
|||
|
||||
if (bytesWritten < 0) {
|
||||
// when saturating a link this isn't an uncommon message - suppress it so it doesn't bomb the debug
|
||||
HIFI_FCDEBUG(networking(), "Socket::writeDatagram" << _udpSocket.error() << "-" << qPrintable(_udpSocket.errorString()) );
|
||||
HIFI_FCDEBUG(networking(), "Socket::writeDatagram" << _udpSocket.error());
|
||||
}
|
||||
|
||||
return bytesWritten;
|
||||
|
@ -513,7 +513,7 @@ std::vector<HifiSockAddr> Socket::getConnectionSockAddrs() {
|
|||
}
|
||||
|
||||
void Socket::handleSocketError(QAbstractSocket::SocketError socketError) {
|
||||
HIFI_FCDEBUG(networking(), "udt::Socket error - " << socketError << _udpSocket.errorString());
|
||||
HIFI_FCDEBUG(networking(), "udt::Socket error - " << socketError);
|
||||
}
|
||||
|
||||
void Socket::handleStateChanged(QAbstractSocket::SocketState socketState) {
|
||||
|
|
|
@ -29,13 +29,25 @@ function executeLater(callback) {
|
|||
Script.setTimeout(callback, 300);
|
||||
}
|
||||
|
||||
function getMyAvatarWearables() {
|
||||
var wearablesArray = MyAvatar.getAvatarEntitiesVariant();
|
||||
var INVALID_JOINT_INDEX = -1
|
||||
function isWearable(avatarEntity) {
|
||||
return avatarEntity.properties.visible === true && avatarEntity.properties.parentJointIndex !== INVALID_JOINT_INDEX &&
|
||||
(avatarEntity.properties.parentID === MyAvatar.sessionUUID || avatarEntity.properties.parentID === MyAvatar.SELF_ID);
|
||||
}
|
||||
|
||||
for(var i = 0; i < wearablesArray.length; ++i) {
|
||||
var wearable = wearablesArray[i];
|
||||
var localRotation = wearable.properties.localRotation;
|
||||
wearable.properties.localRotationAngles = Quat.safeEulerAngles(localRotation)
|
||||
function getMyAvatarWearables() {
|
||||
var entitiesArray = MyAvatar.getAvatarEntitiesVariant();
|
||||
var wearablesArray = [];
|
||||
|
||||
for (var i = 0; i < entitiesArray.length; ++i) {
|
||||
var entity = entitiesArray[i];
|
||||
if (!isWearable(entity)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
var localRotation = entity.properties.localRotation;
|
||||
entity.properties.localRotationAngles = Quat.safeEulerAngles(localRotation)
|
||||
wearablesArray.push(entity);
|
||||
}
|
||||
|
||||
return wearablesArray;
|
||||
|
@ -159,13 +171,12 @@ function fromQml(message) { // messages are {method, params}, like json-rpc. See
|
|||
|
||||
for(var bookmarkName in message.data.bookmarks) {
|
||||
var bookmark = message.data.bookmarks[bookmarkName];
|
||||
if (!bookmark.avatarEntites) { // ensure avatarEntites always exist
|
||||
bookmark.avatarEntites = [];
|
||||
}
|
||||
|
||||
bookmark.avatarEntites.forEach(function(avatarEntity) {
|
||||
avatarEntity.properties.localRotationAngles = Quat.safeEulerAngles(avatarEntity.properties.localRotation)
|
||||
})
|
||||
if (bookmark.avatarEntites) {
|
||||
bookmark.avatarEntites.forEach(function(avatarEntity) {
|
||||
avatarEntity.properties.localRotationAngles = Quat.safeEulerAngles(avatarEntity.properties.localRotation);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
sendToQml(message)
|
||||
|
|
|
@ -263,7 +263,7 @@ SelectionManager = (function() {
|
|||
|
||||
that.worldDimensions = properties.boundingBox.dimensions;
|
||||
that.worldPosition = properties.boundingBox.center;
|
||||
that.worldRotation = properties.boundingBox.rotation;
|
||||
that.worldRotation = Quat.IDENTITY;
|
||||
|
||||
that.entityType = properties.type;
|
||||
|
||||
|
@ -271,10 +271,6 @@ SelectionManager = (function() {
|
|||
SelectionDisplay.setSpaceMode(SPACE_LOCAL);
|
||||
}
|
||||
} else {
|
||||
that.localRotation = null;
|
||||
that.localDimensions = null;
|
||||
that.localPosition = null;
|
||||
|
||||
properties = Entities.getEntityProperties(that.selections[0]);
|
||||
|
||||
that.entityType = properties.type;
|
||||
|
@ -293,6 +289,7 @@ SelectionManager = (function() {
|
|||
tfl.z = Math.max(bb.tfl.z, tfl.z);
|
||||
}
|
||||
|
||||
that.localRotation = null;
|
||||
that.localDimensions = null;
|
||||
that.localPosition = null;
|
||||
that.worldDimensions = {
|
||||
|
@ -300,6 +297,7 @@ SelectionManager = (function() {
|
|||
y: tfl.y - brn.y,
|
||||
z: tfl.z - brn.z
|
||||
};
|
||||
that.worldRotation = Quat.IDENTITY;
|
||||
that.worldPosition = {
|
||||
x: brn.x + (that.worldDimensions.x / 2),
|
||||
y: brn.y + (that.worldDimensions.y / 2),
|
||||
|
@ -381,6 +379,8 @@ SelectionDisplay = (function() {
|
|||
|
||||
var CTRL_KEY_CODE = 16777249;
|
||||
|
||||
var RAIL_AXIS_LENGTH = 10000;
|
||||
|
||||
var TRANSLATE_DIRECTION = {
|
||||
X: 0,
|
||||
Y: 1,
|
||||
|
@ -616,6 +616,40 @@ SelectionDisplay = (function() {
|
|||
dashed: false
|
||||
});
|
||||
|
||||
var xRailOverlay = Overlays.addOverlay("line3d", {
|
||||
visible: false,
|
||||
start: Vec3.ZERO,
|
||||
end: Vec3.ZERO,
|
||||
color: {
|
||||
red: 255,
|
||||
green: 0,
|
||||
blue: 0
|
||||
},
|
||||
ignoreRayIntersection: true // always ignore this
|
||||
});
|
||||
var yRailOverlay = Overlays.addOverlay("line3d", {
|
||||
visible: false,
|
||||
start: Vec3.ZERO,
|
||||
end: Vec3.ZERO,
|
||||
color: {
|
||||
red: 0,
|
||||
green: 255,
|
||||
blue: 0
|
||||
},
|
||||
ignoreRayIntersection: true // always ignore this
|
||||
});
|
||||
var zRailOverlay = Overlays.addOverlay("line3d", {
|
||||
visible: false,
|
||||
start: Vec3.ZERO,
|
||||
end: Vec3.ZERO,
|
||||
color: {
|
||||
red: 0,
|
||||
green: 0,
|
||||
blue: 255
|
||||
},
|
||||
ignoreRayIntersection: true // always ignore this
|
||||
});
|
||||
|
||||
var allOverlays = [
|
||||
handleTranslateXCone,
|
||||
handleTranslateXCylinder,
|
||||
|
@ -656,7 +690,11 @@ SelectionDisplay = (function() {
|
|||
handleScaleFLEdge,
|
||||
handleCloner,
|
||||
selectionBox,
|
||||
iconSelectionBox
|
||||
iconSelectionBox,
|
||||
xRailOverlay,
|
||||
yRailOverlay,
|
||||
zRailOverlay
|
||||
|
||||
];
|
||||
var maximumHandleInAllOverlays = handleCloner;
|
||||
|
||||
|
@ -873,11 +911,13 @@ SelectionDisplay = (function() {
|
|||
};
|
||||
|
||||
// FUNCTION: MOUSE MOVE EVENT
|
||||
var lastMouseEvent = null;
|
||||
that.mouseMoveEvent = function(event) {
|
||||
var wantDebug = false;
|
||||
if (wantDebug) {
|
||||
print("=============== eST::MouseMoveEvent BEG =======================");
|
||||
}
|
||||
lastMouseEvent = event;
|
||||
if (activeTool) {
|
||||
if (wantDebug) {
|
||||
print(" Trigger ActiveTool(" + activeTool.mode + ")'s onMove");
|
||||
|
@ -999,19 +1039,35 @@ SelectionDisplay = (function() {
|
|||
};
|
||||
|
||||
// Control key remains active only while key is held down
|
||||
that.keyReleaseEvent = function(key) {
|
||||
if (key.key === CTRL_KEY_CODE) {
|
||||
that.keyReleaseEvent = function(event) {
|
||||
if (event.key === CTRL_KEY_CODE) {
|
||||
ctrlPressed = false;
|
||||
that.updateActiveRotateRing();
|
||||
}
|
||||
if (activeTool && lastMouseEvent !== null) {
|
||||
lastMouseEvent.isShifted = event.isShifted;
|
||||
lastMouseEvent.isMeta = event.isMeta;
|
||||
lastMouseEvent.isControl = event.isControl;
|
||||
lastMouseEvent.isAlt = event.isAlt;
|
||||
activeTool.onMove(lastMouseEvent);
|
||||
SelectionManager._update();
|
||||
}
|
||||
};
|
||||
|
||||
// Triggers notification on specific key driven events
|
||||
that.keyPressEvent = function(key) {
|
||||
if (key.key === CTRL_KEY_CODE) {
|
||||
that.keyPressEvent = function(event) {
|
||||
if (event.key === CTRL_KEY_CODE) {
|
||||
ctrlPressed = true;
|
||||
that.updateActiveRotateRing();
|
||||
}
|
||||
if (activeTool && lastMouseEvent !== null) {
|
||||
lastMouseEvent.isShifted = event.isShifted;
|
||||
lastMouseEvent.isMeta = event.isMeta;
|
||||
lastMouseEvent.isControl = event.isControl;
|
||||
lastMouseEvent.isAlt = event.isAlt;
|
||||
activeTool.onMove(lastMouseEvent);
|
||||
SelectionManager._update();
|
||||
}
|
||||
};
|
||||
|
||||
// NOTE: mousePressEvent and mouseMoveEvent from the main script should call us., so we don't hook these:
|
||||
|
@ -1705,6 +1761,14 @@ SelectionDisplay = (function() {
|
|||
},
|
||||
onEnd: function(event, reason) {
|
||||
pushCommandForSelections(duplicatedEntityIDs);
|
||||
if (isConstrained) {
|
||||
Overlays.editOverlay(xRailOverlay, {
|
||||
visible: false
|
||||
});
|
||||
Overlays.editOverlay(zRailOverlay, {
|
||||
visible: false
|
||||
});
|
||||
}
|
||||
},
|
||||
elevation: function(origin, intersection) {
|
||||
return (origin.y - intersection.y) / Vec3.distance(origin, intersection);
|
||||
|
@ -1768,10 +1832,46 @@ SelectionDisplay = (function() {
|
|||
vector.x = 0;
|
||||
}
|
||||
if (!isConstrained) {
|
||||
var xStart = Vec3.sum(startPosition, {
|
||||
x: -RAIL_AXIS_LENGTH,
|
||||
y: 0,
|
||||
z: 0
|
||||
});
|
||||
var xEnd = Vec3.sum(startPosition, {
|
||||
x: RAIL_AXIS_LENGTH,
|
||||
y: 0,
|
||||
z: 0
|
||||
});
|
||||
var zStart = Vec3.sum(startPosition, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: -RAIL_AXIS_LENGTH
|
||||
});
|
||||
var zEnd = Vec3.sum(startPosition, {
|
||||
x: 0,
|
||||
y: 0,
|
||||
z: RAIL_AXIS_LENGTH
|
||||
});
|
||||
Overlays.editOverlay(xRailOverlay, {
|
||||
start: xStart,
|
||||
end: xEnd,
|
||||
visible: true
|
||||
});
|
||||
Overlays.editOverlay(zRailOverlay, {
|
||||
start: zStart,
|
||||
end: zEnd,
|
||||
visible: true
|
||||
});
|
||||
isConstrained = true;
|
||||
}
|
||||
} else {
|
||||
if (isConstrained) {
|
||||
Overlays.editOverlay(xRailOverlay, {
|
||||
visible: false
|
||||
});
|
||||
Overlays.editOverlay(zRailOverlay, {
|
||||
visible: false
|
||||
});
|
||||
isConstrained = false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -405,7 +405,7 @@ LogWindow.prototype = {
|
|||
}
|
||||
};
|
||||
|
||||
function goHomeClicked() {
|
||||
function visitSandboxClicked() {
|
||||
if (interfacePath) {
|
||||
startInterface('hifi://localhost');
|
||||
} else {
|
||||
|
@ -439,8 +439,8 @@ var labels = {
|
|||
}
|
||||
},
|
||||
goHome: {
|
||||
label: 'Go Home',
|
||||
click: goHomeClicked,
|
||||
label: 'Visit Sandbox',
|
||||
click: visitSandboxClicked,
|
||||
enabled: false
|
||||
},
|
||||
quit: {
|
||||
|
|
Loading…
Reference in a new issue