diff --git a/BUILD.md b/BUILD.md index feed677828..ba38f4b51d 100644 --- a/BUILD.md +++ b/BUILD.md @@ -1,7 +1,7 @@ ### Dependencies - [cmake](https://cmake.org/download/): 3.9 -- [Qt](https://www.qt.io/download-open-source): 5.9.1 +- [Qt](https://www.qt.io/download-open-source): 5.10.1 - [OpenSSL](https://www.openssl.org/): Use the latest available 1.0 version (**NOT** 1.1) of OpenSSL to avoid security vulnerabilities. - [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional) @@ -46,8 +46,8 @@ This can either be entered directly into your shell session before you build or The path it needs to be set to will depend on where and how Qt5 was installed. e.g. - export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.6.2/clang_64/lib/cmake/ - export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.6.2/lib/cmake + export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/clang_64/lib/cmake/ + export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.10.1/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake #### Generating build files @@ -66,7 +66,7 @@ Any variables that need to be set for CMake to find dependencies can be set as E For example, to pass the QT_CMAKE_PREFIX_PATH variable during build file generation: - cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.6.2/lib/cmake + cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/lib/cmake #### Finding Dependencies diff --git a/BUILD_LINUX.md b/BUILD_LINUX.md index 038f53154c..64c0e9a643 100644 --- a/BUILD_LINUX.md +++ b/BUILD_LINUX.md @@ -14,8 +14,8 @@ Should you choose not to install Qt5 via a package manager that handles dependen Install qt: ```bash -wget http://debian.highfidelity.com/pool/h/hi/hifi-qt5.6.1_5.6.1_amd64.deb -sudo dpkg -i hifi-qt5.6.1_5.6.1_amd64.deb +wget http://debian.highfidelity.com/pool/h/hi/hifi-qt5.10.1_5.10.1_amd64.deb +sudo dpkg -i hifi-qt5.10.1_5.10.1_amd64.deb ``` Install build dependencies: @@ -66,7 +66,7 @@ cd hifi/build Prepare makefiles: ```bash -cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.6.1/5.6/gcc_64/lib/cmake .. +cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10/gcc_64/lib/cmake .. ``` Start compilation and get a cup of coffee: @@ -74,7 +74,7 @@ Start compilation and get a cup of coffee: make domain-server assignment-client interface ``` -In a server does not make sense to compile interface +In a server does not make sense to compile interface ### Running the software diff --git a/BUILD_OSX.md b/BUILD_OSX.md index 6b66863534..62102b3e18 100644 --- a/BUILD_OSX.md +++ b/BUILD_OSX.md @@ -20,7 +20,7 @@ Note that this uses the version from the homebrew formula at the time of this wr Assuming you've installed Qt using the homebrew instructions above, you'll need to set QT_CMAKE_PREFIX_PATH so CMake can find your installations. For Qt installed via homebrew, set QT_CMAKE_PREFIX_PATH: - export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.9.1/lib/cmake + export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.10.1/lib/cmake Note that this uses the version from the homebrew formula at the time of this writing, and the version in the path will likely change. diff --git a/BUILD_WIN.md b/BUILD_WIN.md index eea1f85e5b..3222e75c66 100644 --- a/BUILD_WIN.md +++ b/BUILD_WIN.md @@ -1,13 +1,13 @@ This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit. ## Building High Fidelity -Note: We are now using Visual Studio 2017 and Qt 5.9.1. If you are upgrading from Visual Studio 2013 and Qt 5.6.2, do a clean uninstall of those versions before going through this guide. +Note: We are now using Visual Studio 2017 and Qt 5.10.1. If you are upgrading from Visual Studio 2013 and Qt 5.6.2, do a clean uninstall of those versions before going through this guide. Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory. ### Step 1. Visual Studio 2017 -If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/). +If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/). When selecting components, check "Desktop development with C++." Also check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)" on the Summary toolbar on the right. @@ -17,15 +17,15 @@ Download and install the latest version of CMake 3.9. Download the file named w ### Step 3. Installing Qt -Download and install the [Qt Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.9.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)". +Download and install the [Qt Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.10.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)". -Note: Installing the Sources is optional but recommended if you have room for them (~2GB). +Note: Installing the Sources is optional but recommended if you have room for them (~2GB). ### Step 4. Setting Qt Environment Variable Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search). * Set "Variable name": `QT_CMAKE_PREFIX_PATH` -* Set "Variable value": `C:\Qt\5.9.1\msvc2017_64\lib\cmake` +* Set "Variable value": `C:\Qt\5.10.1\msvc2017_64\lib\cmake` ### Step 5. Installing [vcpkg](https://github.com/Microsoft/vcpkg) @@ -39,7 +39,7 @@ Go to `Control Panel > System > Advanced System Settings > Environment Variables * In the vcpkg directory, install the 64 bit OpenSSL package with the command `vcpkg install openssl:x64-windows` * Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl` - + ### Step 7. Running CMake to Generate Build Files Run Command Prompt from Start and run the following commands: @@ -49,7 +49,7 @@ mkdir build cd build cmake .. -G "Visual Studio 15 Win64" ``` - + Where `%HIFI_DIR%` is the directory for the highfidelity repository. ### Step 8. Making a Build @@ -74,10 +74,10 @@ Note: You can also run Interface by launching it from command line or File Explo ## Troubleshooting -For any problems after Step #7, first try this: +For any problems after Step #7, first try this: * Delete your locally cloned copy of the highfidelity repository * Restart your computer -* Redownload the [repository](https://github.com/highfidelity/hifi) +* Redownload the [repository](https://github.com/highfidelity/hifi) * Restart directions from Step #7 #### CMake gives you the same error message repeatedly after the build fails @@ -90,4 +90,4 @@ Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory. Verify that #### Qt is throwing an error -Make sure you have the correct version (5.9.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly. +Make sure you have the correct version (5.10.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly. diff --git a/assignment-client/src/audio/AudioMixerSlave.cpp b/assignment-client/src/audio/AudioMixerSlave.cpp index ccdd2fca4f..3c8e38f278 100644 --- a/assignment-client/src/audio/AudioMixerSlave.cpp +++ b/assignment-client/src/audio/AudioMixerSlave.cpp @@ -322,8 +322,16 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU // stereo sources are not passed through HRTF if (streamToAdd.isStereo()) { - for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; ++i) { - _mixSamples[i] += float(streamPopOutput[i] * gain / AudioConstants::MAX_SAMPLE_VALUE); + + // apply the avatar gain adjustment + auto& hrtf = listenerNodeData.hrtfForStream(sourceNodeID, streamToAdd.getStreamIdentifier()); + gain *= hrtf.getGainAdjustment(); + + const float scale = 1/32768.0f; // int16_t to float + + for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) { + _mixSamples[2*i+0] += (float)streamPopOutput[2*i+0] * gain * scale; + _mixSamples[2*i+1] += (float)streamPopOutput[2*i+1] * gain * scale; } ++stats.manualStereoMixes; @@ -332,10 +340,13 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU // echo sources are not passed through HRTF if (isEcho) { - for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; i += 2) { - auto monoSample = float(streamPopOutput[i / 2] * gain / AudioConstants::MAX_SAMPLE_VALUE); - _mixSamples[i] += monoSample; - _mixSamples[i + 1] += monoSample; + + const float scale = 1/32768.0f; // int16_t to float + + for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) { + float sample = (float)streamPopOutput[i] * gain * scale; + _mixSamples[2*i+0] += sample; + _mixSamples[2*i+1] += sample; } ++stats.manualEchoMixes; diff --git a/cmake/macros/SetupQt.cmake b/cmake/macros/SetupQt.cmake index 00a398761b..71f5314d2f 100644 --- a/cmake/macros/SetupQt.cmake +++ b/cmake/macros/SetupQt.cmake @@ -1,10 +1,10 @@ -# +# # Created by Bradley Austin Davis on 2017/09/02 # Copyright 2013-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 -# +# # Construct a default QT location from a root path, a version and an architecture function(calculate_default_qt_dir _RESULT_NAME) @@ -27,7 +27,7 @@ function(calculate_default_qt_dir _RESULT_NAME) endif() set_from_env(QT_ROOT QT_ROOT ${QT_DEFAULT_ROOT}) - set_from_env(QT_VERSION QT_VERSION "5.9.1") + set_from_env(QT_VERSION QT_VERSION "5.10.1") set_from_env(QT_ARCH QT_ARCH ${QT_DEFAULT_ARCH}) set(${_RESULT_NAME} "${QT_ROOT}/${QT_VERSION}/${QT_ARCH}" PARENT_SCOPE) @@ -60,11 +60,11 @@ macro(setup_qt) #if (NOT EXISTS "${QT_DIR}/include/QtCore/QtGlobal") # message(FATAL_ERROR "Unable to locate Qt includes in ${QT_DIR}") #endif() - + if (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake") message(FATAL_ERROR "Unable to locate Qt cmake config in ${QT_CMAKE_PREFIX_PATH}") endif() - + message(STATUS "The Qt build in use is: \"${QT_DIR}\"") # Instruct CMake to run moc automatically when needed. @@ -72,7 +72,7 @@ macro(setup_qt) # Instruct CMake to run rcc automatically when needed set(CMAKE_AUTORCC ON) - + if (WIN32) add_paths_to_fixup_libs("${QT_DIR}/bin") endif () diff --git a/interface/resources/qml/desktop/Desktop.qml b/interface/resources/qml/desktop/Desktop.qml index aa1049aff5..5f924834d9 100644 --- a/interface/resources/qml/desktop/Desktop.qml +++ b/interface/resources/qml/desktop/Desktop.qml @@ -324,6 +324,18 @@ FocusScope { return false; } + function hideDesktopWindows() { + for (var index = 0; index < desktop.visibleChildren.length; index++) { + var child = desktop.visibleChildren[index]; + if (child.topLevelWindow && child.hasOwnProperty("modality")) { + var TOOLBAR_NAME = "com.highfidelity.interface.toolbar.system" + if (child.objectName !== TOOLBAR_NAME) { + child.setShown(false); + } + } + } + } + function setPinned(newPinned) { pinned = newPinned } diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 343074f61c..aec31f2de4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -225,8 +225,8 @@ #ifdef DEBUG_EVENT_QUEUE // This is a HACK that uses private headers included with the qt source distrubution. // To use this feature you need to add these directores to your include path: -// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1/QtCore -// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1 +// E:/Qt/5.10.1/Src/qtbase/include/QtCore/5.10.1/QtCore +// E:/Qt/5.10.1/Src/qtbase/include/QtCore/5.10.1 #define QT_BOOTSTRAPPED #include #include @@ -2038,7 +2038,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo }); _snapshotSound = DependencyManager::get()->getSound(PathUtils::resourcesUrl("sounds/snap.wav")); - + QVariant testProperty = property(hifi::properties::TEST); qDebug() << testProperty; if (testProperty.isValid()) { @@ -6577,7 +6577,7 @@ void Application::addAssetToWorldFromURL(QString url) { } else { filename.remove(".zip"); } - + } if (!DependencyManager::get()->getThisNodeCanWriteAssets()) { @@ -6751,7 +6751,7 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q addAssetToWorldError(filenameFromPath(filePath), errorInfo); } else { // to prevent files that aren't models or texture files from being loaded into world automatically - if ((filePath.toLower().endsWith(OBJ_EXTENSION) || filePath.toLower().endsWith(FBX_EXTENSION)) || + if ((filePath.toLower().endsWith(OBJ_EXTENSION) || filePath.toLower().endsWith(FBX_EXTENSION)) || ((filePath.toLower().endsWith(JPG_EXTENSION) || filePath.toLower().endsWith(PNG_EXTENSION)) && ((!isBlocks) && (!isZip)))) { addAssetToWorldAddEntity(filePath, mapping); @@ -7400,8 +7400,8 @@ bool Application::isThrottleRendering() const { bool Application::hasFocus() const { bool result = (QApplication::activeWindow() != nullptr); #if defined(Q_OS_WIN) - // On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't - // take user focus away from their current window. So also check whether the application is the user's current foreground + // On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't + // take user focus away from their current window. So also check whether the application is the user's current foreground // window. result = result && (HWND)QApplication::activeWindow()->winId() == GetForegroundWindow(); #endif @@ -7409,7 +7409,7 @@ bool Application::hasFocus() const { } void Application::setFocus() { - // Note: Windows doesn't allow a user focus to be taken away from another application. Instead, it changes the color of and + // Note: Windows doesn't allow a user focus to be taken away from another application. Instead, it changes the color of and // flashes the taskbar icon. auto window = qApp->getWindow(); window->activateWindow(); @@ -7650,7 +7650,7 @@ void Application::updateDisplayMode() { menu->setIsOptionChecked(MenuOption::FirstPerson, true); cameraMenuChanged(); } - + // Remove the mirror camera option from menu if in HMD mode auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror); mirrorAction->setVisible(!isHmd); diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 1c00f57eec..7edc03490c 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -35,7 +35,19 @@ ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) : _url(modelOverlay->_url), _updateModel(false), _scaleToFit(modelOverlay->_scaleToFit), - _loadPriority(modelOverlay->_loadPriority) + _loadPriority(modelOverlay->_loadPriority), + + _animationURL(modelOverlay->_animationURL), + _animationFPS(modelOverlay->_animationFPS), + _animationCurrentFrame(modelOverlay->_animationCurrentFrame), + _animationRunning(modelOverlay->_animationRunning), + _animationLoop(modelOverlay->_animationLoop), + _animationFirstFrame(modelOverlay->_animationFirstFrame), + _animationLastFrame(modelOverlay->_animationLastFrame), + _animationHold(modelOverlay->_animationHold), + _animationAllowTranslation(modelOverlay->_animationAllowTranslation) + + // Joint translations and rotations aren't copied because the model needs to load before they can be applied. { _model->setLoadingPriority(_loadPriority); if (_url.isValid()) { @@ -341,20 +353,25 @@ vectorType ModelOverlay::mapJoints(mapFunction function) const { * parentID is an avatar skeleton. A value of 65535 means "no joint". * * @property {string} url - The URL of the FBX or OBJ model used for the overlay. + * @property {number} loadPriority=0.0 - The priority for loading and displaying the overlay. Overlays with higher values load + * first. * @property {Vec3} dimensions - The dimensions of the overlay. Synonym: size. * @property {Vec3} scale - The scale factor applied to the model's dimensions. * @property {object.} textures - Maps the named textures in the model to the JPG or PNG images in the urls. - * @property {Array.} jointNames - The names of the joints - if any - in the model. Read-only - * @property {Array.} jointRotations - The relative rotations of the model's joints. - * @property {Array.} jointTranslations - The relative translations of the model's joints. + * @property {Array.} jointNames - The names of the joints - if any - in the model. Read-only. + * @property {Array.} jointRotations - The relative rotations of the model's joints. Not copied if overlay is + * cloned. + * @property {Array.} jointTranslations - The relative translations of the model's joints. Not copied if overlay is + * cloned. * @property {Array.} jointOrientations - The absolute orientations of the model's joints, in world coordinates. - * Read-only + * Read-only. * @property {Array.} jointPositions - The absolute positions of the model's joints, in world coordinates. - * Read-only + * Read-only. * @property {string} animationSettings.url="" - The URL of an FBX file containing an animation to play. * @property {number} animationSettings.fps=0 - The frame rate (frames/sec) to play the animation at. * @property {number} animationSettings.firstFrame=0 - The frame to start playing at. * @property {number} animationSettings.lastFrame=0 - The frame to finish playing at. + * @property {number} animationSettings.currentFrame=0 - The current frame being played. * @property {boolean} animationSettings.running=false - Whether or not the animation is playing. * @property {boolean} animationSettings.loop=false - Whether or not the animation should repeat in a loop. * @property {boolean} animationSettings.hold=false - Whether or not when the animation finishes, the rotations and @@ -384,6 +401,10 @@ QVariant ModelOverlay::getProperty(const QString& property) { } } + if (property == "loadPriority") { + return _loadPriority; + } + if (property == "jointNames") { if (_model && _model->isActive()) { // note: going through Rig because Model::getJointNames() (which proxies to FBXGeometry) was always empty diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index dcaae59a38..14868a51ae 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -2059,24 +2059,34 @@ static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities"); static const QString JSON_AVATAR_SCALE = QStringLiteral("scale"); static const QString JSON_AVATAR_VERSION = QStringLiteral("version"); -static const int JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION = 0; -static const int JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION = 1; +enum class JsonAvatarFrameVersion : int { + JointRotationsInRelativeFrame = 0, + JointRotationsInAbsoluteFrame, + JointDefaultPoseBits +}; QJsonValue toJsonValue(const JointData& joint) { QJsonArray result; result.push_back(toJsonValue(joint.rotation)); result.push_back(toJsonValue(joint.translation)); + result.push_back(QJsonValue(joint.rotationIsDefaultPose)); + result.push_back(QJsonValue(joint.translationIsDefaultPose)); return result; } -JointData jointDataFromJsonValue(const QJsonValue& json) { +JointData jointDataFromJsonValue(int version, const QJsonValue& json) { JointData result; if (json.isArray()) { QJsonArray array = json.toArray(); result.rotation = quatFromJsonValue(array[0]); - result.rotationIsDefaultPose = false; result.translation = vec3FromJsonValue(array[1]); - result.translationIsDefaultPose = false; + if (version >= (int)JsonAvatarFrameVersion::JointDefaultPoseBits) { + result.rotationIsDefaultPose = array[2].toBool(); + result.translationIsDefaultPose = array[3].toBool(); + } else { + result.rotationIsDefaultPose = false; + result.translationIsDefaultPose = false; + } } return result; } @@ -2084,7 +2094,7 @@ JointData jointDataFromJsonValue(const QJsonValue& json) { QJsonObject AvatarData::toJson() const { QJsonObject root; - root[JSON_AVATAR_VERSION] = JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION; + root[JSON_AVATAR_VERSION] = (int)JsonAvatarFrameVersion::JointDefaultPoseBits; if (!getSkeletonModelURL().isEmpty()) { root[JSON_AVATAR_BODY_MODEL] = getSkeletonModelURL().toString(); @@ -2159,7 +2169,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) { version = json[JSON_AVATAR_VERSION].toInt(); } else { // initial data did not have a version field. - version = JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION; + version = (int)JsonAvatarFrameVersion::JointRotationsInRelativeFrame; } if (json.contains(JSON_AVATAR_BODY_MODEL)) { @@ -2236,7 +2246,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) { // } if (json.contains(JSON_AVATAR_JOINT_ARRAY)) { - if (version == JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION) { + if (version == (int)JsonAvatarFrameVersion::JointRotationsInRelativeFrame) { // because we don't have the full joint hierarchy skeleton of the model, // we can't properly convert from relative rotations into absolute rotations. quint64 now = usecTimestampNow(); @@ -2248,7 +2258,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) { QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray(); jointArray.reserve(jointArrayJson.size()); for (const auto& jointJson : jointArrayJson) { - auto joint = jointDataFromJsonValue(jointJson); + auto joint = jointDataFromJsonValue(version, jointJson); jointArray.push_back(joint); } setRawJointData(jointArray); @@ -2559,4 +2569,4 @@ void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap& value[EntityID] = binaryEntityProperties; } -} \ No newline at end of file +} diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp index ea8edb8a08..7cea841bf0 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.cpp @@ -18,7 +18,7 @@ bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP if (entity->getMaterial() != _drawMaterial) { return true; } - if (entity->getParentID() != _parentID || entity->getClientOnly() != _clientOnly || entity->getOwningAvatarID() != _owningAvatarID) { + if (entity->getParentID() != _parentID) { return true; } if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) { @@ -31,8 +31,6 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& withWriteLock([&] { _drawMaterial = entity->getMaterial(); _parentID = entity->getParentID(); - _clientOnly = entity->getClientOnly(); - _owningAvatarID = entity->getOwningAvatarID(); _materialMappingPos = entity->getMaterialMappingPos(); _materialMappingScale = entity->getMaterialMappingScale(); _materialMappingRot = entity->getMaterialMappingRot(); @@ -102,7 +100,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) { graphics::MaterialPointer drawMaterial; Transform textureTransform; withReadLock([&] { - parentID = _clientOnly ? _owningAvatarID : _parentID; + parentID = _parentID; renderTransform = _renderTransform; drawMaterial = _drawMaterial; textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0)); diff --git a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h index 8de2190a0c..96c720f79f 100644 --- a/libraries/entities-renderer/src/RenderableMaterialEntityItem.h +++ b/libraries/entities-renderer/src/RenderableMaterialEntityItem.h @@ -32,8 +32,6 @@ private: ShapeKey getShapeKey() override; QUuid _parentID; - bool _clientOnly; - QUuid _owningAvatarID; glm::vec2 _materialMappingPos; glm::vec2 _materialMappingScale; float _materialMappingRot; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f9a96d2293..8b916a875f 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -363,6 +363,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_POS, materialMappingPos); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot); + CHECK_PROPERTY_CHANGE(PROP_MATERIAL_DATA, materialData); // Certifiable Properties CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName); @@ -1208,6 +1209,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACTION_DATA, actionData); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); // Certifiable Properties COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ITEM_NAME, itemName); @@ -1252,7 +1254,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_SPREAD, colorSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_START, colorStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_FINISH, colorFinish); - COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish); @@ -1376,6 +1377,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_POS, materialMappingPos); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_DATA, materialData); } /**jsdoc @@ -1539,6 +1541,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingPos, glmVec2, setMaterialMappingPos); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, glmVec2, setMaterialMappingScale); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot); + COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData); // Certifiable Properties COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName); @@ -1902,6 +1905,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glmVec2); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glmVec2); ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float); + ADD_PROPERTY_TO_MAP(PROP_MATERIAL_DATA, MaterialData, materialData, QString); // Certifiable Properties ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString); @@ -2298,6 +2302,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_POS, properties.getMaterialMappingPos()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, properties.getMaterialMappingScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, properties.getMaterialMappingRot()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, properties.getMaterialData()); } APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); @@ -2666,6 +2671,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_POS, glmVec2, setMaterialMappingPos); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_SCALE, glmVec2, setMaterialMappingScale); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_DATA, QString, setMaterialData); } READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); @@ -2849,6 +2855,7 @@ void EntityItemProperties::markAllChanged() { _materialMappingPosChanged = true; _materialMappingScaleChanged = true; _materialMappingRotChanged = true; + _materialDataChanged = true; // Certifiable Properties _itemNameChanged = true; @@ -3200,6 +3207,9 @@ QList EntityItemProperties::listChangedProperties() { if (materialMappingRotChanged()) { out += "materialMappingRot"; } + if (materialDataChanged()) { + out += "materialData"; + } // Certifiable Properties if (itemNameChanged()) { diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index cc832146e8..38e4f0c8c0 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -230,6 +230,7 @@ public: DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glmVec2, glm::vec2(0, 0)); DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glmVec2, glm::vec2(1, 1)); DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0); + DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, ""); // Certifiable Properties - related to Proof of Purchase certificates DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index 07908fe6cf..99a5f287ea 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -240,6 +240,7 @@ enum EntityPropertyList { PROP_MATERIAL_MAPPING_POS, PROP_MATERIAL_MAPPING_SCALE, PROP_MATERIAL_MAPPING_ROT, + PROP_MATERIAL_DATA, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 81fb2d7d37..0d363d236f 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -2382,6 +2382,30 @@ bool EntityTree::readFromMap(QVariantMap& map) { } } + // Convert old materials so that they use materialData instead of userData + if (contentVersion < (int)EntityVersion::MaterialData && properties.getType() == EntityTypes::EntityType::Material) { + if (properties.getMaterialURL().startsWith("userData")) { + QString materialURL = properties.getMaterialURL(); + properties.setMaterialURL(materialURL.replace("userData", "materialData")); + + QJsonObject userData = QJsonDocument::fromJson(properties.getUserData().toUtf8()).object(); + QJsonObject materialData; + QJsonValue materialVersion = userData["materialVersion"]; + if (!materialVersion.isNull()) { + materialData.insert("materialVersion", materialVersion); + userData.remove("materialVersion"); + } + QJsonValue materials = userData["materials"]; + if (!materials.isNull()) { + materialData.insert("materials", materials); + userData.remove("materials"); + } + + properties.setMaterialData(QJsonDocument(materialData).toJson()); + properties.setUserData(QJsonDocument(userData).toJson()); + } + } + EntityItemPointer entity = addEntity(entityItemID, properties); if (!entity) { qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType(); diff --git a/libraries/entities/src/MaterialEntityItem.cpp b/libraries/entities/src/MaterialEntityItem.cpp index 8b595bf69d..6c040296a3 100644 --- a/libraries/entities/src/MaterialEntityItem.cpp +++ b/libraries/entities/src/MaterialEntityItem.cpp @@ -27,6 +27,10 @@ MaterialEntityItem::MaterialEntityItem(const EntityItemID& entityItemID) : Entit _type = EntityTypes::Material; } +MaterialEntityItem::~MaterialEntityItem() { + removeMaterial(); +} + EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); @@ -36,6 +40,7 @@ EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desir COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingPos, getMaterialMappingPos); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingScale, getMaterialMappingScale); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingRot, getMaterialMappingRot); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialData, getMaterialData); return properties; } @@ -49,6 +54,7 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) { SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingPos, setMaterialMappingPos); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingScale, setMaterialMappingScale); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingRot, setMaterialMappingRot); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialData, setMaterialData); if (somethingChanged) { bool wantDebug = false; @@ -78,6 +84,7 @@ int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_POS, glm::vec2, setMaterialMappingPos); READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, glm::vec2, setMaterialMappingScale); READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot); + READ_ENTITY_PROPERTY(PROP_MATERIAL_DATA, QString, setMaterialData); return bytesRead; } @@ -93,6 +100,7 @@ EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParam requestedProperties += PROP_MATERIAL_MAPPING_POS; requestedProperties += PROP_MATERIAL_MAPPING_SCALE; requestedProperties += PROP_MATERIAL_MAPPING_ROT; + requestedProperties += PROP_MATERIAL_DATA; return requestedProperties; } @@ -112,6 +120,7 @@ void MaterialEntityItem::appendSubclassData(OctreePacketData* packetData, Encode APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_POS, getMaterialMappingPos()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, getMaterialMappingScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, getMaterialMappingRot()); + APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, getMaterialData()); } void MaterialEntityItem::debugDump() const { @@ -145,9 +154,9 @@ std::shared_ptr MaterialEntityItem::getMaterial() const { } } -void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool userDataChanged) { - bool usingUserData = materialURLString.startsWith("userData"); - if (_materialURL != materialURLString || (usingUserData && userDataChanged)) { +void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool materialDataChanged) { + bool usingMaterialData = materialDataChanged || materialURLString.startsWith("materialData"); + if (_materialURL != materialURLString || (usingMaterialData && materialDataChanged)) { removeMaterial(); _materialURL = materialURLString; @@ -156,8 +165,8 @@ void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool u _currentMaterialName = split.last().toStdString(); } - if (usingUserData) { - _parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getUserData().toUtf8()), materialURLString); + if (usingMaterialData) { + _parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getMaterialData().toUtf8()), materialURLString); // Since our material changed, the current name might not be valid anymore, so we need to update setCurrentMaterialName(_currentMaterialName); @@ -191,11 +200,11 @@ void MaterialEntityItem::setCurrentMaterialName(const std::string& currentMateri } } -void MaterialEntityItem::setUserData(const QString& userData) { - if (_userData != userData) { - EntityItem::setUserData(userData); - if (_materialURL.startsWith("userData")) { - // Trigger material update when user data changes +void MaterialEntityItem::setMaterialData(const QString& materialData) { + if (_materialData != materialData) { + _materialData = materialData; + if (_materialURL.startsWith("materialData")) { + // Trigger material update when material data changes setMaterialURL(_materialURL, true); } } @@ -249,28 +258,12 @@ void MaterialEntityItem::setParentID(const QUuid& parentID) { } } -void MaterialEntityItem::setClientOnly(bool clientOnly) { - if (getClientOnly() != clientOnly) { - removeMaterial(); - EntityItem::setClientOnly(clientOnly); - applyMaterial(); - } -} - -void MaterialEntityItem::setOwningAvatarID(const QUuid& owningAvatarID) { - if (getOwningAvatarID() != owningAvatarID) { - removeMaterial(); - EntityItem::setOwningAvatarID(owningAvatarID); - applyMaterial(); - } -} - void MaterialEntityItem::removeMaterial() { graphics::MaterialPointer material = getMaterial(); if (!material) { return; } - QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID(); + QUuid parentID = getParentID(); if (parentID.isNull()) { return; } @@ -294,7 +287,7 @@ void MaterialEntityItem::removeMaterial() { void MaterialEntityItem::applyMaterial() { _retryApply = false; graphics::MaterialPointer material = getMaterial(); - QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID(); + QUuid parentID = getParentID(); if (!material || parentID.isNull()) { return; } @@ -328,11 +321,6 @@ void MaterialEntityItem::postParentFixup() { applyMaterial(); } -void MaterialEntityItem::preDelete() { - EntityItem::preDelete(); - removeMaterial(); -} - void MaterialEntityItem::update(const quint64& now) { if (_retryApply) { applyMaterial(); diff --git a/libraries/entities/src/MaterialEntityItem.h b/libraries/entities/src/MaterialEntityItem.h index f77077a782..969eb577ff 100644 --- a/libraries/entities/src/MaterialEntityItem.h +++ b/libraries/entities/src/MaterialEntityItem.h @@ -21,6 +21,7 @@ public: static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); MaterialEntityItem(const EntityItemID& entityItemID); + ~MaterialEntityItem(); ALLOW_INSTANTIATION // This class can be instantiated @@ -53,7 +54,7 @@ public: virtual void setUnscaledDimensions(const glm::vec3& value) override; QString getMaterialURL() const { return _materialURL; } - void setMaterialURL(const QString& materialURLString, bool userDataChanged = false); + void setMaterialURL(const QString& materialURLString, bool materialDataChanged = false); void setCurrentMaterialName(const std::string& currentMaterialName); @@ -73,21 +74,20 @@ public: float getMaterialMappingRot() const { return _materialMappingRot; } void setMaterialMappingRot(const float& materialMappingRot); + QString getMaterialData() const { return _materialData; } + void setMaterialData(const QString& materialData); + std::shared_ptr getMaterial() const; - void setUserData(const QString& userData) override; void setParentID(const QUuid& parentID) override; - void setClientOnly(bool clientOnly) override; - void setOwningAvatarID(const QUuid& owningAvatarID) override; void applyMaterial(); void removeMaterial(); void postParentFixup() override; - void preDelete() override; private: - // URL for this material. Currently, only JSON format is supported. Set to "userData" to use the user data to live edit a material. + // URL for this material. Currently, only JSON format is supported. Set to "materialData" to use the material data to live edit a material. // The following fields are supported in the JSON: // materialVersion: a uint for the version of this network material (currently, only 1 is supported) // materials, which is either an object or an array of objects, each with the following properties: @@ -117,6 +117,7 @@ private: glm::vec2 _materialMappingScale { 1, 1 }; // How much to rotate this material within its parent's UV-space (degrees) float _materialMappingRot { 0 }; + QString _materialData; NetworkMaterialResourcePointer _networkMaterial; NetworkMaterialResource::ParsedMaterials _parsedMaterials; diff --git a/libraries/entities/src/ShapeEntityItem.cpp b/libraries/entities/src/ShapeEntityItem.cpp index 60ba429938..99f18d2dac 100644 --- a/libraries/entities/src/ShapeEntityItem.cpp +++ b/libraries/entities/src/ShapeEntityItem.cpp @@ -117,8 +117,10 @@ ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem( EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class - properties.setColor(getXColor()); properties.setShape(entity::stringFromShape(getShape())); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha); + return properties; } diff --git a/libraries/entities/src/ShapeEntityItem.h b/libraries/entities/src/ShapeEntityItem.h index 97202afcf7..adc33b764b 100644 --- a/libraries/entities/src/ShapeEntityItem.h +++ b/libraries/entities/src/ShapeEntityItem.h @@ -105,7 +105,7 @@ public: protected: - float _alpha { 1 }; // FIXME: This property is not used. + float _alpha { 1.0f }; rgbColor _color; entity::Shape _shape { entity::Shape::Sphere }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp index 99a9afb4c4..4d94f8d8e7 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLTexelFormat.cpp @@ -370,7 +370,36 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) { case gpu::COMPRESSED_BC7_SRGBA: result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; break; - + case gpu::COMPRESSED_ETC2_RGB: + result = GL_COMPRESSED_RGB8_ETC2; + break; + case gpu::COMPRESSED_ETC2_SRGB: + result = GL_COMPRESSED_SRGB8_ETC2; + break; + case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA: + result = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + break; + case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA: + result = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; + break; + case gpu::COMPRESSED_ETC2_RGBA: + result = GL_COMPRESSED_RGBA8_ETC2_EAC; + break; + case gpu::COMPRESSED_ETC2_SRGBA: + result = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; + break; + case gpu::COMPRESSED_EAC_RED: + result = GL_COMPRESSED_R11_EAC; + break; + case gpu::COMPRESSED_EAC_RED_SIGNED: + result = GL_COMPRESSED_SIGNED_R11_EAC; + break; + case gpu::COMPRESSED_EAC_XY: + result = GL_COMPRESSED_RG11_EAC; + break; + case gpu::COMPRESSED_EAC_XY_SIGNED: + result = GL_COMPRESSED_SIGNED_RG11_EAC; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } @@ -531,6 +560,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::COMPRESSED_BC7_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; break; + case gpu::COMPRESSED_ETC2_RGB: + texel.internalFormat = GL_COMPRESSED_RGB8_ETC2; + break; + case gpu::COMPRESSED_ETC2_SRGB: + texel.internalFormat = GL_COMPRESSED_SRGB8_ETC2; + break; + case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA: + texel.internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + break; + case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA: + texel.internalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; + break; + case gpu::COMPRESSED_ETC2_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; + break; + case gpu::COMPRESSED_ETC2_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; + break; + case gpu::COMPRESSED_EAC_RED: + texel.internalFormat = GL_COMPRESSED_R11_EAC; + break; + case gpu::COMPRESSED_EAC_RED_SIGNED: + texel.internalFormat = GL_COMPRESSED_SIGNED_R11_EAC; + break; + case gpu::COMPRESSED_EAC_XY: + texel.internalFormat = GL_COMPRESSED_RG11_EAC; + break; + case gpu::COMPRESSED_EAC_XY_SIGNED: + texel.internalFormat = GL_COMPRESSED_SIGNED_RG11_EAC; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } @@ -895,7 +954,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E case gpu::COMPRESSED_BC7_SRGBA: texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; break; - + case gpu::COMPRESSED_ETC2_RGB: + texel.internalFormat = GL_COMPRESSED_RGB8_ETC2; + break; + case gpu::COMPRESSED_ETC2_SRGB: + texel.internalFormat = GL_COMPRESSED_SRGB8_ETC2; + break; + case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA: + texel.internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2; + break; + case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA: + texel.internalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2; + break; + case gpu::COMPRESSED_ETC2_RGBA: + texel.internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC; + break; + case gpu::COMPRESSED_ETC2_SRGBA: + texel.internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC; + break; + case gpu::COMPRESSED_EAC_RED: + texel.internalFormat = GL_COMPRESSED_R11_EAC; + break; + case gpu::COMPRESSED_EAC_RED_SIGNED: + texel.internalFormat = GL_COMPRESSED_SIGNED_R11_EAC; + break; + case gpu::COMPRESSED_EAC_XY: + texel.internalFormat = GL_COMPRESSED_RG11_EAC; + break; + case gpu::COMPRESSED_EAC_XY_SIGNED: + texel.internalFormat = GL_COMPRESSED_SIGNED_RG11_EAC; + break; default: qCWarning(gpugllogging) << "Unknown combination of texel format"; } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h index 3c59781f78..9479321747 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h +++ b/libraries/gpu-gl/src/gpu/gl41/GL41Backend.h @@ -173,6 +173,8 @@ protected: void makeProgramBindings(ShaderObject& shaderObject) override; int makeResourceBufferSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override; + static bool supportedTextureFormat(const gpu::Element& format); + }; } } diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 722ea63a77..0298b8b892 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -19,6 +19,24 @@ using namespace gpu; using namespace gpu::gl; using namespace gpu::gl41; +bool GL41Backend::supportedTextureFormat(const gpu::Element& format) { + switch (format.getSemantic()) { + case gpu::Semantic::COMPRESSED_ETC2_RGB: + case gpu::Semantic::COMPRESSED_ETC2_SRGB: + case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA: + case gpu::Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA: + case gpu::Semantic::COMPRESSED_ETC2_RGBA: + case gpu::Semantic::COMPRESSED_ETC2_SRGBA: + case gpu::Semantic::COMPRESSED_EAC_RED: + case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED: + case gpu::Semantic::COMPRESSED_EAC_XY: + case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED: + return false; + default: + return true; + } +} + GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) { if (!texturePointer) { return nullptr; @@ -34,6 +52,11 @@ GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) { return nullptr; } + // Check whether the texture is in a format we can deal with + if (!supportedTextureFormat(texture.getTexelFormat())) { + return nullptr; + } + GL41Texture* object = Backend::getGPUObject(texture); if (!object) { switch (texture.getUsageType()) { diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 5a5d701150..4d5ffefa67 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -206,6 +206,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case GL_COMPRESSED_R11_EAC: + case GL_COMPRESSED_SIGNED_R11_EAC: + case GL_COMPRESSED_RG11_EAC: + case GL_COMPRESSED_SIGNED_RG11_EAC: glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat, static_cast(sourceSize), sourcePointer); break; @@ -222,6 +232,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: + case GL_COMPRESSED_RGB8_ETC2: + case GL_COMPRESSED_SRGB8_ETC2: + case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case GL_COMPRESSED_RGBA8_ETC2_EAC: + case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case GL_COMPRESSED_R11_EAC: + case GL_COMPRESSED_SIGNED_R11_EAC: + case GL_COMPRESSED_RG11_EAC: + case GL_COMPRESSED_SIGNED_RG11_EAC: if (glCompressedTextureSubImage2DEXT) { auto target = GLTexture::CUBE_FACE_LAYOUT[face]; glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat, diff --git a/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp b/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp index 6bc55a23d4..2009dc5dc9 100644 --- a/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp +++ b/libraries/gpu-gles/src/gpu/gles/GLESBackendTexture.cpp @@ -20,9 +20,21 @@ using namespace gpu::gl; using namespace gpu::gles; bool GLESBackend::supportedTextureFormat(const gpu::Element& format) { - // FIXME distinguish between GLES and GL compressed formats after support - // for the former is added to gpu::Element - return !format.isCompressed(); + switch (format.getSemantic()) { + case gpu::Semantic::COMPRESSED_ETC2_RGB: + case gpu::Semantic::COMPRESSED_ETC2_SRGB: + case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA: + case gpu::Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA: + case gpu::Semantic::COMPRESSED_ETC2_RGBA: + case gpu::Semantic::COMPRESSED_ETC2_SRGBA: + case gpu::Semantic::COMPRESSED_EAC_RED: + case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED: + case gpu::Semantic::COMPRESSED_EAC_XY: + case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED: + return true; + default: + return !format.isCompressed(); + } } GLTexture* GLESBackend::syncGPUObject(const TexturePointer& texturePointer) { @@ -231,6 +243,29 @@ GLESFixedAllocationTexture::GLESFixedAllocationTexture(const std::weak_ptrgetStoredMipFormat(); - if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGB) { + if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGB) { compressionOptions.setFormat(nvtt::Format_BC1); - } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA_MASK) { + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_MASK) { alphaMode = nvtt::AlphaMode_Transparency; compressionOptions.setFormat(nvtt::Format_BC1a); - } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA) { + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA) { alphaMode = nvtt::AlphaMode_Transparency; compressionOptions.setFormat(nvtt::Format_BC3); - } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_RED) { + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_RED) { compressionOptions.setFormat(nvtt::Format_BC4); - } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_XY) { + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_XY) { compressionOptions.setFormat(nvtt::Format_BC5); - } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA_HIGH) { + } else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH) { alphaMode = nvtt::AlphaMode_Transparency; compressionOptions.setFormat(nvtt::Format_BC7); } else if (mipFormat == gpu::Element::COLOR_RGBA_32) { @@ -736,13 +738,21 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma gpu::Element formatMip; gpu::Element formatGPU; if (isColorTexturesCompressionEnabled()) { +#ifndef USE_GLES if (validAlpha) { // NOTE: This disables BC1a compression because it was producing odd artifacts on text textures // for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts). - formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA; + formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGBA; } else { - formatGPU = gpu::Element::COLOR_COMPRESSED_SRGB; + formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGB; } +#else + if (validAlpha) { + formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGBA; + } else { + formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGB; + } +#endif formatMip = formatGPU; } else { #ifdef USE_GLES @@ -869,8 +879,12 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr gpu::Element formatMip = gpu::Element::VEC2NU8_XY; gpu::Element formatGPU = gpu::Element::VEC2NU8_XY; if (isNormalTexturesCompressionEnabled()) { - formatMip = gpu::Element::COLOR_COMPRESSED_XY; - formatGPU = gpu::Element::COLOR_COMPRESSED_XY; +#ifndef USE_GLES + formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY; +#else + formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_XY; +#endif + formatMip = formatGPU; } theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR)); @@ -903,8 +917,12 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr gpu::Element formatMip; gpu::Element formatGPU; if (isGrayscaleTexturesCompressionEnabled()) { - formatMip = gpu::Element::COLOR_COMPRESSED_RED; - formatGPU = gpu::Element::COLOR_COMPRESSED_RED; +#ifndef USE_GLES + formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED; +#else + formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_RED; +#endif + formatMip = formatGPU; } else { formatMip = gpu::Element::COLOR_R_8; formatGPU = gpu::Element::COLOR_R_8; @@ -1271,8 +1289,9 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI gpu::Element formatMip; gpu::Element formatGPU; if (isCubeTexturesCompressionEnabled()) { - formatMip = gpu::Element::COLOR_COMPRESSED_HDR_RGB; - formatGPU = gpu::Element::COLOR_COMPRESSED_HDR_RGB; + // TODO: gles: pick HDR ETC format + formatMip = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB; + formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB; } else { formatMip = HDR_FORMAT; formatGPU = HDR_FORMAT; diff --git a/libraries/ktx/src/khronos/KHR.h b/libraries/ktx/src/khronos/KHR.h index cda22513ee..4ee893e4fc 100644 --- a/libraries/ktx/src/khronos/KHR.h +++ b/libraries/ktx/src/khronos/KHR.h @@ -358,6 +358,17 @@ namespace khronos { case InternalFormat::COMPRESSED_RG_RGTC2: // BC5 case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: // BC6 case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7 + // ETC2 / EAC + case InternalFormat::COMPRESSED_RGB8_ETC2: + case InternalFormat::COMPRESSED_SRGB8_ETC2: + case InternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case InternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case InternalFormat::COMPRESSED_RGBA8_ETC2_EAC: + case InternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case InternalFormat::COMPRESSED_R11_EAC: + case InternalFormat::COMPRESSED_SIGNED_R11_EAC: + case InternalFormat::COMPRESSED_RG11_EAC: + case InternalFormat::COMPRESSED_SIGNED_RG11_EAC: return evalAlignedCompressedBlockCount<4>(value); default: @@ -370,12 +381,22 @@ namespace khronos { case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case InternalFormat::COMPRESSED_RED_RGTC1: + case InternalFormat::COMPRESSED_RGB8_ETC2: + case InternalFormat::COMPRESSED_SRGB8_ETC2: + case InternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case InternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2: + case InternalFormat::COMPRESSED_R11_EAC: + case InternalFormat::COMPRESSED_SIGNED_R11_EAC: return 8; case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: case InternalFormat::COMPRESSED_RG_RGTC2: + case InternalFormat::COMPRESSED_RGBA8_ETC2_EAC: + case InternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC: + case InternalFormat::COMPRESSED_RG11_EAC: + case InternalFormat::COMPRESSED_SIGNED_RG11_EAC: return 16; default: diff --git a/libraries/networking/src/AddressManager.cpp b/libraries/networking/src/AddressManager.cpp index 3c24cc796c..52253b1cbc 100644 --- a/libraries/networking/src/AddressManager.cpp +++ b/libraries/networking/src/AddressManager.cpp @@ -39,6 +39,10 @@ bool AddressManager::isConnected() { return DependencyManager::get()->getDomainHandler().isConnected(); } +QString AddressManager::getProtocol() const { + return _domainURL.scheme(); +} + QUrl AddressManager::currentAddress(bool domainOnly) const { QUrl hifiURL = _domainURL; diff --git a/libraries/networking/src/AddressManager.h b/libraries/networking/src/AddressManager.h index b42aec2771..b6a18b117d 100644 --- a/libraries/networking/src/AddressManager.h +++ b/libraries/networking/src/AddressManager.h @@ -145,7 +145,7 @@ public: }; bool isConnected(); - const QString& getProtocol() { return URL_SCHEME_HIFI; }; + QString getProtocol() const; QUrl currentAddress(bool domainOnly = false) const; QUrl currentFacingAddress() const; diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index a83924ee58..b49b954b99 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::ShadowControl); + return static_cast(EntityVersion::MaterialData); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::RemovedJurisdictions); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 09fd31a41e..e0d3bcdb97 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -231,7 +231,8 @@ enum class EntityVersion : PacketVersion { ZoneStageRemoved, SoftEntities, MaterialEntities, - ShadowControl + ShadowControl, + MaterialData }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index fc35267ddc..956b6c4a58 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -532,7 +532,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext, } } - auto& program = deferredLightingEffect->_directionalSkyboxLight; + auto program = deferredLightingEffect->_directionalSkyboxLight; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; auto keyLight = lightAndShadow.first; diff --git a/libraries/ui/src/OffscreenUi.cpp b/libraries/ui/src/OffscreenUi.cpp index 7a938f39c8..a1d09139e3 100644 --- a/libraries/ui/src/OffscreenUi.cpp +++ b/libraries/ui/src/OffscreenUi.cpp @@ -154,6 +154,13 @@ void OffscreenUi::show(const QUrl& url, const QString& name, std::function f) { QQuickItem* item = getRootItem()->findChild(name); if (!item) { diff --git a/libraries/ui/src/OffscreenUi.h b/libraries/ui/src/OffscreenUi.h index cb8ee29068..26f9f58dd5 100644 --- a/libraries/ui/src/OffscreenUi.h +++ b/libraries/ui/src/OffscreenUi.h @@ -60,6 +60,7 @@ public: void createDesktop(const QUrl& url); void show(const QUrl& url, const QString& name, std::function f = [](QQmlContext*, QObject*) {}); void hide(const QString& name); + void hideDesktopWindows(); bool isVisible(const QString& name); void toggle(const QUrl& url, const QString& name, std::function f = [](QQmlContext*, QObject*) {}); bool shouldSwallowShortcut(QEvent* event); diff --git a/libraries/ui/src/ui/TabletScriptingInterface.cpp b/libraries/ui/src/ui/TabletScriptingInterface.cpp index 0191baca5e..a079609bb7 100644 --- a/libraries/ui/src/ui/TabletScriptingInterface.cpp +++ b/libraries/ui/src/ui/TabletScriptingInterface.cpp @@ -387,6 +387,8 @@ void TabletProxy::setToolbarMode(bool toolbarMode) { offscreenUi->hide("RunningScripts"); _showRunningScripts = true; } + + offscreenUi->hideDesktopWindows(); // destroy desktop window if (_desktopWindow) { _desktopWindow->deleteLater(); diff --git a/scripts/system/controllers/grab.js b/scripts/system/controllers/grab.js index 1171703847..776fd11e5c 100644 --- a/scripts/system/controllers/grab.js +++ b/scripts/system/controllers/grab.js @@ -8,7 +8,7 @@ // // Grab's physically moveable entities with the mouse, by applying a spring force. // -// Updated November 22, 2016 by Philip Rosedale: Add distance attenuation of grab effect +// Updated November 22, 2016 by Philip Rosedale: Add distance attenuation of grab effect // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -444,6 +444,7 @@ Grabber.prototype.releaseEvent = function(event) { this.actionID = null; Pointers.setRenderState(this.mouseRayEntities, ""); + Pointers.setLockEndUUID(this.mouseRayEntities, null, false); var args = "mouse"; Entities.callEntityMethod(this.entityID, "releaseGrab", args); diff --git a/scripts/system/edit.js b/scripts/system/edit.js index ea22359805..fd7a488eb7 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -416,6 +416,12 @@ var toolBar = (function () { // default: // shapeType = "uv"; //} + var materialData = ""; + if (materialURL.startsWith("materialData")) { + materialData = JSON.stringify({ + "materials": {} + }) + } var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1; if (materialURL) { @@ -423,7 +429,8 @@ var toolBar = (function () { type: "Material", materialURL: materialURL, //materialMappingMode: materialMappingMode, - priority: DEFAULT_LAYERED_MATERIAL_PRIORITY + priority: DEFAULT_LAYERED_MATERIAL_PRIORITY, + materialData: materialData }); } } @@ -2061,7 +2068,7 @@ var PropertiesTool = function (opts) { parentSelectedEntities(); } else if (data.type === 'unparent') { unparentSelectedEntities(); - } else if (data.type === 'saveUserData') { + } else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') { //the event bridge and json parsing handle our avatar id string differently. var actualID = data.id.split('"')[1]; Entities.editEntity(actualID, data.properties); diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 7664ae8714..6c1931932a 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -1387,12 +1387,14 @@ input#reset-to-natural-dimensions { margin-top: 48px; } -#userdata-clear{ +#userdata-clear, +#materialdata-clear { margin-bottom: 10px; } -#static-userdata { +#static-userdata, +#static-materialData { display: none; z-index: 99; position: absolute; @@ -1403,7 +1405,8 @@ input#reset-to-natural-dimensions { background-color: #2e2e2e; } -#userdata-saved { +#userdata-saved, +#materialData-saved { margin-top:5px; font-size:16px; display:none; diff --git a/scripts/system/html/entityProperties.html b/scripts/system/html/entityProperties.html index 82a450bedd..8647dca035 100644 --- a/scripts/system/html/entityProperties.html +++ b/scripts/system/html/entityProperties.html @@ -781,6 +781,20 @@ + +
+ +

+
+ + + + Saved! +
+
+
+ +
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js index d2fa2eeeb0..4b6329db44 100644 --- a/scripts/system/html/js/entityProperties.js +++ b/scripts/system/html/js/entityProperties.js @@ -66,6 +66,7 @@ function enableProperties() { if (elLocked.checked === false) { removeStaticUserData(); + removeStaticMaterialData(); } } @@ -78,8 +79,13 @@ function disableProperties() { } var elLocked = document.getElementById("property-locked"); - if ($('#userdata-editor').css('display') === "block" && elLocked.checked === true) { - showStaticUserData(); + if (elLocked.checked === true) { + if ($('#userdata-editor').css('display') === "block") { + showStaticUserData(); + } + if ($('#materialdata-editor').css('display') === "block") { + showStaticMaterialData(); + } } } @@ -356,15 +362,139 @@ function userDataChanger(groupName, keyName, values, userDataElement, defaultVal multiDataUpdater(groupName, val, userDataElement, def); } +function setMaterialDataFromEditor(noUpdate) { + var json = null; + try { + json = materialEditor.get(); + } catch (e) { + alert('Invalid JSON code - look for red X in your code ', +e); + } + if (json === null) { + return; + } else { + var text = materialEditor.getText(); + if (noUpdate === true) { + EventBridge.emitWebEvent( + JSON.stringify({ + id: lastEntityID, + type: "saveMaterialData", + properties: { + materialData: text + } + }) + ); + return; + } else { + updateProperty('materialData', text); + } + } +} + function setTextareaScrolling(element) { var isScrolling = element.scrollHeight > element.offsetHeight; element.setAttribute("scrolling", isScrolling ? "true" : "false"); } +var materialEditor = null; + +function createJSONMaterialEditor() { + var container = document.getElementById("materialdata-editor"); + var options = { + search: false, + mode: 'tree', + modes: ['code', 'tree'], + name: 'materialData', + onModeChange: function() { + $('.jsoneditor-poweredBy').remove(); + }, + onError: function(e) { + alert('JSON editor:' + e); + }, + onChange: function() { + var currentJSONString = materialEditor.getText(); + + if (currentJSONString === '{"":""}') { + return; + } + $('#materialdata-save').attr('disabled', false); + + + } + }; + materialEditor = new JSONEditor(container, options); +} + +function hideNewJSONMaterialEditorButton() { + $('#materialdata-new-editor').hide(); +} + +function showSaveMaterialDataButton() { + $('#materialdata-save').show(); +} + +function hideSaveMaterialDataButton() { + $('#materialdata-save').hide(); +} + +function showNewJSONMaterialEditorButton() { + $('#materialdata-new-editor').show(); +} + +function showMaterialDataTextArea() { + $('#property-material-data').show(); +} + +function hideMaterialDataTextArea() { + $('#property-material-data').hide(); +} + +function showStaticMaterialData() { + if (materialEditor !== null) { + $('#static-materialdata').show(); + $('#static-materialdata').css('height', $('#materialdata-editor').height()); + $('#static-materialdata').text(materialEditor.getText()); + } +} + +function removeStaticMaterialData() { + $('#static-materialdata').hide(); +} + +function setMaterialEditorJSON(json) { + materialEditor.set(json); + if (materialEditor.hasOwnProperty('expandAll')) { + materialEditor.expandAll(); + } +} + +function getMaterialEditorJSON() { + return materialEditor.get(); +} + +function deleteJSONMaterialEditor() { + if (materialEditor !== null) { + materialEditor.destroy(); + materialEditor = null; + } +} + +var savedMaterialJSONTimer = null; + +function saveJSONMaterialData(noUpdate) { + setMaterialDataFromEditor(noUpdate); + $('#materialdata-saved').show(); + $('#materialdata-save').attr('disabled', true); + if (savedMaterialJSONTimer !== null) { + clearTimeout(savedMaterialJSONTimer); + } + savedMaterialJSONTimer = setTimeout(function() { + $('#materialdata-saved').hide(); + + }, EDITOR_TIMEOUT_DURATION); +} + var editor = null; -var editorTimeout = null; -var lastJSONString = null; function createJSONEditor() { var container = document.getElementById("userdata-editor"); @@ -395,11 +525,6 @@ function createJSONEditor() { function hideNewJSONEditorButton() { $('#userdata-new-editor').hide(); - -} - -function hideClearUserDataButton() { - $('#userdata-clear').hide(); } function showSaveUserDataButton() { @@ -408,17 +533,10 @@ function showSaveUserDataButton() { function hideSaveUserDataButton() { $('#userdata-save').hide(); - } function showNewJSONEditorButton() { $('#userdata-new-editor').show(); - -} - -function showClearUserDataButton() { - $('#userdata-clear').show(); - } function showUserDataTextArea() { @@ -446,7 +564,6 @@ function setEditorJSON(json) { if (editor.hasOwnProperty('expandAll')) { editor.expandAll(); } - } function getEditorJSON() { @@ -484,12 +601,15 @@ function bindAllNonJSONEditorElements() { // TODO FIXME: (JSHint) Functions declared within loops referencing // an outer scoped variable may lead to confusing semantics. field.on('focus', function(e) { - if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear") { + if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear" || e.target.id === "materialdata-new-editor" || e.target.id === "materialdata-clear") { return; } else { if ($('#userdata-editor').css('height') !== "0px") { saveJSONUserData(true); } + if ($('#materialdata-editor').css('height') !== "0px") { + saveJSONMaterialData(true); + } } }); } @@ -652,6 +772,10 @@ function loaded() { var elMaterialMappingScaleX = document.getElementById("property-material-mapping-scale-x"); var elMaterialMappingScaleY = document.getElementById("property-material-mapping-scale-y"); var elMaterialMappingRot = document.getElementById("property-material-mapping-rot"); + var elMaterialData = document.getElementById("property-material-data"); + var elClearMaterialData = document.getElementById("materialdata-clear"); + var elSaveMaterialData = document.getElementById("materialdata-save"); + var elNewJSONMaterialEditor = document.getElementById('materialdata-new-editor'); var elImageURL = document.getElementById("property-image-url"); @@ -772,9 +896,15 @@ function loaded() { } else if (data.type === "update") { if (!data.selections || data.selections.length === 0) { - if (editor !== null && lastEntityID !== null) { - saveJSONUserData(true); - deleteJSONEditor(); + if (lastEntityID !== null) { + if (editor !== null) { + saveJSONUserData(true); + deleteJSONEditor(); + } + if (materialEditor !== null) { + saveJSONMaterialData(true); + deleteJSONMaterialEditor(); + } } elTypeIcon.style.display = "none"; elType.innerHTML = "No selection"; @@ -783,6 +913,7 @@ function loaded() { disableProperties(); } else if (data.selections && data.selections.length > 1) { deleteJSONEditor(); + deleteJSONMaterialEditor(); var selections = data.selections; var ids = []; @@ -815,8 +946,13 @@ function loaded() { } else { properties = data.selections[0].properties; - if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) { - saveJSONUserData(true); + if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null) { + if (editor !== null) { + saveJSONUserData(true); + } + if (materialEditor !== null) { + saveJSONMaterialData(true); + } } var doSelectElement = lastEntityID === '"' + properties.id + '"'; @@ -993,6 +1129,28 @@ function loaded() { hideNewJSONEditorButton(); } + var materialJson = null; + try { + materialJson = JSON.parse(properties.materialData); + } catch (e) { + // normal text + deleteJSONMaterialEditor(); + elMaterialData.value = properties.materialData; + showMaterialDataTextArea(); + showNewJSONMaterialEditorButton(); + hideSaveMaterialDataButton(); + } + if (materialJson !== null) { + if (materialEditor === null) { + createJSONMaterialEditor(); + } + + setMaterialEditorJSON(materialJson); + showSaveMaterialDataButton(); + hideMaterialDataTextArea(); + hideNewJSONMaterialEditorButton(); + } + elHyperlinkHref.value = properties.href; elDescription.value = properties.description; @@ -1200,6 +1358,7 @@ function loaded() { } else { enableProperties(); elSaveUserData.disabled = true; + elSaveMaterialData.disabled = true; } var activeElement = document.activeElement; @@ -1384,6 +1543,31 @@ function loaded() { showSaveUserDataButton(); }); + elClearMaterialData.addEventListener("click", function() { + deleteJSONMaterialEditor(); + elMaterialData.value = ""; + showMaterialDataTextArea(); + showNewJSONMaterialEditorButton(); + hideSaveMaterialDataButton(); + updateProperty('materialData', elMaterialData.value); + }); + + elSaveMaterialData.addEventListener("click", function() { + saveJSONMaterialData(true); + }); + + elMaterialData.addEventListener('change', createEmitTextPropertyUpdateFunction('materialData')); + + elNewJSONMaterialEditor.addEventListener('click', function() { + deleteJSONMaterialEditor(); + createJSONMaterialEditor(); + var data = {}; + setMaterialEditorJSON(data); + hideMaterialDataTextArea(); + hideNewJSONMaterialEditorButton(); + showSaveMaterialDataButton(); + }); + var colorChangeFunction = createEmitColorPropertyUpdateFunction( 'color', elColorRed, elColorGreen, elColorBlue); elColorRed.addEventListener('change', colorChangeFunction); diff --git a/tools/bake-tools/bake.py b/tools/bake-tools/bake.py index cad638c911..edbfdf9e9f 100644 --- a/tools/bake-tools/bake.py +++ b/tools/bake-tools/bake.py @@ -44,26 +44,35 @@ def groupKTXFiles(directory, filePath): originalFilePath.strip() shutil.move(originalFilePath, newFilePath) -def bakeFile(filePath, outputDirectory): +def bakeFile(filePath, outputDirectory, fileType): createDirectory(outputDirectory) - cmd = EXE + ' -i ' + filePath + ' -o ' + outputDirectory + ' -t fbx' + cmd = EXE + ' -i ' + filePath + ' -o ' + outputDirectory + ' -t ' + fileType args = shlex.split(cmd) process = subprocess.Popen(cmd, stdout=False, stderr=False) process.wait() bakedFile = os.path.splitext(filePath)[0] - groupKTXFiles(outputDirectory, bakedFile) + if fileType == 'fbx': + groupKTXFiles(outputDirectory, bakedFile) def bakeFilesInDirectory(directory, outputDirectory): rootDirectory = os.path.basename(os.path.normpath(directory)) for root, subFolders, filenames in os.walk(directory): for filename in filenames: appendPath = getRelativePath(directory, root, rootDirectory); + name, ext = os.path.splitext('file.txt') if filename.endswith('.fbx'): filePath = os.sep.join([root, filename]) absFilePath = os.path.abspath(filePath) outputFolder = os.path.join(outputDirectory, appendPath) print "Baking file: " + filename - bakeFile(absFilePath, outputFolder) + bakeFile(absFilePath, outputFolder, 'fbx') + elif os.path.basename(root) == 'skyboxes': + filePath = os.sep.join([root, filename]) + absFilePath = os.path.abspath(filePath) + outputFolder = os.path.join(outputDirectory, appendPath) + print "Baking file: " + filename + bakeType = os.path.splitext(filename)[1][1:] + bakeFile(absFilePath, outputFolder, bakeType) else: filePath = os.sep.join([root, filename]) absFilePath = os.path.abspath(filePath) diff --git a/tools/bake-tools/convertToRelativePaths.py b/tools/bake-tools/convertToRelativePaths.py index 27a7b7ac02..70a6a30cfb 100644 --- a/tools/bake-tools/convertToRelativePaths.py +++ b/tools/bake-tools/convertToRelativePaths.py @@ -6,7 +6,7 @@ def createAssetMapping(assetDirectory): baseDirectory = os.path.basename(os.path.normpath(assetDirectory)) for root, subfolder, filenames in os.walk(assetDirectory): for filename in filenames: - if not filename.endswith('.ktx'): + if not filename.endswith('.ktx') or os.path.basename(root) == 'skyboxes': substring = os.path.commonprefix([assetDirectory, root]) newPath = root.replace(substring, ''); filePath = os.sep.join([newPath, filename]) @@ -30,7 +30,7 @@ def handleURL(url): baseFilename = os.path.basename(url) filename = os.path.splitext(baseFilename)[0] newUrl = MAP[filename] - print newUrl + print url + ' -> ' + newUrl return newUrl def handleOptions(): @@ -43,8 +43,12 @@ def main(): argsLength = len(sys.argv) if argsLength == 3: jsonFile = sys.argv[1] - gzipFile = jsonFile + '.gz' assetDirectory = sys.argv[2] + inputFilename = os.path.basename(jsonFile); + absPath = os.path.abspath(assetDirectory) + finalPath = absPath.replace('\\', '/'); + gzipFile = finalPath + '/' + inputFilename + '.gz' + print gzipFile createAssetMapping(assetDirectory) f = open(jsonFile) data = json.load(f) @@ -65,6 +69,15 @@ def main(): except: value = handleURL(value) + + if prop == "ambientLight": + for index in value: + value[index] = handleURL(value[index]) + + if prop == "skybox": + for index in value: + value[index] = handleURL(value[index]) + if prop == "serverScripts": value = handleURL(value)