Merge branch 'master' of github.com:highfidelity/hifi into feat/hasScriptedBlendshapes

This commit is contained in:
Thijs Wenker 2018-04-13 23:33:02 +02:00
commit 22e7f80356
47 changed files with 828 additions and 201 deletions

View file

@ -1,7 +1,7 @@
### Dependencies ### Dependencies
- [cmake](https://cmake.org/download/): 3.9 - [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. - [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) - [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. 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/qt/5.10.1/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/Cellar/qt5/5.10.1/lib/cmake
export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
#### Generating build files #### 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: 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 #### Finding Dependencies

View file

@ -14,8 +14,8 @@ Should you choose not to install Qt5 via a package manager that handles dependen
Install qt: Install qt:
```bash ```bash
wget http://debian.highfidelity.com/pool/h/hi/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.6.1_5.6.1_amd64.deb sudo dpkg -i hifi-qt5.10.1_5.10.1_amd64.deb
``` ```
Install build dependencies: Install build dependencies:
@ -66,7 +66,7 @@ cd hifi/build
Prepare makefiles: Prepare makefiles:
```bash ```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: 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 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 ### Running the software

View file

@ -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. 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: 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. 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.

View file

@ -1,13 +1,13 @@
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit. This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
## Building High Fidelity ## 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. 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 ### Step 1. Visual Studio 2017
If you dont have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/). If you dont 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. 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 ### 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 ### Step 4. Setting Qt Environment Variable
Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search). 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 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) ### 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` * 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` * 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 ### Step 7. Running CMake to Generate Build Files
Run Command Prompt from Start and run the following commands: Run Command Prompt from Start and run the following commands:
@ -49,7 +49,7 @@ mkdir build
cd build cd build
cmake .. -G "Visual Studio 15 Win64" cmake .. -G "Visual Studio 15 Win64"
``` ```
Where `%HIFI_DIR%` is the directory for the highfidelity repository. Where `%HIFI_DIR%` is the directory for the highfidelity repository.
### Step 8. Making a Build ### 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 ## 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 * Delete your locally cloned copy of the highfidelity repository
* Restart your computer * Restart your computer
* Redownload the [repository](https://github.com/highfidelity/hifi) * Redownload the [repository](https://github.com/highfidelity/hifi)
* Restart directions from Step #7 * Restart directions from Step #7
#### CMake gives you the same error message repeatedly after the build fails #### 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 #### 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.

View file

@ -322,8 +322,16 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU
// stereo sources are not passed through HRTF // stereo sources are not passed through HRTF
if (streamToAdd.isStereo()) { 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; ++stats.manualStereoMixes;
@ -332,10 +340,13 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU
// echo sources are not passed through HRTF // echo sources are not passed through HRTF
if (isEcho) { 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); const float scale = 1/32768.0f; // int16_t to float
_mixSamples[i] += monoSample;
_mixSamples[i + 1] += monoSample; 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; ++stats.manualEchoMixes;

View file

@ -1,10 +1,10 @@
# #
# Created by Bradley Austin Davis on 2017/09/02 # Created by Bradley Austin Davis on 2017/09/02
# Copyright 2013-2017 High Fidelity, Inc. # Copyright 2013-2017 High Fidelity, Inc.
# #
# Distributed under the Apache License, Version 2.0. # Distributed under the Apache License, Version 2.0.
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html # 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 # Construct a default QT location from a root path, a version and an architecture
function(calculate_default_qt_dir _RESULT_NAME) function(calculate_default_qt_dir _RESULT_NAME)
@ -27,7 +27,7 @@ function(calculate_default_qt_dir _RESULT_NAME)
endif() endif()
set_from_env(QT_ROOT QT_ROOT ${QT_DEFAULT_ROOT}) 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_from_env(QT_ARCH QT_ARCH ${QT_DEFAULT_ARCH})
set(${_RESULT_NAME} "${QT_ROOT}/${QT_VERSION}/${QT_ARCH}" PARENT_SCOPE) 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") #if (NOT EXISTS "${QT_DIR}/include/QtCore/QtGlobal")
# message(FATAL_ERROR "Unable to locate Qt includes in ${QT_DIR}") # message(FATAL_ERROR "Unable to locate Qt includes in ${QT_DIR}")
#endif() #endif()
if (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake") if (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake")
message(FATAL_ERROR "Unable to locate Qt cmake config in ${QT_CMAKE_PREFIX_PATH}") message(FATAL_ERROR "Unable to locate Qt cmake config in ${QT_CMAKE_PREFIX_PATH}")
endif() endif()
message(STATUS "The Qt build in use is: \"${QT_DIR}\"") message(STATUS "The Qt build in use is: \"${QT_DIR}\"")
# Instruct CMake to run moc automatically when needed. # Instruct CMake to run moc automatically when needed.
@ -72,7 +72,7 @@ macro(setup_qt)
# Instruct CMake to run rcc automatically when needed # Instruct CMake to run rcc automatically when needed
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
if (WIN32) if (WIN32)
add_paths_to_fixup_libs("${QT_DIR}/bin") add_paths_to_fixup_libs("${QT_DIR}/bin")
endif () endif ()

View file

@ -324,6 +324,18 @@ FocusScope {
return false; 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) { function setPinned(newPinned) {
pinned = newPinned pinned = newPinned
} }

View file

@ -225,8 +225,8 @@
#ifdef DEBUG_EVENT_QUEUE #ifdef DEBUG_EVENT_QUEUE
// This is a HACK that uses private headers included with the qt source distrubution. // 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: // 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.10.1/Src/qtbase/include/QtCore/5.10.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
#define QT_BOOTSTRAPPED #define QT_BOOTSTRAPPED
#include <private/qthread_p.h> #include <private/qthread_p.h>
#include <private/qobject_p.h> #include <private/qobject_p.h>
@ -2038,7 +2038,7 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
}); });
_snapshotSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/snap.wav")); _snapshotSound = DependencyManager::get<SoundCache>()->getSound(PathUtils::resourcesUrl("sounds/snap.wav"));
QVariant testProperty = property(hifi::properties::TEST); QVariant testProperty = property(hifi::properties::TEST);
qDebug() << testProperty; qDebug() << testProperty;
if (testProperty.isValid()) { if (testProperty.isValid()) {
@ -6577,7 +6577,7 @@ void Application::addAssetToWorldFromURL(QString url) {
} else { } else {
filename.remove(".zip"); filename.remove(".zip");
} }
} }
if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) { if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) {
@ -6751,7 +6751,7 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q
addAssetToWorldError(filenameFromPath(filePath), errorInfo); addAssetToWorldError(filenameFromPath(filePath), errorInfo);
} else { } else {
// to prevent files that aren't models or texture files from being loaded into world automatically // 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)) && ((filePath.toLower().endsWith(JPG_EXTENSION) || filePath.toLower().endsWith(PNG_EXTENSION)) &&
((!isBlocks) && (!isZip)))) { ((!isBlocks) && (!isZip)))) {
addAssetToWorldAddEntity(filePath, mapping); addAssetToWorldAddEntity(filePath, mapping);
@ -7400,8 +7400,8 @@ bool Application::isThrottleRendering() const {
bool Application::hasFocus() const { bool Application::hasFocus() const {
bool result = (QApplication::activeWindow() != nullptr); bool result = (QApplication::activeWindow() != nullptr);
#if defined(Q_OS_WIN) #if defined(Q_OS_WIN)
// On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't // 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 // take user focus away from their current window. So also check whether the application is the user's current foreground
// window. // window.
result = result && (HWND)QApplication::activeWindow()->winId() == GetForegroundWindow(); result = result && (HWND)QApplication::activeWindow()->winId() == GetForegroundWindow();
#endif #endif
@ -7409,7 +7409,7 @@ bool Application::hasFocus() const {
} }
void Application::setFocus() { 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. // flashes the taskbar icon.
auto window = qApp->getWindow(); auto window = qApp->getWindow();
window->activateWindow(); window->activateWindow();
@ -7650,7 +7650,7 @@ void Application::updateDisplayMode() {
menu->setIsOptionChecked(MenuOption::FirstPerson, true); menu->setIsOptionChecked(MenuOption::FirstPerson, true);
cameraMenuChanged(); cameraMenuChanged();
} }
// Remove the mirror camera option from menu if in HMD mode // Remove the mirror camera option from menu if in HMD mode
auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror); auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror);
mirrorAction->setVisible(!isHmd); mirrorAction->setVisible(!isHmd);

View file

@ -35,7 +35,19 @@ ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
_url(modelOverlay->_url), _url(modelOverlay->_url),
_updateModel(false), _updateModel(false),
_scaleToFit(modelOverlay->_scaleToFit), _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); _model->setLoadingPriority(_loadPriority);
if (_url.isValid()) { if (_url.isValid()) {
@ -341,20 +353,25 @@ vectorType ModelOverlay::mapJoints(mapFunction<itemType> function) const {
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint". * <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
* *
* @property {string} url - The URL of the FBX or OBJ model used for the overlay. * @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: <code>size</code>. * @property {Vec3} dimensions - The dimensions of the overlay. Synonym: <code>size</code>.
* @property {Vec3} scale - The scale factor applied to the model's dimensions. * @property {Vec3} scale - The scale factor applied to the model's dimensions.
* @property {object.<name, url>} textures - Maps the named textures in the model to the JPG or PNG images in the urls. * @property {object.<name, url>} textures - Maps the named textures in the model to the JPG or PNG images in the urls.
* @property {Array.<string>} jointNames - The names of the joints - if any - in the model. <em>Read-only</em> * @property {Array.<string>} jointNames - The names of the joints - if any - in the model. <em>Read-only.</em>
* @property {Array.<Quat>} jointRotations - The relative rotations of the model's joints. * @property {Array.<Quat>} jointRotations - The relative rotations of the model's joints. <em>Not copied if overlay is
* @property {Array.<Vec3>} jointTranslations - The relative translations of the model's joints. * cloned.</em>
* @property {Array.<Vec3>} jointTranslations - The relative translations of the model's joints. <em>Not copied if overlay is
* cloned.</em>
* @property {Array.<Quat>} jointOrientations - The absolute orientations of the model's joints, in world coordinates. * @property {Array.<Quat>} jointOrientations - The absolute orientations of the model's joints, in world coordinates.
* <em>Read-only</em> * <em>Read-only.</em>
* @property {Array.<Vec3>} jointPositions - The absolute positions of the model's joints, in world coordinates. * @property {Array.<Vec3>} jointPositions - The absolute positions of the model's joints, in world coordinates.
* <em>Read-only</em> * <em>Read-only.</em>
* @property {string} animationSettings.url="" - The URL of an FBX file containing an animation to play. * @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.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.firstFrame=0 - The frame to start playing at.
* @property {number} animationSettings.lastFrame=0 - The frame to finish 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.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.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 * @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 (property == "jointNames") {
if (_model && _model->isActive()) { if (_model && _model->isActive()) {
// note: going through Rig because Model::getJointNames() (which proxies to FBXGeometry) was always empty // note: going through Rig because Model::getJointNames() (which proxies to FBXGeometry) was always empty

View file

@ -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_SCALE = QStringLiteral("scale");
static const QString JSON_AVATAR_VERSION = QStringLiteral("version"); static const QString JSON_AVATAR_VERSION = QStringLiteral("version");
static const int JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION = 0; enum class JsonAvatarFrameVersion : int {
static const int JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION = 1; JointRotationsInRelativeFrame = 0,
JointRotationsInAbsoluteFrame,
JointDefaultPoseBits
};
QJsonValue toJsonValue(const JointData& joint) { QJsonValue toJsonValue(const JointData& joint) {
QJsonArray result; QJsonArray result;
result.push_back(toJsonValue(joint.rotation)); result.push_back(toJsonValue(joint.rotation));
result.push_back(toJsonValue(joint.translation)); result.push_back(toJsonValue(joint.translation));
result.push_back(QJsonValue(joint.rotationIsDefaultPose));
result.push_back(QJsonValue(joint.translationIsDefaultPose));
return result; return result;
} }
JointData jointDataFromJsonValue(const QJsonValue& json) { JointData jointDataFromJsonValue(int version, const QJsonValue& json) {
JointData result; JointData result;
if (json.isArray()) { if (json.isArray()) {
QJsonArray array = json.toArray(); QJsonArray array = json.toArray();
result.rotation = quatFromJsonValue(array[0]); result.rotation = quatFromJsonValue(array[0]);
result.rotationIsDefaultPose = false;
result.translation = vec3FromJsonValue(array[1]); 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; return result;
} }
@ -2084,7 +2094,7 @@ JointData jointDataFromJsonValue(const QJsonValue& json) {
QJsonObject AvatarData::toJson() const { QJsonObject AvatarData::toJson() const {
QJsonObject root; QJsonObject root;
root[JSON_AVATAR_VERSION] = JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION; root[JSON_AVATAR_VERSION] = (int)JsonAvatarFrameVersion::JointDefaultPoseBits;
if (!getSkeletonModelURL().isEmpty()) { if (!getSkeletonModelURL().isEmpty()) {
root[JSON_AVATAR_BODY_MODEL] = getSkeletonModelURL().toString(); 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(); version = json[JSON_AVATAR_VERSION].toInt();
} else { } else {
// initial data did not have a version field. // 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)) { 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 (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, // because we don't have the full joint hierarchy skeleton of the model,
// we can't properly convert from relative rotations into absolute rotations. // we can't properly convert from relative rotations into absolute rotations.
quint64 now = usecTimestampNow(); quint64 now = usecTimestampNow();
@ -2248,7 +2258,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray(); QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray();
jointArray.reserve(jointArrayJson.size()); jointArray.reserve(jointArrayJson.size());
for (const auto& jointJson : jointArrayJson) { for (const auto& jointJson : jointArrayJson) {
auto joint = jointDataFromJsonValue(jointJson); auto joint = jointDataFromJsonValue(version, jointJson);
jointArray.push_back(joint); jointArray.push_back(joint);
} }
setRawJointData(jointArray); setRawJointData(jointArray);
@ -2559,4 +2569,4 @@ void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap&
value[EntityID] = binaryEntityProperties; value[EntityID] = binaryEntityProperties;
} }
} }

View file

@ -18,7 +18,7 @@ bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP
if (entity->getMaterial() != _drawMaterial) { if (entity->getMaterial() != _drawMaterial) {
return true; return true;
} }
if (entity->getParentID() != _parentID || entity->getClientOnly() != _clientOnly || entity->getOwningAvatarID() != _owningAvatarID) { if (entity->getParentID() != _parentID) {
return true; return true;
} }
if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) { if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) {
@ -31,8 +31,6 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
withWriteLock([&] { withWriteLock([&] {
_drawMaterial = entity->getMaterial(); _drawMaterial = entity->getMaterial();
_parentID = entity->getParentID(); _parentID = entity->getParentID();
_clientOnly = entity->getClientOnly();
_owningAvatarID = entity->getOwningAvatarID();
_materialMappingPos = entity->getMaterialMappingPos(); _materialMappingPos = entity->getMaterialMappingPos();
_materialMappingScale = entity->getMaterialMappingScale(); _materialMappingScale = entity->getMaterialMappingScale();
_materialMappingRot = entity->getMaterialMappingRot(); _materialMappingRot = entity->getMaterialMappingRot();
@ -102,7 +100,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
graphics::MaterialPointer drawMaterial; graphics::MaterialPointer drawMaterial;
Transform textureTransform; Transform textureTransform;
withReadLock([&] { withReadLock([&] {
parentID = _clientOnly ? _owningAvatarID : _parentID; parentID = _parentID;
renderTransform = _renderTransform; renderTransform = _renderTransform;
drawMaterial = _drawMaterial; drawMaterial = _drawMaterial;
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0)); textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));

View file

@ -32,8 +32,6 @@ private:
ShapeKey getShapeKey() override; ShapeKey getShapeKey() override;
QUuid _parentID; QUuid _parentID;
bool _clientOnly;
QUuid _owningAvatarID;
glm::vec2 _materialMappingPos; glm::vec2 _materialMappingPos;
glm::vec2 _materialMappingScale; glm::vec2 _materialMappingScale;
float _materialMappingRot; float _materialMappingRot;

View file

@ -363,6 +363,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_POS, materialMappingPos); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_POS, materialMappingPos);
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_DATA, materialData);
// Certifiable Properties // Certifiable Properties
CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName); 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_ACTION_DATA, actionData);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
// Certifiable Properties // Certifiable Properties
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ITEM_NAME, itemName); 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_SPREAD, colorSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_START, colorStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_START, colorStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_FINISH, colorFinish); 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_SPREAD, alphaSpread);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish); 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_POS, materialMappingPos);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_DATA, materialData);
} }
/**jsdoc /**jsdoc
@ -1539,6 +1541,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingPos, glmVec2, setMaterialMappingPos); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingPos, glmVec2, setMaterialMappingPos);
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, glmVec2, setMaterialMappingScale); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, glmVec2, setMaterialMappingScale);
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot);
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData);
// Certifiable Properties // Certifiable Properties
COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName); 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_POS, MaterialMappingPos, materialMappingPos, glmVec2);
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, 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_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float);
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_DATA, MaterialData, materialData, QString);
// Certifiable Properties // Certifiable Properties
ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString); 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_POS, properties.getMaterialMappingPos());
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, properties.getMaterialMappingScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, properties.getMaterialMappingScale());
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, properties.getMaterialMappingRot()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, properties.getMaterialMappingRot());
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, properties.getMaterialData());
} }
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName()); 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_POS, glmVec2, setMaterialMappingPos);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_SCALE, glmVec2, setMaterialMappingScale); 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_MAPPING_ROT, float, setMaterialMappingRot);
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_DATA, QString, setMaterialData);
} }
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
@ -2849,6 +2855,7 @@ void EntityItemProperties::markAllChanged() {
_materialMappingPosChanged = true; _materialMappingPosChanged = true;
_materialMappingScaleChanged = true; _materialMappingScaleChanged = true;
_materialMappingRotChanged = true; _materialMappingRotChanged = true;
_materialDataChanged = true;
// Certifiable Properties // Certifiable Properties
_itemNameChanged = true; _itemNameChanged = true;
@ -3200,6 +3207,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
if (materialMappingRotChanged()) { if (materialMappingRotChanged()) {
out += "materialMappingRot"; out += "materialMappingRot";
} }
if (materialDataChanged()) {
out += "materialData";
}
// Certifiable Properties // Certifiable Properties
if (itemNameChanged()) { if (itemNameChanged()) {

View file

@ -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_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_SCALE, MaterialMappingScale, materialMappingScale, glmVec2, glm::vec2(1, 1));
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0); 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 // Certifiable Properties - related to Proof of Purchase certificates
DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME); DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME);

View file

@ -240,6 +240,7 @@ enum EntityPropertyList {
PROP_MATERIAL_MAPPING_POS, PROP_MATERIAL_MAPPING_POS,
PROP_MATERIAL_MAPPING_SCALE, PROP_MATERIAL_MAPPING_SCALE,
PROP_MATERIAL_MAPPING_ROT, PROP_MATERIAL_MAPPING_ROT,
PROP_MATERIAL_DATA,
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
// ATTENTION: add new properties to end of list just ABOVE this line // ATTENTION: add new properties to end of list just ABOVE this line

View file

@ -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); EntityItemPointer entity = addEntity(entityItemID, properties);
if (!entity) { if (!entity) {
qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType(); qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType();

View file

@ -27,6 +27,10 @@ MaterialEntityItem::MaterialEntityItem(const EntityItemID& entityItemID) : Entit
_type = EntityTypes::Material; _type = EntityTypes::Material;
} }
MaterialEntityItem::~MaterialEntityItem() {
removeMaterial();
}
EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL); 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(materialMappingPos, getMaterialMappingPos);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingScale, getMaterialMappingScale); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingScale, getMaterialMappingScale);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingRot, getMaterialMappingRot); COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingRot, getMaterialMappingRot);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialData, getMaterialData);
return properties; return properties;
} }
@ -49,6 +54,7 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) {
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingPos, setMaterialMappingPos); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingPos, setMaterialMappingPos);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingScale, setMaterialMappingScale); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingScale, setMaterialMappingScale);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingRot, setMaterialMappingRot); SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingRot, setMaterialMappingRot);
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialData, setMaterialData);
if (somethingChanged) { if (somethingChanged) {
bool wantDebug = false; 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_POS, glm::vec2, setMaterialMappingPos);
READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, glm::vec2, setMaterialMappingScale); READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, glm::vec2, setMaterialMappingScale);
READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot); READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot);
READ_ENTITY_PROPERTY(PROP_MATERIAL_DATA, QString, setMaterialData);
return bytesRead; return bytesRead;
} }
@ -93,6 +100,7 @@ EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParam
requestedProperties += PROP_MATERIAL_MAPPING_POS; requestedProperties += PROP_MATERIAL_MAPPING_POS;
requestedProperties += PROP_MATERIAL_MAPPING_SCALE; requestedProperties += PROP_MATERIAL_MAPPING_SCALE;
requestedProperties += PROP_MATERIAL_MAPPING_ROT; requestedProperties += PROP_MATERIAL_MAPPING_ROT;
requestedProperties += PROP_MATERIAL_DATA;
return requestedProperties; 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_POS, getMaterialMappingPos());
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, getMaterialMappingScale()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, getMaterialMappingScale());
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, getMaterialMappingRot()); APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, getMaterialMappingRot());
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, getMaterialData());
} }
void MaterialEntityItem::debugDump() const { void MaterialEntityItem::debugDump() const {
@ -145,9 +154,9 @@ std::shared_ptr<NetworkMaterial> MaterialEntityItem::getMaterial() const {
} }
} }
void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool userDataChanged) { void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool materialDataChanged) {
bool usingUserData = materialURLString.startsWith("userData"); bool usingMaterialData = materialDataChanged || materialURLString.startsWith("materialData");
if (_materialURL != materialURLString || (usingUserData && userDataChanged)) { if (_materialURL != materialURLString || (usingMaterialData && materialDataChanged)) {
removeMaterial(); removeMaterial();
_materialURL = materialURLString; _materialURL = materialURLString;
@ -156,8 +165,8 @@ void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool u
_currentMaterialName = split.last().toStdString(); _currentMaterialName = split.last().toStdString();
} }
if (usingUserData) { if (usingMaterialData) {
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getUserData().toUtf8()), materialURLString); _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 // Since our material changed, the current name might not be valid anymore, so we need to update
setCurrentMaterialName(_currentMaterialName); setCurrentMaterialName(_currentMaterialName);
@ -191,11 +200,11 @@ void MaterialEntityItem::setCurrentMaterialName(const std::string& currentMateri
} }
} }
void MaterialEntityItem::setUserData(const QString& userData) { void MaterialEntityItem::setMaterialData(const QString& materialData) {
if (_userData != userData) { if (_materialData != materialData) {
EntityItem::setUserData(userData); _materialData = materialData;
if (_materialURL.startsWith("userData")) { if (_materialURL.startsWith("materialData")) {
// Trigger material update when user data changes // Trigger material update when material data changes
setMaterialURL(_materialURL, true); 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() { void MaterialEntityItem::removeMaterial() {
graphics::MaterialPointer material = getMaterial(); graphics::MaterialPointer material = getMaterial();
if (!material) { if (!material) {
return; return;
} }
QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID(); QUuid parentID = getParentID();
if (parentID.isNull()) { if (parentID.isNull()) {
return; return;
} }
@ -294,7 +287,7 @@ void MaterialEntityItem::removeMaterial() {
void MaterialEntityItem::applyMaterial() { void MaterialEntityItem::applyMaterial() {
_retryApply = false; _retryApply = false;
graphics::MaterialPointer material = getMaterial(); graphics::MaterialPointer material = getMaterial();
QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID(); QUuid parentID = getParentID();
if (!material || parentID.isNull()) { if (!material || parentID.isNull()) {
return; return;
} }
@ -328,11 +321,6 @@ void MaterialEntityItem::postParentFixup() {
applyMaterial(); applyMaterial();
} }
void MaterialEntityItem::preDelete() {
EntityItem::preDelete();
removeMaterial();
}
void MaterialEntityItem::update(const quint64& now) { void MaterialEntityItem::update(const quint64& now) {
if (_retryApply) { if (_retryApply) {
applyMaterial(); applyMaterial();

View file

@ -21,6 +21,7 @@ public:
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties); static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
MaterialEntityItem(const EntityItemID& entityItemID); MaterialEntityItem(const EntityItemID& entityItemID);
~MaterialEntityItem();
ALLOW_INSTANTIATION // This class can be instantiated ALLOW_INSTANTIATION // This class can be instantiated
@ -53,7 +54,7 @@ public:
virtual void setUnscaledDimensions(const glm::vec3& value) override; virtual void setUnscaledDimensions(const glm::vec3& value) override;
QString getMaterialURL() const { return _materialURL; } 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); void setCurrentMaterialName(const std::string& currentMaterialName);
@ -73,21 +74,20 @@ public:
float getMaterialMappingRot() const { return _materialMappingRot; } float getMaterialMappingRot() const { return _materialMappingRot; }
void setMaterialMappingRot(const float& materialMappingRot); void setMaterialMappingRot(const float& materialMappingRot);
QString getMaterialData() const { return _materialData; }
void setMaterialData(const QString& materialData);
std::shared_ptr<NetworkMaterial> getMaterial() const; std::shared_ptr<NetworkMaterial> getMaterial() const;
void setUserData(const QString& userData) override;
void setParentID(const QUuid& parentID) override; void setParentID(const QUuid& parentID) override;
void setClientOnly(bool clientOnly) override;
void setOwningAvatarID(const QUuid& owningAvatarID) override;
void applyMaterial(); void applyMaterial();
void removeMaterial(); void removeMaterial();
void postParentFixup() override; void postParentFixup() override;
void preDelete() override;
private: 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: // The following fields are supported in the JSON:
// materialVersion: a uint for the version of this network material (currently, only 1 is supported) // 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: // 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 }; glm::vec2 _materialMappingScale { 1, 1 };
// How much to rotate this material within its parent's UV-space (degrees) // How much to rotate this material within its parent's UV-space (degrees)
float _materialMappingRot { 0 }; float _materialMappingRot { 0 };
QString _materialData;
NetworkMaterialResourcePointer _networkMaterial; NetworkMaterialResourcePointer _networkMaterial;
NetworkMaterialResource::ParsedMaterials _parsedMaterials; NetworkMaterialResource::ParsedMaterials _parsedMaterials;

View file

@ -117,8 +117,10 @@ ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem(
EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const { EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
properties.setColor(getXColor());
properties.setShape(entity::stringFromShape(getShape())); properties.setShape(entity::stringFromShape(getShape()));
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
return properties; return properties;
} }

View file

@ -105,7 +105,7 @@ public:
protected: protected:
float _alpha { 1 }; // FIXME: This property is not used. float _alpha { 1.0f };
rgbColor _color; rgbColor _color;
entity::Shape _shape { entity::Shape::Sphere }; entity::Shape _shape { entity::Shape::Sphere };

View file

@ -370,7 +370,36 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
case gpu::COMPRESSED_BC7_SRGBA: case gpu::COMPRESSED_BC7_SRGBA:
result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break; 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: default:
qCWarning(gpugllogging) << "Unknown combination of texel format"; qCWarning(gpugllogging) << "Unknown combination of texel format";
} }
@ -531,6 +560,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
case gpu::COMPRESSED_BC7_SRGBA: case gpu::COMPRESSED_BC7_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break; 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: default:
qCWarning(gpugllogging) << "Unknown combination of texel format"; qCWarning(gpugllogging) << "Unknown combination of texel format";
} }
@ -895,7 +954,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
case gpu::COMPRESSED_BC7_SRGBA: case gpu::COMPRESSED_BC7_SRGBA:
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM; texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
break; 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: default:
qCWarning(gpugllogging) << "Unknown combination of texel format"; qCWarning(gpugllogging) << "Unknown combination of texel format";
} }

View file

@ -173,6 +173,8 @@ protected:
void makeProgramBindings(ShaderObject& shaderObject) override; void makeProgramBindings(ShaderObject& shaderObject) override;
int makeResourceBufferSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override; int makeResourceBufferSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override;
static bool supportedTextureFormat(const gpu::Element& format);
}; };
} } } }

View file

@ -19,6 +19,24 @@ using namespace gpu;
using namespace gpu::gl; using namespace gpu::gl;
using namespace gpu::gl41; 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) { GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) {
if (!texturePointer) { if (!texturePointer) {
return nullptr; return nullptr;
@ -34,6 +52,11 @@ GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) {
return nullptr; return nullptr;
} }
// Check whether the texture is in a format we can deal with
if (!supportedTextureFormat(texture.getTexelFormat())) {
return nullptr;
}
GL41Texture* object = Backend::getGPUObject<GL41Texture>(texture); GL41Texture* object = Backend::getGPUObject<GL41Texture>(texture);
if (!object) { if (!object) {
switch (texture.getUsageType()) { switch (texture.getUsageType()) {

View file

@ -206,6 +206,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: 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, glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat,
static_cast<GLsizei>(sourceSize), sourcePointer); static_cast<GLsizei>(sourceSize), sourcePointer);
break; break;
@ -222,6 +232,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
case GL_COMPRESSED_RG_RGTC2: case GL_COMPRESSED_RG_RGTC2:
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM: case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: 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) { if (glCompressedTextureSubImage2DEXT) {
auto target = GLTexture::CUBE_FACE_LAYOUT[face]; auto target = GLTexture::CUBE_FACE_LAYOUT[face];
glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat, glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat,

View file

@ -20,9 +20,21 @@ using namespace gpu::gl;
using namespace gpu::gles; using namespace gpu::gles;
bool GLESBackend::supportedTextureFormat(const gpu::Element& format) { bool GLESBackend::supportedTextureFormat(const gpu::Element& format) {
// FIXME distinguish between GLES and GL compressed formats after support switch (format.getSemantic()) {
// for the former is added to gpu::Element case gpu::Semantic::COMPRESSED_ETC2_RGB:
return !format.isCompressed(); 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) { GLTexture* GLESBackend::syncGPUObject(const TexturePointer& texturePointer) {
@ -231,6 +243,29 @@ GLESFixedAllocationTexture::GLESFixedAllocationTexture(const std::weak_ptr<GLBac
GLESFixedAllocationTexture::~GLESFixedAllocationTexture() { GLESFixedAllocationTexture::~GLESFixedAllocationTexture() {
} }
GLsizei getCompressedImageSize(int width, int height, GLenum internalFormat) {
GLsizei blockSize;
switch (internalFormat) {
case GL_COMPRESSED_R11_EAC:
case GL_COMPRESSED_SIGNED_R11_EAC:
case GL_COMPRESSED_RGB8_ETC2:
case GL_COMPRESSED_SRGB8_ETC2:
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
blockSize = 8;
break;
case GL_COMPRESSED_RG11_EAC:
case GL_COMPRESSED_SIGNED_RG11_EAC:
case GL_COMPRESSED_RGBA8_ETC2_EAC:
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
default:
blockSize = 16;
}
// See https://www.khronos.org/registry/OpenGL-Refpages/es3.0/html/glCompressedTexImage2D.xhtml
return (GLsizei)ceil(width / 4.0f) * (GLsizei)ceil(height / 4.0f) * blockSize;
}
void GLESFixedAllocationTexture::allocateStorage() const { void GLESFixedAllocationTexture::allocateStorage() const {
const GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat()); const GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
const auto numMips = _gpuObject.getNumMips(); const auto numMips = _gpuObject.getNumMips();
@ -239,7 +274,12 @@ void GLESFixedAllocationTexture::allocateStorage() const {
for (GLint level = 0; level < numMips; level++) { for (GLint level = 0; level < numMips; level++) {
Vec3u dimensions = _gpuObject.evalMipDimensions(level); Vec3u dimensions = _gpuObject.evalMipDimensions(level);
for (GLenum target : getFaceTargets(_target)) { for (GLenum target : getFaceTargets(_target)) {
glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, texelFormat.type, nullptr); if (texelFormat.isCompressed()) {
glCompressedTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0,
getCompressedImageSize(dimensions.x, dimensions.y, texelFormat.internalFormat), nullptr);
} else {
glTexImage2D(target, level, texelFormat.internalFormat, dimensions.x, dimensions.y, 0, texelFormat.format, texelFormat.type, nullptr);
}
} }
} }

View file

@ -21,13 +21,24 @@ const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA };
const Element Element::COLOR_RGBA_2{ VEC4, NUINT2, RGBA }; const Element Element::COLOR_RGBA_2{ VEC4, NUINT2, RGBA };
const Element Element::COLOR_COMPRESSED_RED{ TILE4x4, COMPRESSED, COMPRESSED_BC4_RED }; const Element Element::COLOR_COMPRESSED_BCX_RED { TILE4x4, COMPRESSED, COMPRESSED_BC4_RED };
const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB }; const Element Element::COLOR_COMPRESSED_BCX_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB };
const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA }; const Element Element::COLOR_COMPRESSED_BCX_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };
const Element Element::COLOR_COMPRESSED_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA }; const Element Element::COLOR_COMPRESSED_BCX_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA };
const Element Element::COLOR_COMPRESSED_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY }; const Element Element::COLOR_COMPRESSED_BCX_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY };
const Element Element::COLOR_COMPRESSED_SRGBA_HIGH{ TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA }; const Element Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH { TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
const Element Element::COLOR_COMPRESSED_HDR_RGB{ TILE4x4, COMPRESSED, COMPRESSED_BC6_RGB }; const Element Element::COLOR_COMPRESSED_BCX_HDR_RGB { TILE4x4, COMPRESSED, COMPRESSED_BC6_RGB };
const Element Element::COLOR_COMPRESSED_ETC2_RGB { TILE4x4, COMPRESSED, COMPRESSED_ETC2_RGB };
const Element Element::COLOR_COMPRESSED_ETC2_SRGB { TILE4x4, COMPRESSED, COMPRESSED_ETC2_SRGB };
const Element Element::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA };
const Element Element::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA };
const Element Element::COLOR_COMPRESSED_ETC2_RGBA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_RGBA };
const Element Element::COLOR_COMPRESSED_ETC2_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_ETC2_SRGBA };
const Element Element::COLOR_COMPRESSED_EAC_RED { TILE4x4, COMPRESSED, COMPRESSED_EAC_RED };
const Element Element::COLOR_COMPRESSED_EAC_RED_SIGNED { TILE4x4, COMPRESSED, COMPRESSED_EAC_RED_SIGNED };
const Element Element::COLOR_COMPRESSED_EAC_XY { TILE4x4, COMPRESSED, COMPRESSED_EAC_XY };
const Element Element::COLOR_COMPRESSED_EAC_XY_SIGNED { TILE4x4, COMPRESSED, COMPRESSED_EAC_XY_SIGNED };
const Element Element::VEC2NU8_XY{ VEC2, NUINT8, XY }; const Element Element::VEC2NU8_XY{ VEC2, NUINT8, XY };

View file

@ -194,6 +194,17 @@ enum Semantic : uint8_t {
COMPRESSED_BC6_RGB, COMPRESSED_BC6_RGB,
COMPRESSED_BC7_SRGBA, COMPRESSED_BC7_SRGBA,
COMPRESSED_ETC2_RGB,
COMPRESSED_ETC2_SRGB,
COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA,
COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA,
COMPRESSED_ETC2_RGBA,
COMPRESSED_ETC2_SRGBA,
COMPRESSED_EAC_RED,
COMPRESSED_EAC_RED_SIGNED,
COMPRESSED_EAC_XY,
COMPRESSED_EAC_XY_SIGNED,
_LAST_COMPRESSED, _LAST_COMPRESSED,
R11G11B10, R11G11B10,
@ -249,6 +260,17 @@ static const int SEMANTIC_SIZE_FACTOR[NUM_SEMANTICS] = {
16, //COMPRESSED_BC6_RGB, 1 byte/pixel * 4x4 pixels = 16 bytes 16, //COMPRESSED_BC6_RGB, 1 byte/pixel * 4x4 pixels = 16 bytes
16, //COMPRESSED_BC7_SRGBA, 1 byte/pixel * 4x4 pixels = 16 bytes 16, //COMPRESSED_BC7_SRGBA, 1 byte/pixel * 4x4 pixels = 16 bytes
8, //COMPRESSED_ETC2_RGB,
8, //COMPRESSED_ETC2_SRGB,
8, //COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA,
8, //COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA,
16, //COMPRESSED_ETC2_RGBA,
16, //COMPRESSED_ETC2_SRGBA,
8, //COMPRESSED_EAC_RED,
8, //COMPRESSED_EAC_RED_SIGNED,
16, //COMPRESSED_EAC_XY,
16, //COMPRESSED_EAC_XY_SIGNED,
1, //_LAST_COMPRESSED, 1, //_LAST_COMPRESSED,
1, //R11G11B10, 1, //R11G11B10,
@ -316,13 +338,23 @@ public:
static const Element COLOR_RGBA_2; static const Element COLOR_RGBA_2;
static const Element COLOR_R11G11B10; static const Element COLOR_R11G11B10;
static const Element COLOR_RGB9E5; static const Element COLOR_RGB9E5;
static const Element COLOR_COMPRESSED_RED; static const Element COLOR_COMPRESSED_BCX_RED;
static const Element COLOR_COMPRESSED_SRGB; static const Element COLOR_COMPRESSED_BCX_SRGB;
static const Element COLOR_COMPRESSED_SRGBA_MASK; static const Element COLOR_COMPRESSED_BCX_SRGBA_MASK;
static const Element COLOR_COMPRESSED_SRGBA; static const Element COLOR_COMPRESSED_BCX_SRGBA;
static const Element COLOR_COMPRESSED_XY; static const Element COLOR_COMPRESSED_BCX_XY;
static const Element COLOR_COMPRESSED_SRGBA_HIGH; static const Element COLOR_COMPRESSED_BCX_SRGBA_HIGH;
static const Element COLOR_COMPRESSED_HDR_RGB; static const Element COLOR_COMPRESSED_BCX_HDR_RGB;
static const Element COLOR_COMPRESSED_ETC2_RGB;
static const Element COLOR_COMPRESSED_ETC2_SRGB;
static const Element COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA;
static const Element COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA;
static const Element COLOR_COMPRESSED_ETC2_RGBA;
static const Element COLOR_COMPRESSED_ETC2_SRGBA;
static const Element COLOR_COMPRESSED_EAC_RED;
static const Element COLOR_COMPRESSED_EAC_RED_SIGNED;
static const Element COLOR_COMPRESSED_EAC_XY;
static const Element COLOR_COMPRESSED_EAC_XY_SIGNED;
static const Element VEC2NU8_XY; static const Element VEC2NU8_XY;
static const Element VEC4F_COLOR_RGBA; static const Element VEC4F_COLOR_RGBA;
static const Element VEC2F_UV; static const Element VEC2F_UV;

View file

@ -128,6 +128,7 @@ public:
uint8 _wrapModeV = WRAP_REPEAT; uint8 _wrapModeV = WRAP_REPEAT;
uint8 _wrapModeW = WRAP_REPEAT; uint8 _wrapModeW = WRAP_REPEAT;
uint8 _mipOffset = 0;
uint8 _minMip = 0; uint8 _minMip = 0;
uint8 _maxMip = MAX_MIP_LEVEL; uint8 _maxMip = MAX_MIP_LEVEL;
@ -142,6 +143,7 @@ public:
_wrapModeU == other._wrapModeU && _wrapModeU == other._wrapModeU &&
_wrapModeV == other._wrapModeV && _wrapModeV == other._wrapModeV &&
_wrapModeW == other._wrapModeW && _wrapModeW == other._wrapModeW &&
_mipOffset == other._mipOffset &&
_minMip == other._minMip && _minMip == other._minMip &&
_maxMip == other._maxMip; _maxMip == other._maxMip;
} }
@ -164,6 +166,7 @@ public:
ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); } ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); }
bool doComparison() const { return getComparisonFunction() != ALWAYS; } bool doComparison() const { return getComparisonFunction() != ALWAYS; }
uint8 getMipOffset() const { return _desc._mipOffset; }
uint8 getMinMip() const { return _desc._minMip; } uint8 getMinMip() const { return _desc._minMip; }
uint8 getMaxMip() const { return _desc._maxMip; } uint8 getMaxMip() const { return _desc._maxMip; }

View file

@ -574,20 +574,40 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat::R8, ktx::GLBaseInternalFormat::RED); header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat::R8, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::VEC2NU8_XY && mipFormat == Format::VEC2NU8_XY) { } else if (texelFormat == Format::VEC2NU8_XY && mipFormat == Format::VEC2NU8_XY) {
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RG, ktx::GLInternalFormat::RG8, ktx::GLBaseInternalFormat::RG); header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RG, ktx::GLInternalFormat::RG8, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGB && mipFormat == Format::COLOR_COMPRESSED_SRGB) { } else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGB && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGB); header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_MASK && mipFormat == Format::COLOR_COMPRESSED_SRGBA_MASK) { } else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_MASK && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_MASK) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGBA); header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA && mipFormat == Format::COLOR_COMPRESSED_SRGBA) { } else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGBA && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGBA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, ktx::GLBaseInternalFormat::RGBA); header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_RED && mipFormat == Format::COLOR_COMPRESSED_RED) { } else if (texelFormat == Format::COLOR_COMPRESSED_BCX_RED && mipFormat == Format::COLOR_COMPRESSED_BCX_RED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RED_RGTC1, ktx::GLBaseInternalFormat::RED); header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RED_RGTC1, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::COLOR_COMPRESSED_XY && mipFormat == Format::COLOR_COMPRESSED_XY) { } else if (texelFormat == Format::COLOR_COMPRESSED_BCX_XY && mipFormat == Format::COLOR_COMPRESSED_BCX_XY) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RG_RGTC2, ktx::GLBaseInternalFormat::RG); header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RG_RGTC2, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH && mipFormat == Format::COLOR_COMPRESSED_SRGBA_HIGH) { } else if (texelFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH && mipFormat == Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA); header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_HDR_RGB && mipFormat == Format::COLOR_COMPRESSED_HDR_RGB) { } else if (texelFormat == Format::COLOR_COMPRESSED_BCX_HDR_RGB && mipFormat == Format::COLOR_COMPRESSED_BCX_HDR_RGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, ktx::GLBaseInternalFormat::RGB); header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_RGB && mipFormat == Format::COLOR_COMPRESSED_ETC2_RGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB8_ETC2, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_SRGB && mipFormat == Format::COLOR_COMPRESSED_ETC2_SRGB) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB8_ETC2, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA && mipFormat == Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA && mipFormat == Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_RGBA && mipFormat == Format::COLOR_COMPRESSED_ETC2_RGBA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RGBA8_ETC2_EAC, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_ETC2_SRGBA && mipFormat == Format::COLOR_COMPRESSED_ETC2_SRGBA) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, ktx::GLBaseInternalFormat::RGBA);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_RED && mipFormat == Format::COLOR_COMPRESSED_EAC_RED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_R11_EAC, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_RED_SIGNED && mipFormat == Format::COLOR_COMPRESSED_EAC_RED_SIGNED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SIGNED_R11_EAC, ktx::GLBaseInternalFormat::RED);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_XY && mipFormat == Format::COLOR_COMPRESSED_EAC_XY) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_RG11_EAC, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_COMPRESSED_EAC_XY_SIGNED && mipFormat == Format::COLOR_COMPRESSED_EAC_XY_SIGNED) {
header.setCompressed(ktx::GLInternalFormat::COMPRESSED_SIGNED_RG11_EAC, ktx::GLBaseInternalFormat::RG);
} else if (texelFormat == Format::COLOR_RGB9E5 && mipFormat == Format::COLOR_RGB9E5) { } else if (texelFormat == Format::COLOR_RGB9E5 && mipFormat == Format::COLOR_RGB9E5) {
header.setUncompressed(ktx::GLType::UNSIGNED_INT_5_9_9_9_REV, 1, ktx::GLFormat::RGB, ktx::GLInternalFormat::RGB9_E5, ktx::GLBaseInternalFormat::RGB); header.setUncompressed(ktx::GLType::UNSIGNED_INT_5_9_9_9_REV, 1, ktx::GLFormat::RGB, ktx::GLInternalFormat::RGB9_E5, ktx::GLBaseInternalFormat::RGB);
} else if (texelFormat == Format::COLOR_R11G11B10 && mipFormat == Format::COLOR_R11G11B10) { } else if (texelFormat == Format::COLOR_R11G11B10 && mipFormat == Format::COLOR_R11G11B10) {
@ -642,31 +662,45 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E
texelFormat = Format::COLOR_RGB9E5; texelFormat = Format::COLOR_RGB9E5;
} else if (header.isCompressed()) { } else if (header.isCompressed()) {
if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) { if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) {
mipFormat = Format::COLOR_COMPRESSED_SRGB; texelFormat = Format::COLOR_COMPRESSED_BCX_SRGB;
texelFormat = Format::COLOR_COMPRESSED_SRGB;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) { } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) {
mipFormat = Format::COLOR_COMPRESSED_SRGBA_MASK; texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_MASK;
texelFormat = Format::COLOR_COMPRESSED_SRGBA_MASK;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) { } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
mipFormat = Format::COLOR_COMPRESSED_SRGBA; texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA;
texelFormat = Format::COLOR_COMPRESSED_SRGBA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RED_RGTC1) { } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RED_RGTC1) {
mipFormat = Format::COLOR_COMPRESSED_RED; texelFormat = Format::COLOR_COMPRESSED_BCX_RED;
texelFormat = Format::COLOR_COMPRESSED_RED;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG_RGTC2) { } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG_RGTC2) {
mipFormat = Format::COLOR_COMPRESSED_XY; texelFormat = Format::COLOR_COMPRESSED_BCX_XY;
texelFormat = Format::COLOR_COMPRESSED_XY;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) { } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) {
mipFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH; texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH;
texelFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) { } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) {
mipFormat = Format::COLOR_COMPRESSED_HDR_RGB; texelFormat = Format::COLOR_COMPRESSED_BCX_HDR_RGB;
texelFormat = Format::COLOR_COMPRESSED_HDR_RGB; } else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB8_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_RGB;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGB;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGBA8_ETC2_EAC) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_RGBA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC) {
texelFormat = Format::COLOR_COMPRESSED_ETC2_SRGBA;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_R11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_RED;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SIGNED_R11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_RED_SIGNED;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_XY;
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SIGNED_RG11_EAC) {
texelFormat = Format::COLOR_COMPRESSED_EAC_XY_SIGNED;
} else { } else {
return false; return false;
} }
mipFormat = texelFormat;
} else { } else {
return false; return false;
} }
return true; return true;
} }

View file

@ -87,6 +87,17 @@ namespace gpu {
{ Semantic::COMPRESSED_BC6_RGB, "compressed_bc6_rgb" }, { Semantic::COMPRESSED_BC6_RGB, "compressed_bc6_rgb" },
{ Semantic::COMPRESSED_BC7_SRGBA, "compressed_bc7_srgba" }, { Semantic::COMPRESSED_BC7_SRGBA, "compressed_bc7_srgba" },
{ Semantic::COMPRESSED_ETC2_RGB, "compressed_etc2_rgb" },
{ Semantic::COMPRESSED_ETC2_SRGB, "compressed_etc2_srgb" },
{ Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA, "compressed_etc2_rgb_punchthrough_alpha" },
{ Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA, "compressed_etc2_srgb_punchthrough_alpha" },
{ Semantic::COMPRESSED_ETC2_RGBA, "compressed_etc2_rgba" },
{ Semantic::COMPRESSED_ETC2_SRGBA, "compressed_etc2_srgba" },
{ Semantic::COMPRESSED_EAC_RED, "compressed_eac_red" },
{ Semantic::COMPRESSED_EAC_RED_SIGNED, "compressed_eac_red_signed" },
{ Semantic::COMPRESSED_EAC_XY, "compressed_eac_xy" },
{ Semantic::COMPRESSED_EAC_XY_SIGNED, "compressed_eac_xy_signed" },
{ Semantic::_LAST_COMPRESSED, "_last_compressed" }, { Semantic::_LAST_COMPRESSED, "_last_compressed" },
{ Semantic::R11G11B10, "r11g11b10" }, { Semantic::R11G11B10, "r11g11b10" },

View file

@ -466,7 +466,8 @@ void generateHDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
nvtt::CompressionOptions compressionOptions; nvtt::CompressionOptions compressionOptions;
compressionOptions.setQuality(nvtt::Quality_Production); compressionOptions.setQuality(nvtt::Quality_Production);
if (mipFormat == gpu::Element::COLOR_COMPRESSED_HDR_RGB) { // TODO: gles: generate ETC mips instead?
if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB) {
compressionOptions.setFormat(nvtt::Format_BC6); compressionOptions.setFormat(nvtt::Format_BC6);
} else if (mipFormat == gpu::Element::COLOR_RGB9E5) { } else if (mipFormat == gpu::Element::COLOR_RGB9E5) {
compressionOptions.setFormat(nvtt::Format_RGB); compressionOptions.setFormat(nvtt::Format_RGB);
@ -583,20 +584,21 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
nvtt::CompressionOptions compressionOptions; nvtt::CompressionOptions compressionOptions;
compressionOptions.setQuality(nvtt::Quality_Production); compressionOptions.setQuality(nvtt::Quality_Production);
// TODO: gles: generate ETC mips instead?
auto mipFormat = texture->getStoredMipFormat(); auto mipFormat = texture->getStoredMipFormat();
if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGB) { if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGB) {
compressionOptions.setFormat(nvtt::Format_BC1); 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; alphaMode = nvtt::AlphaMode_Transparency;
compressionOptions.setFormat(nvtt::Format_BC1a); 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; alphaMode = nvtt::AlphaMode_Transparency;
compressionOptions.setFormat(nvtt::Format_BC3); 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); 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); 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; alphaMode = nvtt::AlphaMode_Transparency;
compressionOptions.setFormat(nvtt::Format_BC7); compressionOptions.setFormat(nvtt::Format_BC7);
} else if (mipFormat == gpu::Element::COLOR_RGBA_32) { } else if (mipFormat == gpu::Element::COLOR_RGBA_32) {
@ -736,13 +738,21 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
gpu::Element formatMip; gpu::Element formatMip;
gpu::Element formatGPU; gpu::Element formatGPU;
if (isColorTexturesCompressionEnabled()) { if (isColorTexturesCompressionEnabled()) {
#ifndef USE_GLES
if (validAlpha) { if (validAlpha) {
// NOTE: This disables BC1a compression because it was producing odd artifacts on text textures // 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). // 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 { } 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; formatMip = formatGPU;
} else { } else {
#ifdef USE_GLES #ifdef USE_GLES
@ -869,8 +879,12 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
gpu::Element formatMip = gpu::Element::VEC2NU8_XY; gpu::Element formatMip = gpu::Element::VEC2NU8_XY;
gpu::Element formatGPU = gpu::Element::VEC2NU8_XY; gpu::Element formatGPU = gpu::Element::VEC2NU8_XY;
if (isNormalTexturesCompressionEnabled()) { if (isNormalTexturesCompressionEnabled()) {
formatMip = gpu::Element::COLOR_COMPRESSED_XY; #ifndef USE_GLES
formatGPU = gpu::Element::COLOR_COMPRESSED_XY; 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)); 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 formatMip;
gpu::Element formatGPU; gpu::Element formatGPU;
if (isGrayscaleTexturesCompressionEnabled()) { if (isGrayscaleTexturesCompressionEnabled()) {
formatMip = gpu::Element::COLOR_COMPRESSED_RED; #ifndef USE_GLES
formatGPU = gpu::Element::COLOR_COMPRESSED_RED; formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED;
#else
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_RED;
#endif
formatMip = formatGPU;
} else { } else {
formatMip = gpu::Element::COLOR_R_8; formatMip = gpu::Element::COLOR_R_8;
formatGPU = 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 formatMip;
gpu::Element formatGPU; gpu::Element formatGPU;
if (isCubeTexturesCompressionEnabled()) { if (isCubeTexturesCompressionEnabled()) {
formatMip = gpu::Element::COLOR_COMPRESSED_HDR_RGB; // TODO: gles: pick HDR ETC format
formatGPU = gpu::Element::COLOR_COMPRESSED_HDR_RGB; formatMip = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
} else { } else {
formatMip = HDR_FORMAT; formatMip = HDR_FORMAT;
formatGPU = HDR_FORMAT; formatGPU = HDR_FORMAT;

View file

@ -358,6 +358,17 @@ namespace khronos {
case InternalFormat::COMPRESSED_RG_RGTC2: // BC5 case InternalFormat::COMPRESSED_RG_RGTC2: // BC5
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: // BC6 case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: // BC6
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7 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); return evalAlignedCompressedBlockCount<4>(value);
default: default:
@ -370,12 +381,22 @@ namespace khronos {
case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT: case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT:
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT: case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
case InternalFormat::COMPRESSED_RED_RGTC1: 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; return 8;
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT: case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
case InternalFormat::COMPRESSED_RG_RGTC2: 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; return 16;
default: default:

View file

@ -39,6 +39,10 @@ bool AddressManager::isConnected() {
return DependencyManager::get<NodeList>()->getDomainHandler().isConnected(); return DependencyManager::get<NodeList>()->getDomainHandler().isConnected();
} }
QString AddressManager::getProtocol() const {
return _domainURL.scheme();
}
QUrl AddressManager::currentAddress(bool domainOnly) const { QUrl AddressManager::currentAddress(bool domainOnly) const {
QUrl hifiURL = _domainURL; QUrl hifiURL = _domainURL;

View file

@ -145,7 +145,7 @@ public:
}; };
bool isConnected(); bool isConnected();
const QString& getProtocol() { return URL_SCHEME_HIFI; }; QString getProtocol() const;
QUrl currentAddress(bool domainOnly = false) const; QUrl currentAddress(bool domainOnly = false) const;
QUrl currentFacingAddress() const; QUrl currentFacingAddress() const;

View file

@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityEdit: case PacketType::EntityEdit:
case PacketType::EntityData: case PacketType::EntityData:
case PacketType::EntityPhysics: case PacketType::EntityPhysics:
return static_cast<PacketVersion>(EntityVersion::ShadowControl); return static_cast<PacketVersion>(EntityVersion::MaterialData);
case PacketType::EntityQuery: case PacketType::EntityQuery:
return static_cast<PacketVersion>(EntityQueryPacketVersion::RemovedJurisdictions); return static_cast<PacketVersion>(EntityQueryPacketVersion::RemovedJurisdictions);
case PacketType::AvatarIdentity: case PacketType::AvatarIdentity:

View file

@ -231,7 +231,8 @@ enum class EntityVersion : PacketVersion {
ZoneStageRemoved, ZoneStageRemoved,
SoftEntities, SoftEntities,
MaterialEntities, MaterialEntities,
ShadowControl ShadowControl,
MaterialData
}; };
enum class EntityScriptCallMethodVersion : PacketVersion { enum class EntityScriptCallMethodVersion : PacketVersion {

View file

@ -532,7 +532,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
} }
} }
auto& program = deferredLightingEffect->_directionalSkyboxLight; auto program = deferredLightingEffect->_directionalSkyboxLight;
LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations; LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
auto keyLight = lightAndShadow.first; auto keyLight = lightAndShadow.first;

View file

@ -154,6 +154,13 @@ void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(
} }
} }
void OffscreenUi::hideDesktopWindows() {
if (QThread::currentThread() != thread()) {
BLOCKING_INVOKE_METHOD(this, "hideDesktopWindows");
}
QMetaObject::invokeMethod(_desktop, "hideDesktopWindows");
}
void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) { void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name); QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
if (!item) { if (!item) {

View file

@ -60,6 +60,7 @@ public:
void createDesktop(const QUrl& url); void createDesktop(const QUrl& url);
void show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}); void show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
void hide(const QString& name); void hide(const QString& name);
void hideDesktopWindows();
bool isVisible(const QString& name); bool isVisible(const QString& name);
void toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}); void toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
bool shouldSwallowShortcut(QEvent* event); bool shouldSwallowShortcut(QEvent* event);

View file

@ -387,6 +387,8 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
offscreenUi->hide("RunningScripts"); offscreenUi->hide("RunningScripts");
_showRunningScripts = true; _showRunningScripts = true;
} }
offscreenUi->hideDesktopWindows();
// destroy desktop window // destroy desktop window
if (_desktopWindow) { if (_desktopWindow) {
_desktopWindow->deleteLater(); _desktopWindow->deleteLater();

View file

@ -8,7 +8,7 @@
// //
// Grab's physically moveable entities with the mouse, by applying a spring force. // 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. // Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // 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; this.actionID = null;
Pointers.setRenderState(this.mouseRayEntities, ""); Pointers.setRenderState(this.mouseRayEntities, "");
Pointers.setLockEndUUID(this.mouseRayEntities, null, false);
var args = "mouse"; var args = "mouse";
Entities.callEntityMethod(this.entityID, "releaseGrab", args); Entities.callEntityMethod(this.entityID, "releaseGrab", args);

View file

@ -416,6 +416,12 @@ var toolBar = (function () {
// default: // default:
// shapeType = "uv"; // shapeType = "uv";
//} //}
var materialData = "";
if (materialURL.startsWith("materialData")) {
materialData = JSON.stringify({
"materials": {}
})
}
var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1; var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1;
if (materialURL) { if (materialURL) {
@ -423,7 +429,8 @@ var toolBar = (function () {
type: "Material", type: "Material",
materialURL: materialURL, materialURL: materialURL,
//materialMappingMode: materialMappingMode, //materialMappingMode: materialMappingMode,
priority: DEFAULT_LAYERED_MATERIAL_PRIORITY priority: DEFAULT_LAYERED_MATERIAL_PRIORITY,
materialData: materialData
}); });
} }
} }
@ -2061,7 +2068,7 @@ var PropertiesTool = function (opts) {
parentSelectedEntities(); parentSelectedEntities();
} else if (data.type === 'unparent') { } else if (data.type === 'unparent') {
unparentSelectedEntities(); 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. //the event bridge and json parsing handle our avatar id string differently.
var actualID = data.id.split('"')[1]; var actualID = data.id.split('"')[1];
Entities.editEntity(actualID, data.properties); Entities.editEntity(actualID, data.properties);

View file

@ -1387,12 +1387,14 @@ input#reset-to-natural-dimensions {
margin-top: 48px; margin-top: 48px;
} }
#userdata-clear{ #userdata-clear,
#materialdata-clear {
margin-bottom: 10px; margin-bottom: 10px;
} }
#static-userdata { #static-userdata,
#static-materialData {
display: none; display: none;
z-index: 99; z-index: 99;
position: absolute; position: absolute;
@ -1403,7 +1405,8 @@ input#reset-to-natural-dimensions {
background-color: #2e2e2e; background-color: #2e2e2e;
} }
#userdata-saved { #userdata-saved,
#materialData-saved {
margin-top:5px; margin-top:5px;
font-size:16px; font-size:16px;
display:none; display:none;

View file

@ -781,6 +781,20 @@
<label for="property-material-url">Material URL</label> <label for="property-material-url">Material URL</label>
<input type="text" id="property-material-url"> <input type="text" id="property-material-url">
</div> </div>
<div class="property textarea">
<label for="property-material-data">Material data</label>
<br><br>
<div class="row">
<input type="button" class="red" id="materialdata-clear" value="Clear Material Data">
<input type="button" class="blue" id="materialdata-new-editor" value="Edit as JSON">
<input disabled type="button" class="black" id="materialdata-save" value="Save Material Data">
<span id="materialdata-saved" visible="false">Saved!</span>
</div>
<div id="static-naterialdata"></div>
<div id="materialdata-editor"></div>
<textarea id="property-material-data"></textarea>
</div>
</fieldset> </fieldset>
<fieldset class="minor"> <fieldset class="minor">
<div class="material-group material-section property text" id="property-parent-material-id-string-container"> <div class="material-group material-section property text" id="property-parent-material-id-string-container">

View file

@ -66,6 +66,7 @@ function enableProperties() {
if (elLocked.checked === false) { if (elLocked.checked === false) {
removeStaticUserData(); removeStaticUserData();
removeStaticMaterialData();
} }
} }
@ -78,8 +79,13 @@ function disableProperties() {
} }
var elLocked = document.getElementById("property-locked"); var elLocked = document.getElementById("property-locked");
if ($('#userdata-editor').css('display') === "block" && elLocked.checked === true) { if (elLocked.checked === true) {
showStaticUserData(); 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); 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) { function setTextareaScrolling(element) {
var isScrolling = element.scrollHeight > element.offsetHeight; var isScrolling = element.scrollHeight > element.offsetHeight;
element.setAttribute("scrolling", isScrolling ? "true" : "false"); 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 editor = null;
var editorTimeout = null;
var lastJSONString = null;
function createJSONEditor() { function createJSONEditor() {
var container = document.getElementById("userdata-editor"); var container = document.getElementById("userdata-editor");
@ -395,11 +525,6 @@ function createJSONEditor() {
function hideNewJSONEditorButton() { function hideNewJSONEditorButton() {
$('#userdata-new-editor').hide(); $('#userdata-new-editor').hide();
}
function hideClearUserDataButton() {
$('#userdata-clear').hide();
} }
function showSaveUserDataButton() { function showSaveUserDataButton() {
@ -408,17 +533,10 @@ function showSaveUserDataButton() {
function hideSaveUserDataButton() { function hideSaveUserDataButton() {
$('#userdata-save').hide(); $('#userdata-save').hide();
} }
function showNewJSONEditorButton() { function showNewJSONEditorButton() {
$('#userdata-new-editor').show(); $('#userdata-new-editor').show();
}
function showClearUserDataButton() {
$('#userdata-clear').show();
} }
function showUserDataTextArea() { function showUserDataTextArea() {
@ -446,7 +564,6 @@ function setEditorJSON(json) {
if (editor.hasOwnProperty('expandAll')) { if (editor.hasOwnProperty('expandAll')) {
editor.expandAll(); editor.expandAll();
} }
} }
function getEditorJSON() { function getEditorJSON() {
@ -484,12 +601,15 @@ function bindAllNonJSONEditorElements() {
// TODO FIXME: (JSHint) Functions declared within loops referencing // TODO FIXME: (JSHint) Functions declared within loops referencing
// an outer scoped variable may lead to confusing semantics. // an outer scoped variable may lead to confusing semantics.
field.on('focus', function(e) { 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; return;
} else { } else {
if ($('#userdata-editor').css('height') !== "0px") { if ($('#userdata-editor').css('height') !== "0px") {
saveJSONUserData(true); 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 elMaterialMappingScaleX = document.getElementById("property-material-mapping-scale-x");
var elMaterialMappingScaleY = document.getElementById("property-material-mapping-scale-y"); var elMaterialMappingScaleY = document.getElementById("property-material-mapping-scale-y");
var elMaterialMappingRot = document.getElementById("property-material-mapping-rot"); 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"); var elImageURL = document.getElementById("property-image-url");
@ -772,9 +896,15 @@ function loaded() {
} else if (data.type === "update") { } else if (data.type === "update") {
if (!data.selections || data.selections.length === 0) { if (!data.selections || data.selections.length === 0) {
if (editor !== null && lastEntityID !== null) { if (lastEntityID !== null) {
saveJSONUserData(true); if (editor !== null) {
deleteJSONEditor(); saveJSONUserData(true);
deleteJSONEditor();
}
if (materialEditor !== null) {
saveJSONMaterialData(true);
deleteJSONMaterialEditor();
}
} }
elTypeIcon.style.display = "none"; elTypeIcon.style.display = "none";
elType.innerHTML = "<i>No selection</i>"; elType.innerHTML = "<i>No selection</i>";
@ -783,6 +913,7 @@ function loaded() {
disableProperties(); disableProperties();
} else if (data.selections && data.selections.length > 1) { } else if (data.selections && data.selections.length > 1) {
deleteJSONEditor(); deleteJSONEditor();
deleteJSONMaterialEditor();
var selections = data.selections; var selections = data.selections;
var ids = []; var ids = [];
@ -815,8 +946,13 @@ function loaded() {
} else { } else {
properties = data.selections[0].properties; properties = data.selections[0].properties;
if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) { if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null) {
saveJSONUserData(true); if (editor !== null) {
saveJSONUserData(true);
}
if (materialEditor !== null) {
saveJSONMaterialData(true);
}
} }
var doSelectElement = lastEntityID === '"' + properties.id + '"'; var doSelectElement = lastEntityID === '"' + properties.id + '"';
@ -993,6 +1129,28 @@ function loaded() {
hideNewJSONEditorButton(); 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; elHyperlinkHref.value = properties.href;
elDescription.value = properties.description; elDescription.value = properties.description;
@ -1200,6 +1358,7 @@ function loaded() {
} else { } else {
enableProperties(); enableProperties();
elSaveUserData.disabled = true; elSaveUserData.disabled = true;
elSaveMaterialData.disabled = true;
} }
var activeElement = document.activeElement; var activeElement = document.activeElement;
@ -1384,6 +1543,31 @@ function loaded() {
showSaveUserDataButton(); 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( var colorChangeFunction = createEmitColorPropertyUpdateFunction(
'color', elColorRed, elColorGreen, elColorBlue); 'color', elColorRed, elColorGreen, elColorBlue);
elColorRed.addEventListener('change', colorChangeFunction); elColorRed.addEventListener('change', colorChangeFunction);

View file

@ -44,26 +44,35 @@ def groupKTXFiles(directory, filePath):
originalFilePath.strip() originalFilePath.strip()
shutil.move(originalFilePath, newFilePath) shutil.move(originalFilePath, newFilePath)
def bakeFile(filePath, outputDirectory): def bakeFile(filePath, outputDirectory, fileType):
createDirectory(outputDirectory) createDirectory(outputDirectory)
cmd = EXE + ' -i ' + filePath + ' -o ' + outputDirectory + ' -t fbx' cmd = EXE + ' -i ' + filePath + ' -o ' + outputDirectory + ' -t ' + fileType
args = shlex.split(cmd) args = shlex.split(cmd)
process = subprocess.Popen(cmd, stdout=False, stderr=False) process = subprocess.Popen(cmd, stdout=False, stderr=False)
process.wait() process.wait()
bakedFile = os.path.splitext(filePath)[0] bakedFile = os.path.splitext(filePath)[0]
groupKTXFiles(outputDirectory, bakedFile) if fileType == 'fbx':
groupKTXFiles(outputDirectory, bakedFile)
def bakeFilesInDirectory(directory, outputDirectory): def bakeFilesInDirectory(directory, outputDirectory):
rootDirectory = os.path.basename(os.path.normpath(directory)) rootDirectory = os.path.basename(os.path.normpath(directory))
for root, subFolders, filenames in os.walk(directory): for root, subFolders, filenames in os.walk(directory):
for filename in filenames: for filename in filenames:
appendPath = getRelativePath(directory, root, rootDirectory); appendPath = getRelativePath(directory, root, rootDirectory);
name, ext = os.path.splitext('file.txt')
if filename.endswith('.fbx'): if filename.endswith('.fbx'):
filePath = os.sep.join([root, filename]) filePath = os.sep.join([root, filename])
absFilePath = os.path.abspath(filePath) absFilePath = os.path.abspath(filePath)
outputFolder = os.path.join(outputDirectory, appendPath) outputFolder = os.path.join(outputDirectory, appendPath)
print "Baking file: " + filename 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: else:
filePath = os.sep.join([root, filename]) filePath = os.sep.join([root, filename])
absFilePath = os.path.abspath(filePath) absFilePath = os.path.abspath(filePath)

View file

@ -6,7 +6,7 @@ def createAssetMapping(assetDirectory):
baseDirectory = os.path.basename(os.path.normpath(assetDirectory)) baseDirectory = os.path.basename(os.path.normpath(assetDirectory))
for root, subfolder, filenames in os.walk(assetDirectory): for root, subfolder, filenames in os.walk(assetDirectory):
for filename in filenames: 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]) substring = os.path.commonprefix([assetDirectory, root])
newPath = root.replace(substring, ''); newPath = root.replace(substring, '');
filePath = os.sep.join([newPath, filename]) filePath = os.sep.join([newPath, filename])
@ -30,7 +30,7 @@ def handleURL(url):
baseFilename = os.path.basename(url) baseFilename = os.path.basename(url)
filename = os.path.splitext(baseFilename)[0] filename = os.path.splitext(baseFilename)[0]
newUrl = MAP[filename] newUrl = MAP[filename]
print newUrl print url + ' -> ' + newUrl
return newUrl return newUrl
def handleOptions(): def handleOptions():
@ -43,8 +43,12 @@ def main():
argsLength = len(sys.argv) argsLength = len(sys.argv)
if argsLength == 3: if argsLength == 3:
jsonFile = sys.argv[1] jsonFile = sys.argv[1]
gzipFile = jsonFile + '.gz'
assetDirectory = sys.argv[2] 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) createAssetMapping(assetDirectory)
f = open(jsonFile) f = open(jsonFile)
data = json.load(f) data = json.load(f)
@ -65,6 +69,15 @@ def main():
except: except:
value = handleURL(value) 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": if prop == "serverScripts":
value = handleURL(value) value = handleURL(value)