mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 18:42:58 +02:00
Merge branch 'master' of github.com:highfidelity/hifi into blackProp
This commit is contained in:
commit
6539482cc2
21 changed files with 1199 additions and 645 deletions
|
@ -52,6 +52,9 @@ else()
|
||||||
set(MOBILE 0)
|
set(MOBILE 0)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Use default time server if none defined in environment
|
||||||
|
set_from_env(TIMESERVER_URL TIMESERVER_URL "http://sha256timestamp.ws.symantec.com/sha256/timestamp")
|
||||||
|
|
||||||
set(HIFI_USE_OPTIMIZED_IK OFF)
|
set(HIFI_USE_OPTIMIZED_IK OFF)
|
||||||
set(BUILD_CLIENT_OPTION ON)
|
set(BUILD_CLIENT_OPTION ON)
|
||||||
set(BUILD_SERVER_OPTION ON)
|
set(BUILD_SERVER_OPTION ON)
|
||||||
|
|
|
@ -22,7 +22,7 @@ macro(optional_win_executable_signing)
|
||||||
# setup a post build command to sign the executable
|
# setup a post build command to sign the executable
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
TARGET ${TARGET_NAME} POST_BUILD
|
TARGET ${TARGET_NAME} POST_BUILD
|
||||||
COMMAND ${SIGNTOOL_EXECUTABLE} sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr http://sha256timestamp.ws.symantec.com/sha256/timestamp /td SHA256 ${EXECUTABLE_PATH}
|
COMMAND ${SIGNTOOL_EXECUTABLE} sign /fd sha256 /f %HF_PFX_FILE% /p %HF_PFX_PASSPHRASE% /tr ${TIMESERVER_URL} /td SHA256 ${EXECUTABLE_PATH}
|
||||||
)
|
)
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "HF_PFX_PASSPHRASE must be set for executables to be signed.")
|
message(FATAL_ERROR "HF_PFX_PASSPHRASE must be set for executables to be signed.")
|
||||||
|
|
|
@ -27,9 +27,10 @@ std::function<QThread*()> MaterialBaker::_getNextOvenWorkerThreadOperator;
|
||||||
|
|
||||||
static int materialNum = 0;
|
static int materialNum = 0;
|
||||||
|
|
||||||
MaterialBaker::MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir) :
|
MaterialBaker::MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir, QUrl destinationPath) :
|
||||||
_materialData(materialData),
|
_materialData(materialData),
|
||||||
_isURL(isURL),
|
_isURL(isURL),
|
||||||
|
_destinationPath(destinationPath),
|
||||||
_bakedOutputDir(bakedOutputDir),
|
_bakedOutputDir(bakedOutputDir),
|
||||||
_textureOutputDir(bakedOutputDir + "/materialTextures/" + QString::number(materialNum++))
|
_textureOutputDir(bakedOutputDir + "/materialTextures/" + QString::number(materialNum++))
|
||||||
{
|
{
|
||||||
|
@ -177,6 +178,10 @@ void MaterialBaker::handleFinishedTextureBaker() {
|
||||||
auto newURL = QUrl(_textureOutputDir).resolved(baker->getMetaTextureFileName());
|
auto newURL = QUrl(_textureOutputDir).resolved(baker->getMetaTextureFileName());
|
||||||
auto relativeURL = QDir(_bakedOutputDir).relativeFilePath(newURL.toString());
|
auto relativeURL = QDir(_bakedOutputDir).relativeFilePath(newURL.toString());
|
||||||
|
|
||||||
|
if (!_destinationPath.isEmpty()) {
|
||||||
|
relativeURL = _destinationPath.resolved(relativeURL).toDisplayString();
|
||||||
|
}
|
||||||
|
|
||||||
// Replace the old texture URLs
|
// Replace the old texture URLs
|
||||||
for (auto networkMaterial : _materialsNeedingRewrite.values(textureKey)) {
|
for (auto networkMaterial : _materialsNeedingRewrite.values(textureKey)) {
|
||||||
networkMaterial->getTextureMap(baker->getMapChannel())->getTextureSource()->setUrl(relativeURL);
|
networkMaterial->getTextureMap(baker->getMapChannel())->getTextureSource()->setUrl(relativeURL);
|
||||||
|
|
|
@ -24,7 +24,7 @@ static const QString BAKED_MATERIAL_EXTENSION = ".baked.json";
|
||||||
class MaterialBaker : public Baker {
|
class MaterialBaker : public Baker {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir);
|
MaterialBaker(const QString& materialData, bool isURL, const QString& bakedOutputDir, QUrl destinationPath = QUrl());
|
||||||
|
|
||||||
QString getMaterialData() const { return _materialData; }
|
QString getMaterialData() const { return _materialData; }
|
||||||
bool isURL() const { return _isURL; }
|
bool isURL() const { return _isURL; }
|
||||||
|
@ -51,6 +51,7 @@ private:
|
||||||
|
|
||||||
QString _materialData;
|
QString _materialData;
|
||||||
bool _isURL;
|
bool _isURL;
|
||||||
|
QUrl _destinationPath;
|
||||||
|
|
||||||
NetworkMaterialResourcePointer _materialResource;
|
NetworkMaterialResourcePointer _materialResource;
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,10 @@ void ModelBaker::saveSourceModel() {
|
||||||
|
|
||||||
connect(networkReply, &QNetworkReply::finished, this, &ModelBaker::handleModelNetworkReply);
|
connect(networkReply, &QNetworkReply::finished, this, &ModelBaker::handleModelNetworkReply);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (_mappingURL.isEmpty()) {
|
||||||
|
outputUnbakedFST();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModelBaker::handleModelNetworkReply() {
|
void ModelBaker::handleModelNetworkReply() {
|
||||||
|
@ -313,6 +317,37 @@ void ModelBaker::handleFinishedMaterialBaker() {
|
||||||
outputBakedFST();
|
outputBakedFST();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ModelBaker::outputUnbakedFST() {
|
||||||
|
// Output an unbaked FST file in the original output folder to make it easier for FSTBaker to rebake this model
|
||||||
|
// TODO: Consider a more robust method that does not depend on FSTBaker navigating to a hardcoded relative path
|
||||||
|
QString outputFSTFilename = _modelURL.fileName();
|
||||||
|
auto extensionStart = outputFSTFilename.indexOf(".");
|
||||||
|
if (extensionStart != -1) {
|
||||||
|
outputFSTFilename.resize(extensionStart);
|
||||||
|
}
|
||||||
|
outputFSTFilename += FST_EXTENSION;
|
||||||
|
QString outputFSTURL = _originalOutputDir + "/" + outputFSTFilename;
|
||||||
|
|
||||||
|
hifi::VariantHash outputMapping;
|
||||||
|
outputMapping[FST_VERSION_FIELD] = FST_VERSION;
|
||||||
|
outputMapping[FILENAME_FIELD] = _modelURL.fileName();
|
||||||
|
outputMapping[COMMENT_FIELD] = "This FST file was generated by Oven for use during rebaking. It is not part of the original model. This file's existence is subject to change.";
|
||||||
|
hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping);
|
||||||
|
|
||||||
|
QFile fstOutputFile { outputFSTURL };
|
||||||
|
if (fstOutputFile.exists()) {
|
||||||
|
handleWarning("The file '" + outputFSTURL + "' already exists. Should that be baked instead of '" + _modelURL.toString() + "'?");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!fstOutputFile.open(QIODevice::WriteOnly)) {
|
||||||
|
handleWarning("Failed to open file '" + outputFSTURL + "' for writing. Rebaking may fail on the associated model.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fstOutputFile.write(fstOut) == -1) {
|
||||||
|
handleWarning("Failed to write to file '" + outputFSTURL + "'. Rebaking may fail on the associated model.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ModelBaker::outputBakedFST() {
|
void ModelBaker::outputBakedFST() {
|
||||||
// Output FST file, copying over input mappings if available
|
// Output FST file, copying over input mappings if available
|
||||||
QString outputFSTFilename = !_mappingURL.isEmpty() ? _mappingURL.fileName() : _modelURL.fileName();
|
QString outputFSTFilename = !_mappingURL.isEmpty() ? _mappingURL.fileName() : _modelURL.fileName();
|
||||||
|
@ -327,6 +362,7 @@ void ModelBaker::outputBakedFST() {
|
||||||
outputMapping[FST_VERSION_FIELD] = FST_VERSION;
|
outputMapping[FST_VERSION_FIELD] = FST_VERSION;
|
||||||
outputMapping[FILENAME_FIELD] = _bakedModelURL.fileName();
|
outputMapping[FILENAME_FIELD] = _bakedModelURL.fileName();
|
||||||
outputMapping.remove(TEXDIR_FIELD);
|
outputMapping.remove(TEXDIR_FIELD);
|
||||||
|
outputMapping.remove(COMMENT_FIELD);
|
||||||
hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping);
|
hifi::ByteArray fstOut = FSTReader::writeMapping(outputMapping);
|
||||||
|
|
||||||
QFile fstOutputFile { outputFSTURL };
|
QFile fstOutputFile { outputFSTURL };
|
||||||
|
|
|
@ -82,6 +82,7 @@ protected slots:
|
||||||
void handleFinishedMaterialBaker();
|
void handleFinishedMaterialBaker();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void outputUnbakedFST();
|
||||||
void outputBakedFST();
|
void outputBakedFST();
|
||||||
|
|
||||||
bool _hasBeenBaked { false };
|
bool _hasBeenBaked { false };
|
||||||
|
|
|
@ -358,7 +358,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me
|
||||||
std::vector<QString> dracoMaterialList;
|
std::vector<QString> dracoMaterialList;
|
||||||
for (const auto& dracoChild : child.children) {
|
for (const auto& dracoChild : child.children) {
|
||||||
if (dracoChild.name == "FBXDracoMeshVersion") {
|
if (dracoChild.name == "FBXDracoMeshVersion") {
|
||||||
if (!dracoChild.children.isEmpty()) {
|
if (!dracoChild.properties.isEmpty()) {
|
||||||
dracoMeshNodeVersion = dracoChild.properties[0].toUInt();
|
dracoMeshNodeVersion = dracoChild.properties[0].toUInt();
|
||||||
}
|
}
|
||||||
} else if (dracoChild.name == "MaterialList") {
|
} else if (dracoChild.name == "MaterialList") {
|
||||||
|
@ -492,7 +492,7 @@ ExtractedMesh FBXSerializer::extractMesh(const FBXNode& object, unsigned int& me
|
||||||
// Figure out what material this part is
|
// Figure out what material this part is
|
||||||
if (dracoMeshNodeVersion >= 2) {
|
if (dracoMeshNodeVersion >= 2) {
|
||||||
// Define the materialID now
|
// Define the materialID now
|
||||||
if (dracoMaterialList.size() - 1 <= materialID) {
|
if (materialID < dracoMaterialList.size()) {
|
||||||
part.materialID = dracoMaterialList[materialID];
|
part.materialID = dracoMaterialList[materialID];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -33,6 +33,7 @@ static const QString BLENDSHAPE_FIELD = "bs";
|
||||||
static const QString SCRIPT_FIELD = "script";
|
static const QString SCRIPT_FIELD = "script";
|
||||||
static const QString JOINT_NAME_MAPPING_FIELD = "jointMap";
|
static const QString JOINT_NAME_MAPPING_FIELD = "jointMap";
|
||||||
static const QString MATERIAL_MAPPING_FIELD = "materialMap";
|
static const QString MATERIAL_MAPPING_FIELD = "materialMap";
|
||||||
|
static const QString COMMENT_FIELD = "comment";
|
||||||
|
|
||||||
class FSTReader {
|
class FSTReader {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -318,6 +318,7 @@ public:
|
||||||
void setTextureTransforms(const Transform& transform, MaterialMappingMode mode, bool repeat);
|
void setTextureTransforms(const Transform& transform, MaterialMappingMode mode, bool repeat);
|
||||||
|
|
||||||
const std::string& getName() const { return _name; }
|
const std::string& getName() const { return _name; }
|
||||||
|
void setName(const std::string& name) { _name = name; }
|
||||||
|
|
||||||
const std::string& getModel() const { return _model; }
|
const std::string& getModel() const { return _model; }
|
||||||
void setModel(const std::string& model) { _model = model; }
|
void setModel(const std::string& model) { _model = model; }
|
||||||
|
|
|
@ -184,6 +184,7 @@ std::pair<std::string, std::shared_ptr<NetworkMaterial>> NetworkMaterialResource
|
||||||
auto nameJSON = materialJSON.value(key);
|
auto nameJSON = materialJSON.value(key);
|
||||||
if (nameJSON.isString()) {
|
if (nameJSON.isString()) {
|
||||||
name = nameJSON.toString().toStdString();
|
name = nameJSON.toString().toStdString();
|
||||||
|
material->setName(name);
|
||||||
}
|
}
|
||||||
} else if (key == "model") {
|
} else if (key == "model") {
|
||||||
auto modelJSON = materialJSON.value(key);
|
auto modelJSON = materialJSON.value(key);
|
||||||
|
|
|
@ -108,6 +108,7 @@ private:
|
||||||
|
|
||||||
using NetworkMaterialResourcePointer = QSharedPointer<NetworkMaterialResource>;
|
using NetworkMaterialResourcePointer = QSharedPointer<NetworkMaterialResource>;
|
||||||
using MaterialMapping = std::vector<std::pair<std::string, NetworkMaterialResourcePointer>>;
|
using MaterialMapping = std::vector<std::pair<std::string, NetworkMaterialResourcePointer>>;
|
||||||
|
Q_DECLARE_METATYPE(MaterialMapping)
|
||||||
|
|
||||||
class MaterialCache : public ResourceCache {
|
class MaterialCache : public ResourceCache {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -282,8 +282,16 @@ void GeometryReader::run() {
|
||||||
hfmModel->scripts.push_back(script.toString());
|
hfmModel->scripts.push_back(script.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Do processing on the model
|
||||||
|
baker::Baker modelBaker(hfmModel, _mapping.second, _mapping.first);
|
||||||
|
modelBaker.run();
|
||||||
|
|
||||||
|
auto processedHFMModel = modelBaker.getHFMModel();
|
||||||
|
auto materialMapping = modelBaker.getMaterialMapping();
|
||||||
|
|
||||||
QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition",
|
QMetaObject::invokeMethod(resource.data(), "setGeometryDefinition",
|
||||||
Q_ARG(HFMModel::Pointer, hfmModel), Q_ARG(GeometryMappingPair, _mapping));
|
Q_ARG(HFMModel::Pointer, processedHFMModel), Q_ARG(MaterialMapping, materialMapping));
|
||||||
} catch (const std::exception&) {
|
} catch (const std::exception&) {
|
||||||
auto resource = _resource.toStrongRef();
|
auto resource = _resource.toStrongRef();
|
||||||
if (resource) {
|
if (resource) {
|
||||||
|
@ -317,7 +325,7 @@ public:
|
||||||
void setExtra(void* extra) override;
|
void setExtra(void* extra) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Q_INVOKABLE void setGeometryDefinition(HFMModel::Pointer hfmModel, const GeometryMappingPair& mapping);
|
Q_INVOKABLE void setGeometryDefinition(HFMModel::Pointer hfmModel, const MaterialMapping& materialMapping);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ModelLoader _modelLoader;
|
ModelLoader _modelLoader;
|
||||||
|
@ -340,14 +348,10 @@ void GeometryDefinitionResource::downloadFinished(const QByteArray& data) {
|
||||||
QThreadPool::globalInstance()->start(new GeometryReader(_modelLoader, _self, _effectiveBaseURL, _mapping, data, _combineParts, _request->getWebMediaType()));
|
QThreadPool::globalInstance()->start(new GeometryReader(_modelLoader, _self, _effectiveBaseURL, _mapping, data, _combineParts, _request->getWebMediaType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void GeometryDefinitionResource::setGeometryDefinition(HFMModel::Pointer hfmModel, const GeometryMappingPair& mapping) {
|
void GeometryDefinitionResource::setGeometryDefinition(HFMModel::Pointer hfmModel, const MaterialMapping& materialMapping) {
|
||||||
// Do processing on the model
|
|
||||||
baker::Baker modelBaker(hfmModel, mapping.second, mapping.first);
|
|
||||||
modelBaker.run();
|
|
||||||
|
|
||||||
// Assume ownership of the processed HFMModel
|
// Assume ownership of the processed HFMModel
|
||||||
_hfmModel = modelBaker.getHFMModel();
|
_hfmModel = hfmModel;
|
||||||
_materialMapping = modelBaker.getMaterialMapping();
|
_materialMapping = materialMapping;
|
||||||
|
|
||||||
// Copy materials
|
// Copy materials
|
||||||
QHash<QString, size_t> materialIDAtlas;
|
QHash<QString, size_t> materialIDAtlas;
|
||||||
|
@ -498,6 +502,20 @@ bool Geometry::areTexturesLoaded() const {
|
||||||
material->checkResetOpacityMap();
|
material->checkResetOpacityMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (auto& materialMapping : _materialMapping) {
|
||||||
|
if (materialMapping.second) {
|
||||||
|
for (auto& materialPair : materialMapping.second->parsedMaterials.networkMaterials) {
|
||||||
|
if (materialPair.second) {
|
||||||
|
if (materialPair.second->isMissingTexture()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
materialPair.second->checkResetOpacityMap();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_areTexturesLoaded = true;
|
_areTexturesLoaded = true;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -2363,41 +2363,62 @@ var PropertiesTool = function (opts) {
|
||||||
}
|
}
|
||||||
var i, properties, dY, diff, newPosition;
|
var i, properties, dY, diff, newPosition;
|
||||||
if (data.type === "update") {
|
if (data.type === "update") {
|
||||||
if (selectionManager.selections.length > 1) {
|
|
||||||
for (i = 0; i < selectionManager.selections.length; i++) {
|
if (data.properties || data.propertiesMap) {
|
||||||
Entities.editEntity(selectionManager.selections[i], data.properties);
|
var propertiesMap = data.propertiesMap;
|
||||||
|
if (propertiesMap === undefined) {
|
||||||
|
propertiesMap = [{
|
||||||
|
entityIDs: data.ids,
|
||||||
|
properties: data.properties,
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
} else if (data.properties) {
|
|
||||||
if (data.properties.dynamic === false) {
|
var sendListUpdate = false;
|
||||||
|
propertiesMap.forEach(function(propertiesObject) {
|
||||||
|
var properties = propertiesObject.properties;
|
||||||
|
var updateEntityIDs = propertiesObject.entityIDs;
|
||||||
|
if (properties.dynamic === false) {
|
||||||
// this object is leaving dynamic, so we zero its velocities
|
// this object is leaving dynamic, so we zero its velocities
|
||||||
data.properties.localVelocity = Vec3.ZERO;
|
properties.localVelocity = Vec3.ZERO;
|
||||||
data.properties.localAngularVelocity = Vec3.ZERO;
|
properties.localAngularVelocity = Vec3.ZERO;
|
||||||
}
|
}
|
||||||
if (data.properties.rotation !== undefined) {
|
if (properties.rotation !== undefined) {
|
||||||
data.properties.rotation = Quat.fromVec3Degrees(data.properties.rotation);
|
properties.rotation = Quat.fromVec3Degrees(properties.rotation);
|
||||||
}
|
}
|
||||||
if (data.properties.localRotation !== undefined) {
|
if (properties.localRotation !== undefined) {
|
||||||
data.properties.localRotation = Quat.fromVec3Degrees(data.properties.localRotation);
|
properties.localRotation = Quat.fromVec3Degrees(properties.localRotation);
|
||||||
}
|
}
|
||||||
if (data.properties.emitOrientation !== undefined) {
|
if (properties.emitOrientation !== undefined) {
|
||||||
data.properties.emitOrientation = Quat.fromVec3Degrees(data.properties.emitOrientation);
|
properties.emitOrientation = Quat.fromVec3Degrees(properties.emitOrientation);
|
||||||
}
|
}
|
||||||
if (data.properties.keyLight !== undefined && data.properties.keyLight.direction !== undefined) {
|
if (properties.keyLight !== undefined && properties.keyLight.direction !== undefined) {
|
||||||
var currentKeyLightDirection = Vec3.toPolar(Entities.getEntityProperties(selectionManager.selections[0], ['keyLight.direction']).keyLight.direction);
|
var currentKeyLightDirection = Vec3.toPolar(Entities.getEntityProperties(selectionManager.selections[0], ['keyLight.direction']).keyLight.direction);
|
||||||
if (data.properties.keyLight.direction.x === undefined) {
|
if (properties.keyLight.direction.x === undefined) {
|
||||||
data.properties.keyLight.direction.x = currentKeyLightDirection.x;
|
properties.keyLight.direction.x = currentKeyLightDirection.x;
|
||||||
}
|
}
|
||||||
if (data.properties.keyLight.direction.y === undefined) {
|
if (properties.keyLight.direction.y === undefined) {
|
||||||
data.properties.keyLight.direction.y = currentKeyLightDirection.y;
|
properties.keyLight.direction.y = currentKeyLightDirection.y;
|
||||||
}
|
}
|
||||||
data.properties.keyLight.direction = Vec3.fromPolar(data.properties.keyLight.direction.x, data.properties.keyLight.direction.y);
|
properties.keyLight.direction = Vec3.fromPolar(properties.keyLight.direction.x, properties.keyLight.direction.y);
|
||||||
}
|
}
|
||||||
Entities.editEntity(selectionManager.selections[0], data.properties);
|
|
||||||
if (data.properties.name !== undefined || data.properties.modelURL !== undefined || data.properties.materialURL !== undefined ||
|
updateEntityIDs.forEach(function (entityID) {
|
||||||
data.properties.visible !== undefined || data.properties.locked !== undefined) {
|
Entities.editEntity(entityID, properties);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (properties.name !== undefined || properties.modelURL !== undefined || properties.materialURL !== undefined ||
|
||||||
|
properties.visible !== undefined || properties.locked !== undefined) {
|
||||||
|
|
||||||
|
sendListUpdate = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
if (sendListUpdate) {
|
||||||
entityListTool.sendUpdate();
|
entityListTool.sendUpdate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (data.onlyUpdateEntities) {
|
if (data.onlyUpdateEntities) {
|
||||||
blockPropertyUpdates = true;
|
blockPropertyUpdates = true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -2407,9 +2428,9 @@ var PropertiesTool = function (opts) {
|
||||||
selectionManager._update(false, this);
|
selectionManager._update(false, this);
|
||||||
blockPropertyUpdates = false;
|
blockPropertyUpdates = false;
|
||||||
} else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') {
|
} else if (data.type === 'saveUserData' || data.type === 'saveMaterialData') {
|
||||||
//the event bridge and json parsing handle our avatar id string differently.
|
data.ids.forEach(function(entityID) {
|
||||||
var actualID = data.id.split('"')[1];
|
Entities.editEntity(entityID, data.properties);
|
||||||
Entities.editEntity(actualID, data.properties);
|
});
|
||||||
} else if (data.type === "showMarketplace") {
|
} else if (data.type === "showMarketplace") {
|
||||||
showMarketplace();
|
showMarketplace();
|
||||||
} else if (data.type === "action") {
|
} else if (data.type === "action") {
|
||||||
|
|
|
@ -193,8 +193,8 @@ td {
|
||||||
}
|
}
|
||||||
|
|
||||||
td.hidden {
|
td.hidden {
|
||||||
padding-left: 0px;
|
padding-left: 0;
|
||||||
padding-right: 0px;
|
padding-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
td.url {
|
td.url {
|
||||||
|
@ -262,6 +262,42 @@ input[type="text"] {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input.multi-diff:not(:focus) + span.multi-diff,
|
||||||
|
textarea.multi-diff:not(:focus) + span.multi-diff,
|
||||||
|
.draggable-number.multi-diff>input:not(:focus)+span.multi-diff,
|
||||||
|
dl>dt.multi-diff:not(:focus) + span.multi-diff {
|
||||||
|
visibility: visible;
|
||||||
|
position: absolute;
|
||||||
|
display: inline-block;
|
||||||
|
z-index: 2;
|
||||||
|
top: 7.5px;
|
||||||
|
left: 20px;
|
||||||
|
max-width: 50px;
|
||||||
|
min-width: 10px;
|
||||||
|
width: 50%;
|
||||||
|
height: 13px;
|
||||||
|
background-image: linear-gradient(transparent 0%, transparent 10%, #afafaf 10%, #afafaf 20%, transparent 20%, transparent 45%, #afafaf 45%, #afafaf 55%, transparent 55%, transparent 80%, #afafaf 80%, #afafaf 90%, transparent 90%, transparent 100%);
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.multi-diff:not(:focus)::-webkit-input-placeholder, input.multi-diff:not(:focus) {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.draggable-number.multi-diff .text {
|
||||||
|
color: transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dropdown > span.multi-diff {
|
||||||
|
top: 5px;
|
||||||
|
left: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text, .url, .texture, .textarea {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
input[type="search"] {
|
input[type="search"] {
|
||||||
height: 28px;
|
height: 28px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -333,7 +369,7 @@ input[type=range]::-webkit-slider-thumb {
|
||||||
input[type=range]::-webkit-slider-thumb:hover {
|
input[type=range]::-webkit-slider-thumb:hover {
|
||||||
background-color: white;
|
background-color: white;
|
||||||
}
|
}
|
||||||
input[type=range]:focus { /*#252525*/
|
input[type=range]:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -443,6 +479,21 @@ input[type=checkbox]:checked + label {
|
||||||
input[type=checkbox]:checked + label:hover {
|
input[type=checkbox]:checked + label:hover {
|
||||||
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEySURBVDhPnZLPSsNAEMa/XVPBCE0RhNy0OarP4Av4AD6JB0GwVBA8efBBxHsgh4CQswcRoUIpiIpVAm3zZ5M4szFSbQPBH3xkJvNNZskOer2eLIriKM/ze1JOcS1UHmdZduF5ngEKjr/fN4Z6+oKerwA2gxC4HAFPEWVLsAzgZAvYt3Q6Enw6jg7uBAaTFMNwhpnKdbXCkAJdy8ROu4XrXW2HTJIErHcFDD6nC02Mom8PwymeE2gvS0ZRBBaTlsOXEmdlrfLLOI7Bakrl/zWxCT8T/904f9QW/b06qtrCUdtFCqdjYs2Q2jAPX8c2XQd7Kr/wfV8vwIPs4Ga1ixe5Xrr/YFLTYfKIvWzM6ZtwXZdX7lxXG0L+sxXHcW5t254opRzawQ0S72+dPmjTroIgOP0CQSMt5LDn1T8AAAAASUVORK5CYII=);
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAEySURBVDhPnZLPSsNAEMa/XVPBCE0RhNy0OarP4Av4AD6JB0GwVBA8efBBxHsgh4CQswcRoUIpiIpVAm3zZ5M4szFSbQPBH3xkJvNNZskOer2eLIriKM/ze1JOcS1UHmdZduF5ngEKjr/fN4Z6+oKerwA2gxC4HAFPEWVLsAzgZAvYt3Q6Enw6jg7uBAaTFMNwhpnKdbXCkAJdy8ROu4XrXW2HTJIErHcFDD6nC02Mom8PwymeE2gvS0ZRBBaTlsOXEmdlrfLLOI7Bakrl/zWxCT8T/904f9QW/b06qtrCUdtFCqdjYs2Q2jAPX8c2XQd7Kr/wfV8vwIPs4Ga1ixe5Xrr/YFLTYfKIvWzM6ZtwXZdX7lxXG0L+sxXHcW5t254opRzawQ0S72+dPmjTroIgOP0CQSMt5LDn1T8AAAAASUVORK5CYII=);
|
||||||
}
|
}
|
||||||
|
input.multi-diff[type=checkbox] + label {
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFbSURBVDhPY2xoaGD68+dPMSMjY9L////VgTQjAw4AlH8PxLOPHj1azWxjY1MBVNsBFBfBpwkEgNKcQGwtJyfHyALkF4IE34gqM9zU9WT4wicG4mIA1l/fGIyOL2EQeP8EZEAiC5AQBUlcMQ5ieMXIwfDo9SeG73/+gRXDAAsTI4Pd9wdgTVAgw/Tv3z8GEP7Jwctw78M3DE0goPr6BoPludVgdTAM1wgCv//9B9PIQOPNDYaAGxtRNIEw03+gYhDGBtSBNgVc3wiWR8dM//4DTQBidKD++jqD//X1YDlsGMWpMKD26jqD79V1GM5DxihOZQWGntqrawy+V9ZiOA0dw21k/f6JwerzHQbvS2swTMeGGfPz8l8BLRP9KizDwP0WHk+EwGum/3//94M8y/nmEdZAwIb//vs7g/nk6ZPHzE3NvwITrxLDfwYhIAamZpz4PcM/hslXrl6pBwAmfz5iaAlAuAAAAABJRU5ErkJggg==);
|
||||||
|
}
|
||||||
|
input.multi-diff[type=checkbox] + label:hover {
|
||||||
|
background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAYAAAAfSC3RAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAFPSURBVDhPjZJBSwJBHMXfrG6rWEkl1MFDGOihDn2JIIrqc3QJunbyFhUkRieD+hYepWteuxctXiJ1Q5xmdmZ3bWZTUHezfvAu/3lv3n+HRblcTrbb7fN+v/8eBMFgFpxz13Gcu3q9bqHb7V4M5/9GhatE3cIsy0o99YBKC3jliCWbBK43gK0MoDI9otfTB/vPBC9Uwu4xMC8IzSOSBsFxIYNqMTGcAIYQAlodD3j5/IqENIc5gqt1P/SNZKhaXR0a5E/5BEcrwH1xEHrGZbiuC604DpZ81AoiPJ/WROM4e4sSt3kaaRopNrg7z1FZdSLmcU2saqrX20lTXC5/RFabFmk2m+GLnBnbWJMOThJv4SV/QRqNBjNNM9UiGeQHdDiejZSSG5TSG71zjnVivyVOKlNLlEqlx+xCds7zvU31G6Z938dvEq4QjLMH27ZPvwHFVYQr3h7uHwAAAABJRU5ErkJggg==);
|
||||||
|
}
|
||||||
|
|
||||||
|
.rgb.fstuple .color-picker.multi-diff:after {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
content: ' ';
|
||||||
|
background: darkgray;
|
||||||
|
display: flex;
|
||||||
|
clip-path: polygon(0 0, 0 100%, 100% 100%);
|
||||||
|
}
|
||||||
|
|
||||||
.icon-input input {
|
.icon-input input {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
@ -535,7 +586,6 @@ input[type=checkbox]:checked + label:hover {
|
||||||
div.section-header, hr {
|
div.section-header, hr {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: row nowrap;
|
flex-flow: row nowrap;
|
||||||
|
|
||||||
padding: 10px 16px;
|
padding: 10px 16px;
|
||||||
font-family: Raleway-Regular;
|
font-family: Raleway-Regular;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
@ -731,8 +781,6 @@ span.indented {
|
||||||
.dropdown dl {
|
.dropdown dl {
|
||||||
clear: both;
|
clear: both;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
|
||||||
.dropdown dl {
|
|
||||||
font-family: FiraSans-SemiBold;
|
font-family: FiraSans-SemiBold;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
width: 292px;
|
width: 292px;
|
||||||
|
@ -741,7 +789,10 @@ span.indented {
|
||||||
color: #afafaf;
|
color: #afafaf;
|
||||||
background: #575757;
|
background: #575757;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown dl[dropped="true"] {
|
.dropdown dl[dropped="true"] {
|
||||||
color: #404040;
|
color: #404040;
|
||||||
background: linear-gradient(#afafaf, #afafaf);
|
background: linear-gradient(#afafaf, #afafaf);
|
||||||
|
@ -878,6 +929,8 @@ div.refresh {
|
||||||
div.refresh input[type="button"] {
|
div.refresh input[type="button"] {
|
||||||
float: right;
|
float: right;
|
||||||
margin-right: -44px;
|
margin-right: -44px;
|
||||||
|
position: relative;
|
||||||
|
left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.color-picker {
|
.color-picker {
|
||||||
|
@ -930,6 +983,8 @@ div.refresh input[type="button"] {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
flex: 0 1 124px;
|
flex: 0 1 124px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
.draggable-number .text {
|
.draggable-number .text {
|
||||||
|
@ -1735,3 +1790,7 @@ input[type=number].hide-spinner::-webkit-inner-spin-button {
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.jsoneditor-menu a.jsoneditor-poweredBy {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,7 @@ function DraggableNumber(min, max, step, decimals, dragStart, dragEnd) {
|
||||||
this.min = min;
|
this.min = min;
|
||||||
this.max = max;
|
this.max = max;
|
||||||
this.step = step !== undefined ? step : 1;
|
this.step = step !== undefined ? step : 1;
|
||||||
|
this.multiDiffModeEnabled = false;
|
||||||
this.decimals = decimals;
|
this.decimals = decimals;
|
||||||
this.dragStartFunction = dragStart;
|
this.dragStartFunction = dragStart;
|
||||||
this.dragEndFunction = dragEnd;
|
this.dragEndFunction = dragEnd;
|
||||||
|
@ -20,6 +21,7 @@ function DraggableNumber(min, max, step, decimals, dragStart, dragEnd) {
|
||||||
this.initialMouseEvent = null;
|
this.initialMouseEvent = null;
|
||||||
this.lastMouseEvent = null;
|
this.lastMouseEvent = null;
|
||||||
this.valueChangeFunction = null;
|
this.valueChangeFunction = null;
|
||||||
|
this.multiDiffStepFunction = null;
|
||||||
this.initialize();
|
this.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,24 +72,24 @@ DraggableNumber.prototype = {
|
||||||
this.lastMouseEvent = event;
|
this.lastMouseEvent = event;
|
||||||
}
|
}
|
||||||
if (this.dragging && this.lastMouseEvent) {
|
if (this.dragging && this.lastMouseEvent) {
|
||||||
let initialValue = this.elInput.value;
|
let dragDelta = event.clientX - this.lastMouseEvent.clientX;
|
||||||
let dx = event.clientX - this.lastMouseEvent.clientX;
|
if (dragDelta !== 0) {
|
||||||
let changeValue = dx !== 0;
|
if (this.multiDiffModeEnabled) {
|
||||||
if (changeValue) {
|
if (this.multiDiffStepFunction) {
|
||||||
while (dx !== 0) {
|
this.multiDiffStepFunction(dragDelta * this.step);
|
||||||
if (dx > 0) {
|
|
||||||
this.elInput.stepUp();
|
|
||||||
--dx;
|
|
||||||
} else {
|
|
||||||
this.elInput.stepDown();
|
|
||||||
++dx;
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
if (dragDelta > 0) {
|
||||||
|
this.elInput.stepUp(dragDelta);
|
||||||
|
} else {
|
||||||
|
this.elInput.stepDown(-dragDelta);
|
||||||
}
|
}
|
||||||
this.inputChange();
|
this.inputChange();
|
||||||
if (this.valueChangeFunction) {
|
if (this.valueChangeFunction) {
|
||||||
this.valueChangeFunction();
|
this.valueChangeFunction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
this.lastMouseEvent = event;
|
this.lastMouseEvent = event;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -106,25 +108,46 @@ DraggableNumber.prototype = {
|
||||||
|
|
||||||
stepUp: function() {
|
stepUp: function() {
|
||||||
if (!this.isDisabled()) {
|
if (!this.isDisabled()) {
|
||||||
|
if (this.multiDiffModeEnabled) {
|
||||||
|
if (this.multiDiffStepFunction) {
|
||||||
|
this.multiDiffStepFunction(this.step, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.elInput.value = parseFloat(this.elInput.value) + this.step;
|
this.elInput.value = parseFloat(this.elInput.value) + this.step;
|
||||||
this.inputChange();
|
this.inputChange();
|
||||||
if (this.valueChangeFunction) {
|
if (this.valueChangeFunction) {
|
||||||
this.valueChangeFunction();
|
this.valueChangeFunction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
stepDown: function() {
|
stepDown: function() {
|
||||||
if (!this.isDisabled()) {
|
if (!this.isDisabled()) {
|
||||||
|
if (this.multiDiffModeEnabled) {
|
||||||
|
if (this.multiDiffStepFunction) {
|
||||||
|
this.multiDiffStepFunction(-this.step, true);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
this.elInput.value = parseFloat(this.elInput.value) - this.step;
|
this.elInput.value = parseFloat(this.elInput.value) - this.step;
|
||||||
this.inputChange();
|
this.inputChange();
|
||||||
if (this.valueChangeFunction) {
|
if (this.valueChangeFunction) {
|
||||||
this.valueChangeFunction();
|
this.valueChangeFunction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setValue: function(newValue) {
|
setValue: function(newValue, isMultiDiff) {
|
||||||
|
if (isMultiDiff !== undefined) {
|
||||||
|
this.setMultiDiff(isMultiDiff);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(newValue)) {
|
||||||
|
console.error("DraggableNumber.setValue() > " + newValue + " is not a number.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (newValue !== "" && this.decimals !== undefined) {
|
if (newValue !== "" && this.decimals !== undefined) {
|
||||||
this.elInput.value = parseFloat(newValue).toFixed(this.decimals);
|
this.elInput.value = parseFloat(newValue).toFixed(this.decimals);
|
||||||
} else {
|
} else {
|
||||||
|
@ -133,11 +156,24 @@ DraggableNumber.prototype = {
|
||||||
this.elText.firstChild.data = this.elInput.value;
|
this.elText.firstChild.data = this.elInput.value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setMultiDiff: function(isMultiDiff) {
|
||||||
|
this.multiDiffModeEnabled = isMultiDiff;
|
||||||
|
if (isMultiDiff) {
|
||||||
|
this.elDiv.classList.add('multi-diff');
|
||||||
|
} else {
|
||||||
|
this.elDiv.classList.remove('multi-diff');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
setValueChangeFunction: function(valueChangeFunction) {
|
setValueChangeFunction: function(valueChangeFunction) {
|
||||||
this.valueChangeFunction = valueChangeFunction.bind(this.elInput);
|
this.valueChangeFunction = valueChangeFunction.bind(this.elInput);
|
||||||
this.elInput.addEventListener("change", this.valueChangeFunction);
|
this.elInput.addEventListener("change", this.valueChangeFunction);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
setMultiDiffStepFunction: function (multiDiffStepFunction) {
|
||||||
|
this.multiDiffStepFunction = multiDiffStepFunction;
|
||||||
|
},
|
||||||
|
|
||||||
inputChange: function() {
|
inputChange: function() {
|
||||||
let value = this.elInput.value;
|
let value = this.elInput.value;
|
||||||
if (this.max !== undefined) {
|
if (this.max !== undefined) {
|
||||||
|
@ -155,6 +191,9 @@ DraggableNumber.prototype = {
|
||||||
|
|
||||||
keyPress: function(event) {
|
keyPress: function(event) {
|
||||||
if (event.keyCode === ENTER_KEY) {
|
if (event.keyCode === ENTER_KEY) {
|
||||||
|
if (this.valueChangeFunction) {
|
||||||
|
this.valueChangeFunction();
|
||||||
|
}
|
||||||
this.inputBlur();
|
this.inputBlur();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -204,6 +243,9 @@ DraggableNumber.prototype = {
|
||||||
this.elRightArrow.innerHTML = 'D';
|
this.elRightArrow.innerHTML = 'D';
|
||||||
this.elRightArrow.addEventListener("click", this.onStepUp);
|
this.elRightArrow.addEventListener("click", this.onStepUp);
|
||||||
|
|
||||||
|
this.elMultiDiff = document.createElement('span');
|
||||||
|
this.elMultiDiff.className = 'multi-diff';
|
||||||
|
|
||||||
this.elInput = document.createElement('input');
|
this.elInput = document.createElement('input');
|
||||||
this.elInput.className = "input";
|
this.elInput.className = "input";
|
||||||
this.elInput.setAttribute("type", "number");
|
this.elInput.setAttribute("type", "number");
|
||||||
|
@ -220,6 +262,7 @@ DraggableNumber.prototype = {
|
||||||
this.elDiv.appendChild(this.elLeftArrow);
|
this.elDiv.appendChild(this.elLeftArrow);
|
||||||
this.elDiv.appendChild(this.elText);
|
this.elDiv.appendChild(this.elText);
|
||||||
this.elDiv.appendChild(this.elInput);
|
this.elDiv.appendChild(this.elInput);
|
||||||
|
this.elDiv.appendChild(this.elMultiDiff);
|
||||||
this.elDiv.appendChild(this.elRightArrow);
|
this.elDiv.appendChild(this.elRightArrow);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,3 +25,70 @@ function disableDragDrop() {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// mergeDeep function from https://stackoverflow.com/a/34749873
|
||||||
|
/**
|
||||||
|
* Simple object check.
|
||||||
|
* @param item
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
function mergeDeepIsObject(item) {
|
||||||
|
return (item && typeof item === 'object' && !Array.isArray(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deep merge two objects.
|
||||||
|
* @param target
|
||||||
|
* @param sources
|
||||||
|
*/
|
||||||
|
function mergeDeep(target, ...sources) {
|
||||||
|
if (!sources.length) {
|
||||||
|
return target;
|
||||||
|
}
|
||||||
|
const source = sources.shift();
|
||||||
|
|
||||||
|
if (mergeDeepIsObject(target) && mergeDeepIsObject(source)) {
|
||||||
|
for (const key in source) {
|
||||||
|
if (!source.hasOwnProperty(key)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (mergeDeepIsObject(source[key])) {
|
||||||
|
if (!target[key]) {
|
||||||
|
Object.assign(target, { [key]: {} });
|
||||||
|
}
|
||||||
|
mergeDeep(target[key], source[key]);
|
||||||
|
} else {
|
||||||
|
Object.assign(target, { [key]: source[key] });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mergeDeep(target, ...sources);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deepEqual(a, b) {
|
||||||
|
if (a === b) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof(a) !== "object" || typeof(b) !== "object") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Object.keys(a).length !== Object.keys(b).length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let property in a) {
|
||||||
|
if (!a.hasOwnProperty(property)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (!b.hasOwnProperty(property)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!deepEqual(a[property], b[property])) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ protected:
|
||||||
|
|
||||||
QString _workingFolder;
|
QString _workingFolder;
|
||||||
|
|
||||||
const QString DEV_BUILD_XML_URL{ "https://highfidelity.com/dev-builds.xml" };
|
const QString DEV_BUILD_XML_URL{ "https://metaverse.highfidelity.com/dev-builds.xml" };
|
||||||
const QString DEV_BUILD_XML_FILENAME{ "dev-builds.xml" };
|
const QString DEV_BUILD_XML_FILENAME{ "dev-builds.xml" };
|
||||||
|
|
||||||
bool buildXMLDownloaded;
|
bool buildXMLDownloaded;
|
||||||
|
|
|
@ -60,5 +60,5 @@ const double R_Y = 0.212655f;
|
||||||
const double G_Y = 0.715158f;
|
const double G_Y = 0.715158f;
|
||||||
const double B_Y = 0.072187f;
|
const double B_Y = 0.072187f;
|
||||||
|
|
||||||
const QString nitpickVersion{ "v3.2.0" };
|
const QString nitpickVersion{ "v3.2.1" };
|
||||||
#endif // hifi_common_h
|
#endif // hifi_common_h
|
|
@ -258,7 +258,7 @@ void DomainBaker::addScriptBaker(const QString& property, const QString& url, co
|
||||||
_entitiesNeedingRewrite.insert(scriptURL, { property, jsonRef });
|
_entitiesNeedingRewrite.insert(scriptURL, { property, jsonRef });
|
||||||
}
|
}
|
||||||
|
|
||||||
void DomainBaker::addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef) {
|
void DomainBaker::addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef, QUrl destinationPath) {
|
||||||
// grab a clean version of the URL without a query or fragment
|
// grab a clean version of the URL without a query or fragment
|
||||||
QString materialData;
|
QString materialData;
|
||||||
if (isURL) {
|
if (isURL) {
|
||||||
|
@ -272,7 +272,7 @@ void DomainBaker::addMaterialBaker(const QString& property, const QString& data,
|
||||||
|
|
||||||
// setup a baker for this material
|
// setup a baker for this material
|
||||||
QSharedPointer<MaterialBaker> materialBaker {
|
QSharedPointer<MaterialBaker> materialBaker {
|
||||||
new MaterialBaker(data, isURL, _contentOutputPath),
|
new MaterialBaker(data, isURL, _contentOutputPath, destinationPath),
|
||||||
&MaterialBaker::deleteLater
|
&MaterialBaker::deleteLater
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -412,13 +412,9 @@ void DomainBaker::enumerateEntities() {
|
||||||
if (entity.contains(MATERIAL_URL_KEY)) {
|
if (entity.contains(MATERIAL_URL_KEY)) {
|
||||||
addMaterialBaker(MATERIAL_URL_KEY, entity[MATERIAL_URL_KEY].toString(), true, *it);
|
addMaterialBaker(MATERIAL_URL_KEY, entity[MATERIAL_URL_KEY].toString(), true, *it);
|
||||||
}
|
}
|
||||||
// FIXME: Disabled for now because relative texture URLs are not supported for embedded materials in material entities
|
|
||||||
// We need to make texture URLs absolute in this particular case only, keeping in mind that FSTBaker also uses embedded materials
|
|
||||||
/*
|
|
||||||
if (entity.contains(MATERIAL_DATA_KEY)) {
|
if (entity.contains(MATERIAL_DATA_KEY)) {
|
||||||
addMaterialBaker(MATERIAL_DATA_KEY, entity[MATERIAL_DATA_KEY].toString(), false, *it);
|
addMaterialBaker(MATERIAL_DATA_KEY, entity[MATERIAL_DATA_KEY].toString(), false, *it, _destinationPath);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ private:
|
||||||
void addModelBaker(const QString& property, const QString& url, const QJsonValueRef& jsonRef);
|
void addModelBaker(const QString& property, const QString& url, const QJsonValueRef& jsonRef);
|
||||||
void addTextureBaker(const QString& property, const QString& url, image::TextureUsage::Type type, const QJsonValueRef& jsonRef);
|
void addTextureBaker(const QString& property, const QString& url, image::TextureUsage::Type type, const QJsonValueRef& jsonRef);
|
||||||
void addScriptBaker(const QString& property, const QString& url, const QJsonValueRef& jsonRef);
|
void addScriptBaker(const QString& property, const QString& url, const QJsonValueRef& jsonRef);
|
||||||
void addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef);
|
void addMaterialBaker(const QString& property, const QString& data, bool isURL, const QJsonValueRef& jsonRef, QUrl destinationPath = QUrl());
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_DomainBaker_h
|
#endif // hifi_DomainBaker_h
|
||||||
|
|
Loading…
Reference in a new issue