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

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

View file

@ -1,7 +1,7 @@
### Dependencies
- [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

View file

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

View file

@ -20,7 +20,7 @@ Note that this uses the version from the homebrew formula at the time of this wr
Assuming you've installed Qt using the homebrew instructions above, you'll need to set QT_CMAKE_PREFIX_PATH so CMake can find your installations.
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.

View file

@ -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 dont have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
If you dont have Community or Professional edition of Visual Studio 2017, download [Visual Studio Community 2017](https://www.visualstudio.com/downloads/).
When selecting components, check "Desktop development with C++." Also check "Windows 8.1 SDK and UCRT SDK" and "VC++ 2015.3 v140 toolset (x86,x64)" on the Summary toolbar on the right.
@ -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.

View file

@ -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;

View file

@ -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 ()

View file

@ -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
}

View file

@ -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);

View file

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

View file

@ -2059,24 +2059,34 @@ static const QString JSON_AVATAR_ENTITIES = QStringLiteral("attachedEntities");
static const QString JSON_AVATAR_SCALE = QStringLiteral("scale");
static const QString JSON_AVATAR_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;
}
}
}

View file

@ -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));

View file

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

View file

@ -363,6 +363,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_POS, materialMappingPos);
CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_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()) {

View file

@ -230,6 +230,7 @@ public:
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_POS, MaterialMappingPos, materialMappingPos, glmVec2, glm::vec2(0, 0));
DEFINE_PROPERTY_REF(PROP_MATERIAL_MAPPING_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);

View file

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

View file

@ -2382,6 +2382,30 @@ bool EntityTree::readFromMap(QVariantMap& map) {
}
}
// Convert old materials so that they use materialData instead of userData
if (contentVersion < (int)EntityVersion::MaterialData && properties.getType() == EntityTypes::EntityType::Material) {
if (properties.getMaterialURL().startsWith("userData")) {
QString materialURL = properties.getMaterialURL();
properties.setMaterialURL(materialURL.replace("userData", "materialData"));
QJsonObject userData = QJsonDocument::fromJson(properties.getUserData().toUtf8()).object();
QJsonObject materialData;
QJsonValue materialVersion = userData["materialVersion"];
if (!materialVersion.isNull()) {
materialData.insert("materialVersion", materialVersion);
userData.remove("materialVersion");
}
QJsonValue materials = userData["materials"];
if (!materials.isNull()) {
materialData.insert("materials", materials);
userData.remove("materials");
}
properties.setMaterialData(QJsonDocument(materialData).toJson());
properties.setUserData(QJsonDocument(userData).toJson());
}
}
EntityItemPointer entity = addEntity(entityItemID, properties);
if (!entity) {
qCDebug(entities) << "adding Entity failed:" << entityItemID << properties.getType();

View file

@ -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();

View file

@ -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;

View file

@ -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;
}

View file

@ -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 };

View file

@ -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";
}

View file

@ -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);
};
} }

View file

@ -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()) {

View file

@ -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,

View file

@ -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);
}
}
}

View file

@ -21,13 +21,24 @@ const Element Element::COLOR_SBGRA_32{ VEC4, NUINT8, SBGRA };
const Element Element::COLOR_RGBA_2{ VEC4, NUINT2, RGBA };
const Element Element::COLOR_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 };

View file

@ -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;

View file

@ -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; }

View file

@ -574,20 +574,40 @@ bool Texture::evalKTXFormat(const Element& mipFormat, const Element& texelFormat
header.setUncompressed(ktx::GLType::UNSIGNED_BYTE, 1, ktx::GLFormat::RED, ktx::GLInternalFormat::R8, ktx::GLBaseInternalFormat::RED);
} 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;
}
}

View file

@ -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" },

View file

@ -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;

View file

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

View file

@ -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;

View file

@ -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;

View file

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

View file

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

View file

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

View file

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

View file

@ -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);

View file

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

View file

@ -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);

View file

@ -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);

View file

@ -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;

View file

@ -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">

View file

@ -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);

View file

@ -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)

View file

@ -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)