mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 08:13:13 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into feat/hasScriptedBlendshapes
This commit is contained in:
commit
22e7f80356
47 changed files with 828 additions and 201 deletions
8
BUILD.md
8
BUILD.md
|
@ -1,7 +1,7 @@
|
|||
### Dependencies
|
||||
|
||||
- [cmake](https://cmake.org/download/): 3.9
|
||||
- [Qt](https://www.qt.io/download-open-source): 5.9.1
|
||||
- [Qt](https://www.qt.io/download-open-source): 5.10.1
|
||||
- [OpenSSL](https://www.openssl.org/): Use the latest available 1.0 version (**NOT** 1.1) of OpenSSL to avoid security vulnerabilities.
|
||||
- [VHACD](https://github.com/virneo/v-hacd)(clone this repository)(Optional)
|
||||
|
||||
|
@ -46,8 +46,8 @@ This can either be entered directly into your shell session before you build or
|
|||
|
||||
The path it needs to be set to will depend on where and how Qt5 was installed. e.g.
|
||||
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.6.2/clang_64/lib/cmake/
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.6.2/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/clang_64/lib/cmake/
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt5/5.10.1/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/opt/qt5/lib/cmake
|
||||
|
||||
#### Generating build files
|
||||
|
@ -66,7 +66,7 @@ Any variables that need to be set for CMake to find dependencies can be set as E
|
|||
|
||||
For example, to pass the QT_CMAKE_PREFIX_PATH variable during build file generation:
|
||||
|
||||
cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.6.2/lib/cmake
|
||||
cmake .. -DQT_CMAKE_PREFIX_PATH=/usr/local/qt/5.10.1/lib/cmake
|
||||
|
||||
#### Finding Dependencies
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ Should you choose not to install Qt5 via a package manager that handles dependen
|
|||
|
||||
Install qt:
|
||||
```bash
|
||||
wget http://debian.highfidelity.com/pool/h/hi/hifi-qt5.6.1_5.6.1_amd64.deb
|
||||
sudo dpkg -i hifi-qt5.6.1_5.6.1_amd64.deb
|
||||
wget http://debian.highfidelity.com/pool/h/hi/hifi-qt5.10.1_5.10.1_amd64.deb
|
||||
sudo dpkg -i hifi-qt5.10.1_5.10.1_amd64.deb
|
||||
```
|
||||
|
||||
Install build dependencies:
|
||||
|
@ -66,7 +66,7 @@ cd hifi/build
|
|||
|
||||
Prepare makefiles:
|
||||
```bash
|
||||
cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.6.1/5.6/gcc_64/lib/cmake ..
|
||||
cmake -DQT_CMAKE_PREFIX_PATH=/usr/local/Qt5.10.1/5.10/gcc_64/lib/cmake ..
|
||||
```
|
||||
|
||||
Start compilation and get a cup of coffee:
|
||||
|
@ -74,7 +74,7 @@ Start compilation and get a cup of coffee:
|
|||
make domain-server assignment-client interface
|
||||
```
|
||||
|
||||
In a server does not make sense to compile interface
|
||||
In a server does not make sense to compile interface
|
||||
|
||||
### Running the software
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ Note that this uses the version from the homebrew formula at the time of this wr
|
|||
Assuming you've installed Qt using the homebrew instructions above, you'll need to set QT_CMAKE_PREFIX_PATH so CMake can find your installations.
|
||||
For Qt installed via homebrew, set QT_CMAKE_PREFIX_PATH:
|
||||
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.9.1/lib/cmake
|
||||
export QT_CMAKE_PREFIX_PATH=/usr/local/Cellar/qt/5.10.1/lib/cmake
|
||||
|
||||
Note that this uses the version from the homebrew formula at the time of this writing, and the version in the path will likely change.
|
||||
|
||||
|
|
20
BUILD_WIN.md
20
BUILD_WIN.md
|
@ -1,13 +1,13 @@
|
|||
This is a stand-alone guide for creating your first High Fidelity build for Windows 64-bit.
|
||||
|
||||
## Building High Fidelity
|
||||
Note: We are now using Visual Studio 2017 and Qt 5.9.1. If you are upgrading from Visual Studio 2013 and Qt 5.6.2, do a clean uninstall of those versions before going through this guide.
|
||||
Note: We are now using Visual Studio 2017 and Qt 5.10.1. If you are upgrading from Visual Studio 2013 and Qt 5.6.2, do a clean uninstall of those versions before going through this guide.
|
||||
|
||||
Note: The prerequisites will require about 10 GB of space on your drive. You will also need a system with at least 8GB of main memory.
|
||||
|
||||
### Step 1. Visual Studio 2017
|
||||
|
||||
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
||||
If you don’t have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
|
||||
|
||||
When selecting components, check "Desktop development with C++." Also check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)" on the Summary toolbar on the right.
|
||||
|
||||
|
@ -17,15 +17,15 @@ Download and install the latest version of CMake 3.9. Download the file named w
|
|||
|
||||
### Step 3. Installing Qt
|
||||
|
||||
Download and install the [Qt Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.9.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)".
|
||||
Download and install the [Qt Online Installer](https://www.qt.io/download-open-source/?hsCtaTracking=f977210e-de67-475f-a32b-65cec207fd03%7Cd62710cd-e1db-46aa-8d4d-2f1c1ffdacea). While installing, you only need to have the following components checked under Qt 5.10.1: "msvc2017 64-bit", "Qt WebEngine", and "Qt Script (Deprecated)".
|
||||
|
||||
Note: Installing the Sources is optional but recommended if you have room for them (~2GB).
|
||||
Note: Installing the Sources is optional but recommended if you have room for them (~2GB).
|
||||
|
||||
### Step 4. Setting Qt Environment Variable
|
||||
|
||||
Go to `Control Panel > System > Advanced System Settings > Environment Variables > New...` (or search “Environment Variables” in Start Search).
|
||||
* Set "Variable name": `QT_CMAKE_PREFIX_PATH`
|
||||
* Set "Variable value": `C:\Qt\5.9.1\msvc2017_64\lib\cmake`
|
||||
* Set "Variable value": `C:\Qt\5.10.1\msvc2017_64\lib\cmake`
|
||||
|
||||
### Step 5. Installing [vcpkg](https://github.com/Microsoft/vcpkg)
|
||||
|
||||
|
@ -39,7 +39,7 @@ Go to `Control Panel > System > Advanced System Settings > Environment Variables
|
|||
|
||||
* In the vcpkg directory, install the 64 bit OpenSSL package with the command `vcpkg install openssl:x64-windows`
|
||||
* Once the build completes you should have a file `ssl.h` in `${VCPKG_ROOT}/installed/x64-windows/include/openssl`
|
||||
|
||||
|
||||
### Step 7. Running CMake to Generate Build Files
|
||||
|
||||
Run Command Prompt from Start and run the following commands:
|
||||
|
@ -49,7 +49,7 @@ mkdir build
|
|||
cd build
|
||||
cmake .. -G "Visual Studio 15 Win64"
|
||||
```
|
||||
|
||||
|
||||
Where `%HIFI_DIR%` is the directory for the highfidelity repository.
|
||||
|
||||
### Step 8. Making a Build
|
||||
|
@ -74,10 +74,10 @@ Note: You can also run Interface by launching it from command line or File Explo
|
|||
|
||||
## Troubleshooting
|
||||
|
||||
For any problems after Step #7, first try this:
|
||||
For any problems after Step #7, first try this:
|
||||
* Delete your locally cloned copy of the highfidelity repository
|
||||
* Restart your computer
|
||||
* Redownload the [repository](https://github.com/highfidelity/hifi)
|
||||
* Redownload the [repository](https://github.com/highfidelity/hifi)
|
||||
* Restart directions from Step #7
|
||||
|
||||
#### CMake gives you the same error message repeatedly after the build fails
|
||||
|
@ -90,4 +90,4 @@ Remove `CMakeCache.txt` found in the `%HIFI_DIR%\build` directory. Verify that
|
|||
|
||||
#### Qt is throwing an error
|
||||
|
||||
Make sure you have the correct version (5.9.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.
|
||||
Make sure you have the correct version (5.10.1) installed and `QT_CMAKE_PREFIX_PATH` environment variable is set correctly.
|
||||
|
|
|
@ -322,8 +322,16 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU
|
|||
|
||||
// stereo sources are not passed through HRTF
|
||||
if (streamToAdd.isStereo()) {
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; ++i) {
|
||||
_mixSamples[i] += float(streamPopOutput[i] * gain / AudioConstants::MAX_SAMPLE_VALUE);
|
||||
|
||||
// apply the avatar gain adjustment
|
||||
auto& hrtf = listenerNodeData.hrtfForStream(sourceNodeID, streamToAdd.getStreamIdentifier());
|
||||
gain *= hrtf.getGainAdjustment();
|
||||
|
||||
const float scale = 1/32768.0f; // int16_t to float
|
||||
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) {
|
||||
_mixSamples[2*i+0] += (float)streamPopOutput[2*i+0] * gain * scale;
|
||||
_mixSamples[2*i+1] += (float)streamPopOutput[2*i+1] * gain * scale;
|
||||
}
|
||||
|
||||
++stats.manualStereoMixes;
|
||||
|
@ -332,10 +340,13 @@ void AudioMixerSlave::addStream(AudioMixerClientData& listenerNodeData, const QU
|
|||
|
||||
// echo sources are not passed through HRTF
|
||||
if (isEcho) {
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_STEREO; i += 2) {
|
||||
auto monoSample = float(streamPopOutput[i / 2] * gain / AudioConstants::MAX_SAMPLE_VALUE);
|
||||
_mixSamples[i] += monoSample;
|
||||
_mixSamples[i + 1] += monoSample;
|
||||
|
||||
const float scale = 1/32768.0f; // int16_t to float
|
||||
|
||||
for (int i = 0; i < AudioConstants::NETWORK_FRAME_SAMPLES_PER_CHANNEL; i++) {
|
||||
float sample = (float)streamPopOutput[i] * gain * scale;
|
||||
_mixSamples[2*i+0] += sample;
|
||||
_mixSamples[2*i+1] += sample;
|
||||
}
|
||||
|
||||
++stats.manualEchoMixes;
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
#
|
||||
#
|
||||
# Created by Bradley Austin Davis on 2017/09/02
|
||||
# Copyright 2013-2017 High Fidelity, Inc.
|
||||
#
|
||||
# Distributed under the Apache License, Version 2.0.
|
||||
# See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
#
|
||||
#
|
||||
|
||||
# Construct a default QT location from a root path, a version and an architecture
|
||||
function(calculate_default_qt_dir _RESULT_NAME)
|
||||
|
@ -27,7 +27,7 @@ function(calculate_default_qt_dir _RESULT_NAME)
|
|||
endif()
|
||||
|
||||
set_from_env(QT_ROOT QT_ROOT ${QT_DEFAULT_ROOT})
|
||||
set_from_env(QT_VERSION QT_VERSION "5.9.1")
|
||||
set_from_env(QT_VERSION QT_VERSION "5.10.1")
|
||||
set_from_env(QT_ARCH QT_ARCH ${QT_DEFAULT_ARCH})
|
||||
|
||||
set(${_RESULT_NAME} "${QT_ROOT}/${QT_VERSION}/${QT_ARCH}" PARENT_SCOPE)
|
||||
|
@ -60,11 +60,11 @@ macro(setup_qt)
|
|||
#if (NOT EXISTS "${QT_DIR}/include/QtCore/QtGlobal")
|
||||
# message(FATAL_ERROR "Unable to locate Qt includes in ${QT_DIR}")
|
||||
#endif()
|
||||
|
||||
|
||||
if (NOT EXISTS "${QT_CMAKE_PREFIX_PATH}/Qt5Core/Qt5CoreConfig.cmake")
|
||||
message(FATAL_ERROR "Unable to locate Qt cmake config in ${QT_CMAKE_PREFIX_PATH}")
|
||||
endif()
|
||||
|
||||
|
||||
message(STATUS "The Qt build in use is: \"${QT_DIR}\"")
|
||||
|
||||
# Instruct CMake to run moc automatically when needed.
|
||||
|
@ -72,7 +72,7 @@ macro(setup_qt)
|
|||
|
||||
# Instruct CMake to run rcc automatically when needed
|
||||
set(CMAKE_AUTORCC ON)
|
||||
|
||||
|
||||
if (WIN32)
|
||||
add_paths_to_fixup_libs("${QT_DIR}/bin")
|
||||
endif ()
|
||||
|
|
|
@ -324,6 +324,18 @@ FocusScope {
|
|||
return false;
|
||||
}
|
||||
|
||||
function hideDesktopWindows() {
|
||||
for (var index = 0; index < desktop.visibleChildren.length; index++) {
|
||||
var child = desktop.visibleChildren[index];
|
||||
if (child.topLevelWindow && child.hasOwnProperty("modality")) {
|
||||
var TOOLBAR_NAME = "com.highfidelity.interface.toolbar.system"
|
||||
if (child.objectName !== TOOLBAR_NAME) {
|
||||
child.setShown(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setPinned(newPinned) {
|
||||
pinned = newPinned
|
||||
}
|
||||
|
|
|
@ -225,8 +225,8 @@
|
|||
#ifdef DEBUG_EVENT_QUEUE
|
||||
// This is a HACK that uses private headers included with the qt source distrubution.
|
||||
// To use this feature you need to add these directores to your include path:
|
||||
// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1/QtCore
|
||||
// E:/Qt/5.9.1/Src/qtbase/include/QtCore/5.9.1
|
||||
// E:/Qt/5.10.1/Src/qtbase/include/QtCore/5.10.1/QtCore
|
||||
// E:/Qt/5.10.1/Src/qtbase/include/QtCore/5.10.1
|
||||
#define QT_BOOTSTRAPPED
|
||||
#include <private/qthread_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"));
|
||||
|
||||
|
||||
QVariant testProperty = property(hifi::properties::TEST);
|
||||
qDebug() << testProperty;
|
||||
if (testProperty.isValid()) {
|
||||
|
@ -6577,7 +6577,7 @@ void Application::addAssetToWorldFromURL(QString url) {
|
|||
} else {
|
||||
filename.remove(".zip");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if (!DependencyManager::get<NodeList>()->getThisNodeCanWriteAssets()) {
|
||||
|
@ -6751,7 +6751,7 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q
|
|||
addAssetToWorldError(filenameFromPath(filePath), errorInfo);
|
||||
} else {
|
||||
// to prevent files that aren't models or texture files from being loaded into world automatically
|
||||
if ((filePath.toLower().endsWith(OBJ_EXTENSION) || filePath.toLower().endsWith(FBX_EXTENSION)) ||
|
||||
if ((filePath.toLower().endsWith(OBJ_EXTENSION) || filePath.toLower().endsWith(FBX_EXTENSION)) ||
|
||||
((filePath.toLower().endsWith(JPG_EXTENSION) || filePath.toLower().endsWith(PNG_EXTENSION)) &&
|
||||
((!isBlocks) && (!isZip)))) {
|
||||
addAssetToWorldAddEntity(filePath, mapping);
|
||||
|
@ -7400,8 +7400,8 @@ bool Application::isThrottleRendering() const {
|
|||
bool Application::hasFocus() const {
|
||||
bool result = (QApplication::activeWindow() != nullptr);
|
||||
#if defined(Q_OS_WIN)
|
||||
// On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't
|
||||
// take user focus away from their current window. So also check whether the application is the user's current foreground
|
||||
// On Windows, QWidget::activateWindow() - as called in setFocus() - makes the application's taskbar icon flash but doesn't
|
||||
// take user focus away from their current window. So also check whether the application is the user's current foreground
|
||||
// window.
|
||||
result = result && (HWND)QApplication::activeWindow()->winId() == GetForegroundWindow();
|
||||
#endif
|
||||
|
@ -7409,7 +7409,7 @@ bool Application::hasFocus() const {
|
|||
}
|
||||
|
||||
void Application::setFocus() {
|
||||
// Note: Windows doesn't allow a user focus to be taken away from another application. Instead, it changes the color of and
|
||||
// Note: Windows doesn't allow a user focus to be taken away from another application. Instead, it changes the color of and
|
||||
// flashes the taskbar icon.
|
||||
auto window = qApp->getWindow();
|
||||
window->activateWindow();
|
||||
|
@ -7650,7 +7650,7 @@ void Application::updateDisplayMode() {
|
|||
menu->setIsOptionChecked(MenuOption::FirstPerson, true);
|
||||
cameraMenuChanged();
|
||||
}
|
||||
|
||||
|
||||
// Remove the mirror camera option from menu if in HMD mode
|
||||
auto mirrorAction = menu->getActionForOption(MenuOption::FullscreenMirror);
|
||||
mirrorAction->setVisible(!isHmd);
|
||||
|
|
|
@ -35,7 +35,19 @@ ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
|
|||
_url(modelOverlay->_url),
|
||||
_updateModel(false),
|
||||
_scaleToFit(modelOverlay->_scaleToFit),
|
||||
_loadPriority(modelOverlay->_loadPriority)
|
||||
_loadPriority(modelOverlay->_loadPriority),
|
||||
|
||||
_animationURL(modelOverlay->_animationURL),
|
||||
_animationFPS(modelOverlay->_animationFPS),
|
||||
_animationCurrentFrame(modelOverlay->_animationCurrentFrame),
|
||||
_animationRunning(modelOverlay->_animationRunning),
|
||||
_animationLoop(modelOverlay->_animationLoop),
|
||||
_animationFirstFrame(modelOverlay->_animationFirstFrame),
|
||||
_animationLastFrame(modelOverlay->_animationLastFrame),
|
||||
_animationHold(modelOverlay->_animationHold),
|
||||
_animationAllowTranslation(modelOverlay->_animationAllowTranslation)
|
||||
|
||||
// Joint translations and rotations aren't copied because the model needs to load before they can be applied.
|
||||
{
|
||||
_model->setLoadingPriority(_loadPriority);
|
||||
if (_url.isValid()) {
|
||||
|
@ -341,20 +353,25 @@ vectorType ModelOverlay::mapJoints(mapFunction<itemType> function) const {
|
|||
* <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 {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} 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 {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.<Vec3>} jointTranslations - The relative translations of the model's joints.
|
||||
* @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. <em>Not copied if overlay is
|
||||
* 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.
|
||||
* <em>Read-only</em>
|
||||
* <em>Read-only.</em>
|
||||
* @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 {number} animationSettings.fps=0 - The frame rate (frames/sec) to play the animation at.
|
||||
* @property {number} animationSettings.firstFrame=0 - The frame to start playing at.
|
||||
* @property {number} animationSettings.lastFrame=0 - The frame to finish playing at.
|
||||
* @property {number} animationSettings.currentFrame=0 - The current frame being played.
|
||||
* @property {boolean} animationSettings.running=false - Whether or not the animation is playing.
|
||||
* @property {boolean} animationSettings.loop=false - Whether or not the animation should repeat in a loop.
|
||||
* @property {boolean} animationSettings.hold=false - Whether or not when the animation finishes, the rotations and
|
||||
|
@ -384,6 +401,10 @@ QVariant ModelOverlay::getProperty(const QString& property) {
|
|||
}
|
||||
}
|
||||
|
||||
if (property == "loadPriority") {
|
||||
return _loadPriority;
|
||||
}
|
||||
|
||||
if (property == "jointNames") {
|
||||
if (_model && _model->isActive()) {
|
||||
// note: going through Rig because Model::getJointNames() (which proxies to FBXGeometry) was always empty
|
||||
|
|
|
@ -2059,24 +2059,34 @@ static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities");
|
|||
static const QString JSON_AVATAR_SCALE = QStringLiteral("scale");
|
||||
static const QString JSON_AVATAR_VERSION = QStringLiteral("version");
|
||||
|
||||
static const int JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION = 0;
|
||||
static const int JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION = 1;
|
||||
enum class JsonAvatarFrameVersion : int {
|
||||
JointRotationsInRelativeFrame = 0,
|
||||
JointRotationsInAbsoluteFrame,
|
||||
JointDefaultPoseBits
|
||||
};
|
||||
|
||||
QJsonValue toJsonValue(const JointData& joint) {
|
||||
QJsonArray result;
|
||||
result.push_back(toJsonValue(joint.rotation));
|
||||
result.push_back(toJsonValue(joint.translation));
|
||||
result.push_back(QJsonValue(joint.rotationIsDefaultPose));
|
||||
result.push_back(QJsonValue(joint.translationIsDefaultPose));
|
||||
return result;
|
||||
}
|
||||
|
||||
JointData jointDataFromJsonValue(const QJsonValue& json) {
|
||||
JointData jointDataFromJsonValue(int version, const QJsonValue& json) {
|
||||
JointData result;
|
||||
if (json.isArray()) {
|
||||
QJsonArray array = json.toArray();
|
||||
result.rotation = quatFromJsonValue(array[0]);
|
||||
result.rotationIsDefaultPose = false;
|
||||
result.translation = vec3FromJsonValue(array[1]);
|
||||
result.translationIsDefaultPose = false;
|
||||
if (version >= (int)JsonAvatarFrameVersion::JointDefaultPoseBits) {
|
||||
result.rotationIsDefaultPose = array[2].toBool();
|
||||
result.translationIsDefaultPose = array[3].toBool();
|
||||
} else {
|
||||
result.rotationIsDefaultPose = false;
|
||||
result.translationIsDefaultPose = false;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -2084,7 +2094,7 @@ JointData jointDataFromJsonValue(const QJsonValue& json) {
|
|||
QJsonObject AvatarData::toJson() const {
|
||||
QJsonObject root;
|
||||
|
||||
root[JSON_AVATAR_VERSION] = JSON_AVATAR_JOINT_ROTATIONS_IN_ABSOLUTE_FRAME_VERSION;
|
||||
root[JSON_AVATAR_VERSION] = (int)JsonAvatarFrameVersion::JointDefaultPoseBits;
|
||||
|
||||
if (!getSkeletonModelURL().isEmpty()) {
|
||||
root[JSON_AVATAR_BODY_MODEL] = getSkeletonModelURL().toString();
|
||||
|
@ -2159,7 +2169,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
version = json[JSON_AVATAR_VERSION].toInt();
|
||||
} else {
|
||||
// initial data did not have a version field.
|
||||
version = JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION;
|
||||
version = (int)JsonAvatarFrameVersion::JointRotationsInRelativeFrame;
|
||||
}
|
||||
|
||||
if (json.contains(JSON_AVATAR_BODY_MODEL)) {
|
||||
|
@ -2236,7 +2246,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
// }
|
||||
|
||||
if (json.contains(JSON_AVATAR_JOINT_ARRAY)) {
|
||||
if (version == JSON_AVATAR_JOINT_ROTATIONS_IN_RELATIVE_FRAME_VERSION) {
|
||||
if (version == (int)JsonAvatarFrameVersion::JointRotationsInRelativeFrame) {
|
||||
// because we don't have the full joint hierarchy skeleton of the model,
|
||||
// we can't properly convert from relative rotations into absolute rotations.
|
||||
quint64 now = usecTimestampNow();
|
||||
|
@ -2248,7 +2258,7 @@ void AvatarData::fromJson(const QJsonObject& json, bool useFrameSkeleton) {
|
|||
QJsonArray jointArrayJson = json[JSON_AVATAR_JOINT_ARRAY].toArray();
|
||||
jointArray.reserve(jointArrayJson.size());
|
||||
for (const auto& jointJson : jointArrayJson) {
|
||||
auto joint = jointDataFromJsonValue(jointJson);
|
||||
auto joint = jointDataFromJsonValue(version, jointJson);
|
||||
jointArray.push_back(joint);
|
||||
}
|
||||
setRawJointData(jointArray);
|
||||
|
@ -2559,4 +2569,4 @@ void AvatarEntityMapFromScriptValue(const QScriptValue& object, AvatarEntityMap&
|
|||
|
||||
value[EntityID] = binaryEntityProperties;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ bool MaterialEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityP
|
|||
if (entity->getMaterial() != _drawMaterial) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getParentID() != _parentID || entity->getClientOnly() != _clientOnly || entity->getOwningAvatarID() != _owningAvatarID) {
|
||||
if (entity->getParentID() != _parentID) {
|
||||
return true;
|
||||
}
|
||||
if (entity->getMaterialMappingPos() != _materialMappingPos || entity->getMaterialMappingScale() != _materialMappingScale || entity->getMaterialMappingRot() != _materialMappingRot) {
|
||||
|
@ -31,8 +31,6 @@ void MaterialEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer&
|
|||
withWriteLock([&] {
|
||||
_drawMaterial = entity->getMaterial();
|
||||
_parentID = entity->getParentID();
|
||||
_clientOnly = entity->getClientOnly();
|
||||
_owningAvatarID = entity->getOwningAvatarID();
|
||||
_materialMappingPos = entity->getMaterialMappingPos();
|
||||
_materialMappingScale = entity->getMaterialMappingScale();
|
||||
_materialMappingRot = entity->getMaterialMappingRot();
|
||||
|
@ -102,7 +100,7 @@ void MaterialEntityRenderer::doRender(RenderArgs* args) {
|
|||
graphics::MaterialPointer drawMaterial;
|
||||
Transform textureTransform;
|
||||
withReadLock([&] {
|
||||
parentID = _clientOnly ? _owningAvatarID : _parentID;
|
||||
parentID = _parentID;
|
||||
renderTransform = _renderTransform;
|
||||
drawMaterial = _drawMaterial;
|
||||
textureTransform.setTranslation(glm::vec3(_materialMappingPos, 0));
|
||||
|
|
|
@ -32,8 +32,6 @@ private:
|
|||
ShapeKey getShapeKey() override;
|
||||
|
||||
QUuid _parentID;
|
||||
bool _clientOnly;
|
||||
QUuid _owningAvatarID;
|
||||
glm::vec2 _materialMappingPos;
|
||||
glm::vec2 _materialMappingScale;
|
||||
float _materialMappingRot;
|
||||
|
|
|
@ -363,6 +363,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_POS, materialMappingPos);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_DATA, materialData);
|
||||
|
||||
// Certifiable Properties
|
||||
CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName);
|
||||
|
@ -1208,6 +1209,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ACTION_DATA, actionData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LOCKED, locked);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_USER_DATA, userData);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
|
||||
// Certifiable Properties
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ITEM_NAME, itemName);
|
||||
|
@ -1252,7 +1254,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_SPREAD, colorSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_START, colorStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_COLOR_FINISH, colorFinish);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA, alpha);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_SPREAD, alphaSpread);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish);
|
||||
|
@ -1376,6 +1377,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_POS, materialMappingPos);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_SCALE, materialMappingScale);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_MATERIAL_DATA, materialData);
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
|
@ -1539,6 +1541,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingPos, glmVec2, setMaterialMappingPos);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingScale, glmVec2, setMaterialMappingScale);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData);
|
||||
|
||||
// Certifiable Properties
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName);
|
||||
|
@ -1902,6 +1905,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glmVec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glmVec2);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float);
|
||||
ADD_PROPERTY_TO_MAP(PROP_MATERIAL_DATA, MaterialData, materialData, QString);
|
||||
|
||||
// Certifiable Properties
|
||||
ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString);
|
||||
|
@ -2298,6 +2302,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
|
|||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_POS, properties.getMaterialMappingPos());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, properties.getMaterialMappingScale());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, properties.getMaterialMappingRot());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, properties.getMaterialData());
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
|
||||
|
@ -2666,6 +2671,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_POS, glmVec2, setMaterialMappingPos);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_SCALE, glmVec2, setMaterialMappingScale);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MATERIAL_DATA, QString, setMaterialData);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
|
||||
|
@ -2849,6 +2855,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_materialMappingPosChanged = true;
|
||||
_materialMappingScaleChanged = true;
|
||||
_materialMappingRotChanged = true;
|
||||
_materialDataChanged = true;
|
||||
|
||||
// Certifiable Properties
|
||||
_itemNameChanged = true;
|
||||
|
@ -3200,6 +3207,9 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (materialMappingRotChanged()) {
|
||||
out += "materialMappingRot";
|
||||
}
|
||||
if (materialDataChanged()) {
|
||||
out += "materialData";
|
||||
}
|
||||
|
||||
// Certifiable Properties
|
||||
if (itemNameChanged()) {
|
||||
|
|
|
@ -230,6 +230,7 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glmVec2, glm::vec2(0, 0));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_SCALE, MaterialMappingScale, materialMappingScale, glmVec2, glm::vec2(1, 1));
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_ROT, MaterialMappingRot, materialMappingRot, float, 0);
|
||||
DEFINE_PROPERTY_REF(PROP_MATERIAL_DATA, MaterialData, materialData, QString, "");
|
||||
|
||||
// Certifiable Properties - related to Proof of Purchase certificates
|
||||
DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME);
|
||||
|
|
|
@ -240,6 +240,7 @@ enum EntityPropertyList {
|
|||
PROP_MATERIAL_MAPPING_POS,
|
||||
PROP_MATERIAL_MAPPING_SCALE,
|
||||
PROP_MATERIAL_MAPPING_ROT,
|
||||
PROP_MATERIAL_DATA,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
|
|
|
@ -2382,6 +2382,30 @@ bool EntityTree::readFromMap(QVariantMap& map) {
|
|||
}
|
||||
}
|
||||
|
||||
// Convert old materials so that they use materialData instead of userData
|
||||
if (contentVersion < (int)EntityVersion::MaterialData && properties.getType() == EntityTypes::EntityType::Material) {
|
||||
if (properties.getMaterialURL().startsWith("userData")) {
|
||||
QString materialURL = properties.getMaterialURL();
|
||||
properties.setMaterialURL(materialURL.replace("userData", "materialData"));
|
||||
|
||||
QJsonObject userData = QJsonDocument::fromJson(properties.getUserData().toUtf8()).object();
|
||||
QJsonObject materialData;
|
||||
QJsonValue materialVersion = userData["materialVersion"];
|
||||
if (!materialVersion.isNull()) {
|
||||
materialData.insert("materialVersion", materialVersion);
|
||||
userData.remove("materialVersion");
|
||||
}
|
||||
QJsonValue materials = userData["materials"];
|
||||
if (!materials.isNull()) {
|
||||
materialData.insert("materials", materials);
|
||||
userData.remove("materials");
|
||||
}
|
||||
|
||||
properties.setMaterialData(QJsonDocument(materialData).toJson());
|
||||
properties.setUserData(QJsonDocument(userData).toJson());
|
||||
}
|
||||
}
|
||||
|
||||
EntityItemPointer entity = addEntity(entityItemID, properties);
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType();
|
||||
|
|
|
@ -27,6 +27,10 @@ MaterialEntityItem::MaterialEntityItem(const EntityItemID& entityItemID) : Entit
|
|||
_type = EntityTypes::Material;
|
||||
}
|
||||
|
||||
MaterialEntityItem::~MaterialEntityItem() {
|
||||
removeMaterial();
|
||||
}
|
||||
|
||||
EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialURL, getMaterialURL);
|
||||
|
@ -36,6 +40,7 @@ EntityItemProperties MaterialEntityItem::getProperties(EntityPropertyFlags desir
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingPos, getMaterialMappingPos);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingScale, getMaterialMappingScale);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialMappingRot, getMaterialMappingRot);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(materialData, getMaterialData);
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -49,6 +54,7 @@ bool MaterialEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingPos, setMaterialMappingPos);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingScale, setMaterialMappingScale);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialMappingRot, setMaterialMappingRot);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(materialData, setMaterialData);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -78,6 +84,7 @@ int MaterialEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_POS, glm::vec2, setMaterialMappingPos);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, glm::vec2, setMaterialMappingScale);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, float, setMaterialMappingRot);
|
||||
READ_ENTITY_PROPERTY(PROP_MATERIAL_DATA, QString, setMaterialData);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -93,6 +100,7 @@ EntityPropertyFlags MaterialEntityItem::getEntityProperties(EncodeBitstreamParam
|
|||
requestedProperties += PROP_MATERIAL_MAPPING_POS;
|
||||
requestedProperties += PROP_MATERIAL_MAPPING_SCALE;
|
||||
requestedProperties += PROP_MATERIAL_MAPPING_ROT;
|
||||
requestedProperties += PROP_MATERIAL_DATA;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -112,6 +120,7 @@ void MaterialEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_POS, getMaterialMappingPos());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_SCALE, getMaterialMappingScale());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_MAPPING_ROT, getMaterialMappingRot());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MATERIAL_DATA, getMaterialData());
|
||||
}
|
||||
|
||||
void MaterialEntityItem::debugDump() const {
|
||||
|
@ -145,9 +154,9 @@ std::shared_ptr<NetworkMaterial> MaterialEntityItem::getMaterial() const {
|
|||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool userDataChanged) {
|
||||
bool usingUserData = materialURLString.startsWith("userData");
|
||||
if (_materialURL != materialURLString || (usingUserData && userDataChanged)) {
|
||||
void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool materialDataChanged) {
|
||||
bool usingMaterialData = materialDataChanged || materialURLString.startsWith("materialData");
|
||||
if (_materialURL != materialURLString || (usingMaterialData && materialDataChanged)) {
|
||||
removeMaterial();
|
||||
_materialURL = materialURLString;
|
||||
|
||||
|
@ -156,8 +165,8 @@ void MaterialEntityItem::setMaterialURL(const QString& materialURLString, bool u
|
|||
_currentMaterialName = split.last().toStdString();
|
||||
}
|
||||
|
||||
if (usingUserData) {
|
||||
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getUserData().toUtf8()), materialURLString);
|
||||
if (usingMaterialData) {
|
||||
_parsedMaterials = NetworkMaterialResource::parseJSONMaterials(QJsonDocument::fromJson(getMaterialData().toUtf8()), materialURLString);
|
||||
|
||||
// Since our material changed, the current name might not be valid anymore, so we need to update
|
||||
setCurrentMaterialName(_currentMaterialName);
|
||||
|
@ -191,11 +200,11 @@ void MaterialEntityItem::setCurrentMaterialName(const std::string& currentMateri
|
|||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setUserData(const QString& userData) {
|
||||
if (_userData != userData) {
|
||||
EntityItem::setUserData(userData);
|
||||
if (_materialURL.startsWith("userData")) {
|
||||
// Trigger material update when user data changes
|
||||
void MaterialEntityItem::setMaterialData(const QString& materialData) {
|
||||
if (_materialData != materialData) {
|
||||
_materialData = materialData;
|
||||
if (_materialURL.startsWith("materialData")) {
|
||||
// Trigger material update when material data changes
|
||||
setMaterialURL(_materialURL, true);
|
||||
}
|
||||
}
|
||||
|
@ -249,28 +258,12 @@ void MaterialEntityItem::setParentID(const QUuid& parentID) {
|
|||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setClientOnly(bool clientOnly) {
|
||||
if (getClientOnly() != clientOnly) {
|
||||
removeMaterial();
|
||||
EntityItem::setClientOnly(clientOnly);
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::setOwningAvatarID(const QUuid& owningAvatarID) {
|
||||
if (getOwningAvatarID() != owningAvatarID) {
|
||||
removeMaterial();
|
||||
EntityItem::setOwningAvatarID(owningAvatarID);
|
||||
applyMaterial();
|
||||
}
|
||||
}
|
||||
|
||||
void MaterialEntityItem::removeMaterial() {
|
||||
graphics::MaterialPointer material = getMaterial();
|
||||
if (!material) {
|
||||
return;
|
||||
}
|
||||
QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID();
|
||||
QUuid parentID = getParentID();
|
||||
if (parentID.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
@ -294,7 +287,7 @@ void MaterialEntityItem::removeMaterial() {
|
|||
void MaterialEntityItem::applyMaterial() {
|
||||
_retryApply = false;
|
||||
graphics::MaterialPointer material = getMaterial();
|
||||
QUuid parentID = getClientOnly() ? getOwningAvatarID() : getParentID();
|
||||
QUuid parentID = getParentID();
|
||||
if (!material || parentID.isNull()) {
|
||||
return;
|
||||
}
|
||||
|
@ -328,11 +321,6 @@ void MaterialEntityItem::postParentFixup() {
|
|||
applyMaterial();
|
||||
}
|
||||
|
||||
void MaterialEntityItem::preDelete() {
|
||||
EntityItem::preDelete();
|
||||
removeMaterial();
|
||||
}
|
||||
|
||||
void MaterialEntityItem::update(const quint64& now) {
|
||||
if (_retryApply) {
|
||||
applyMaterial();
|
||||
|
|
|
@ -21,6 +21,7 @@ public:
|
|||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
MaterialEntityItem(const EntityItemID& entityItemID);
|
||||
~MaterialEntityItem();
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
|
@ -53,7 +54,7 @@ public:
|
|||
virtual void setUnscaledDimensions(const glm::vec3& value) override;
|
||||
|
||||
QString getMaterialURL() const { return _materialURL; }
|
||||
void setMaterialURL(const QString& materialURLString, bool userDataChanged = false);
|
||||
void setMaterialURL(const QString& materialURLString, bool materialDataChanged = false);
|
||||
|
||||
void setCurrentMaterialName(const std::string& currentMaterialName);
|
||||
|
||||
|
@ -73,21 +74,20 @@ public:
|
|||
float getMaterialMappingRot() const { return _materialMappingRot; }
|
||||
void setMaterialMappingRot(const float& materialMappingRot);
|
||||
|
||||
QString getMaterialData() const { return _materialData; }
|
||||
void setMaterialData(const QString& materialData);
|
||||
|
||||
std::shared_ptr<NetworkMaterial> getMaterial() const;
|
||||
|
||||
void setUserData(const QString& userData) override;
|
||||
void setParentID(const QUuid& parentID) override;
|
||||
void setClientOnly(bool clientOnly) override;
|
||||
void setOwningAvatarID(const QUuid& owningAvatarID) override;
|
||||
|
||||
void applyMaterial();
|
||||
void removeMaterial();
|
||||
|
||||
void postParentFixup() override;
|
||||
void preDelete() override;
|
||||
|
||||
private:
|
||||
// URL for this material. Currently, only JSON format is supported. Set to "userData" to use the user data to live edit a material.
|
||||
// URL for this material. Currently, only JSON format is supported. Set to "materialData" to use the material data to live edit a material.
|
||||
// The following fields are supported in the JSON:
|
||||
// materialVersion: a uint for the version of this network material (currently, only 1 is supported)
|
||||
// materials, which is either an object or an array of objects, each with the following properties:
|
||||
|
@ -117,6 +117,7 @@ private:
|
|||
glm::vec2 _materialMappingScale { 1, 1 };
|
||||
// How much to rotate this material within its parent's UV-space (degrees)
|
||||
float _materialMappingRot { 0 };
|
||||
QString _materialData;
|
||||
|
||||
NetworkMaterialResourcePointer _networkMaterial;
|
||||
NetworkMaterialResource::ParsedMaterials _parsedMaterials;
|
||||
|
|
|
@ -117,8 +117,10 @@ ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem(
|
|||
|
||||
EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
properties.setColor(getXColor());
|
||||
properties.setShape(entity::stringFromShape(getShape()));
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(alpha, getAlpha);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -105,7 +105,7 @@ public:
|
|||
|
||||
protected:
|
||||
|
||||
float _alpha { 1 }; // FIXME: This property is not used.
|
||||
float _alpha { 1.0f };
|
||||
rgbColor _color;
|
||||
entity::Shape _shape { entity::Shape::Sphere };
|
||||
|
||||
|
|
|
@ -370,7 +370,36 @@ GLenum GLTexelFormat::evalGLTexelFormatInternal(const gpu::Element& dstFormat) {
|
|||
case gpu::COMPRESSED_BC7_SRGBA:
|
||||
result = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
|
||||
break;
|
||||
|
||||
case gpu::COMPRESSED_ETC2_RGB:
|
||||
result = GL_COMPRESSED_RGB8_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGB:
|
||||
result = GL_COMPRESSED_SRGB8_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
|
||||
result = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
|
||||
result = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_RGBA:
|
||||
result = GL_COMPRESSED_RGBA8_ETC2_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGBA:
|
||||
result = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_RED:
|
||||
result = GL_COMPRESSED_R11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_RED_SIGNED:
|
||||
result = GL_COMPRESSED_SIGNED_R11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_XY:
|
||||
result = GL_COMPRESSED_RG11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_XY_SIGNED:
|
||||
result = GL_COMPRESSED_SIGNED_RG11_EAC;
|
||||
break;
|
||||
default:
|
||||
qCWarning(gpugllogging) << "Unknown combination of texel format";
|
||||
}
|
||||
|
@ -531,6 +560,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
|
|||
case gpu::COMPRESSED_BC7_SRGBA:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_RGB:
|
||||
texel.internalFormat = GL_COMPRESSED_RGB8_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGB:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB8_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
|
||||
texel.internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_RGBA:
|
||||
texel.internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGBA:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_RED:
|
||||
texel.internalFormat = GL_COMPRESSED_R11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_RED_SIGNED:
|
||||
texel.internalFormat = GL_COMPRESSED_SIGNED_R11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_XY:
|
||||
texel.internalFormat = GL_COMPRESSED_RG11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_XY_SIGNED:
|
||||
texel.internalFormat = GL_COMPRESSED_SIGNED_RG11_EAC;
|
||||
break;
|
||||
default:
|
||||
qCWarning(gpugllogging) << "Unknown combination of texel format";
|
||||
}
|
||||
|
@ -895,7 +954,36 @@ GLTexelFormat GLTexelFormat::evalGLTexelFormat(const Element& dstFormat, const E
|
|||
case gpu::COMPRESSED_BC7_SRGBA:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM;
|
||||
break;
|
||||
|
||||
case gpu::COMPRESSED_ETC2_RGB:
|
||||
texel.internalFormat = GL_COMPRESSED_RGB8_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGB:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB8_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
|
||||
texel.internalFormat = GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_RGBA:
|
||||
texel.internalFormat = GL_COMPRESSED_RGBA8_ETC2_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_ETC2_SRGBA:
|
||||
texel.internalFormat = GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_RED:
|
||||
texel.internalFormat = GL_COMPRESSED_R11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_RED_SIGNED:
|
||||
texel.internalFormat = GL_COMPRESSED_SIGNED_R11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_XY:
|
||||
texel.internalFormat = GL_COMPRESSED_RG11_EAC;
|
||||
break;
|
||||
case gpu::COMPRESSED_EAC_XY_SIGNED:
|
||||
texel.internalFormat = GL_COMPRESSED_SIGNED_RG11_EAC;
|
||||
break;
|
||||
default:
|
||||
qCWarning(gpugllogging) << "Unknown combination of texel format";
|
||||
}
|
||||
|
|
|
@ -173,6 +173,8 @@ protected:
|
|||
void makeProgramBindings(ShaderObject& shaderObject) override;
|
||||
int makeResourceBufferSlots(GLuint glprogram, const Shader::BindingSet& slotBindings,Shader::SlotSet& resourceBuffers) override;
|
||||
|
||||
static bool supportedTextureFormat(const gpu::Element& format);
|
||||
|
||||
};
|
||||
|
||||
} }
|
||||
|
|
|
@ -19,6 +19,24 @@ using namespace gpu;
|
|||
using namespace gpu::gl;
|
||||
using namespace gpu::gl41;
|
||||
|
||||
bool GL41Backend::supportedTextureFormat(const gpu::Element& format) {
|
||||
switch (format.getSemantic()) {
|
||||
case gpu::Semantic::COMPRESSED_ETC2_RGB:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_SRGB:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_RGBA:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_SRGBA:
|
||||
case gpu::Semantic::COMPRESSED_EAC_RED:
|
||||
case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED:
|
||||
case gpu::Semantic::COMPRESSED_EAC_XY:
|
||||
case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||
if (!texturePointer) {
|
||||
return nullptr;
|
||||
|
@ -34,6 +52,11 @@ GLTexture* GL41Backend::syncGPUObject(const TexturePointer& texturePointer) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Check whether the texture is in a format we can deal with
|
||||
if (!supportedTextureFormat(texture.getTexelFormat())) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
GL41Texture* object = Backend::getGPUObject<GL41Texture>(texture);
|
||||
if (!object) {
|
||||
switch (texture.getUsageType()) {
|
||||
|
|
|
@ -206,6 +206,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
|
|||
case GL_COMPRESSED_RG_RGTC2:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
|
||||
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
|
||||
case GL_COMPRESSED_RGB8_ETC2:
|
||||
case GL_COMPRESSED_SRGB8_ETC2:
|
||||
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case GL_COMPRESSED_RGBA8_ETC2_EAC:
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
||||
case GL_COMPRESSED_R11_EAC:
|
||||
case GL_COMPRESSED_SIGNED_R11_EAC:
|
||||
case GL_COMPRESSED_RG11_EAC:
|
||||
case GL_COMPRESSED_SIGNED_RG11_EAC:
|
||||
glCompressedTextureSubImage2D(_id, mip, 0, yOffset, size.x, size.y, internalFormat,
|
||||
static_cast<GLsizei>(sourceSize), sourcePointer);
|
||||
break;
|
||||
|
@ -222,6 +232,16 @@ Size GL45Texture::copyMipFaceLinesFromTexture(uint16_t mip, uint8_t face, const
|
|||
case GL_COMPRESSED_RG_RGTC2:
|
||||
case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
|
||||
case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
|
||||
case GL_COMPRESSED_RGB8_ETC2:
|
||||
case GL_COMPRESSED_SRGB8_ETC2:
|
||||
case GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case GL_COMPRESSED_RGBA8_ETC2_EAC:
|
||||
case GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
||||
case GL_COMPRESSED_R11_EAC:
|
||||
case GL_COMPRESSED_SIGNED_R11_EAC:
|
||||
case GL_COMPRESSED_RG11_EAC:
|
||||
case GL_COMPRESSED_SIGNED_RG11_EAC:
|
||||
if (glCompressedTextureSubImage2DEXT) {
|
||||
auto target = GLTexture::CUBE_FACE_LAYOUT[face];
|
||||
glCompressedTextureSubImage2DEXT(_id, target, mip, 0, yOffset, size.x, size.y, internalFormat,
|
||||
|
|
|
@ -20,9 +20,21 @@ using namespace gpu::gl;
|
|||
using namespace gpu::gles;
|
||||
|
||||
bool GLESBackend::supportedTextureFormat(const gpu::Element& format) {
|
||||
// FIXME distinguish between GLES and GL compressed formats after support
|
||||
// for the former is added to gpu::Element
|
||||
return !format.isCompressed();
|
||||
switch (format.getSemantic()) {
|
||||
case gpu::Semantic::COMPRESSED_ETC2_RGB:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_SRGB:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_SRGB_PUNCHTHROUGH_ALPHA:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_RGBA:
|
||||
case gpu::Semantic::COMPRESSED_ETC2_SRGBA:
|
||||
case gpu::Semantic::COMPRESSED_EAC_RED:
|
||||
case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED:
|
||||
case gpu::Semantic::COMPRESSED_EAC_XY:
|
||||
case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED:
|
||||
return true;
|
||||
default:
|
||||
return !format.isCompressed();
|
||||
}
|
||||
}
|
||||
|
||||
GLTexture* GLESBackend::syncGPUObject(const TexturePointer& texturePointer) {
|
||||
|
@ -231,6 +243,29 @@ GLESFixedAllocationTexture::GLESFixedAllocationTexture(const std::weak_ptr<GLBac
|
|||
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 {
|
||||
const GLTexelFormat texelFormat = GLTexelFormat::evalGLTexelFormat(_gpuObject.getTexelFormat());
|
||||
const auto numMips = _gpuObject.getNumMips();
|
||||
|
@ -239,7 +274,12 @@ void GLESFixedAllocationTexture::allocateStorage() const {
|
|||
for (GLint level = 0; level < numMips; level++) {
|
||||
Vec3u dimensions = _gpuObject.evalMipDimensions(level);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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_COMPRESSED_RED{ TILE4x4, COMPRESSED, COMPRESSED_BC4_RED };
|
||||
const Element Element::COLOR_COMPRESSED_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB };
|
||||
const Element Element::COLOR_COMPRESSED_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };
|
||||
const Element Element::COLOR_COMPRESSED_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA };
|
||||
const Element Element::COLOR_COMPRESSED_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY };
|
||||
const Element Element::COLOR_COMPRESSED_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_RED { TILE4x4, COMPRESSED, COMPRESSED_BC4_RED };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_SRGB { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGB };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_SRGBA_MASK { TILE4x4, COMPRESSED, COMPRESSED_BC1_SRGBA };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_SRGBA { TILE4x4, COMPRESSED, COMPRESSED_BC3_SRGBA };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_XY { TILE4x4, COMPRESSED, COMPRESSED_BC5_XY };
|
||||
const Element Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH { TILE4x4, COMPRESSED, COMPRESSED_BC7_SRGBA };
|
||||
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 };
|
||||
|
||||
|
|
|
@ -194,6 +194,17 @@ enum Semantic : uint8_t {
|
|||
COMPRESSED_BC6_RGB,
|
||||
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,
|
||||
|
||||
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_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, //R11G11B10,
|
||||
|
@ -316,13 +338,23 @@ public:
|
|||
static const Element COLOR_RGBA_2;
|
||||
static const Element COLOR_R11G11B10;
|
||||
static const Element COLOR_RGB9E5;
|
||||
static const Element COLOR_COMPRESSED_RED;
|
||||
static const Element COLOR_COMPRESSED_SRGB;
|
||||
static const Element COLOR_COMPRESSED_SRGBA_MASK;
|
||||
static const Element COLOR_COMPRESSED_SRGBA;
|
||||
static const Element COLOR_COMPRESSED_XY;
|
||||
static const Element COLOR_COMPRESSED_SRGBA_HIGH;
|
||||
static const Element COLOR_COMPRESSED_HDR_RGB;
|
||||
static const Element COLOR_COMPRESSED_BCX_RED;
|
||||
static const Element COLOR_COMPRESSED_BCX_SRGB;
|
||||
static const Element COLOR_COMPRESSED_BCX_SRGBA_MASK;
|
||||
static const Element COLOR_COMPRESSED_BCX_SRGBA;
|
||||
static const Element COLOR_COMPRESSED_BCX_XY;
|
||||
static const Element COLOR_COMPRESSED_BCX_SRGBA_HIGH;
|
||||
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 VEC4F_COLOR_RGBA;
|
||||
static const Element VEC2F_UV;
|
||||
|
|
|
@ -128,6 +128,7 @@ public:
|
|||
uint8 _wrapModeV = WRAP_REPEAT;
|
||||
uint8 _wrapModeW = WRAP_REPEAT;
|
||||
|
||||
uint8 _mipOffset = 0;
|
||||
uint8 _minMip = 0;
|
||||
uint8 _maxMip = MAX_MIP_LEVEL;
|
||||
|
||||
|
@ -142,6 +143,7 @@ public:
|
|||
_wrapModeU == other._wrapModeU &&
|
||||
_wrapModeV == other._wrapModeV &&
|
||||
_wrapModeW == other._wrapModeW &&
|
||||
_mipOffset == other._mipOffset &&
|
||||
_minMip == other._minMip &&
|
||||
_maxMip == other._maxMip;
|
||||
}
|
||||
|
@ -164,6 +166,7 @@ public:
|
|||
ComparisonFunction getComparisonFunction() const { return ComparisonFunction(_desc._comparisonFunc); }
|
||||
bool doComparison() const { return getComparisonFunction() != ALWAYS; }
|
||||
|
||||
uint8 getMipOffset() const { return _desc._mipOffset; }
|
||||
uint8 getMinMip() const { return _desc._minMip; }
|
||||
uint8 getMaxMip() const { return _desc._maxMip; }
|
||||
|
||||
|
|
|
@ -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);
|
||||
} 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);
|
||||
} 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);
|
||||
} 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);
|
||||
} 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);
|
||||
} 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);
|
||||
} 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);
|
||||
} 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);
|
||||
} 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);
|
||||
} 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) {
|
||||
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) {
|
||||
|
@ -642,31 +662,45 @@ bool Texture::evalTextureFormat(const ktx::Header& header, Element& mipFormat, E
|
|||
texelFormat = Format::COLOR_RGB9E5;
|
||||
} else if (header.isCompressed()) {
|
||||
if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT) {
|
||||
mipFormat = Format::COLOR_COMPRESSED_SRGB;
|
||||
texelFormat = Format::COLOR_COMPRESSED_SRGB;
|
||||
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGB;
|
||||
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT) {
|
||||
mipFormat = Format::COLOR_COMPRESSED_SRGBA_MASK;
|
||||
texelFormat = Format::COLOR_COMPRESSED_SRGBA_MASK;
|
||||
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_MASK;
|
||||
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT) {
|
||||
mipFormat = Format::COLOR_COMPRESSED_SRGBA;
|
||||
texelFormat = Format::COLOR_COMPRESSED_SRGBA;
|
||||
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA;
|
||||
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RED_RGTC1) {
|
||||
mipFormat = Format::COLOR_COMPRESSED_RED;
|
||||
texelFormat = Format::COLOR_COMPRESSED_RED;
|
||||
texelFormat = Format::COLOR_COMPRESSED_BCX_RED;
|
||||
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RG_RGTC2) {
|
||||
mipFormat = Format::COLOR_COMPRESSED_XY;
|
||||
texelFormat = Format::COLOR_COMPRESSED_XY;
|
||||
texelFormat = Format::COLOR_COMPRESSED_BCX_XY;
|
||||
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM) {
|
||||
mipFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH;
|
||||
texelFormat = Format::COLOR_COMPRESSED_SRGBA_HIGH;
|
||||
texelFormat = Format::COLOR_COMPRESSED_BCX_SRGBA_HIGH;
|
||||
} else if (header.getGLInternaFormat() == ktx::GLInternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT) {
|
||||
mipFormat = Format::COLOR_COMPRESSED_HDR_RGB;
|
||||
texelFormat = Format::COLOR_COMPRESSED_HDR_RGB;
|
||||
texelFormat = Format::COLOR_COMPRESSED_BCX_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 {
|
||||
return false;
|
||||
}
|
||||
mipFormat = texelFormat;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -87,6 +87,17 @@ namespace gpu {
|
|||
{ Semantic::COMPRESSED_BC6_RGB, "compressed_bc6_rgb" },
|
||||
{ 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::R11G11B10, "r11g11b10" },
|
||||
|
|
|
@ -466,7 +466,8 @@ void generateHDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
|
|||
nvtt::CompressionOptions compressionOptions;
|
||||
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);
|
||||
} else if (mipFormat == gpu::Element::COLOR_RGB9E5) {
|
||||
compressionOptions.setFormat(nvtt::Format_RGB);
|
||||
|
@ -583,20 +584,21 @@ void generateLDRMips(gpu::Texture* texture, QImage&& image, const std::atomic<bo
|
|||
nvtt::CompressionOptions compressionOptions;
|
||||
compressionOptions.setQuality(nvtt::Quality_Production);
|
||||
|
||||
// TODO: gles: generate ETC mips instead?
|
||||
auto mipFormat = texture->getStoredMipFormat();
|
||||
if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGB) {
|
||||
if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGB) {
|
||||
compressionOptions.setFormat(nvtt::Format_BC1);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA_MASK) {
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_MASK) {
|
||||
alphaMode = nvtt::AlphaMode_Transparency;
|
||||
compressionOptions.setFormat(nvtt::Format_BC1a);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA) {
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA) {
|
||||
alphaMode = nvtt::AlphaMode_Transparency;
|
||||
compressionOptions.setFormat(nvtt::Format_BC3);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_RED) {
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_RED) {
|
||||
compressionOptions.setFormat(nvtt::Format_BC4);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_XY) {
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_XY) {
|
||||
compressionOptions.setFormat(nvtt::Format_BC5);
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_SRGBA_HIGH) {
|
||||
} else if (mipFormat == gpu::Element::COLOR_COMPRESSED_BCX_SRGBA_HIGH) {
|
||||
alphaMode = nvtt::AlphaMode_Transparency;
|
||||
compressionOptions.setFormat(nvtt::Format_BC7);
|
||||
} else if (mipFormat == gpu::Element::COLOR_RGBA_32) {
|
||||
|
@ -736,13 +738,21 @@ gpu::TexturePointer TextureUsage::process2DTextureColorFromImage(QImage&& srcIma
|
|||
gpu::Element formatMip;
|
||||
gpu::Element formatGPU;
|
||||
if (isColorTexturesCompressionEnabled()) {
|
||||
#ifndef USE_GLES
|
||||
if (validAlpha) {
|
||||
// NOTE: This disables BC1a compression because it was producing odd artifacts on text textures
|
||||
// for the tutorial. Instead we use BC3 (which is larger) but doesn't produce the same artifacts).
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_SRGBA;
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGBA;
|
||||
} else {
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_SRGB;
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_SRGB;
|
||||
}
|
||||
#else
|
||||
if (validAlpha) {
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGBA;
|
||||
} else {
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_ETC2_SRGB;
|
||||
}
|
||||
#endif
|
||||
formatMip = formatGPU;
|
||||
} else {
|
||||
#ifdef USE_GLES
|
||||
|
@ -869,8 +879,12 @@ gpu::TexturePointer TextureUsage::process2DTextureNormalMapFromImage(QImage&& sr
|
|||
gpu::Element formatMip = gpu::Element::VEC2NU8_XY;
|
||||
gpu::Element formatGPU = gpu::Element::VEC2NU8_XY;
|
||||
if (isNormalTexturesCompressionEnabled()) {
|
||||
formatMip = gpu::Element::COLOR_COMPRESSED_XY;
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_XY;
|
||||
#ifndef USE_GLES
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_XY;
|
||||
#else
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_XY;
|
||||
#endif
|
||||
formatMip = formatGPU;
|
||||
}
|
||||
|
||||
theTexture = gpu::Texture::create2D(formatGPU, image.width(), image.height(), gpu::Texture::MAX_NUM_MIPS, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_MIP_LINEAR));
|
||||
|
@ -903,8 +917,12 @@ gpu::TexturePointer TextureUsage::process2DTextureGrayscaleFromImage(QImage&& sr
|
|||
gpu::Element formatMip;
|
||||
gpu::Element formatGPU;
|
||||
if (isGrayscaleTexturesCompressionEnabled()) {
|
||||
formatMip = gpu::Element::COLOR_COMPRESSED_RED;
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_RED;
|
||||
#ifndef USE_GLES
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_RED;
|
||||
#else
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_EAC_RED;
|
||||
#endif
|
||||
formatMip = formatGPU;
|
||||
} else {
|
||||
formatMip = gpu::Element::COLOR_R_8;
|
||||
formatGPU = gpu::Element::COLOR_R_8;
|
||||
|
@ -1271,8 +1289,9 @@ gpu::TexturePointer TextureUsage::processCubeTextureColorFromImage(QImage&& srcI
|
|||
gpu::Element formatMip;
|
||||
gpu::Element formatGPU;
|
||||
if (isCubeTexturesCompressionEnabled()) {
|
||||
formatMip = gpu::Element::COLOR_COMPRESSED_HDR_RGB;
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_HDR_RGB;
|
||||
// TODO: gles: pick HDR ETC format
|
||||
formatMip = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
|
||||
formatGPU = gpu::Element::COLOR_COMPRESSED_BCX_HDR_RGB;
|
||||
} else {
|
||||
formatMip = HDR_FORMAT;
|
||||
formatGPU = HDR_FORMAT;
|
||||
|
|
|
@ -358,6 +358,17 @@ namespace khronos {
|
|||
case InternalFormat::COMPRESSED_RG_RGTC2: // BC5
|
||||
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT: // BC6
|
||||
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM: // BC7
|
||||
// ETC2 / EAC
|
||||
case InternalFormat::COMPRESSED_RGB8_ETC2:
|
||||
case InternalFormat::COMPRESSED_SRGB8_ETC2:
|
||||
case InternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case InternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case InternalFormat::COMPRESSED_RGBA8_ETC2_EAC:
|
||||
case InternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
||||
case InternalFormat::COMPRESSED_R11_EAC:
|
||||
case InternalFormat::COMPRESSED_SIGNED_R11_EAC:
|
||||
case InternalFormat::COMPRESSED_RG11_EAC:
|
||||
case InternalFormat::COMPRESSED_SIGNED_RG11_EAC:
|
||||
return evalAlignedCompressedBlockCount<4>(value);
|
||||
|
||||
default:
|
||||
|
@ -370,12 +381,22 @@ namespace khronos {
|
|||
case InternalFormat::COMPRESSED_SRGB_S3TC_DXT1_EXT:
|
||||
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT:
|
||||
case InternalFormat::COMPRESSED_RED_RGTC1:
|
||||
case InternalFormat::COMPRESSED_RGB8_ETC2:
|
||||
case InternalFormat::COMPRESSED_SRGB8_ETC2:
|
||||
case InternalFormat::COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case InternalFormat::COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2:
|
||||
case InternalFormat::COMPRESSED_R11_EAC:
|
||||
case InternalFormat::COMPRESSED_SIGNED_R11_EAC:
|
||||
return 8;
|
||||
|
||||
case InternalFormat::COMPRESSED_SRGB_ALPHA_BPTC_UNORM:
|
||||
case InternalFormat::COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT:
|
||||
case InternalFormat::COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT:
|
||||
case InternalFormat::COMPRESSED_RG_RGTC2:
|
||||
case InternalFormat::COMPRESSED_RGBA8_ETC2_EAC:
|
||||
case InternalFormat::COMPRESSED_SRGB8_ALPHA8_ETC2_EAC:
|
||||
case InternalFormat::COMPRESSED_RG11_EAC:
|
||||
case InternalFormat::COMPRESSED_SIGNED_RG11_EAC:
|
||||
return 16;
|
||||
|
||||
default:
|
||||
|
|
|
@ -39,6 +39,10 @@ bool AddressManager::isConnected() {
|
|||
return DependencyManager::get<NodeList>()->getDomainHandler().isConnected();
|
||||
}
|
||||
|
||||
QString AddressManager::getProtocol() const {
|
||||
return _domainURL.scheme();
|
||||
}
|
||||
|
||||
QUrl AddressManager::currentAddress(bool domainOnly) const {
|
||||
QUrl hifiURL = _domainURL;
|
||||
|
||||
|
|
|
@ -145,7 +145,7 @@ public:
|
|||
};
|
||||
|
||||
bool isConnected();
|
||||
const QString& getProtocol() { return URL_SCHEME_HIFI; };
|
||||
QString getProtocol() const;
|
||||
|
||||
QUrl currentAddress(bool domainOnly = false) const;
|
||||
QUrl currentFacingAddress() const;
|
||||
|
|
|
@ -30,7 +30,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
case PacketType::EntityPhysics:
|
||||
return static_cast<PacketVersion>(EntityVersion::ShadowControl);
|
||||
return static_cast<PacketVersion>(EntityVersion::MaterialData);
|
||||
case PacketType::EntityQuery:
|
||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::RemovedJurisdictions);
|
||||
case PacketType::AvatarIdentity:
|
||||
|
|
|
@ -231,7 +231,8 @@ enum class EntityVersion : PacketVersion {
|
|||
ZoneStageRemoved,
|
||||
SoftEntities,
|
||||
MaterialEntities,
|
||||
ShadowControl
|
||||
ShadowControl,
|
||||
MaterialData
|
||||
};
|
||||
|
||||
enum class EntityScriptCallMethodVersion : PacketVersion {
|
||||
|
|
|
@ -532,7 +532,7 @@ void RenderDeferredSetup::run(const render::RenderContextPointer& renderContext,
|
|||
}
|
||||
}
|
||||
|
||||
auto& program = deferredLightingEffect->_directionalSkyboxLight;
|
||||
auto program = deferredLightingEffect->_directionalSkyboxLight;
|
||||
LightLocationsPtr locations = deferredLightingEffect->_directionalSkyboxLightLocations;
|
||||
|
||||
auto keyLight = lightAndShadow.first;
|
||||
|
|
|
@ -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) {
|
||||
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
if (!item) {
|
||||
|
|
|
@ -60,6 +60,7 @@ public:
|
|||
void createDesktop(const QUrl& url);
|
||||
void show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
void hide(const QString& name);
|
||||
void hideDesktopWindows();
|
||||
bool isVisible(const QString& name);
|
||||
void toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
|
||||
bool shouldSwallowShortcut(QEvent* event);
|
||||
|
|
|
@ -387,6 +387,8 @@ void TabletProxy::setToolbarMode(bool toolbarMode) {
|
|||
offscreenUi->hide("RunningScripts");
|
||||
_showRunningScripts = true;
|
||||
}
|
||||
|
||||
offscreenUi->hideDesktopWindows();
|
||||
// destroy desktop window
|
||||
if (_desktopWindow) {
|
||||
_desktopWindow->deleteLater();
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
//
|
||||
// Grab's physically moveable entities with the mouse, by applying a spring force.
|
||||
//
|
||||
// Updated November 22, 2016 by Philip Rosedale: Add distance attenuation of grab effect
|
||||
// Updated November 22, 2016 by Philip Rosedale: Add distance attenuation of grab effect
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
@ -444,6 +444,7 @@ Grabber.prototype.releaseEvent = function(event) {
|
|||
this.actionID = null;
|
||||
|
||||
Pointers.setRenderState(this.mouseRayEntities, "");
|
||||
Pointers.setLockEndUUID(this.mouseRayEntities, null, false);
|
||||
|
||||
var args = "mouse";
|
||||
Entities.callEntityMethod(this.entityID, "releaseGrab", args);
|
||||
|
|
|
@ -416,6 +416,12 @@ var toolBar = (function () {
|
|||
// default:
|
||||
// shapeType = "uv";
|
||||
//}
|
||||
var materialData = "";
|
||||
if (materialURL.startsWith("materialData")) {
|
||||
materialData = JSON.stringify({
|
||||
"materials": {}
|
||||
})
|
||||
}
|
||||
|
||||
var DEFAULT_LAYERED_MATERIAL_PRIORITY = 1;
|
||||
if (materialURL) {
|
||||
|
@ -423,7 +429,8 @@ var toolBar = (function () {
|
|||
type: "Material",
|
||||
materialURL: materialURL,
|
||||
//materialMappingMode: materialMappingMode,
|
||||
priority: DEFAULT_LAYERED_MATERIAL_PRIORITY
|
||||
priority: DEFAULT_LAYERED_MATERIAL_PRIORITY,
|
||||
materialData: materialData
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -2061,7 +2068,7 @@ var PropertiesTool = function (opts) {
|
|||
parentSelectedEntities();
|
||||
} else if (data.type === 'unparent') {
|
||||
unparentSelectedEntities();
|
||||
} else if (data.type === 'saveUserData') {
|
||||
} else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') {
|
||||
//the event bridge and json parsing handle our avatar id string differently.
|
||||
var actualID = data.id.split('"')[1];
|
||||
Entities.editEntity(actualID, data.properties);
|
||||
|
|
|
@ -1387,12 +1387,14 @@ input#reset-to-natural-dimensions {
|
|||
margin-top: 48px;
|
||||
}
|
||||
|
||||
#userdata-clear{
|
||||
#userdata-clear,
|
||||
#materialdata-clear {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
|
||||
#static-userdata {
|
||||
#static-userdata,
|
||||
#static-materialData {
|
||||
display: none;
|
||||
z-index: 99;
|
||||
position: absolute;
|
||||
|
@ -1403,7 +1405,8 @@ input#reset-to-natural-dimensions {
|
|||
background-color: #2e2e2e;
|
||||
}
|
||||
|
||||
#userdata-saved {
|
||||
#userdata-saved,
|
||||
#materialData-saved {
|
||||
margin-top:5px;
|
||||
font-size:16px;
|
||||
display:none;
|
||||
|
|
|
@ -781,6 +781,20 @@
|
|||
<label for="property-material-url">Material URL</label>
|
||||
<input type="text" id="property-material-url">
|
||||
</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 class="minor">
|
||||
<div class="material-group material-section property text" id="property-parent-material-id-string-container">
|
||||
|
|
|
@ -66,6 +66,7 @@ function enableProperties() {
|
|||
|
||||
if (elLocked.checked === false) {
|
||||
removeStaticUserData();
|
||||
removeStaticMaterialData();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -78,8 +79,13 @@ function disableProperties() {
|
|||
}
|
||||
var elLocked = document.getElementById("property-locked");
|
||||
|
||||
if ($('#userdata-editor').css('display') === "block" && elLocked.checked === true) {
|
||||
showStaticUserData();
|
||||
if (elLocked.checked === true) {
|
||||
if ($('#userdata-editor').css('display') === "block") {
|
||||
showStaticUserData();
|
||||
}
|
||||
if ($('#materialdata-editor').css('display') === "block") {
|
||||
showStaticMaterialData();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,15 +362,139 @@ function userDataChanger(groupName, keyName, values, userDataElement, defaultVal
|
|||
multiDataUpdater(groupName, val, userDataElement, def);
|
||||
}
|
||||
|
||||
function setMaterialDataFromEditor(noUpdate) {
|
||||
var json = null;
|
||||
try {
|
||||
json = materialEditor.get();
|
||||
} catch (e) {
|
||||
alert('Invalid JSON code - look for red X in your code ', +e);
|
||||
}
|
||||
if (json === null) {
|
||||
return;
|
||||
} else {
|
||||
var text = materialEditor.getText();
|
||||
if (noUpdate === true) {
|
||||
EventBridge.emitWebEvent(
|
||||
JSON.stringify({
|
||||
id: lastEntityID,
|
||||
type: "saveMaterialData",
|
||||
properties: {
|
||||
materialData: text
|
||||
}
|
||||
})
|
||||
);
|
||||
return;
|
||||
} else {
|
||||
updateProperty('materialData', text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function setTextareaScrolling(element) {
|
||||
var isScrolling = element.scrollHeight > element.offsetHeight;
|
||||
element.setAttribute("scrolling", isScrolling ? "true" : "false");
|
||||
}
|
||||
|
||||
|
||||
var materialEditor = null;
|
||||
|
||||
function createJSONMaterialEditor() {
|
||||
var container = document.getElementById("materialdata-editor");
|
||||
var options = {
|
||||
search: false,
|
||||
mode: 'tree',
|
||||
modes: ['code', 'tree'],
|
||||
name: 'materialData',
|
||||
onModeChange: function() {
|
||||
$('.jsoneditor-poweredBy').remove();
|
||||
},
|
||||
onError: function(e) {
|
||||
alert('JSON editor:' + e);
|
||||
},
|
||||
onChange: function() {
|
||||
var currentJSONString = materialEditor.getText();
|
||||
|
||||
if (currentJSONString === '{"":""}') {
|
||||
return;
|
||||
}
|
||||
$('#materialdata-save').attr('disabled', false);
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
materialEditor = new JSONEditor(container, options);
|
||||
}
|
||||
|
||||
function hideNewJSONMaterialEditorButton() {
|
||||
$('#materialdata-new-editor').hide();
|
||||
}
|
||||
|
||||
function showSaveMaterialDataButton() {
|
||||
$('#materialdata-save').show();
|
||||
}
|
||||
|
||||
function hideSaveMaterialDataButton() {
|
||||
$('#materialdata-save').hide();
|
||||
}
|
||||
|
||||
function showNewJSONMaterialEditorButton() {
|
||||
$('#materialdata-new-editor').show();
|
||||
}
|
||||
|
||||
function showMaterialDataTextArea() {
|
||||
$('#property-material-data').show();
|
||||
}
|
||||
|
||||
function hideMaterialDataTextArea() {
|
||||
$('#property-material-data').hide();
|
||||
}
|
||||
|
||||
function showStaticMaterialData() {
|
||||
if (materialEditor !== null) {
|
||||
$('#static-materialdata').show();
|
||||
$('#static-materialdata').css('height', $('#materialdata-editor').height());
|
||||
$('#static-materialdata').text(materialEditor.getText());
|
||||
}
|
||||
}
|
||||
|
||||
function removeStaticMaterialData() {
|
||||
$('#static-materialdata').hide();
|
||||
}
|
||||
|
||||
function setMaterialEditorJSON(json) {
|
||||
materialEditor.set(json);
|
||||
if (materialEditor.hasOwnProperty('expandAll')) {
|
||||
materialEditor.expandAll();
|
||||
}
|
||||
}
|
||||
|
||||
function getMaterialEditorJSON() {
|
||||
return materialEditor.get();
|
||||
}
|
||||
|
||||
function deleteJSONMaterialEditor() {
|
||||
if (materialEditor !== null) {
|
||||
materialEditor.destroy();
|
||||
materialEditor = null;
|
||||
}
|
||||
}
|
||||
|
||||
var savedMaterialJSONTimer = null;
|
||||
|
||||
function saveJSONMaterialData(noUpdate) {
|
||||
setMaterialDataFromEditor(noUpdate);
|
||||
$('#materialdata-saved').show();
|
||||
$('#materialdata-save').attr('disabled', true);
|
||||
if (savedMaterialJSONTimer !== null) {
|
||||
clearTimeout(savedMaterialJSONTimer);
|
||||
}
|
||||
savedMaterialJSONTimer = setTimeout(function() {
|
||||
$('#materialdata-saved').hide();
|
||||
|
||||
}, EDITOR_TIMEOUT_DURATION);
|
||||
}
|
||||
|
||||
var editor = null;
|
||||
var editorTimeout = null;
|
||||
var lastJSONString = null;
|
||||
|
||||
function createJSONEditor() {
|
||||
var container = document.getElementById("userdata-editor");
|
||||
|
@ -395,11 +525,6 @@ function createJSONEditor() {
|
|||
|
||||
function hideNewJSONEditorButton() {
|
||||
$('#userdata-new-editor').hide();
|
||||
|
||||
}
|
||||
|
||||
function hideClearUserDataButton() {
|
||||
$('#userdata-clear').hide();
|
||||
}
|
||||
|
||||
function showSaveUserDataButton() {
|
||||
|
@ -408,17 +533,10 @@ function showSaveUserDataButton() {
|
|||
|
||||
function hideSaveUserDataButton() {
|
||||
$('#userdata-save').hide();
|
||||
|
||||
}
|
||||
|
||||
function showNewJSONEditorButton() {
|
||||
$('#userdata-new-editor').show();
|
||||
|
||||
}
|
||||
|
||||
function showClearUserDataButton() {
|
||||
$('#userdata-clear').show();
|
||||
|
||||
}
|
||||
|
||||
function showUserDataTextArea() {
|
||||
|
@ -446,7 +564,6 @@ function setEditorJSON(json) {
|
|||
if (editor.hasOwnProperty('expandAll')) {
|
||||
editor.expandAll();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getEditorJSON() {
|
||||
|
@ -484,12 +601,15 @@ function bindAllNonJSONEditorElements() {
|
|||
// TODO FIXME: (JSHint) Functions declared within loops referencing
|
||||
// an outer scoped variable may lead to confusing semantics.
|
||||
field.on('focus', function(e) {
|
||||
if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear") {
|
||||
if (e.target.id === "userdata-new-editor" || e.target.id === "userdata-clear" || e.target.id === "materialdata-new-editor" || e.target.id === "materialdata-clear") {
|
||||
return;
|
||||
} else {
|
||||
if ($('#userdata-editor').css('height') !== "0px") {
|
||||
saveJSONUserData(true);
|
||||
}
|
||||
if ($('#materialdata-editor').css('height') !== "0px") {
|
||||
saveJSONMaterialData(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -652,6 +772,10 @@ function loaded() {
|
|||
var elMaterialMappingScaleX = document.getElementById("property-material-mapping-scale-x");
|
||||
var elMaterialMappingScaleY = document.getElementById("property-material-mapping-scale-y");
|
||||
var elMaterialMappingRot = document.getElementById("property-material-mapping-rot");
|
||||
var elMaterialData = document.getElementById("property-material-data");
|
||||
var elClearMaterialData = document.getElementById("materialdata-clear");
|
||||
var elSaveMaterialData = document.getElementById("materialdata-save");
|
||||
var elNewJSONMaterialEditor = document.getElementById('materialdata-new-editor');
|
||||
|
||||
var elImageURL = document.getElementById("property-image-url");
|
||||
|
||||
|
@ -772,9 +896,15 @@ function loaded() {
|
|||
} else if (data.type === "update") {
|
||||
|
||||
if (!data.selections || data.selections.length === 0) {
|
||||
if (editor !== null && lastEntityID !== null) {
|
||||
saveJSONUserData(true);
|
||||
deleteJSONEditor();
|
||||
if (lastEntityID !== null) {
|
||||
if (editor !== null) {
|
||||
saveJSONUserData(true);
|
||||
deleteJSONEditor();
|
||||
}
|
||||
if (materialEditor !== null) {
|
||||
saveJSONMaterialData(true);
|
||||
deleteJSONMaterialEditor();
|
||||
}
|
||||
}
|
||||
elTypeIcon.style.display = "none";
|
||||
elType.innerHTML = "<i>No selection</i>";
|
||||
|
@ -783,6 +913,7 @@ function loaded() {
|
|||
disableProperties();
|
||||
} else if (data.selections && data.selections.length > 1) {
|
||||
deleteJSONEditor();
|
||||
deleteJSONMaterialEditor();
|
||||
var selections = data.selections;
|
||||
|
||||
var ids = [];
|
||||
|
@ -815,8 +946,13 @@ function loaded() {
|
|||
} else {
|
||||
|
||||
properties = data.selections[0].properties;
|
||||
if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null && editor !== null) {
|
||||
saveJSONUserData(true);
|
||||
if (lastEntityID !== '"' + properties.id + '"' && lastEntityID !== null) {
|
||||
if (editor !== null) {
|
||||
saveJSONUserData(true);
|
||||
}
|
||||
if (materialEditor !== null) {
|
||||
saveJSONMaterialData(true);
|
||||
}
|
||||
}
|
||||
|
||||
var doSelectElement = lastEntityID === '"' + properties.id + '"';
|
||||
|
@ -993,6 +1129,28 @@ function loaded() {
|
|||
hideNewJSONEditorButton();
|
||||
}
|
||||
|
||||
var materialJson = null;
|
||||
try {
|
||||
materialJson = JSON.parse(properties.materialData);
|
||||
} catch (e) {
|
||||
// normal text
|
||||
deleteJSONMaterialEditor();
|
||||
elMaterialData.value = properties.materialData;
|
||||
showMaterialDataTextArea();
|
||||
showNewJSONMaterialEditorButton();
|
||||
hideSaveMaterialDataButton();
|
||||
}
|
||||
if (materialJson !== null) {
|
||||
if (materialEditor === null) {
|
||||
createJSONMaterialEditor();
|
||||
}
|
||||
|
||||
setMaterialEditorJSON(materialJson);
|
||||
showSaveMaterialDataButton();
|
||||
hideMaterialDataTextArea();
|
||||
hideNewJSONMaterialEditorButton();
|
||||
}
|
||||
|
||||
elHyperlinkHref.value = properties.href;
|
||||
elDescription.value = properties.description;
|
||||
|
||||
|
@ -1200,6 +1358,7 @@ function loaded() {
|
|||
} else {
|
||||
enableProperties();
|
||||
elSaveUserData.disabled = true;
|
||||
elSaveMaterialData.disabled = true;
|
||||
}
|
||||
|
||||
var activeElement = document.activeElement;
|
||||
|
@ -1384,6 +1543,31 @@ function loaded() {
|
|||
showSaveUserDataButton();
|
||||
});
|
||||
|
||||
elClearMaterialData.addEventListener("click", function() {
|
||||
deleteJSONMaterialEditor();
|
||||
elMaterialData.value = "";
|
||||
showMaterialDataTextArea();
|
||||
showNewJSONMaterialEditorButton();
|
||||
hideSaveMaterialDataButton();
|
||||
updateProperty('materialData', elMaterialData.value);
|
||||
});
|
||||
|
||||
elSaveMaterialData.addEventListener("click", function() {
|
||||
saveJSONMaterialData(true);
|
||||
});
|
||||
|
||||
elMaterialData.addEventListener('change', createEmitTextPropertyUpdateFunction('materialData'));
|
||||
|
||||
elNewJSONMaterialEditor.addEventListener('click', function() {
|
||||
deleteJSONMaterialEditor();
|
||||
createJSONMaterialEditor();
|
||||
var data = {};
|
||||
setMaterialEditorJSON(data);
|
||||
hideMaterialDataTextArea();
|
||||
hideNewJSONMaterialEditorButton();
|
||||
showSaveMaterialDataButton();
|
||||
});
|
||||
|
||||
var colorChangeFunction = createEmitColorPropertyUpdateFunction(
|
||||
'color', elColorRed, elColorGreen, elColorBlue);
|
||||
elColorRed.addEventListener('change', colorChangeFunction);
|
||||
|
|
|
@ -44,26 +44,35 @@ def groupKTXFiles(directory, filePath):
|
|||
originalFilePath.strip()
|
||||
shutil.move(originalFilePath, newFilePath)
|
||||
|
||||
def bakeFile(filePath, outputDirectory):
|
||||
def bakeFile(filePath, outputDirectory, fileType):
|
||||
createDirectory(outputDirectory)
|
||||
cmd = EXE + ' -i ' + filePath + ' -o ' + outputDirectory + ' -t fbx'
|
||||
cmd = EXE + ' -i ' + filePath + ' -o ' + outputDirectory + ' -t ' + fileType
|
||||
args = shlex.split(cmd)
|
||||
process = subprocess.Popen(cmd, stdout=False, stderr=False)
|
||||
process.wait()
|
||||
bakedFile = os.path.splitext(filePath)[0]
|
||||
groupKTXFiles(outputDirectory, bakedFile)
|
||||
if fileType == 'fbx':
|
||||
groupKTXFiles(outputDirectory, bakedFile)
|
||||
|
||||
def bakeFilesInDirectory(directory, outputDirectory):
|
||||
rootDirectory = os.path.basename(os.path.normpath(directory))
|
||||
for root, subFolders, filenames in os.walk(directory):
|
||||
for filename in filenames:
|
||||
appendPath = getRelativePath(directory, root, rootDirectory);
|
||||
name, ext = os.path.splitext('file.txt')
|
||||
if filename.endswith('.fbx'):
|
||||
filePath = os.sep.join([root, filename])
|
||||
absFilePath = os.path.abspath(filePath)
|
||||
outputFolder = os.path.join(outputDirectory, appendPath)
|
||||
print "Baking file: " + filename
|
||||
bakeFile(absFilePath, outputFolder)
|
||||
bakeFile(absFilePath, outputFolder, 'fbx')
|
||||
elif os.path.basename(root) == 'skyboxes':
|
||||
filePath = os.sep.join([root, filename])
|
||||
absFilePath = os.path.abspath(filePath)
|
||||
outputFolder = os.path.join(outputDirectory, appendPath)
|
||||
print "Baking file: " + filename
|
||||
bakeType = os.path.splitext(filename)[1][1:]
|
||||
bakeFile(absFilePath, outputFolder, bakeType)
|
||||
else:
|
||||
filePath = os.sep.join([root, filename])
|
||||
absFilePath = os.path.abspath(filePath)
|
||||
|
|
|
@ -6,7 +6,7 @@ def createAssetMapping(assetDirectory):
|
|||
baseDirectory = os.path.basename(os.path.normpath(assetDirectory))
|
||||
for root, subfolder, filenames in os.walk(assetDirectory):
|
||||
for filename in filenames:
|
||||
if not filename.endswith('.ktx'):
|
||||
if not filename.endswith('.ktx') or os.path.basename(root) == 'skyboxes':
|
||||
substring = os.path.commonprefix([assetDirectory, root])
|
||||
newPath = root.replace(substring, '');
|
||||
filePath = os.sep.join([newPath, filename])
|
||||
|
@ -30,7 +30,7 @@ def handleURL(url):
|
|||
baseFilename = os.path.basename(url)
|
||||
filename = os.path.splitext(baseFilename)[0]
|
||||
newUrl = MAP[filename]
|
||||
print newUrl
|
||||
print url + ' -> ' + newUrl
|
||||
return newUrl
|
||||
|
||||
def handleOptions():
|
||||
|
@ -43,8 +43,12 @@ def main():
|
|||
argsLength = len(sys.argv)
|
||||
if argsLength == 3:
|
||||
jsonFile = sys.argv[1]
|
||||
gzipFile = jsonFile + '.gz'
|
||||
assetDirectory = sys.argv[2]
|
||||
inputFilename = os.path.basename(jsonFile);
|
||||
absPath = os.path.abspath(assetDirectory)
|
||||
finalPath = absPath.replace('\\', '/');
|
||||
gzipFile = finalPath + '/' + inputFilename + '.gz'
|
||||
print gzipFile
|
||||
createAssetMapping(assetDirectory)
|
||||
f = open(jsonFile)
|
||||
data = json.load(f)
|
||||
|
@ -65,6 +69,15 @@ def main():
|
|||
except:
|
||||
value = handleURL(value)
|
||||
|
||||
|
||||
if prop == "ambientLight":
|
||||
for index in value:
|
||||
value[index] = handleURL(value[index])
|
||||
|
||||
if prop == "skybox":
|
||||
for index in value:
|
||||
value[index] = handleURL(value[index])
|
||||
|
||||
if prop == "serverScripts":
|
||||
value = handleURL(value)
|
||||
|
||||
|
|
Loading…
Reference in a new issue