mirror of
https://github.com/lubosz/overte.git
synced 2025-08-08 04:08:13 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into MS14314_multipleSnapshots
This commit is contained in:
commit
bf5d6de780
19 changed files with 202 additions and 255 deletions
|
@ -624,8 +624,8 @@ AudioMixerClientData::IgnoreZone& AudioMixerClientData::IgnoreZoneMemo::get(unsi
|
||||||
scale = MIN_IGNORE_BOX_SCALE;
|
scale = MIN_IGNORE_BOX_SCALE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// quadruple the scale (this is arbitrary number chosen for comfort)
|
// (this is arbitrary number determined empirically for comfort)
|
||||||
const float IGNORE_BOX_SCALE_FACTOR = 4.0f;
|
const float IGNORE_BOX_SCALE_FACTOR = 2.4f;
|
||||||
scale *= IGNORE_BOX_SCALE_FACTOR;
|
scale *= IGNORE_BOX_SCALE_FACTOR;
|
||||||
|
|
||||||
// create the box (we use a box for the zone for convenience)
|
// create the box (we use a box for the zone for convenience)
|
||||||
|
|
|
@ -271,8 +271,9 @@ void AvatarMixerSlave::broadcastAvatarDataToAgent(const SharedNodePointer& node)
|
||||||
if (glm::any(glm::lessThan(otherNodeBoxScale, minBubbleSize))) {
|
if (glm::any(glm::lessThan(otherNodeBoxScale, minBubbleSize))) {
|
||||||
otherNodeBox.setScaleStayCentered(minBubbleSize);
|
otherNodeBox.setScaleStayCentered(minBubbleSize);
|
||||||
}
|
}
|
||||||
// Quadruple the scale of both bounding boxes
|
// Change the scale of both bounding boxes
|
||||||
otherNodeBox.embiggen(4.0f);
|
// (This is an arbitrary number determined empirically)
|
||||||
|
otherNodeBox.embiggen(2.4f);
|
||||||
|
|
||||||
// Perform the collision check between the two bounding boxes
|
// Perform the collision check between the two bounding boxes
|
||||||
if (nodeBox.touches(otherNodeBox)) {
|
if (nodeBox.touches(otherNodeBox)) {
|
||||||
|
|
|
@ -2607,10 +2607,55 @@ void Application::initializeGL() {
|
||||||
_isGLInitialized = true;
|
_isGLInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_glWidget->makeCurrent();
|
if (!_glWidget->makeCurrent()) {
|
||||||
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
qCWarning(interfaceapp, "Unable to make window context current");
|
||||||
glClear(GL_COLOR_BUFFER_BIT);
|
}
|
||||||
_glWidget->swapBuffers();
|
|
||||||
|
#if !defined(DISABLE_QML)
|
||||||
|
// Build a shared canvas / context for the Chromium processes
|
||||||
|
{
|
||||||
|
// Disable signed distance field font rendering on ATI/AMD GPUs, due to
|
||||||
|
// https://highfidelity.manuscript.com/f/cases/13677/Text-showing-up-white-on-Marketplace-app
|
||||||
|
std::string vendor{ (const char*)glGetString(GL_VENDOR) };
|
||||||
|
if ((vendor.find("AMD") != std::string::npos) || (vendor.find("ATI") != std::string::npos)) {
|
||||||
|
qputenv("QTWEBENGINE_CHROMIUM_FLAGS", QByteArray("--disable-distance-field-text"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chromium rendering uses some GL functions that prevent nSight from capturing
|
||||||
|
// frames, so we only create the shared context if nsight is NOT active.
|
||||||
|
if (!nsightActive()) {
|
||||||
|
_chromiumShareContext = new OffscreenGLCanvas();
|
||||||
|
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
||||||
|
_chromiumShareContext->create(_glWidget->qglContext());
|
||||||
|
if (!_chromiumShareContext->makeCurrent()) {
|
||||||
|
qCWarning(interfaceapp, "Unable to make chromium shared context current");
|
||||||
|
}
|
||||||
|
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
||||||
|
_chromiumShareContext->doneCurrent();
|
||||||
|
// Restore the GL widget context
|
||||||
|
if (!_glWidget->makeCurrent()) {
|
||||||
|
qCWarning(interfaceapp, "Unable to make window context current");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
qCWarning(interfaceapp) << "nSight detected, disabling chrome rendering";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Build a shared canvas / context for the QML rendering
|
||||||
|
{
|
||||||
|
_qmlShareContext = new OffscreenGLCanvas();
|
||||||
|
_qmlShareContext->setObjectName("QmlShareContext");
|
||||||
|
_qmlShareContext->create(_glWidget->qglContext());
|
||||||
|
if (!_qmlShareContext->makeCurrent()) {
|
||||||
|
qCWarning(interfaceapp, "Unable to make QML shared context current");
|
||||||
|
}
|
||||||
|
OffscreenQmlSurface::setSharedContext(_qmlShareContext->getContext());
|
||||||
|
_qmlShareContext->doneCurrent();
|
||||||
|
if (!_glWidget->makeCurrent()) {
|
||||||
|
qCWarning(interfaceapp, "Unable to make window context current");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Build an offscreen GL context for the main thread.
|
// Build an offscreen GL context for the main thread.
|
||||||
_offscreenContext = new OffscreenGLCanvas();
|
_offscreenContext = new OffscreenGLCanvas();
|
||||||
|
@ -2622,6 +2667,11 @@ void Application::initializeGL() {
|
||||||
_offscreenContext->doneCurrent();
|
_offscreenContext->doneCurrent();
|
||||||
_offscreenContext->setThreadContext();
|
_offscreenContext->setThreadContext();
|
||||||
|
|
||||||
|
_glWidget->makeCurrent();
|
||||||
|
glClearColor(0.2f, 0.2f, 0.2f, 1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
_glWidget->swapBuffers();
|
||||||
|
|
||||||
// Move the GL widget context to the render event handler thread
|
// Move the GL widget context to the render event handler thread
|
||||||
_renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
_renderEventHandler = new RenderEventHandler(_glWidget->qglContext());
|
||||||
if (!_offscreenContext->makeCurrent()) {
|
if (!_offscreenContext->makeCurrent()) {
|
||||||
|
@ -2744,40 +2794,6 @@ extern void setupPreferences();
|
||||||
static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active = false);
|
static void addDisplayPluginToMenu(const DisplayPluginPointer& displayPlugin, int index, bool active = false);
|
||||||
|
|
||||||
void Application::initializeUi() {
|
void Application::initializeUi() {
|
||||||
// Build a shared canvas / context for the Chromium processes
|
|
||||||
#if !defined(DISABLE_QML)
|
|
||||||
// Chromium rendering uses some GL functions that prevent nSight from capturing
|
|
||||||
// frames, so we only create the shared context if nsight is NOT active.
|
|
||||||
if (!nsightActive()) {
|
|
||||||
_chromiumShareContext = new OffscreenGLCanvas();
|
|
||||||
_chromiumShareContext->setObjectName("ChromiumShareContext");
|
|
||||||
_chromiumShareContext->create(_offscreenContext->getContext());
|
|
||||||
if (!_chromiumShareContext->makeCurrent()) {
|
|
||||||
qCWarning(interfaceapp, "Unable to make chromium shared context current");
|
|
||||||
}
|
|
||||||
qt_gl_set_global_share_context(_chromiumShareContext->getContext());
|
|
||||||
_chromiumShareContext->doneCurrent();
|
|
||||||
// Restore the GL widget context
|
|
||||||
_offscreenContext->makeCurrent();
|
|
||||||
} else {
|
|
||||||
qCWarning(interfaceapp) << "nSIGHT detected, disabling chrome rendering";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Build a shared canvas / context for the QML rendering
|
|
||||||
_qmlShareContext = new OffscreenGLCanvas();
|
|
||||||
_qmlShareContext->setObjectName("QmlShareContext");
|
|
||||||
_qmlShareContext->create(_offscreenContext->getContext());
|
|
||||||
if (!_qmlShareContext->makeCurrent()) {
|
|
||||||
qCWarning(interfaceapp, "Unable to make QML shared context current");
|
|
||||||
}
|
|
||||||
OffscreenQmlSurface::setSharedContext(_qmlShareContext->getContext());
|
|
||||||
_qmlShareContext->doneCurrent();
|
|
||||||
// Restore the GL widget context
|
|
||||||
_offscreenContext->makeCurrent();
|
|
||||||
// Make sure all QML surfaces share the main thread GL context
|
|
||||||
OffscreenQmlSurface::setSharedContext(_offscreenContext->getContext());
|
|
||||||
|
|
||||||
AddressBarDialog::registerType();
|
AddressBarDialog::registerType();
|
||||||
ErrorDialog::registerType();
|
ErrorDialog::registerType();
|
||||||
LoginDialog::registerType();
|
LoginDialog::registerType();
|
||||||
|
|
|
@ -227,10 +227,13 @@ QString QmlCommerce::getInstalledApps() {
|
||||||
QString scriptURL = appFileJsonObject["scriptURL"].toString();
|
QString scriptURL = appFileJsonObject["scriptURL"].toString();
|
||||||
|
|
||||||
// If the script .app.json is on the user's local disk but the associated script isn't running
|
// If the script .app.json is on the user's local disk but the associated script isn't running
|
||||||
// for some reason, start that script again.
|
// for some reason (i.e. the user stopped it from Running Scripts),
|
||||||
|
// delete the .app.json from the user's local disk.
|
||||||
if (!runningScripts.contains(scriptURL)) {
|
if (!runningScripts.contains(scriptURL)) {
|
||||||
if ((DependencyManager::get<ScriptEngines>()->loadScript(scriptURL.trimmed())).isNull()) {
|
if (!appFile.remove()) {
|
||||||
qCDebug(commerce) << "Couldn't start script while checking installed apps.";
|
qCWarning(commerce)
|
||||||
|
<< "Couldn't delete local .app.json file (app's script isn't running). App filename is:"
|
||||||
|
<< appFileName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#include "InterfaceLogging.h"
|
#include "InterfaceLogging.h"
|
||||||
|
|
||||||
OverlayConductor::OverlayConductor() {
|
OverlayConductor::OverlayConductor() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayConductor::~OverlayConductor() {
|
OverlayConductor::~OverlayConductor() {
|
||||||
|
@ -33,8 +32,8 @@ bool OverlayConductor::headOutsideOverlay() const {
|
||||||
glm::vec3 uiPos = uiTransform.getTranslation();
|
glm::vec3 uiPos = uiTransform.getTranslation();
|
||||||
glm::vec3 uiForward = uiTransform.getRotation() * glm::vec3(0.0f, 0.0f, -1.0f);
|
glm::vec3 uiForward = uiTransform.getRotation() * glm::vec3(0.0f, 0.0f, -1.0f);
|
||||||
|
|
||||||
const float MAX_COMPOSITOR_DISTANCE = 0.99f; // If you're 1m from center of ui sphere, you're at the surface.
|
const float MAX_COMPOSITOR_DISTANCE = 0.99f; // If you're 1m from center of ui sphere, you're at the surface.
|
||||||
const float MAX_COMPOSITOR_ANGLE = 180.0f; // rotation check is effectively disabled
|
const float MAX_COMPOSITOR_ANGLE = 180.0f; // rotation check is effectively disabled
|
||||||
if (glm::distance(uiPos, hmdPos) > MAX_COMPOSITOR_DISTANCE ||
|
if (glm::distance(uiPos, hmdPos) > MAX_COMPOSITOR_DISTANCE ||
|
||||||
glm::dot(uiForward, hmdForward) < cosf(glm::radians(MAX_COMPOSITOR_ANGLE))) {
|
glm::dot(uiForward, hmdForward) < cosf(glm::radians(MAX_COMPOSITOR_ANGLE))) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -43,10 +42,9 @@ bool OverlayConductor::headOutsideOverlay() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OverlayConductor::updateAvatarIsAtRest() {
|
bool OverlayConductor::updateAvatarIsAtRest() {
|
||||||
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||||
|
|
||||||
const quint64 REST_ENABLE_TIME_USECS = 1000 * 1000; // 1 s
|
const quint64 REST_ENABLE_TIME_USECS = 1000 * 1000; // 1 s
|
||||||
const quint64 REST_DISABLE_TIME_USECS = 200 * 1000; // 200 ms
|
const quint64 REST_DISABLE_TIME_USECS = 200 * 1000; // 200 ms
|
||||||
|
|
||||||
const float AT_REST_THRESHOLD = 0.01f;
|
const float AT_REST_THRESHOLD = 0.01f;
|
||||||
|
@ -69,31 +67,6 @@ bool OverlayConductor::updateAvatarIsAtRest() {
|
||||||
return _currentAtRest;
|
return _currentAtRest;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OverlayConductor::updateAvatarHasDriveInput() {
|
|
||||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
|
||||||
|
|
||||||
const quint64 DRIVE_ENABLE_TIME_USECS = 200 * 1000; // 200 ms
|
|
||||||
const quint64 DRIVE_DISABLE_TIME_USECS = 1000 * 1000; // 1 s
|
|
||||||
|
|
||||||
bool desiredDriving = myAvatar->hasDriveInput();
|
|
||||||
if (desiredDriving != _desiredDriving) {
|
|
||||||
// start timer
|
|
||||||
_desiredDrivingTimer = usecTimestampNow() + (desiredDriving ? DRIVE_ENABLE_TIME_USECS : DRIVE_DISABLE_TIME_USECS);
|
|
||||||
}
|
|
||||||
|
|
||||||
_desiredDriving = desiredDriving;
|
|
||||||
|
|
||||||
if (_desiredDrivingTimer != 0 && usecTimestampNow() > _desiredDrivingTimer) {
|
|
||||||
// timer expired
|
|
||||||
// change state!
|
|
||||||
_currentDriving = _desiredDriving;
|
|
||||||
// disable timer
|
|
||||||
_desiredDrivingTimer = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _currentDriving;
|
|
||||||
}
|
|
||||||
|
|
||||||
void OverlayConductor::centerUI() {
|
void OverlayConductor::centerUI() {
|
||||||
// place the overlay at the current hmd position in sensor space
|
// place the overlay at the current hmd position in sensor space
|
||||||
auto camMat = cancelOutRollAndPitch(qApp->getHMDSensorPose());
|
auto camMat = cancelOutRollAndPitch(qApp->getHMDSensorPose());
|
||||||
|
@ -115,20 +88,19 @@ void OverlayConductor::update(float dt) {
|
||||||
_hmdMode = false;
|
_hmdMode = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool prevDriving = _currentDriving;
|
|
||||||
bool isDriving = updateAvatarHasDriveInput();
|
|
||||||
bool drivingChanged = prevDriving != isDriving;
|
|
||||||
bool isAtRest = updateAvatarIsAtRest();
|
bool isAtRest = updateAvatarIsAtRest();
|
||||||
|
bool isMoving = !isAtRest;
|
||||||
|
|
||||||
bool shouldRecenter = false;
|
bool shouldRecenter = false;
|
||||||
|
|
||||||
if (_flags & SuppressedByDrive) {
|
if (_flags & SuppressedByMove) {
|
||||||
if (!isDriving) {
|
if (!isMoving) {
|
||||||
_flags &= ~SuppressedByDrive;
|
_flags &= ~SuppressedByMove;
|
||||||
shouldRecenter = true;
|
shouldRecenter = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (myAvatar->getClearOverlayWhenMoving() && drivingChanged && isDriving) {
|
if (myAvatar->getClearOverlayWhenMoving() && isMoving) {
|
||||||
_flags |= SuppressedByDrive;
|
_flags |= SuppressedByMove;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +115,6 @@ void OverlayConductor::update(float dt) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && (0 == (_flags & SuppressMask));
|
bool targetVisible = Menu::getInstance()->isOptionChecked(MenuOption::Overlays) && (0 == (_flags & SuppressMask));
|
||||||
if (targetVisible != currentVisible) {
|
if (targetVisible != currentVisible) {
|
||||||
offscreenUi->setPinned(!targetVisible);
|
offscreenUi->setPinned(!targetVisible);
|
||||||
|
|
|
@ -23,23 +23,17 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool headOutsideOverlay() const;
|
bool headOutsideOverlay() const;
|
||||||
bool updateAvatarHasDriveInput();
|
|
||||||
bool updateAvatarIsAtRest();
|
bool updateAvatarIsAtRest();
|
||||||
|
|
||||||
enum SupressionFlags {
|
enum SupressionFlags {
|
||||||
SuppressedByDrive = 0x01,
|
SuppressedByMove = 0x01,
|
||||||
SuppressedByHead = 0x02,
|
SuppressedByHead = 0x02,
|
||||||
SuppressMask = 0x03,
|
SuppressMask = 0x03,
|
||||||
};
|
};
|
||||||
|
|
||||||
uint8_t _flags { SuppressedByDrive };
|
uint8_t _flags { SuppressedByMove };
|
||||||
bool _hmdMode { false };
|
bool _hmdMode { false };
|
||||||
|
|
||||||
// used by updateAvatarHasDriveInput
|
|
||||||
uint64_t _desiredDrivingTimer { 0 };
|
|
||||||
bool _desiredDriving { false };
|
|
||||||
bool _currentDriving { false };
|
|
||||||
|
|
||||||
// used by updateAvatarIsAtRest
|
// used by updateAvatarIsAtRest
|
||||||
uint64_t _desiredAtRestTimer { 0 };
|
uint64_t _desiredAtRestTimer { 0 };
|
||||||
bool _desiredAtRest { true };
|
bool _desiredAtRest { true };
|
||||||
|
|
|
@ -131,6 +131,9 @@ void ModelOverlay::update(float deltatime) {
|
||||||
|
|
||||||
if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) {
|
if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) {
|
||||||
_texturesLoaded = true;
|
_texturesLoaded = true;
|
||||||
|
if (!_modelTextures.isEmpty()) {
|
||||||
|
_model->setTextures(_modelTextures);
|
||||||
|
}
|
||||||
_model->updateRenderItems();
|
_model->updateRenderItems();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -229,8 +232,7 @@ void ModelOverlay::setProperties(const QVariantMap& properties) {
|
||||||
if (texturesValue.isValid() && texturesValue.canConvert(QVariant::Map)) {
|
if (texturesValue.isValid() && texturesValue.canConvert(QVariant::Map)) {
|
||||||
_texturesLoaded = false;
|
_texturesLoaded = false;
|
||||||
QVariantMap textureMap = texturesValue.toMap();
|
QVariantMap textureMap = texturesValue.toMap();
|
||||||
QMetaObject::invokeMethod(_model.get(), "setTextures", Qt::AutoConnection,
|
_modelTextures = textureMap;
|
||||||
Q_ARG(const QVariantMap&, textureMap));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto groupCulledValue = properties["isGroupCulled"];
|
auto groupCulledValue = properties["isGroupCulled"];
|
||||||
|
|
|
@ -157,18 +157,19 @@ void TextureBaker::processTexture() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat());
|
|
||||||
if (name == nullptr) {
|
|
||||||
handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// attempt to write the baked texture to the destination file path
|
// attempt to write the baked texture to the destination file path
|
||||||
{
|
if (memKTX->_header.isCompressed()) {
|
||||||
|
const char* name = khronos::gl::texture::toString(memKTX->_header.getGLInternaFormat());
|
||||||
|
if (name == nullptr) {
|
||||||
|
handleError("Could not determine internal format for compressed KTX: " + _textureURL.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const char* data = reinterpret_cast<const char*>(memKTX->_storage->data());
|
const char* data = reinterpret_cast<const char*>(memKTX->_storage->data());
|
||||||
const size_t length = memKTX->_storage->size();
|
const size_t length = memKTX->_storage->size();
|
||||||
|
|
||||||
auto fileName = _baseFilename + BAKED_TEXTURE_BCN_SUFFIX;
|
auto fileName = _baseFilename + "_" + name + ".ktx";
|
||||||
auto filePath = _outputDirectory.absoluteFilePath(fileName);
|
auto filePath = _outputDirectory.absoluteFilePath(fileName);
|
||||||
QFile bakedTextureFile { filePath };
|
QFile bakedTextureFile { filePath };
|
||||||
if (!bakedTextureFile.open(QIODevice::WriteOnly) || bakedTextureFile.write(data, length) == -1) {
|
if (!bakedTextureFile.open(QIODevice::WriteOnly) || bakedTextureFile.write(data, length) == -1) {
|
||||||
|
@ -177,6 +178,18 @@ void TextureBaker::processTexture() {
|
||||||
}
|
}
|
||||||
_outputFiles.push_back(filePath);
|
_outputFiles.push_back(filePath);
|
||||||
meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName;
|
meta.availableTextureTypes[memKTX->_header.getGLInternaFormat()] = _metaTexturePathPrefix + fileName;
|
||||||
|
} else {
|
||||||
|
const char* data = reinterpret_cast<const char*>(memKTX->_storage->data());
|
||||||
|
const size_t length = memKTX->_storage->size();
|
||||||
|
|
||||||
|
auto fileName = _baseFilename + ".ktx";
|
||||||
|
auto filePath = _outputDirectory.absoluteFilePath(fileName);
|
||||||
|
QFile ktxTextureFile { filePath };
|
||||||
|
if (!ktxTextureFile.open(QIODevice::WriteOnly) || ktxTextureFile.write(data, length) == -1) {
|
||||||
|
handleError("Could not write ktx texture for " + _textureURL.toString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_outputFiles.push_back(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ layout(std140) uniform particleBuffer {
|
||||||
ParticleUniforms particle;
|
ParticleUniforms particle;
|
||||||
};
|
};
|
||||||
|
|
||||||
in vec3 inPosition;
|
layout(location=0) in vec3 inPosition;
|
||||||
in vec2 inColor; // This is actual Lifetime + Seed
|
layout(location=2) in vec2 inColor; // This is actual Lifetime + Seed
|
||||||
|
|
||||||
out vec4 varColor;
|
out vec4 varColor;
|
||||||
out vec2 varTexcoord;
|
out vec2 varTexcoord;
|
||||||
|
|
|
@ -38,6 +38,11 @@ ResourceManager::ResourceManager(bool atpSupportEnabled) : _atpSupportEnabled(at
|
||||||
_thread.start();
|
_thread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ResourceManager::~ResourceManager() {
|
||||||
|
_thread.terminate();
|
||||||
|
_thread.wait();
|
||||||
|
}
|
||||||
|
|
||||||
void ResourceManager::setUrlPrefixOverride(const QString& prefix, const QString& replacement) {
|
void ResourceManager::setUrlPrefixOverride(const QString& prefix, const QString& replacement) {
|
||||||
QMutexLocker locker(&_prefixMapLock);
|
QMutexLocker locker(&_prefixMapLock);
|
||||||
if (replacement.isEmpty()) {
|
if (replacement.isEmpty()) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ class ResourceManager: public QObject, public Dependency {
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ResourceManager(bool atpSupportEnabled = true);
|
ResourceManager(bool atpSupportEnabled = true);
|
||||||
|
~ResourceManager();
|
||||||
|
|
||||||
void setUrlPrefixOverride(const QString& prefix, const QString& replacement);
|
void setUrlPrefixOverride(const QString& prefix, const QString& replacement);
|
||||||
QString normalizeURL(const QString& urlString);
|
QString normalizeURL(const QString& urlString);
|
||||||
|
|
|
@ -1074,15 +1074,11 @@ int Model::getLastFreeJointIndex(int jointIndex) const {
|
||||||
|
|
||||||
void Model::setTextures(const QVariantMap& textures) {
|
void Model::setTextures(const QVariantMap& textures) {
|
||||||
if (isLoaded()) {
|
if (isLoaded()) {
|
||||||
_needsUpdateTextures = true;
|
_pendingTextures.clear();
|
||||||
_needsFixupInScene = true;
|
_needsFixupInScene = true;
|
||||||
_renderGeometry->setTextures(textures);
|
_renderGeometry->setTextures(textures);
|
||||||
} else {
|
} else {
|
||||||
// FIXME(Huffman): Disconnect previously connected lambdas so we don't set textures multiple
|
_pendingTextures = textures;
|
||||||
// after the geometry has finished loading.
|
|
||||||
connect(&_renderWatcher, &GeometryResourceWatcher::finished, this, [this, textures]() {
|
|
||||||
_renderGeometry->setTextures(textures);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1106,7 +1102,8 @@ void Model::setURL(const QUrl& url) {
|
||||||
}
|
}
|
||||||
|
|
||||||
_needsReload = true;
|
_needsReload = true;
|
||||||
_needsUpdateTextures = true;
|
// One might be tempted to _pendingTextures.clear(), thinking that a new URL means an old texture doesn't apply.
|
||||||
|
// But sometimes, particularly when first setting the values, the texture might be set first. So let's not clear here.
|
||||||
_visualGeometryRequestFailed = false;
|
_visualGeometryRequestFailed = false;
|
||||||
_needsFixupInScene = true;
|
_needsFixupInScene = true;
|
||||||
invalidCalculatedMeshBoxes();
|
invalidCalculatedMeshBoxes();
|
||||||
|
@ -1123,6 +1120,8 @@ void Model::setURL(const QUrl& url) {
|
||||||
void Model::loadURLFinished(bool success) {
|
void Model::loadURLFinished(bool success) {
|
||||||
if (!success) {
|
if (!success) {
|
||||||
_visualGeometryRequestFailed = true;
|
_visualGeometryRequestFailed = true;
|
||||||
|
} else if (!_pendingTextures.empty()) {
|
||||||
|
setTextures(_pendingTextures);
|
||||||
}
|
}
|
||||||
emit setURLFinished(success);
|
emit setURLFinished(success);
|
||||||
}
|
}
|
||||||
|
|
|
@ -457,7 +457,7 @@ protected:
|
||||||
bool _needsFixupInScene { true }; // needs to be removed/re-added to scene
|
bool _needsFixupInScene { true }; // needs to be removed/re-added to scene
|
||||||
bool _needsReload { true };
|
bool _needsReload { true };
|
||||||
bool _needsUpdateClusterMatrices { true };
|
bool _needsUpdateClusterMatrices { true };
|
||||||
mutable bool _needsUpdateTextures { true };
|
QVariantMap _pendingTextures { };
|
||||||
|
|
||||||
friend class ModelMeshPartPayload;
|
friend class ModelMeshPartPayload;
|
||||||
Rig _rig;
|
Rig _rig;
|
||||||
|
|
|
@ -273,7 +273,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
this.shouldSendStart = false;
|
this.shouldSendStart = false;
|
||||||
this.equipedWithSecondary = false;
|
this.equipedWithSecondary = false;
|
||||||
this.handHasBeenRightsideUp = false;
|
this.handHasBeenRightsideUp = false;
|
||||||
this.mouseEquip = false;
|
|
||||||
|
|
||||||
this.parameters = makeDispatcherModuleParameters(
|
this.parameters = makeDispatcherModuleParameters(
|
||||||
300,
|
300,
|
||||||
|
@ -283,11 +282,10 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
|
|
||||||
var equipHotspotBuddy = new EquipHotspotBuddy();
|
var equipHotspotBuddy = new EquipHotspotBuddy();
|
||||||
|
|
||||||
this.setMessageGrabData = function(entityProperties, mouseEquip) {
|
this.setMessageGrabData = function(entityProperties) {
|
||||||
if (entityProperties) {
|
if (entityProperties) {
|
||||||
this.messageGrabEntity = true;
|
this.messageGrabEntity = true;
|
||||||
this.grabEntityProps = entityProperties;
|
this.grabEntityProps = entityProperties;
|
||||||
this.mouseEquip = mouseEquip;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -584,7 +582,6 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
this.targetEntityID = null;
|
this.targetEntityID = null;
|
||||||
this.messageGrabEntity = false;
|
this.messageGrabEntity = false;
|
||||||
this.grabEntityProps = null;
|
this.grabEntityProps = null;
|
||||||
this.mouseEquip = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
this.updateInputs = function (controllerData) {
|
this.updateInputs = function (controllerData) {
|
||||||
|
@ -630,14 +627,12 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
|
|
||||||
// if the potentialHotspot is cloneable, clone it and return it
|
// if the potentialHotspot is cloneable, clone it and return it
|
||||||
// if the potentialHotspot os not cloneable and locked return null
|
// if the potentialHotspot os not cloneable and locked return null
|
||||||
|
|
||||||
if (potentialEquipHotspot &&
|
if (potentialEquipHotspot &&
|
||||||
(((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) ||
|
(((this.triggerSmoothedSqueezed() || this.secondarySmoothedSqueezed()) && !this.waitForTriggerRelease) ||
|
||||||
this.messageGrabEntity)) {
|
this.messageGrabEntity)) {
|
||||||
this.grabbedHotspot = potentialEquipHotspot;
|
this.grabbedHotspot = potentialEquipHotspot;
|
||||||
this.targetEntityID = this.grabbedHotspot.entityID;
|
this.targetEntityID = this.grabbedHotspot.entityID;
|
||||||
this.startEquipEntity(controllerData);
|
this.startEquipEntity(controllerData);
|
||||||
this.messageGrabEntity = false;
|
|
||||||
this.equipedWithSecondary = this.secondarySmoothedSqueezed();
|
this.equipedWithSecondary = this.secondarySmoothedSqueezed();
|
||||||
return makeRunningValues(true, [potentialEquipHotspot.entityID], []);
|
return makeRunningValues(true, [potentialEquipHotspot.entityID], []);
|
||||||
} else {
|
} else {
|
||||||
|
@ -661,7 +656,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
var timestamp = Date.now();
|
var timestamp = Date.now();
|
||||||
this.updateInputs(controllerData);
|
this.updateInputs(controllerData);
|
||||||
|
|
||||||
if (!this.mouseEquip && !this.isTargetIDValid(controllerData)) {
|
if (!this.messageGrabEntity && !this.isTargetIDValid(controllerData)) {
|
||||||
this.endEquipEntity();
|
this.endEquipEntity();
|
||||||
return makeRunningValues(false, [], []);
|
return makeRunningValues(false, [], []);
|
||||||
}
|
}
|
||||||
|
@ -762,9 +757,7 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
var equipModule = (data.hand === "left") ? leftEquipEntity : rightEquipEntity;
|
var equipModule = (data.hand === "left") ? leftEquipEntity : rightEquipEntity;
|
||||||
var entityProperties = Entities.getEntityProperties(data.entityID, DISPATCHER_PROPERTIES);
|
var entityProperties = Entities.getEntityProperties(data.entityID, DISPATCHER_PROPERTIES);
|
||||||
entityProperties.id = data.entityID;
|
entityProperties.id = data.entityID;
|
||||||
var mouseEquip = false;
|
equipModule.setMessageGrabData(entityProperties);
|
||||||
equipModule.setMessageGrabData(entityProperties, mouseEquip);
|
|
||||||
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print("WARNING: equipEntity.js -- error parsing Hifi-Hand-Grab message: " + message);
|
print("WARNING: equipEntity.js -- error parsing Hifi-Hand-Grab message: " + message);
|
||||||
}
|
}
|
||||||
|
@ -812,15 +805,14 @@ EquipHotspotBuddy.prototype.update = function(deltaTime, timestamp, controllerDa
|
||||||
var distanceToLeftHand = Vec3.distance(entityProperties.position, leftHandPosition);
|
var distanceToLeftHand = Vec3.distance(entityProperties.position, leftHandPosition);
|
||||||
var leftHandAvailable = leftEquipEntity.targetEntityID === null;
|
var leftHandAvailable = leftEquipEntity.targetEntityID === null;
|
||||||
var rightHandAvailable = rightEquipEntity.targetEntityID === null;
|
var rightHandAvailable = rightEquipEntity.targetEntityID === null;
|
||||||
var mouseEquip = true;
|
|
||||||
if (rightHandAvailable && (distanceToRightHand < distanceToLeftHand || !leftHandAvailable)) {
|
if (rightHandAvailable && (distanceToRightHand < distanceToLeftHand || !leftHandAvailable)) {
|
||||||
// clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags)
|
// clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags)
|
||||||
clearGrabActions(entityID);
|
clearGrabActions(entityID);
|
||||||
rightEquipEntity.setMessageGrabData(entityProperties, mouseEquip);
|
rightEquipEntity.setMessageGrabData(entityProperties);
|
||||||
} else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) {
|
} else if (leftHandAvailable && (distanceToLeftHand < distanceToRightHand || !rightHandAvailable)) {
|
||||||
// clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags)
|
// clear any existing grab actions on the entity now (their later removal could affect bootstrapping flags)
|
||||||
clearGrabActions(entityID);
|
clearGrabActions(entityID);
|
||||||
leftEquipEntity.setMessageGrabData(entityProperties, mouseEquip);
|
leftEquipEntity.setMessageGrabData(entityProperties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -306,13 +306,21 @@
|
||||||
// change pricing to GET/BUY on button hover
|
// change pricing to GET/BUY on button hover
|
||||||
$('body').on('mouseenter', '#price-or-edit .price', function () {
|
$('body').on('mouseenter', '#price-or-edit .price', function () {
|
||||||
var $this = $(this);
|
var $this = $(this);
|
||||||
|
var buyString = "BUY";
|
||||||
|
var getString = "GET";
|
||||||
|
// Protection against the button getting stuck in the "BUY"/"GET" state.
|
||||||
|
// That happens when the browser gets two MOUSEENTER events before getting a
|
||||||
|
// MOUSELEAVE event.
|
||||||
|
if ($this.text() === buyString || $this.text() === getString) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
$this.data('initialHtml', $this.html());
|
$this.data('initialHtml', $this.html());
|
||||||
|
|
||||||
var cost = $(this).parent().siblings().text();
|
var cost = $(this).parent().siblings().text();
|
||||||
if (parseInt(cost) > 0) {
|
if (parseInt(cost) > 0) {
|
||||||
$this.text('BUY');
|
$this.text(buyString);
|
||||||
} else {
|
} else {
|
||||||
$this.text('GET');
|
$this.text(getString);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@ var HOVER_TEXTURES = {
|
||||||
var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6};
|
var UNSELECTED_COLOR = { red: 0x1F, green: 0xC6, blue: 0xA6};
|
||||||
var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29};
|
var SELECTED_COLOR = {red: 0xF3, green: 0x91, blue: 0x29};
|
||||||
var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now
|
var HOVER_COLOR = {red: 0xD0, green: 0xD0, blue: 0xD0}; // almost white for now
|
||||||
var conserveResources = true;
|
|
||||||
|
|
||||||
Script.include("/~/system/libraries/controllers.js");
|
Script.include("/~/system/libraries/controllers.js");
|
||||||
|
|
||||||
|
@ -431,7 +430,7 @@ function addAvatarNode(id) {
|
||||||
alpha: 0.8,
|
alpha: 0.8,
|
||||||
color: color(selected, false, 0.0),
|
color: color(selected, false, 0.0),
|
||||||
ignoreRayIntersection: false
|
ignoreRayIntersection: false
|
||||||
}, selected, !conserveResources);
|
}, selected, true);
|
||||||
}
|
}
|
||||||
// Each open/refresh will capture a stable set of avatarsOfInterest, within the specified filter.
|
// Each open/refresh will capture a stable set of avatarsOfInterest, within the specified filter.
|
||||||
var avatarsOfInterest = {};
|
var avatarsOfInterest = {};
|
||||||
|
@ -496,7 +495,6 @@ function populateNearbyUserList(selectData, oldAudioData) {
|
||||||
print('PAL data:', JSON.stringify(avatarPalDatum));
|
print('PAL data:', JSON.stringify(avatarPalDatum));
|
||||||
});
|
});
|
||||||
getConnectionData(false, location.domainID); // Even admins don't get relationship data in requestUsernameFromID (which is still needed for admin status, which comes from domain).
|
getConnectionData(false, location.domainID); // Even admins don't get relationship data in requestUsernameFromID (which is still needed for admin status, which comes from domain).
|
||||||
conserveResources = Object.keys(avatarsOfInterest).length > 20;
|
|
||||||
sendToQml({ method: 'nearbyUsers', params: data });
|
sendToQml({ method: 'nearbyUsers', params: data });
|
||||||
if (selectData) {
|
if (selectData) {
|
||||||
selectData[2] = true;
|
selectData[2] = true;
|
||||||
|
@ -719,7 +717,7 @@ function onTabletScreenChanged(type, url) {
|
||||||
ContextOverlay.enabled = false;
|
ContextOverlay.enabled = false;
|
||||||
Users.requestsDomainListData = true;
|
Users.requestsDomainListData = true;
|
||||||
|
|
||||||
audioTimer = createAudioInterval(conserveResources ? AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS : AUDIO_LEVEL_UPDATE_INTERVAL_MS);
|
audioTimer = createAudioInterval(AUDIO_LEVEL_UPDATE_INTERVAL_MS);
|
||||||
|
|
||||||
tablet.tabletShownChanged.connect(tabletVisibilityChanged);
|
tablet.tabletShownChanged.connect(tabletVisibilityChanged);
|
||||||
Script.update.connect(updateOverlays);
|
Script.update.connect(updateOverlays);
|
||||||
|
@ -874,7 +872,6 @@ startup();
|
||||||
var isWired = false;
|
var isWired = false;
|
||||||
var audioTimer;
|
var audioTimer;
|
||||||
var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too)
|
var AUDIO_LEVEL_UPDATE_INTERVAL_MS = 100; // 10hz for now (change this and change the AVERAGING_RATIO too)
|
||||||
var AUDIO_LEVEL_CONSERVED_UPDATE_INTERVAL_MS = 300;
|
|
||||||
function off() {
|
function off() {
|
||||||
if (isWired) {
|
if (isWired) {
|
||||||
Script.update.disconnect(updateOverlays);
|
Script.update.disconnect(updateOverlays);
|
||||||
|
|
|
@ -75,10 +75,14 @@ function getBuildInfo() {
|
||||||
}
|
}
|
||||||
const buildInfo = getBuildInfo();
|
const buildInfo = getBuildInfo();
|
||||||
|
|
||||||
function getRootHifiDataDirectory() {
|
function getRootHifiDataDirectory(local) {
|
||||||
var organization = buildInfo.organization;
|
var organization = buildInfo.organization;
|
||||||
if (osType == 'Windows_NT') {
|
if (osType == 'Windows_NT') {
|
||||||
return path.resolve(osHomeDir(), 'AppData/Roaming', organization);
|
if (local) {
|
||||||
|
return path.resolve(osHomeDir(), 'AppData/Local', organization);
|
||||||
|
} else {
|
||||||
|
return path.resolve(osHomeDir(), 'AppData/Roaming', organization);
|
||||||
|
}
|
||||||
} else if (osType == 'Darwin') {
|
} else if (osType == 'Darwin') {
|
||||||
return path.resolve(osHomeDir(), 'Library/Application Support', organization);
|
return path.resolve(osHomeDir(), 'Library/Application Support', organization);
|
||||||
} else {
|
} else {
|
||||||
|
@ -94,8 +98,8 @@ function getAssignmentClientResourcesDirectory() {
|
||||||
return path.join(getRootHifiDataDirectory(), '/assignment-client');
|
return path.join(getRootHifiDataDirectory(), '/assignment-client');
|
||||||
}
|
}
|
||||||
|
|
||||||
function getApplicationDataDirectory() {
|
function getApplicationDataDirectory(local) {
|
||||||
return path.join(getRootHifiDataDirectory(), '/Server Console');
|
return path.join(getRootHifiDataDirectory(local), '/Server Console');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update lock filepath
|
// Update lock filepath
|
||||||
|
@ -104,7 +108,7 @@ const UPDATER_LOCK_FULL_PATH = getRootHifiDataDirectory() + "/" + UPDATER_LOCK_F
|
||||||
|
|
||||||
// Configure log
|
// Configure log
|
||||||
global.log = require('electron-log');
|
global.log = require('electron-log');
|
||||||
const logFile = getApplicationDataDirectory() + '/log.txt';
|
const logFile = getApplicationDataDirectory(true) + '/log.txt';
|
||||||
fs.ensureFileSync(logFile); // Ensure file exists
|
fs.ensureFileSync(logFile); // Ensure file exists
|
||||||
log.transports.file.maxSize = 5 * 1024 * 1024;
|
log.transports.file.maxSize = 5 * 1024 * 1024;
|
||||||
log.transports.file.file = logFile;
|
log.transports.file.file = logFile;
|
||||||
|
@ -221,7 +225,19 @@ function deleteOldFiles(directoryPath, maxAgeInSeconds, filenameRegex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var logPath = path.join(getApplicationDataDirectory(), '/logs');
|
var oldLogPath = path.join(getApplicationDataDirectory(), '/logs');
|
||||||
|
var logPath = path.join(getApplicationDataDirectory(true), '/logs');
|
||||||
|
|
||||||
|
if (oldLogPath != logPath) {
|
||||||
|
console.log("Migrating old logs from " + oldLogPath + " to " + logPath);
|
||||||
|
fs.copy(oldLogPath, logPath, err => {
|
||||||
|
if (err) {
|
||||||
|
console.error(err);
|
||||||
|
} else {
|
||||||
|
console.log('success!');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
log.debug("Log directory:", logPath);
|
log.debug("Log directory:", logPath);
|
||||||
log.debug("Data directory:", getRootHifiDataDirectory());
|
log.debug("Data directory:", getRootHifiDataDirectory());
|
||||||
|
@ -433,13 +449,6 @@ var labels = {
|
||||||
logWindow.open();
|
logWindow.open();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
restoreBackup: {
|
|
||||||
label: 'Restore Backup Instructions',
|
|
||||||
click: function() {
|
|
||||||
var folder = getRootHifiDataDirectory() + "/Server Backup";
|
|
||||||
openBackupInstructions(folder);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
share: {
|
share: {
|
||||||
label: 'Share',
|
label: 'Share',
|
||||||
click: function() {
|
click: function() {
|
||||||
|
@ -475,7 +484,6 @@ function buildMenuArray(serverState) {
|
||||||
menuArray.push(labels.stopServer);
|
menuArray.push(labels.stopServer);
|
||||||
menuArray.push(labels.settings);
|
menuArray.push(labels.settings);
|
||||||
menuArray.push(labels.viewLogs);
|
menuArray.push(labels.viewLogs);
|
||||||
menuArray.push(labels.restoreBackup);
|
|
||||||
menuArray.push(separator);
|
menuArray.push(separator);
|
||||||
menuArray.push(labels.share);
|
menuArray.push(labels.share);
|
||||||
menuArray.push(separator);
|
menuArray.push(separator);
|
||||||
|
@ -542,103 +550,6 @@ function backupResourceDirectories(folder) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function openBackupInstructions(folder) {
|
|
||||||
// Explain user how to restore server
|
|
||||||
var window = new BrowserWindow({
|
|
||||||
icon: appIcon,
|
|
||||||
width: 800,
|
|
||||||
height: 520,
|
|
||||||
});
|
|
||||||
window.loadURL('file://' + __dirname + '/content-update.html');
|
|
||||||
if (!debug) {
|
|
||||||
window.setMenu(null);
|
|
||||||
}
|
|
||||||
window.show();
|
|
||||||
|
|
||||||
electron.ipcMain.on('setSize', function(event, obj) {
|
|
||||||
window.setSize(obj.width, obj.height);
|
|
||||||
});
|
|
||||||
electron.ipcMain.on('ready', function() {
|
|
||||||
log.debug("got ready");
|
|
||||||
window.webContents.send('update', folder);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function backupResourceDirectoriesAndRestart() {
|
|
||||||
homeServer.stop();
|
|
||||||
|
|
||||||
var folder = getRootHifiDataDirectory() + "/Server Backup - " + Date.now();
|
|
||||||
if (backupResourceDirectories(folder)) {
|
|
||||||
maybeInstallDefaultContentSet(onContentLoaded);
|
|
||||||
openBackupInstructions(folder);
|
|
||||||
} else {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'warning',
|
|
||||||
buttons: ['Ok'],
|
|
||||||
title: 'Update Error',
|
|
||||||
message: 'There was an error updating the content, aborting.'
|
|
||||||
}, function() {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function checkNewContent() {
|
|
||||||
if (argv.noUpdater) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start downloading content set
|
|
||||||
var req = request.head({
|
|
||||||
url: HOME_CONTENT_URL
|
|
||||||
}, function (error, response, body) {
|
|
||||||
if (error === null) {
|
|
||||||
var localContent = Date.parse(userConfig.get('homeContentLastModified'));
|
|
||||||
var remoteContent = Date.parse(response.headers['last-modified']);
|
|
||||||
|
|
||||||
var shouldUpdate = isNaN(localContent) || (!isNaN(remoteContent) && (remoteContent > localContent));
|
|
||||||
|
|
||||||
var wantDebug = false;
|
|
||||||
if (wantDebug) {
|
|
||||||
log.debug('Last Modified: ' + response.headers['last-modified']);
|
|
||||||
log.debug(localContent + " " + remoteContent + " " + shouldUpdate + " " + new Date());
|
|
||||||
log.debug("Remote content is " + (shouldUpdate ? "newer" : "older") + " that local content.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldUpdate) {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'question',
|
|
||||||
buttons: ['Yes', 'No'],
|
|
||||||
defaultId: 1,
|
|
||||||
cancelId: 1,
|
|
||||||
title: 'High Fidelity Sandbox',
|
|
||||||
message: 'A newer version of the home content set is available.\nDo you wish to update?',
|
|
||||||
noLink: true,
|
|
||||||
}, function(idx) {
|
|
||||||
if (idx === 0) {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
type: 'warning',
|
|
||||||
buttons: ['Yes', 'No'],
|
|
||||||
defaultId: 1,
|
|
||||||
cancelId: 1,
|
|
||||||
title: 'Are you sure?',
|
|
||||||
message: 'Updating with the new content will remove all your current content and settings and place them in a backup folder.\nAre you sure?',
|
|
||||||
noLink: true,
|
|
||||||
}, function(idx) {
|
|
||||||
if (idx === 0) {
|
|
||||||
backupResourceDirectoriesAndRestart();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
// They don't want to update, mark content set as current
|
|
||||||
userConfig.set('homeContentLastModified', new Date());
|
|
||||||
userConfig.save(configPath);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else if (fs.existsSync(UPDATER_LOCK_FULL_PATH)) {
|
|
||||||
backupResourceDirectoriesAndRestart();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeIncompleteUpdate(acResourceDirectory, dsResourceDirectory) {
|
function removeIncompleteUpdate(acResourceDirectory, dsResourceDirectory) {
|
||||||
if (fs.existsSync(UPDATER_LOCK_FULL_PATH)) {
|
if (fs.existsSync(UPDATER_LOCK_FULL_PATH)) {
|
||||||
log.debug('Removing incomplete content update files before copying new update');
|
log.debug('Removing incomplete content update files before copying new update');
|
||||||
|
@ -681,7 +592,6 @@ function maybeInstallDefaultContentSet(onComplete) {
|
||||||
log.debug("User has existing data, suppressing downloader");
|
log.debug("User has existing data, suppressing downloader");
|
||||||
onComplete();
|
onComplete();
|
||||||
|
|
||||||
checkNewContent();
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,8 @@
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
#include "OvenCLIApplication.h"
|
#include "OvenCLIApplication.h"
|
||||||
#include "ModelBakingLoggingCategory.h"
|
#include "ModelBakingLoggingCategory.h"
|
||||||
#include "FBXBaker.h"
|
#include "FBXBaker.h"
|
||||||
|
@ -38,17 +40,15 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString&
|
||||||
static const QString MODEL_EXTENSION { "fbx" };
|
static const QString MODEL_EXTENSION { "fbx" };
|
||||||
static const QString SCRIPT_EXTENSION { "js" };
|
static const QString SCRIPT_EXTENSION { "js" };
|
||||||
|
|
||||||
QString extension = type;
|
|
||||||
|
|
||||||
if (extension.isNull()) {
|
|
||||||
auto url = inputUrl.toDisplayString();
|
|
||||||
extension = url.mid(url.lastIndexOf('.'));
|
|
||||||
}
|
|
||||||
|
|
||||||
// check what kind of baker we should be creating
|
// check what kind of baker we should be creating
|
||||||
bool isFBX = extension == MODEL_EXTENSION;
|
bool isFBX = type == MODEL_EXTENSION;
|
||||||
bool isScript = extension == SCRIPT_EXTENSION;
|
bool isScript = type == SCRIPT_EXTENSION;
|
||||||
|
|
||||||
|
// If the type doesn't match the above, we assume we have a texture, and the type specified is the
|
||||||
|
// texture usage type (albedo, cubemap, normals, etc.)
|
||||||
|
auto url = inputUrl.toDisplayString();
|
||||||
|
auto idx = url.lastIndexOf('.');
|
||||||
|
auto extension = idx >= 0 ? url.mid(idx + 1).toLower() : "";
|
||||||
bool isSupportedImage = QImageReader::supportedImageFormats().contains(extension.toLatin1());
|
bool isSupportedImage = QImageReader::supportedImageFormats().contains(extension.toLatin1());
|
||||||
|
|
||||||
_outputPath = outputPath;
|
_outputPath = outputPath;
|
||||||
|
@ -65,7 +65,29 @@ void BakerCLI::bakeFile(QUrl inputUrl, const QString& outputPath, const QString&
|
||||||
_baker = std::unique_ptr<Baker> { new JSBaker(inputUrl, outputPath) };
|
_baker = std::unique_ptr<Baker> { new JSBaker(inputUrl, outputPath) };
|
||||||
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
} else if (isSupportedImage) {
|
} else if (isSupportedImage) {
|
||||||
_baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, image::TextureUsage::CUBE_TEXTURE, outputPath) };
|
static const std::unordered_map<QString, image::TextureUsage::Type> STRING_TO_TEXTURE_USAGE_TYPE_MAP {
|
||||||
|
{ "default", image::TextureUsage::DEFAULT_TEXTURE },
|
||||||
|
{ "strict", image::TextureUsage::STRICT_TEXTURE },
|
||||||
|
{ "albedo", image::TextureUsage::ALBEDO_TEXTURE },
|
||||||
|
{ "normal", image::TextureUsage::NORMAL_TEXTURE },
|
||||||
|
{ "bump", image::TextureUsage::BUMP_TEXTURE },
|
||||||
|
{ "specular", image::TextureUsage::SPECULAR_TEXTURE },
|
||||||
|
{ "metallic", image::TextureUsage::METALLIC_TEXTURE },
|
||||||
|
{ "roughness", image::TextureUsage::ROUGHNESS_TEXTURE },
|
||||||
|
{ "gloss", image::TextureUsage::GLOSS_TEXTURE },
|
||||||
|
{ "emissive", image::TextureUsage::EMISSIVE_TEXTURE },
|
||||||
|
{ "cube", image::TextureUsage::CUBE_TEXTURE },
|
||||||
|
{ "occlusion", image::TextureUsage::OCCLUSION_TEXTURE },
|
||||||
|
{ "scattering", image::TextureUsage::SCATTERING_TEXTURE },
|
||||||
|
{ "lightmap", image::TextureUsage::LIGHTMAP_TEXTURE },
|
||||||
|
};
|
||||||
|
|
||||||
|
auto it = STRING_TO_TEXTURE_USAGE_TYPE_MAP.find(type);
|
||||||
|
if (it == STRING_TO_TEXTURE_USAGE_TYPE_MAP.end()) {
|
||||||
|
qCDebug(model_baking) << "Unknown texture usage type:" << type;
|
||||||
|
QCoreApplication::exit(OVEN_STATUS_CODE_FAIL);
|
||||||
|
}
|
||||||
|
_baker = std::unique_ptr<Baker> { new TextureBaker(inputUrl, it->second, outputPath) };
|
||||||
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
_baker->moveToThread(Oven::instance().getNextWorkerThread());
|
||||||
} else {
|
} else {
|
||||||
qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl;
|
qCDebug(model_baking) << "Failed to determine baker type for file" << inputUrl;
|
||||||
|
|
|
@ -14,11 +14,14 @@
|
||||||
#include <QtCore/QCommandLineParser>
|
#include <QtCore/QCommandLineParser>
|
||||||
#include <QtCore/QUrl>
|
#include <QtCore/QUrl>
|
||||||
|
|
||||||
|
#include <image/Image.h>
|
||||||
|
|
||||||
#include "BakerCLI.h"
|
#include "BakerCLI.h"
|
||||||
|
|
||||||
static const QString CLI_INPUT_PARAMETER = "i";
|
static const QString CLI_INPUT_PARAMETER = "i";
|
||||||
static const QString CLI_OUTPUT_PARAMETER = "o";
|
static const QString CLI_OUTPUT_PARAMETER = "o";
|
||||||
static const QString CLI_TYPE_PARAMETER = "t";
|
static const QString CLI_TYPE_PARAMETER = "t";
|
||||||
|
static const QString CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER = "disable-texture-compression";
|
||||||
|
|
||||||
OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
||||||
QCoreApplication(argc, argv)
|
QCoreApplication(argc, argv)
|
||||||
|
@ -29,7 +32,8 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
||||||
parser.addOptions({
|
parser.addOptions({
|
||||||
{ CLI_INPUT_PARAMETER, "Path to file that you would like to bake.", "input" },
|
{ CLI_INPUT_PARAMETER, "Path to file that you would like to bake.", "input" },
|
||||||
{ CLI_OUTPUT_PARAMETER, "Path to folder that will be used as output.", "output" },
|
{ CLI_OUTPUT_PARAMETER, "Path to folder that will be used as output.", "output" },
|
||||||
{ CLI_TYPE_PARAMETER, "Type of asset.", "type" }
|
{ CLI_TYPE_PARAMETER, "Type of asset.", "type" },
|
||||||
|
{ CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER, "Disable texture compression." }
|
||||||
});
|
});
|
||||||
|
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
@ -40,6 +44,15 @@ OvenCLIApplication::OvenCLIApplication(int argc, char* argv[]) :
|
||||||
QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)));
|
QUrl inputUrl(QDir::fromNativeSeparators(parser.value(CLI_INPUT_PARAMETER)));
|
||||||
QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER)));
|
QUrl outputUrl(QDir::fromNativeSeparators(parser.value(CLI_OUTPUT_PARAMETER)));
|
||||||
QString type = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null;
|
QString type = parser.isSet(CLI_TYPE_PARAMETER) ? parser.value(CLI_TYPE_PARAMETER) : QString::null;
|
||||||
|
|
||||||
|
if (parser.isSet(CLI_DISABLE_TEXTURE_COMPRESSION_PARAMETER)) {
|
||||||
|
qDebug() << "Disabling texture compression";
|
||||||
|
image::setColorTexturesCompressionEnabled(false);
|
||||||
|
image::setGrayscaleTexturesCompressionEnabled(false);
|
||||||
|
image::setNormalTexturesCompressionEnabled(false);
|
||||||
|
image::setCubeTexturesCompressionEnabled(false);
|
||||||
|
}
|
||||||
|
|
||||||
QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, inputUrl),
|
QMetaObject::invokeMethod(cli, "bakeFile", Qt::QueuedConnection, Q_ARG(QUrl, inputUrl),
|
||||||
Q_ARG(QString, outputUrl.toString()), Q_ARG(QString, type));
|
Q_ARG(QString, outputUrl.toString()), Q_ARG(QString, type));
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in a new issue