From 206d1c0157c338de485cedd06a89bf6029cc9255 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sat, 29 Jun 2024 21:50:33 -0700 Subject: [PATCH 01/29] shader error fallback --- interface/resources/shaders/errorShader.frag | 30 +++++++++++++++++++ .../resources/shaders/errorSkyboxShader.frag | 7 +++++ .../procedural/src/procedural/Procedural.cpp | 19 +++++++++++- .../procedural/src/procedural/Procedural.h | 5 ++++ .../src/procedural/ProceduralSkybox.cpp | 2 ++ 5 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 interface/resources/shaders/errorShader.frag create mode 100644 interface/resources/shaders/errorSkyboxShader.frag diff --git a/interface/resources/shaders/errorShader.frag b/interface/resources/shaders/errorShader.frag new file mode 100644 index 0000000000..acfd23505e --- /dev/null +++ b/interface/resources/shaders/errorShader.frag @@ -0,0 +1,30 @@ +vec3 getErrorColor() { + vec3 positionWS = iWorldOrientation * (_positionMS.xyz * iWorldScale) + iWorldPosition; + float checkSize = 0.1; + vec3 edges = round(mod(positionWS, vec3(checkSize)) / checkSize); + float checkerboard = mod(edges.x + edges.y + edges.z, 2.0); + return mix(vec3(1, 0, 1), vec3(0.0), checkerboard); +} + +// version 1 +vec3 getProceduralColor() { + return getErrorColor(); +} + +// version 2 +float getProceduralColors(inout vec3 diffuse, inout vec3 specular, inout float shininess) { + diffuse = getErrorColor(); + return 1.0; +} + +// version 3 +float getProceduralFragment(inout ProceduralFragment data) { + data.emissive = getErrorColor(); + return 1.0; +} + +// version 4 +float getProceduralFragmentWithPosition(inout ProceduralFragmentWithPosition data) { + data.emissive = getErrorColor(); + return 1.0; +} diff --git a/interface/resources/shaders/errorSkyboxShader.frag b/interface/resources/shaders/errorSkyboxShader.frag new file mode 100644 index 0000000000..1c9b333ae5 --- /dev/null +++ b/interface/resources/shaders/errorSkyboxShader.frag @@ -0,0 +1,7 @@ +vec3 getSkyboxColor() { + vec3 normal = normalize(_normal); + float checkSize = 0.1; + vec3 edges = round(mod(normal, vec3(checkSize)) / checkSize); + float checkerboard = mod(edges.x + edges.y + edges.z, 2.0); + return mix(vec3(1, 0, 1), vec3(0.0), checkerboard); +} diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 66dde1ca56..91b949e280 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -377,6 +377,16 @@ void Procedural::prepare(gpu::Batch& batch, _proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState); + if (_errorFallbackFragmentSource.isEmpty()) { + QFile file(_errorFallbackFragmentPath); + file.open(QIODevice::ReadOnly); + _errorFallbackFragmentSource = QTextStream(&file).readAll(); + } + fragmentSource.replacements[PROCEDURAL_BLOCK] = _errorFallbackFragmentSource.toStdString(); + gpu::ShaderPointer errorFragmentShader = gpu::Shader::createPixel(fragmentSource); + gpu::ShaderPointer errorProgram = gpu::Shader::createProgram(vertexShader, errorFragmentShader); + _errorPipelines[key] = gpu::Pipeline::create(errorProgram, _opaqueState); + _lastCompile = usecTimestampNow(); if (_firstCompile == 0) { _firstCompile = _lastCompile; @@ -385,8 +395,13 @@ void Procedural::prepare(gpu::Batch& batch, recompiledShader = true; } + gpu::PipelinePointer finalPipeline = recompiledShader ? _proceduralPipelines[key] : pipeline->second; + if (!finalPipeline || finalPipeline->getProgram()->compilationHasFailed()) { + finalPipeline = _errorPipelines[key]; + } + // FIXME: need to handle forward rendering - batch.setPipeline(recompiledShader ? _proceduralPipelines[key] : pipeline->second); + batch.setPipeline(finalPipeline); bool recreateUniforms = _shaderDirty || _uniformsDirty || recompiledShader || _prevKey != key; if (recreateUniforms) { @@ -533,4 +548,6 @@ void graphics::ProceduralMaterial::initializeProcedural() { // FIXME: Setup proper uniform slots and use correct pipelines for forward rendering _procedural._opaqueFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural); _procedural._transparentFragmentSource = gpu::Shader::getFragmentShaderSource(shader::render_utils::fragment::simple_procedural_translucent); + + _procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorShader.frag").path(); } \ No newline at end of file diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 39c619c687..3b78563b40 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -124,6 +124,8 @@ public: gpu::Shader::Source _opaqueFragmentSource; gpu::Shader::Source _transparentFragmentSource; + QString _errorFallbackFragmentSource; + gpu::StatePointer _opaqueState { std::make_shared() }; gpu::StatePointer _transparentState { std::make_shared() }; @@ -176,11 +178,14 @@ protected: bool _shaderDirty { true }; bool _uniformsDirty { true }; + QString _errorFallbackFragmentPath; + // Rendering objects UniformLambdas _uniforms; NetworkTexturePointer _channels[MAX_PROCEDURAL_TEXTURE_CHANNELS]; std::unordered_map _proceduralPipelines; + std::unordered_map _errorPipelines; StandardInputs _standardInputs; gpu::BufferPointer _standardInputsBuffer; diff --git a/libraries/procedural/src/procedural/ProceduralSkybox.cpp b/libraries/procedural/src/procedural/ProceduralSkybox.cpp index 432e02fe10..5cbf11f298 100644 --- a/libraries/procedural/src/procedural/ProceduralSkybox.cpp +++ b/libraries/procedural/src/procedural/ProceduralSkybox.cpp @@ -22,6 +22,8 @@ ProceduralSkybox::ProceduralSkybox(uint64_t created) : graphics::Skybox(), _crea _procedural._vertexSource = shader::Source::get(shader::graphics::vertex::skybox); _procedural._opaqueFragmentSource = shader::Source::get(shader::procedural::fragment::proceduralSkybox); + _procedural._errorFallbackFragmentPath = ":" + QUrl("qrc:///shaders/errorSkyboxShader.frag").path(); + _procedural.setDoesFade(false); // Adjust the pipeline state for background using the stencil test From 2a3d1c639c73b55285f30f6ace4801632bbe134a Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sat, 29 Jun 2024 22:49:55 -0700 Subject: [PATCH 02/29] disabled fallback --- interface/src/Menu.cpp | 2 +- .../procedural/src/procedural/Procedural.cpp | 19 +++++++++++++++++-- .../procedural/src/procedural/Procedural.h | 7 +++++-- .../render-utils/src/MeshPartPayload.cpp | 5 ----- libraries/render-utils/src/MeshPartPayload.h | 2 -- 5 files changed, 23 insertions(+), 12 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 7017f2a083..c1d7c05f79 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -540,7 +540,7 @@ Menu::Menu() { action = addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::MaterialProceduralShaders, 0, false); connect(action, &QAction::triggered, [action] { - ModelMeshPartPayload::enableMaterialProceduralShaders = action->isChecked(); + Procedural::enableProceduralShaders = action->isChecked(); }); { diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 91b949e280..5a27d393bc 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -28,6 +28,8 @@ Q_LOGGING_CATEGORY(proceduralLog, "hifi.gpu.procedural") +bool Procedural::enableProceduralShaders = false; + // User-data parsing constants static const QString PROCEDURAL_USER_DATA_KEY = "ProceduralEntity"; static const QString VERTEX_URL_KEY = "vertexShaderURL"; @@ -377,16 +379,27 @@ void Procedural::prepare(gpu::Batch& batch, _proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState); + // Error falllback: pink checkerboard if (_errorFallbackFragmentSource.isEmpty()) { QFile file(_errorFallbackFragmentPath); file.open(QIODevice::ReadOnly); _errorFallbackFragmentSource = QTextStream(&file).readAll(); } + vertexSource.replacements.erase(PROCEDURAL_BLOCK); fragmentSource.replacements[PROCEDURAL_BLOCK] = _errorFallbackFragmentSource.toStdString(); + gpu::ShaderPointer errorVertexShader = gpu::Shader::createVertex(vertexSource); gpu::ShaderPointer errorFragmentShader = gpu::Shader::createPixel(fragmentSource); - gpu::ShaderPointer errorProgram = gpu::Shader::createProgram(vertexShader, errorFragmentShader); + gpu::ShaderPointer errorProgram = gpu::Shader::createProgram(errorVertexShader, errorFragmentShader); _errorPipelines[key] = gpu::Pipeline::create(errorProgram, _opaqueState); + // Disabled falllback: nothing + vertexSource.replacements.erase(PROCEDURAL_BLOCK); + fragmentSource.replacements.erase(PROCEDURAL_BLOCK); + gpu::ShaderPointer disabledVertexShader = gpu::Shader::createVertex(vertexSource); + gpu::ShaderPointer disabledFragmentShader = gpu::Shader::createPixel(fragmentSource); + gpu::ShaderPointer disabledProgram = gpu::Shader::createProgram(disabledVertexShader, disabledFragmentShader); + _disabledPipelines[key] = gpu::Pipeline::create(disabledProgram, _opaqueState); + _lastCompile = usecTimestampNow(); if (_firstCompile == 0) { _firstCompile = _lastCompile; @@ -396,7 +409,9 @@ void Procedural::prepare(gpu::Batch& batch, } gpu::PipelinePointer finalPipeline = recompiledShader ? _proceduralPipelines[key] : pipeline->second; - if (!finalPipeline || finalPipeline->getProgram()->compilationHasFailed()) { + if (!enableProceduralShaders) { + finalPipeline = _disabledPipelines[key]; + } else if (!finalPipeline || finalPipeline->getProgram()->compilationHasFailed()) { finalPipeline = _errorPipelines[key]; } diff --git a/libraries/procedural/src/procedural/Procedural.h b/libraries/procedural/src/procedural/Procedural.h index 3b78563b40..9e6f102e36 100644 --- a/libraries/procedural/src/procedural/Procedural.h +++ b/libraries/procedural/src/procedural/Procedural.h @@ -124,7 +124,7 @@ public: gpu::Shader::Source _opaqueFragmentSource; gpu::Shader::Source _transparentFragmentSource; - QString _errorFallbackFragmentSource; + QString _errorFallbackFragmentPath; gpu::StatePointer _opaqueState { std::make_shared() }; gpu::StatePointer _transparentState { std::make_shared() }; @@ -132,6 +132,8 @@ public: static std::function opaqueStencil; static std::function transparentStencil; + static bool enableProceduralShaders; + protected: // DO NOT TOUCH // We have to pack these in a particular way to match the ProceduralCommon.slh @@ -178,7 +180,7 @@ protected: bool _shaderDirty { true }; bool _uniformsDirty { true }; - QString _errorFallbackFragmentPath; + QString _errorFallbackFragmentSource; // Rendering objects UniformLambdas _uniforms; @@ -186,6 +188,7 @@ protected: std::unordered_map _proceduralPipelines; std::unordered_map _errorPipelines; + std::unordered_map _disabledPipelines; StandardInputs _standardInputs; gpu::BufferPointer _standardInputsBuffer; diff --git a/libraries/render-utils/src/MeshPartPayload.cpp b/libraries/render-utils/src/MeshPartPayload.cpp index e095d9b15d..a77dc6b160 100644 --- a/libraries/render-utils/src/MeshPartPayload.cpp +++ b/libraries/render-utils/src/MeshPartPayload.cpp @@ -25,8 +25,6 @@ using namespace render; -bool ModelMeshPartPayload::enableMaterialProceduralShaders = false; - ModelMeshPartPayload::ModelMeshPartPayload(ModelPointer model, int meshIndex, int partIndex, int shapeIndex, const Transform& transform, const uint64_t& created) : _meshIndex(meshIndex), @@ -345,9 +343,6 @@ void ModelMeshPartPayload::render(RenderArgs* args) { } if (_shapeKey.hasOwnPipeline()) { - if (!(enableMaterialProceduralShaders)) { - return; - } auto procedural = std::static_pointer_cast(_drawMaterials.top().material); auto& schema = _drawMaterials.getSchemaBuffer().get(); glm::vec4 outColor = glm::vec4(ColorUtils::tosRGBVec3(schema._albedo), schema._opacity); diff --git a/libraries/render-utils/src/MeshPartPayload.h b/libraries/render-utils/src/MeshPartPayload.h index b502865f94..0818340981 100644 --- a/libraries/render-utils/src/MeshPartPayload.h +++ b/libraries/render-utils/src/MeshPartPayload.h @@ -68,8 +68,6 @@ public: void setBlendshapeBuffer(const std::unordered_map& blendshapeBuffers, const QVector& blendedMeshSizes); - static bool enableMaterialProceduralShaders; - private: void initCache(const ModelPointer& model, int shapeID); From 200a6e4821dda381b4f10f4446b5a34f30545618 Mon Sep 17 00:00:00 2001 From: HifiExperiments Date: Sat, 6 Jul 2024 16:40:36 -0700 Subject: [PATCH 03/29] typo --- libraries/procedural/src/procedural/Procedural.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/procedural/src/procedural/Procedural.cpp b/libraries/procedural/src/procedural/Procedural.cpp index 5a27d393bc..49d05d8059 100644 --- a/libraries/procedural/src/procedural/Procedural.cpp +++ b/libraries/procedural/src/procedural/Procedural.cpp @@ -379,7 +379,7 @@ void Procedural::prepare(gpu::Batch& batch, _proceduralPipelines[key] = gpu::Pipeline::create(program, key.isTransparent() ? _transparentState : _opaqueState); - // Error falllback: pink checkerboard + // Error fallback: pink checkerboard if (_errorFallbackFragmentSource.isEmpty()) { QFile file(_errorFallbackFragmentPath); file.open(QIODevice::ReadOnly); @@ -392,7 +392,7 @@ void Procedural::prepare(gpu::Batch& batch, gpu::ShaderPointer errorProgram = gpu::Shader::createProgram(errorVertexShader, errorFragmentShader); _errorPipelines[key] = gpu::Pipeline::create(errorProgram, _opaqueState); - // Disabled falllback: nothing + // Disabled fallback: nothing vertexSource.replacements.erase(PROCEDURAL_BLOCK); fragmentSource.replacements.erase(PROCEDURAL_BLOCK); gpu::ShaderPointer disabledVertexShader = gpu::Shader::createVertex(vertexSource); From e901cea8efcff1e62320ee06ae5c4407bb7b9682 Mon Sep 17 00:00:00 2001 From: Armored Dragon Date: Fri, 12 Jul 2024 16:01:45 -0500 Subject: [PATCH 04/29] Check if setting is enabled. Signed-off-by: Armored Dragon --- scripts/system/controllers/mouseLook.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/scripts/system/controllers/mouseLook.js b/scripts/system/controllers/mouseLook.js index e29a741865..c8e822646d 100644 --- a/scripts/system/controllers/mouseLook.js +++ b/scripts/system/controllers/mouseLook.js @@ -31,6 +31,7 @@ // Program ---- function onMouseLookChanged(newMouseLook) { + disableMouseLook(); mouseLookEnabled = newMouseLook; } @@ -38,8 +39,6 @@ // Toggle using the m key if (event.text.toLowerCase() === "m") { if (Camera.captureMouse) { - mouseLookActive = false; - Settings.setValue("mouselook-active", false); disableMouseLook(); } else { mouseLookActive = true; @@ -82,12 +81,16 @@ if (hmdActive) return; if (tablet.tabletShown) return; if (overlayActive) return; + if (!mouseLookEnabled) return; // Mouse look disabled via setting if (!mouseLookActive) return; // Mouse look disabled via the hotkey Camera.captureMouse = true; } function disableMouseLook() { + mouseLookActive = false; + Settings.setValue("mouselook-active", false); + Camera.captureMouse = false; } From 06f4550e55acf3b4b0c3f966d2bca3498eeff3b2 Mon Sep 17 00:00:00 2001 From: Armored Dragon Date: Sat, 13 Jul 2024 14:38:56 -0500 Subject: [PATCH 05/29] Hardcode link colorization. Signed-off-by: Armored Dragon --- scripts/communityScripts/armored-chat/armored_chat.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/communityScripts/armored-chat/armored_chat.qml b/scripts/communityScripts/armored-chat/armored_chat.qml index 13506c226a..ede60fca71 100644 --- a/scripts/communityScripts/armored-chat/armored_chat.qml +++ b/scripts/communityScripts/armored-chat/armored_chat.qml @@ -510,7 +510,7 @@ Rectangle { mess = mess.replace(arrow, "<"); var link = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; - mess = mess.replace(link, (match) => {return "" + match + " "}); + mess = mess.replace(link, (match) => {return `` + match + ` `}); var newline = /\n/gi; mess = mess.replace(newline, "
"); From 76de0958b140f88b80075a4a12b5583ab77b2c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Gro=C3=9F?= Date: Sat, 13 Jul 2024 22:26:46 +0200 Subject: [PATCH 06/29] Update LICENSE --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 02fef6ca74..dcbbcee40c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ Copyright (c) 2013-2019, High Fidelity, Inc. Copyright (c) 2019-2021, Vircadia contributors. -Copyright (c) 2022-2023, Overte e.V. +Copyright (c) 2022-2024, Overte e.V. All rights reserved. https://overte.org From 8656f23147a8afbcf80cafab1914f243c4e44059 Mon Sep 17 00:00:00 2001 From: Armored Dragon Date: Tue, 16 Jul 2024 17:38:32 -0500 Subject: [PATCH 07/29] Fix variable name. Signed-off-by: Armored Dragon --- scripts/system/controllers/controllerScripts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerScripts.js b/scripts/system/controllers/controllerScripts.js index 2901f7c024..6d0cd6f96e 100644 --- a/scripts/system/controllers/controllerScripts.js +++ b/scripts/system/controllers/controllerScripts.js @@ -58,7 +58,7 @@ function runDefaultsTogether() { function runDefaultsSeparately() { for (var i in CONTOLLER_SCRIPTS) { if (CONTOLLER_SCRIPTS.hasOwnProperty(i)) { - print("loading " + CONTOLLER_SCRIPTS[j]); + print("loading " + CONTOLLER_SCRIPTS[i]); Script.load(CONTOLLER_SCRIPTS[i]); } } From afddb463ec455961be2d9f9f64996b451e3a2b8d Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Wed, 17 Jul 2024 23:32:40 +0200 Subject: [PATCH 08/29] Remove question mark, the guess was correct --- interface/src/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 7e8c1afff3..4de09fca1f 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -97,7 +97,7 @@ int main(int argc, const char* argv[]) { ); QCommandLineOption protocolVersionOption( "protocolVersion", - "Writes the protocol version base64 signature to a file?", + "Writes the protocol version base64 signature to a file", "path" ); QCommandLineOption noUpdaterOption( From 13579a2b6ba9d95c850dd7fffb5ef40ece8de8da Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Wed, 17 Jul 2024 23:33:25 +0200 Subject: [PATCH 09/29] Add --getProtocolVersionData and --getProtocolVersionHash arguments --- interface/src/main.cpp | 38 +++++++++++ .../networking/src/udt/PacketHeaders.cpp | 16 +++++ libraries/networking/src/udt/PacketHeaders.h | 66 ++++++++++++++++++- 3 files changed, 117 insertions(+), 3 deletions(-) diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 4de09fca1f..c1854de446 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -275,6 +275,14 @@ int main(int argc, const char* argv[]) { "abortAfterInit", "Debug option. Aborts after initialization, right before the program starts running the event loop." ); + QCommandLineOption getProtocolVersionHashOption( + "getProtocolVersionHash", + "Debug option. Returns the network protocol version MD5 hash." + ); + QCommandLineOption getProtocolVersionDataOption( + "getProtocolVersionData", + "Debug option. Returns the network protocol detailed data in JSON." + ); // "--qmljsdebugger", which appears in output from "--help-all". // Those below don't seem to be optional. @@ -321,6 +329,8 @@ int main(int argc, const char* argv[]) { parser.addOption(abortAfterStartupOption); parser.addOption(abortAfterInitOption); parser.addOption(getPluginsOption); + parser.addOption(getProtocolVersionHashOption); + parser.addOption(getProtocolVersionDataOption); QString applicationPath; @@ -455,6 +465,34 @@ int main(int argc, const char* argv[]) { return 1; } } + if (parser.isSet(getProtocolVersionHashOption)) { + std::cout << protocolVersionsSignatureHex().toStdString() << std::endl; + return 0; + } + if (parser.isSet(getProtocolVersionDataOption)) { + auto protocolMap = protocolVersionsSignatureMap(); + QMetaEnum packetMetaEnum = QMetaEnum::fromType(); + + QJsonArray packetTypesList; + auto keyList = protocolMap.keys(); + std::sort(keyList.begin(), keyList.end()); // Sort by numeric value + + for(const auto packet : keyList) { + QJsonObject data; + int intValue = static_cast(packet); + QString keyName = packetMetaEnum.valueToKey(intValue); + + data["name"] = keyName; + data["value"] = intValue; + data["version"] = versionForPacketType(packet); + + packetTypesList.append(data); + } + + std::cout << QJsonDocument(packetTypesList).toJson().toStdString() << std::endl; + return 0; + } + static const QString APPLICATION_CONFIG_FILENAME = "config.json"; QDir applicationDir(applicationPath); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index e561bfe21e..2aafc5501e 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -130,6 +130,10 @@ void sendWrongProtocolVersionsSignature(bool sendWrongVersion) { static QByteArray protocolVersionSignature; static QString protocolVersionSignatureBase64; +static QString protocolVersionSignatureHex; +static QMap protocolVersionMap; + + static void ensureProtocolVersionsSignature() { static std::once_flag once; std::call_once(once, [&] { @@ -139,12 +143,14 @@ static void ensureProtocolVersionsSignature() { stream << numberOfProtocols; for (uint8_t packetType = 0; packetType < numberOfProtocols; packetType++) { uint8_t packetTypeVersion = static_cast(versionForPacketType(static_cast(packetType))); + protocolVersionMap[static_cast(packetType)] = packetTypeVersion; stream << packetTypeVersion; } QCryptographicHash hash(QCryptographicHash::Md5); hash.addData(buffer); protocolVersionSignature = hash.result(); protocolVersionSignatureBase64 = protocolVersionSignature.toBase64(); + protocolVersionSignatureHex = protocolVersionSignature.toHex(0); }); } QByteArray protocolVersionsSignature() { @@ -161,3 +167,13 @@ QString protocolVersionsSignatureBase64() { ensureProtocolVersionsSignature(); return protocolVersionSignatureBase64; } + +QString protocolVersionsSignatureHex() { + ensureProtocolVersionsSignature(); + return protocolVersionSignatureHex; +} + +QMap protocolVersionsSignatureMap() { + ensureProtocolVersionsSignature(); + return protocolVersionMap; +} \ No newline at end of file diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 3badfdf418..bc36d9444a 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -31,8 +31,15 @@ class PacketTypeEnum { Q_GADGET Q_ENUMS(Value) public: - // If adding a new packet packetType, you can replace one marked usable or add at the end. - // This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t + + /** + * @brief Packet type identifier + * + * Identifies the type of packet being sent. + * + * @note If adding a new packet packetType, you can replace one marked usable or add at the end. + * @note This enum must hold 256 or fewer packet types (so the value is <= 255) since it is statically typed as a uint8_t + */ enum class Value : uint8_t { Unknown, DomainConnectRequestPending, @@ -143,6 +150,8 @@ public: NUM_PACKET_TYPE }; + Q_ENUM(Value) + const static QHash getReplicatedPacketMapping() { const static QHash REPLICATED_PACKET_MAPPING { { PacketTypeEnum::Value::MicrophoneAudioNoEcho, PacketTypeEnum::Value::ReplicatedMicrophoneAudioNoEcho }, @@ -219,10 +228,60 @@ const int NUM_BYTES_MD5_HASH = 16; // NOTE: There is a max limit of 255, hopefully we have a better way to manage this by then. typedef uint8_t PacketVersion; +/** + * @brief Returns the version number of the given packet type + * + * If the implementation of a packet type is modified in an incompatible way, the implementation + * of this function needs to be modified to return an incremented value. + * + * This is used to determine whether the protocol is compatible between client and server. + * + * @note Version is limited to a max of 255. + * + * @param packetType Type of packet + * @return PacketVersion Version + */ PacketVersion versionForPacketType(PacketType packetType); -QByteArray protocolVersionsSignature(); /// returns a unique signature for all the current protocols + +/** + * @brief Returns a unique signature for all the current protocols + * + * This computes a MD5 hash that expresses the state of the protocol's specification. The calculation + * is done in ensureProtocolVersionsSignature and accounts for the following: + * + * * Number of known packet types + * * versionForPacketType(type) for each packet type. + * + * There's no provision for backwards compatibility, anything that changes this calculation is a protocol break. + * + * @return QByteArray MD5 digest as a byte array + */ +QByteArray protocolVersionsSignature(); + +/*** + * @brief Returns a unique signature for all the current protocols + * + * Same as protocolVersionsSignature(), in base64. + */ QString protocolVersionsSignatureBase64(); +/*** + * @brief Returns a unique signature for all the current protocols + * + * Same as protocolVersionsSignature(), in hex; + */ +QString protocolVersionsSignatureHex(); + +/*** + * @brief Returns the data used to compute the protocol version + * + * The key is the packet type. The value is the version for that packet type. + * + * Used for aiding in development. + */ +QMap protocolVersionsSignatureMap(); + + #if (PR_BUILD || DEV_BUILD) void sendWrongProtocolVersionsSignature(bool sendWrongVersion); /// for debugging version negotiation #endif @@ -428,4 +487,5 @@ enum class AvatarQueryVersion : PacketVersion { ConicalFrustums = 22 }; + #endif // hifi_PacketHeaders_h From c06a60eaea1b42acb3683d4a1cf1b57f0d077782 Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Thu, 18 Jul 2024 16:39:37 +0200 Subject: [PATCH 10/29] Fix wireshark dissector, update with new packet types. Probably still incomplete, but getting closer. --- tools/dissectors/1-hfudt.lua | 53 +++++++++++++++++++++++++----- tools/dissectors/2-hf-audio.lua | 2 +- tools/dissectors/3-hf-avatar.lua | 1 + tools/dissectors/4-hf-entity.lua | 1 + tools/dissectors/5-hf-domain.lua | 2 ++ tools/dissectors/README.md | 56 ++++++++++++++++++++++++++------ 6 files changed, 96 insertions(+), 19 deletions(-) diff --git a/tools/dissectors/1-hfudt.lua b/tools/dissectors/1-hfudt.lua index 5a03331fc6..2be889c8c9 100644 --- a/tools/dissectors/1-hfudt.lua +++ b/tools/dissectors/1-hfudt.lua @@ -1,4 +1,5 @@ print("Loading hfudt") +bit32 = require("bit32") -- create the HFUDT protocol p_hfudt = Proto("hfudt", "HFUDT Protocol") @@ -154,19 +155,55 @@ local packet_types = { [99] = "EntityQueryInitialResultsComplete", [100] = "BulkAvatarTraits", [101] = "AudioSoloRequest", - [102] = "BulkAvatarTraitsAck" + [102] = "BulkAvatarTraitsAck", + [103] = "StopInjector", + [104] = "AvatarZonePresence", + [105] = "WebRTCSignaling" } +-- PacketHeaders.h, getNonSourcedPackets() local unsourced_packet_types = { - ["DomainList"] = true, + ["DomainConnectRequestPending"] = true, + ["CreateAssignment"] = true, + ["RequestAssignment"] = true, + ["DomainServerRequireDTLS"] = true, ["DomainConnectRequest"] = true, - ["ICEPing"] = true, - ["ICEPingReply"] = true, + ["DomainList"] = true, + ["DomainConnectionDenied"] = true, + ["DomainServerPathQuery"] = true, + ["DomainServerPathResponse"] = true, + ["DomainServerAddedNode"] = true, ["DomainServerConnectionToken"] = true, ["DomainSettingsRequest"] = true, - ["ICEServerHeartbeatACK"] = true + ["OctreeDataFileRequest"] = true, + ["OctreeDataFileReply"] = true, + ["OctreeDataPersist"] = true, + ["DomainContentReplacementFromUrl"] = true, + ["DomainSettings"] = true, + ["ICEServerPeerInformation"] = true, + ["ICEServerQuery"] = true, + ["ICEServerHeartbeat"] = true, + ["ICEServerHeartbeatACK"] = true, + ["ICEPing"] = true, + ["ICEPingReply"] = true, + ["ICEServerHeartbeatDenied"] = true, + ["AssignmentClientStatus"] = true, + ["StopNode"] = true, + ["DomainServerRemovedNode"] = true, + ["UsernameFromIDReply"] = true, + ["OctreeFileReplacement"] = true, + ["ReplicatedMicrophoneAudioNoEcho"] = true, + ["ReplicatedMicrophoneAudioWithEcho"] = true, + ["ReplicatedInjectAudio"] = true, + ["ReplicatedSilentAudioFrame"] = true, + ["ReplicatedAvatarIdentity"] = true, + ["ReplicatedKillAvatar"] = true, + ["ReplicatedBulkAvatarData"] = true, + ["AvatarZonePresence"] = true, + ["WebRTCSignaling"] = true } +-- PacketHeaders.h, getNonVerifiedPackets() local nonverified_packet_types = { ["NodeJsonStats"] = true, ["EntityQuery"] = true, @@ -257,7 +294,7 @@ function p_hfudt.dissector(buf, pinfo, tree) -- read the obfuscation level local obfuscation_bits = bit32.band(0x03, bit32.rshift(first_word, 27)) subtree:add(f_obfuscation_level, obfuscation_bits) - + -- read the sequence number subtree:add(f_sequence_number, bit32.band(first_word, SEQUENCE_NUMBER_MASK)) @@ -431,12 +468,12 @@ function deobfuscate(message_bit, buf, level) else return end - + local start = 4 if message_bit == 1 then local start = 12 end - + local p = 0 for i = start, buf:len() - 1 do out:set_index(i, bit.bxor(buf(i, 1):le_uint(), key:get_index(7 - (p % 8))) ) diff --git a/tools/dissectors/2-hf-audio.lua b/tools/dissectors/2-hf-audio.lua index fa4d50fab1..1e6b0b6431 100644 --- a/tools/dissectors/2-hf-audio.lua +++ b/tools/dissectors/2-hf-audio.lua @@ -1,5 +1,5 @@ print("Loading hf-audio") - +bit32 = require("bit32") -- create the audio protocol p_hf_audio = Proto("hf-audio", "HF Audio Protocol") diff --git a/tools/dissectors/3-hf-avatar.lua b/tools/dissectors/3-hf-avatar.lua index 9b8567c55f..8104649b0d 100644 --- a/tools/dissectors/3-hf-avatar.lua +++ b/tools/dissectors/3-hf-avatar.lua @@ -1,4 +1,5 @@ print("Loading hf-avatar") +bit32 = require("bit32") -- create the avatar protocol p_hf_avatar = Proto("hf-avatar", "HF Avatar Protocol") diff --git a/tools/dissectors/4-hf-entity.lua b/tools/dissectors/4-hf-entity.lua index 568eb5baa3..7de5eeee4d 100644 --- a/tools/dissectors/4-hf-entity.lua +++ b/tools/dissectors/4-hf-entity.lua @@ -1,4 +1,5 @@ print("Loading hf-entity") +bit32 = require("bit32") -- create the entity protocol p_hf_entity = Proto("hf-entity", "HF Entity Protocol") diff --git a/tools/dissectors/5-hf-domain.lua b/tools/dissectors/5-hf-domain.lua index 093026bc92..e2f9da4d9b 100644 --- a/tools/dissectors/5-hf-domain.lua +++ b/tools/dissectors/5-hf-domain.lua @@ -1,4 +1,6 @@ -- create the domain protocol +print("Loading hf-domain") +bit32 = require("bit32") p_hf_domain = Proto("hf-domain", "HF Domain Protocol") -- domain packet fields diff --git a/tools/dissectors/README.md b/tools/dissectors/README.md index 1e618a7b4c..b97e9e3b7a 100644 --- a/tools/dissectors/README.md +++ b/tools/dissectors/README.md @@ -1,14 +1,50 @@ -High Fidelity Wireshark Plugins ---------------------------------- +# High Fidelity Wireshark Plugins -Install wireshark 2.4.6 or higher. -Copy these lua files into c:\Users\username\AppData\Roaming\Wireshark\Plugins +## Installation -After a capture any detected High Fidelity Packets should be easily identifiable by one of the following protocols -* HF-AUDIO - Streaming audio packets -* HF-AVATAR - Streaming avatar mixer packets -* HF-ENTITY - Entity server traffic -* HF-DOMAIN - Domain server traffic -* HFUDT - All other UDP traffic +* Install wireshark 2.4.6 or higher. +* Copy these lua files into `c:\Users\username\AppData\Roaming\Wireshark\Plugins` on Windows, or `$HOME/.local/lib/wireshark/plugins` on Linux. + +## Lua version + +This is a Lua plugin, which requires the bit32 module to be installed. You can find the Lua version wireshark uses in the About dialog, eg: + + Version 4.2.5 (Git commit 798e06a0f7be). + + Compiled (64-bit) using GCC 14.1.1 20240507 (Red Hat 14.1.1-1), with GLib + 2.80.2, with Qt 6.7.0, with libpcap, with POSIX capabilities (Linux), with libnl + 3, with zlib 1.3.0.zlib-ng, with PCRE2, with Lua 5.1.5, with GnuTLS 3.8.5 and + +This indicates Lua 5.1 is used (see on the last line) + + +## Requirements + +On Fedora 40: + +* wireshark-devel +* lua5.1-bit32 + + +## Usage + +After a capture any detected Overte Packets should be easily identifiable by one of the following protocols + +* `HF-AUDIO` - Streaming audio packets +* `HF-AVATAR` - Streaming avatar mixer packets +* `HF-ENTITY` - Entity server traffic +* `HF-DOMAIN` - Domain server traffic +* `HFUDT` - All other UDP traffic + + + + +## Troubleshooting + +### attempt to index global 'bit32' (a nil value) + +`[Expert Info (Error/Undecoded): Lua Error: /home/dale/.local/lib/wireshark/plugins/1-hfudt.lua:207: attempt to index global 'bit32' (a nil value)]` + +See the installation requirements, you need to install the bit32 Lua module for the right Lua version. From 56ab058543bf63de1cc9794b0ee04f16025185cf Mon Sep 17 00:00:00 2001 From: Dale Glass Date: Thu, 18 Jul 2024 20:00:22 +0200 Subject: [PATCH 11/29] Expand documentation and add packet type to the info column --- tools/dissectors/1-hfudt.lua | 3 +++ tools/dissectors/README.md | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/tools/dissectors/1-hfudt.lua b/tools/dissectors/1-hfudt.lua index 2be889c8c9..0a7937e980 100644 --- a/tools/dissectors/1-hfudt.lua +++ b/tools/dissectors/1-hfudt.lua @@ -259,6 +259,7 @@ function p_hfudt.dissector(buf, pinfo, tree) type:append_text(" (".. control_types[shifted_type][1] .. ")") subtree:add(f_control_type_text, control_types[shifted_type][1]) + pinfo.cols.info:append(" [" .. control_types[shifted_type][1] .. "]") end if shifted_type == 0 then @@ -337,10 +338,12 @@ function p_hfudt.dissector(buf, pinfo, tree) local packet_type = buf(payload_offset, 1):le_uint() local ptype = subtree:add_le(f_type, buf(payload_offset, 1)) local packet_type_text = packet_types[packet_type] + if packet_type_text ~= nil then subtree:add(f_type_text, packet_type_text) -- if we know this packet type then add the name ptype:append_text(" (".. packet_type_text .. ")") + pinfo.cols.info:append(" [" .. packet_type_text .. "]") end -- read the version diff --git a/tools/dissectors/README.md b/tools/dissectors/README.md index b97e9e3b7a..3b391f60c0 100644 --- a/tools/dissectors/README.md +++ b/tools/dissectors/README.md @@ -48,3 +48,26 @@ After a capture any detected Overte Packets should be easily identifiable by one `[Expert Info (Error/Undecoded): Lua Error: /home/dale/.local/lib/wireshark/plugins/1-hfudt.lua:207: attempt to index global 'bit32' (a nil value)]` See the installation requirements, you need to install the bit32 Lua module for the right Lua version. + +## Development hints + + +* Symlink files from the development tree to `$HOME/.local/lib/wireshark/plugins`, to have Wireshark work on the latest dissector code. +* Capture packets for later analysis in a PCAPNG file. +* Only save needed packets in the dump + +Decode on the commandline with: + + tshark -r packets.pcapng.gz -V + +Decode only the first packet: + + tshark -r packets.pcapng.gz -V -c 1 + +### Useful tshark arguments + +* `-x` hex dump +* `-c N` Only decode first N packets +* `-O hfudt,hf-domain,hf-entity,hf-avatar,hf-audio` Only dump Overte protocol data, skip dumping UDP/etc parts. +* `-V` decode protocols +* \ No newline at end of file From ffe6e3a323be8631c04dea2d215b82081580ce34 Mon Sep 17 00:00:00 2001 From: Armored Dragon Date: Thu, 18 Jul 2024 15:04:35 -0500 Subject: [PATCH 12/29] Remove onFirstRun.js Signed-off-by: Armored Dragon --- scripts/defaultScripts.js | 1 - scripts/system/onFirstRun.js | 35 ----------------------------------- 2 files changed, 36 deletions(-) delete mode 100644 scripts/system/onFirstRun.js diff --git a/scripts/defaultScripts.js b/scripts/defaultScripts.js index a9bc2be591..31afd6e2db 100644 --- a/scripts/defaultScripts.js +++ b/scripts/defaultScripts.js @@ -37,7 +37,6 @@ var DEFAULT_SCRIPTS_COMBINED = [ "system/inspect.js", "system/keyboardShortcuts/keyboardShortcuts.js", "system/onEscape.js", - "system/onFirstRun.js", "system/places/places.js" //"developer/debugging/scriptMemoryReport.js" ]; diff --git a/scripts/system/onFirstRun.js b/scripts/system/onFirstRun.js deleted file mode 100644 index e7052c0e3a..0000000000 --- a/scripts/system/onFirstRun.js +++ /dev/null @@ -1,35 +0,0 @@ -'use strict'; - -// -// onFirstRun.js -// -// Created by Kalila L. on Oct 5 2020. -// Copyright 2020 Vircadia contributors. -// -// This script triggers on first run to perform bootstrapping actions. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -(function() { // BEGIN LOCAL_SCOPE - // Check to see if we should run this script or bail... - var SETTING_TO_CHECK = 'firstRun'; - var DEFAULT_DISPLAY_NAME = ''; - - if (!Settings.getValue(SETTING_TO_CHECK, false)) { - return; - } - - // If this is our first run, then proceed... - - if (MyAvatar.displayName === '') { - var selectedDisplayName = Window.prompt('Enter a display name.', MyAvatar.displayName); - - if (selectedDisplayName === '') { - MyAvatar.displayName = DEFAULT_DISPLAY_NAME; - } else { - MyAvatar.displayName = selectedDisplayName; - } - } -}()); From 4a69e90035414857bcc6a0e4bc1efca642912e41 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 21 Jul 2024 22:31:56 -0400 Subject: [PATCH 13/29] Support MTOON in Material Assistant Support MTOON in Material Assistant --- scripts/system/html/css/materialAssistant.css | 57 ++++++++++++++++++- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/scripts/system/html/css/materialAssistant.css b/scripts/system/html/css/materialAssistant.css index 9944baf73f..6403bd018c 100644 --- a/scripts/system/html/css/materialAssistant.css +++ b/scripts/system/html/css/materialAssistant.css @@ -3,7 +3,7 @@ // // Created by Alezia Kurdis on May 17th, 2022. // Copyright 2022 Vircadia contributors. -// Copyright 2022 Overte e.V. +// Copyright 2022-2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -22,7 +22,12 @@ background-color: #404040; z-index: 2; border-collapse: collapse; +} + +#uiMaterialAssistant-scrollable { + border-collapse: collapse; overflow-y: scroll; + height: 100%; } #uiMaterialAssistant-headerContainer { @@ -80,12 +85,21 @@ font.uiMaterialAssistant-label{ color: #D2D2D2; } +label.uiMaterialAssistant-label{ + background-color: #2E2E2E; + font-family: Raleway-SemiBold; + text-decoration: none; + font-size: 12px; + color: #D2D2D2; +} + font.uiMaterialAssistant-title{ background-color: #404040; font-family: Raleway-Bold; font-size: 18px; text-decoration: none; color: #F2F2F2; + white-space: normal; } input[type=range].uiMaterialAssistant-slider { @@ -151,6 +165,18 @@ input[type=text].uiMaterialAssistant-input { color: #000000; } +textarea.uiMaterialAssistant-textarea { + background-color: #ffffff; + border: 1px solid #000000; + font-family: FiraSans-SemiBold; + font-size: 12px; + width: 100%; + height: 200px; + padding: 3px; + margin: 3px 0px 3px 0px; + color: #000000; +} + input[type=text].uiMaterialAssistant-input:disabled { background-color: #555555; color: #888888; @@ -171,8 +197,8 @@ input[type=checkbox].uiMaterialAssistant-checkbox { height: 16px; margin: 2px; padding: 3px; - display: block; text-align: left; + display: block; } input[type=checkbox].uiMaterialAssistant-checkbox:focus { @@ -221,3 +247,30 @@ div.uiMaterialAssistant-color-picker { width: 120px; height: 30px; } + +button.uiMaterialAssistant-smallButton { + font-family: Raleway-Regular; + font-size: 12px; + border-radius: 5px; + border: none; + color: #cccccc; + background-color: #000000; + background: linear-gradient(#575757 20%, #000000 100%); + cursor: pointer; + padding: 3px 10px 3px 10px; +} + +button.uiMaterialAssistant-smallButton:hover { + background: linear-gradient(#383838, #000000); + color: #eeeeee; + border: none; +} + +button.uiMaterialAssistant-smallButton:disabled { + color: #555555; +} + +button.uiMaterialAssistant-smallButton:focus { + outline: none; +} + From d189f70b367b7eca8d5843865d8e30b2ecddf033 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 21 Jul 2024 22:34:16 -0400 Subject: [PATCH 14/29] Support MTOON in Material Assistant Support MTOON in Material Assistant --- .../html/js/entityProperties.js | 17 +- .../html/js/materialAssistant.js | 1840 +++++++++++++++-- 2 files changed, 1736 insertions(+), 121 deletions(-) diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index dd8d67e24d..f94f6d2ffc 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -1841,6 +1841,7 @@ let createAppTooltip = new CreateAppTooltip(); let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL; let zonesList = []; let canViewAssetURLs = false; +let maSelectedId; function createElementFromHTML(htmlString) { let elTemplate = document.createElement('template'); @@ -3613,10 +3614,9 @@ function saveMaterialData() { function openMaterialAssistant() { if (materialEditor === null) { - loadDataInMaUi({}); - } else { - loadDataInMaUi(materialEditor.getText()); + newJSONMaterialEditor(); } + loadDataInMaUi(materialEditor.getText()); $('#uiMaterialAssistant').show(); $('#properties-list').hide(); } @@ -4177,7 +4177,16 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { const multipleSelections = currentSelections.length > 1; const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); - closeMaterialAssistant(); + if (selections.length === 1) { + if (maSelectedId !== selections[0].id) { + closeMaterialAssistant(); + } + maSelectedId = selections[0].id; + } else { + closeMaterialAssistant(); + maSelectedId = ""; + } + requestZoneList(); if (selections.length === 0) { diff --git a/scripts/system/create/entityProperties/html/js/materialAssistant.js b/scripts/system/create/entityProperties/html/js/materialAssistant.js index 02af601330..2b85eb1a38 100644 --- a/scripts/system/create/entityProperties/html/js/materialAssistant.js +++ b/scripts/system/create/entityProperties/html/js/materialAssistant.js @@ -2,7 +2,7 @@ // // Created by Alezia Kurdis on May 19th, 2022. // Copyright 2022 Vircadia contributors. -// Copyright 2022 Overte e.V. +// Copyright 2022-2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -20,12 +20,15 @@ let maClose, maMetallic, maMetallicSlider, maMetallicMap, + maUseSpecular, maRoughnessIsActive, maRoughness, maRoughnessSlider, maRoughnessMap, + maUseGloss, maNormalMapIsActive, maNormalMap, + maUseBump, maOpacityIsActive, maOpacity, maOpacitySlider, @@ -47,9 +50,71 @@ let maClose, maScatteringMap, maOcclusionMapIsActive, maOcclusionMap, + maLightMapIsActive, + maLightMap, + maShadeIsActive, + maShadeColorPicker, + maShadeColorPickerSel, + maShadeMapIsActive, + maShadeMap, + maMatcapIsActive, + maMatcapColorPicker, + maMatcapColorPickerSel, + maMatcapMapIsActive, + maMatcapMap, + maShadingShiftIsActive, + maShadingShift, + maShadingShiftSlider, + maShadingShiftMapIsActive, + maShadingShiftMap, + maShadingToonyIsActive, + maShadingToony, + maShadingToonySlider, + maParametricRimIsActive, + maParametricRimColorPicker, + maParametricRimColorPickerSel, + maRimMapIsActive, + maRimMap, + maParametricRimFresnelPowerIsActive, + maParametricRimFresnelPower, + maParametricRimFresnelPowerSlider, + maParametricRimLiftIsActive, + maParametricRimLift, + maParametricRimLiftSlider, + maRimLightingMixIsActive, + maRimLightingMix, + maRimLightingMixSlider, +/* ############## Not yet supported, but the code is ready (commented) ################### + maOutlineWidthModeIsActive, + maOutlineWidthModeNone, + maOutlineWidthModeWorld, + maOutlineWidthModeScreen, + maOutlineWidthIsActive, + maOutlineWidth, + maOutlineWidthSlider, + maOutlineIsActive, + maOutlineColorPicker, + maOutlineColorPickerSel, +*/ + maUvAnimationMaskMapIsActive, + maUvAnimationMaskMap, + maUvAnimationScrollXSpeedIsActive, + maUvAnimationScrollXSpeed, + maUvAnimationScrollXSpeedSlider, + maUvAnimationScrollYSpeedIsActive, + maUvAnimationScrollYSpeed, + maUvAnimationScrollYSpeedSlider, + maUvAnimationRotationSpeedIsActive, + maUvAnimationRotationSpeed, + maUvAnimationRotationSpeedSlider, + maProcedural, + maAddProceduralTemplate, maCullFaceModeBack, maCullFaceModeFront, - maCullFaceModeNone; + maCullFaceModeNone, + maModelHifiPbr, + maModelVrmMtoon, + maModelHifiShaderSimple; let DEFAULT_ALBEDO = [1,1,1]; let DEFAULT_EMISSIVE = [0,0,0]; @@ -60,6 +125,25 @@ let DEFAULT_METALLIC = 0; let DEFAULT_OPACITY = 1; let DEFAULT_OPACITY_CUTOFF = 0.5; let DEFAULT_SCATTERING = 0; +let DEFAULT_MODEL = "hifi_pbr"; +let DEFAULT_SHADE = [1,1,1]; +let DEFAULT_MATCAP = [1,1,1]; +let DEFAULT_SHADING_SHIFT = 0.0; +let DEFAULT_SHADING_TOONY = 0.9; +let DEFAULT_PARAMETRIC_RIM = [0,0,0]; +let DEFAULT_RIM_LIGHTING_MIX = 1.0; +let DEFAULT_PARAMETRIC_RIM_FRESNEL_POWER = 5.0; +let DEFAULT_PARAMETRIC_RIM_LIFT = 0.0; + +/* ############## Not yet supported, but the code is ready ################### +let DEFAULT_OUTLINE = [0,0,0]; +let DEFAULT_OUTLINE_WIDTH_MODE = "none"; +let DEFAULT_OUTLINE_WIDTH = 0.0; +//################################################################# +*/ +let DEFAULT_UV_ANIMATION_SCROLL_X_SPEED = 0.0; +let DEFAULT_UV_ANIMATION_SCROLL_Y_SPEED = 0.0; +let DEFAULT_UV_ANIMATION_ROTATION_SPEED = 0.0; function initiateMaUi() { maClose = document.getElementById("uiMaterialAssistant-closeButton"); @@ -72,12 +156,15 @@ function initiateMaUi() { maMetallic = document.getElementById("ma-metallic"); maMetallicSlider = document.getElementById("ma-metallic-slider"); maMetallicMap = document.getElementById("ma-metallicMap"); + maUseSpecular = document.getElementById("ma-useSpecular"); maRoughnessIsActive = document.getElementById("ma-roughness-isActive"); maRoughness = document.getElementById("ma-roughness"); maRoughnessSlider = document.getElementById("ma-roughness-slider"); maRoughnessMap = document.getElementById("ma-roughnessMap"); + maUseGloss = document.getElementById("ma-useGloss"); maNormalMapIsActive = document.getElementById("ma-normalMap-isActive"); maNormalMap = document.getElementById("ma-normalMap"); + maUseBump = document.getElementById("ma-useBump"); maOpacityIsActive = document.getElementById("ma-opacity-isActive"); maOpacity = document.getElementById("ma-opacity"); maOpacitySlider = document.getElementById("ma-opacity-slider"); @@ -98,9 +185,69 @@ function initiateMaUi() { maScatteringMap = document.getElementById("ma-scatteringMap"); maOcclusionMapIsActive = document.getElementById("ma-occlusionMap-isActive"); maOcclusionMap = document.getElementById("ma-occlusionMap"); + maLightMapIsActive = document.getElementById("ma-lightMap-isActive"); + maLightMap = document.getElementById("ma-lightMap"); + maShadeIsActive = document.getElementById("ma-shade-isActive"); + maShadeColorPicker = document.getElementById("ma-shade-colorPicker"); + maShadeMapIsActive = document.getElementById("ma-shadeMap-isActive"); + maShadeMap = document.getElementById("ma-shadeMap"); + maMatcapIsActive = document.getElementById("ma-matcap-isActive"); + maMatcapColorPicker = document.getElementById("ma-matcap-colorPicker"); + maMatcapMapIsActive = document.getElementById("ma-matcapMap-isActive"); + maMatcapMap = document.getElementById("ma-matcapMap"); + maShadingShiftIsActive = document.getElementById("ma-shadingShift-isActive"); + maShadingShift = document.getElementById("ma-shadingShift"); + maShadingShiftSlider = document.getElementById("ma-shadingShift-slider"); + maShadingShiftMapIsActive = document.getElementById("ma-shadingShiftMap-isActive"); + maShadingShiftMap = document.getElementById("ma-shadingShiftMap"); + maShadingToonyIsActive = document.getElementById("ma-shadingToony-isActive"); + maShadingToony = document.getElementById("ma-shadingToony"); + maShadingToonySlider = document.getElementById("ma-shadingToony-slider"); + maParametricRimIsActive = document.getElementById("ma-parametricRim-isActive"); + maParametricRimColorPicker = document.getElementById("ma-parametricRim-colorPicker"); + maRimMapIsActive = document.getElementById("ma-rimMap-isActive"); + maRimMap = document.getElementById("ma-rimMap"); + maParametricRimFresnelPowerIsActive = document.getElementById("ma-parametricRimFresnelPower-isActive"); + maParametricRimFresnelPower = document.getElementById("ma-parametricRimFresnelPower"); + maParametricRimFresnelPowerSlider = document.getElementById("ma-parametricRimFresnelPower-slider"); + maParametricRimLiftIsActive = document.getElementById("ma-parametricRimLift-isActive"); + maParametricRimLift = document.getElementById("ma-parametricRimLift"); + maParametricRimLiftSlider = document.getElementById("ma-parametricRimLift-slider"); + maRimLightingMixIsActive = document.getElementById("ma-rimLightingMix-isActive"); + maRimLightingMix = document.getElementById("ma-rimLightingMix"); + maRimLightingMixSlider = document.getElementById("ma-rimLightingMix-slider"); + +/* ############## Not yet supported, but the code is ready ################################ + maOutlineWidthModeIsActive = document.getElementById("ma-outlineWidthMode-isActive"); + maOutlineWidthModeNone = document.getElementById("ma-outlineWidthMode-none"); + maOutlineWidthModeWorld = document.getElementById("ma-outlineWidthMode-world"); + maOutlineWidthModeScreen = document.getElementById("ma-outlineWidthMode-screen"); + maOutlineWidthIsActive = document.getElementById("ma-outlineWidth-isActive"); + maOutlineWidth = document.getElementById("ma-outlineWidth"); + maOutlineWidthSlider = document.getElementById("ma-outlineWidth-slider"); + maOutlineIsActive = document.getElementById("ma-outline-isActive"); + maOutlineColorPicker = document.getElementById("ma-outline-colorPicker"); + //################################################################################# +*/ + maUvAnimationMaskMapIsActive = document.getElementById("ma-uvAnimationMaskMap-isActive"); + maUvAnimationMaskMap = document.getElementById("ma-uvAnimationMaskMap"); + maUvAnimationScrollXSpeedIsActive = document.getElementById("ma-uvAnimationScrollXSpeed-isActive"); + maUvAnimationScrollXSpeed = document.getElementById("ma-uvAnimationScrollXSpeed"); + maUvAnimationScrollXSpeedSlider = document.getElementById("ma-uvAnimationScrollXSpeed-slider"); + maUvAnimationScrollYSpeedIsActive = document.getElementById("ma-uvAnimationScrollYSpeed-isActive"); + maUvAnimationScrollYSpeed = document.getElementById("ma-uvAnimationScrollYSpeed"); + maUvAnimationScrollYSpeedSlider = document.getElementById("ma-uvAnimationScrollYSpeed-slider"); + maUvAnimationRotationSpeedIsActive = document.getElementById("ma-uvAnimationRotationSpeed-isActive"); + maUvAnimationRotationSpeed = document.getElementById("ma-uvAnimationRotationSpeed"); + maUvAnimationRotationSpeedSlider = document.getElementById("ma-uvAnimationRotationSpeed-slider"); + maProcedural = document.getElementById("ma-procedural"); + maAddProceduralTemplate = document.getElementById("ma-addProceduralTemplate"); maCullFaceModeBack = document.getElementById("ma-cullFaceMode-back"); maCullFaceModeFront = document.getElementById("ma-cullFaceMode-front"); maCullFaceModeNone = document.getElementById("ma-cullFaceMode-none"); + maModelHifiPbr = document.getElementById("ma-Model-hifi_pbr"); + maModelVrmMtoon = document.getElementById("ma-Model-vrm_mtoon"); + maModelHifiShaderSimple = document.getElementById("ma-Model-hifi_shader_simple"); maClose.onclick = function() { closeMaterialAssistant(); @@ -128,8 +275,11 @@ function initiateMaUi() { maMaterialData.albedoMapIsActive = true; maAlbedoMapIsActive.className = "uiMaterialAssistant-active"; maAlbedoMap.disabled = false; + if (maMaterialData.albedoMap === undefined) { + maMaterialData.albedoMap = ""; + } } - maGenerateJsonAndSave(); + maGenerateJsonAndSave(); }; maMetallicIsActive.onclick = function() { if (maMaterialData.metallicIsActive) { @@ -138,12 +288,14 @@ function initiateMaUi() { maMetallic.disabled = true; maMetallicSlider.disabled = true; maMetallicMap.disabled = true; + maUseSpecular.disabled = true; } else { maMaterialData.metallicIsActive = true; maMetallicIsActive.className = "uiMaterialAssistant-active"; maMetallic.disabled = false; maMetallicSlider.disabled = false; - maMetallicMap.disabled = false; + maMetallicMap.disabled = false; + maUseSpecular.disabled = false; } maGenerateJsonAndSave(); }; @@ -154,12 +306,14 @@ function initiateMaUi() { maRoughness.disabled = true; maRoughnessSlider.disabled = true; maRoughnessMap.disabled = true; + maUseGloss.disabled = true; } else { maMaterialData.roughnessIsActive = true; maRoughnessIsActive.className = "uiMaterialAssistant-active"; maRoughness.disabled = false; maRoughnessSlider.disabled = false; - maRoughnessMap.disabled = false; + maRoughnessMap.disabled = false; + maUseGloss.disabled = false; } maGenerateJsonAndSave(); }; @@ -168,10 +322,15 @@ function initiateMaUi() { maMaterialData.normalMapIsActive = false; maNormalMapIsActive.className = "uiMaterialAssistant-inactive"; maNormalMap.disabled = true; + maUseBump.disabled = true; } else { maMaterialData.normalMapIsActive = true; maNormalMapIsActive.className = "uiMaterialAssistant-active"; maNormalMap.disabled = false; + maUseBump.disabled = false; + if (maMaterialData.normalMap === undefined) { + maMaterialData.normalMap = ""; + } } maGenerateJsonAndSave(); }; @@ -244,16 +403,34 @@ function initiateMaUi() { maMaterialData.occlusionMapIsActive = true; maOcclusionMapIsActive.className = "uiMaterialAssistant-active"; maOcclusionMap.disabled = false; + if (maMaterialData.occlusionMap === undefined) { + maMaterialData.occlusionMap = ""; + } } maGenerateJsonAndSave(); }; + maLightMapIsActive.onclick = function() { + if (maMaterialData.lightMapIsActive) { + maMaterialData.lightMapIsActive = false; + maLightMapIsActive.className = "uiMaterialAssistant-inactive"; + maLightMap.disabled = true; + } else { + maMaterialData.lightMapIsActive = true; + maLightMapIsActive.className = "uiMaterialAssistant-active"; + maLightMap.disabled = false; + if (maMaterialData.lightMap === undefined) { + maMaterialData.lightMap = ""; + } + } + maGenerateJsonAndSave(); + }; maName.oninput = function() { maMaterialData.name = maName.value; maGenerateJsonAndSave(); }; maAlbedoMap.oninput = function() { maMaterialData.albedoMap = maAlbedoMap.value; - maGenerateJsonAndSave(); + maGenerateJsonAndSave(); }; maMetallicSlider.oninput = function() { maMetallic.value = maMetallicSlider.value/1000; @@ -264,6 +441,10 @@ function initiateMaUi() { maMaterialData.metallicMap = maMetallicMap.value; maGenerateJsonAndSave(); }; + maUseSpecular.oninput = function() { + maMaterialData.useSpecular = maUseSpecular.checked; + maGenerateJsonAndSave(); + }; maRoughnessSlider.oninput = function() { maRoughness.value = maRoughnessSlider.value/1000; maMaterialData.roughness = parseFloat(maRoughness.value); @@ -273,10 +454,18 @@ function initiateMaUi() { maMaterialData.roughnessMap = maRoughnessMap.value; maGenerateJsonAndSave(); }; + maUseGloss.oninput = function() { + maMaterialData.useGloss = maUseGloss.checked; + maGenerateJsonAndSave(); + }; maNormalMap.oninput = function() { maMaterialData.normalMap = maNormalMap.value; maGenerateJsonAndSave(); }; + maUseBump.oninput = function() { + maMaterialData.useBump = maUseBump.checked; + maGenerateJsonAndSave(); + }; maOpacitySlider.oninput = function() { maOpacity.value = maOpacitySlider.value/1000; maMaterialData.opacity = parseFloat(maOpacity.value); @@ -325,6 +514,427 @@ function initiateMaUi() { maMaterialData.occlusionMap = maOcclusionMap.value; maGenerateJsonAndSave(); }; + maLightMap.oninput = function() { + maMaterialData.lightMap = maLightMap.value; + maGenerateJsonAndSave(); + }; + maShadeIsActive.onclick = function() { + if (maMaterialData.shadeIsActive) { + maMaterialData.shadeIsActive = false; + maShadeIsActive.className = "uiMaterialAssistant-inactive"; + maShadeColorPicker.style.pointerEvents = 'none'; + maShadeColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.shadeIsActive = true; + maShadeIsActive.className = "uiMaterialAssistant-active"; + maShadeColorPicker.style.pointerEvents = 'auto'; + maShadeColorPicker.style.backgroundColor = maGetRGB(maMaterialData.shade); + } + maGenerateJsonAndSave(); + }; + maShadeMapIsActive.onclick = function() { + if (maMaterialData.shadeMapIsActive) { + maMaterialData.shadeMapIsActive = false; + maShadeMapIsActive.className = "uiMaterialAssistant-inactive"; + maShadeMap.disabled = true; + } else { + maMaterialData.shadeMapIsActive = true; + maShadeMapIsActive.className = "uiMaterialAssistant-active"; + maShadeMap.disabled = false; + if (maMaterialData.shadeMap === undefined) { + maMaterialData.shadeMap = ""; + } + } + maGenerateJsonAndSave(); + }; + + maShadeMap.oninput = function() { + maMaterialData.shadeMap = maShadeMap.value; + maGenerateJsonAndSave(); + }; + + maMatcapIsActive.onclick = function() { + if (maMaterialData.matcapIsActive) { + maMaterialData.matcapIsActive = false; + maMatcapIsActive.className = "uiMaterialAssistant-inactive"; + maMatcapColorPicker.style.pointerEvents = 'none'; + maMatcapColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.matcapIsActive = true; + maMatcapIsActive.className = "uiMaterialAssistant-active"; + maMatcapColorPicker.style.pointerEvents = 'auto'; + maMatcapColorPicker.style.backgroundColor = maGetRGB(maMaterialData.matcap); + } + maGenerateJsonAndSave(); + }; + maMatcapMapIsActive.onclick = function() { + if (maMaterialData.matcapMapIsActive) { + maMaterialData.matcapMapIsActive = false; + maMatcapMapIsActive.className = "uiMaterialAssistant-inactive"; + maMatcapMap.disabled = true; + } else { + maMaterialData.matcapMapIsActive = true; + maMatcapMapIsActive.className = "uiMaterialAssistant-active"; + maMatcapMap.disabled = false; + if (maMaterialData.matcapMap === undefined) { + maMaterialData.matcapMap = ""; + } + } + maGenerateJsonAndSave(); + }; + + maMatcapMap.oninput = function() { + maMaterialData.matcapMap = maMatcapMap.value; + maGenerateJsonAndSave(); + }; + + maParametricRimIsActive.onclick = function() { + if (maMaterialData.parametricRimIsActive) { + maMaterialData.parametricRimIsActive = false; + maParametricRimIsActive.className = "uiMaterialAssistant-inactive"; + maParametricRimColorPicker.style.pointerEvents = 'none'; + maParametricRimColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.parametricRimIsActive = true; + maParametricRimIsActive.className = "uiMaterialAssistant-active"; + maParametricRimColorPicker.style.pointerEvents = 'auto'; + maParametricRimColorPicker.style.backgroundColor = maGetRGB(maMaterialData.parametricRim); + } + maGenerateJsonAndSave(); + }; + + maRimMapIsActive.onclick = function() { + if (maMaterialData.rimMapIsActive) { + maMaterialData.rimMapIsActive = false; + maRimMapIsActive.className = "uiMaterialAssistant-inactive"; + maRimMap.disabled = true; + } else { + maMaterialData.rimMapIsActive = true; + maRimMapIsActive.className = "uiMaterialAssistant-active"; + maRimMap.disabled = false; + if (maMaterialData.rimMap === undefined) { + maMaterialData.rimMap = ""; + } + } + maGenerateJsonAndSave(); + }; + + maRimMap.oninput = function() { + maMaterialData.rimMap = maRimMap.value; + maGenerateJsonAndSave(); + }; + + maRimLightingMixIsActive.onclick = function() { + if (maMaterialData.rimLightingMixIsActive) { + maMaterialData.rimLightingMixIsActive = false; + maRimLightingMixIsActive.className = "uiMaterialAssistant-inactive"; + maRimLightingMix.disabled = true; + maRimLightingMixSlider.disabled = true; + } else { + maMaterialData.rimLightingMixIsActive = true; + maRimLightingMixIsActive.className = "uiMaterialAssistant-active"; + maRimLightingMix.disabled = false; + maRimLightingMixSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maRimLightingMixSlider.oninput = function() { + maRimLightingMix.value = maRimLightingMixSlider.value/1000; + maMaterialData.rimLightingMix = parseFloat(maRimLightingMix.value); + maGenerateJsonAndSave(); + }; + + maParametricRimFresnelPowerIsActive.onclick = function() { + if (maMaterialData.parametricRimFresnelPowerIsActive) { + maMaterialData.parametricRimFresnelPowerIsActive = false; + maParametricRimFresnelPowerIsActive.className = "uiMaterialAssistant-inactive"; + maParametricRimFresnelPower.disabled = true; + maParametricRimFresnelPowerSlider.disabled = true; + } else { + maMaterialData.parametricRimFresnelPowerIsActive = true; + maParametricRimFresnelPowerIsActive.className = "uiMaterialAssistant-active"; + maParametricRimFresnelPower.disabled = false; + maParametricRimFresnelPowerSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maParametricRimFresnelPowerSlider.oninput = function() { + maParametricRimFresnelPower.value = maParametricRimFresnelPowerSlider.value/1000; + maMaterialData.parametricRimFresnelPower = parseFloat(maParametricRimFresnelPower.value); + maGenerateJsonAndSave(); + }; + + maParametricRimLiftIsActive.onclick = function() { + if (maMaterialData.parametricRimLiftIsActive) { + maMaterialData.parametricRimLiftIsActive = false; + maParametricRimLiftIsActive.className = "uiMaterialAssistant-inactive"; + maParametricRimLift.disabled = true; + maParametricRimLiftSlider.disabled = true; + } else { + maMaterialData.parametricRimLiftIsActive = true; + maParametricRimLiftIsActive.className = "uiMaterialAssistant-active"; + maParametricRimLift.disabled = false; + maParametricRimLiftSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maParametricRimLiftSlider.oninput = function() { + maParametricRimLift.value = maParametricRimLiftSlider.value/1000; + maMaterialData.parametricRimLift = parseFloat(maParametricRimLift.value); + maGenerateJsonAndSave(); + }; + + maShadingShiftIsActive.onclick = function() { + if (maMaterialData.shadingShiftIsActive) { + maMaterialData.shadingShiftIsActive = false; + maShadingShiftIsActive.className = "uiMaterialAssistant-inactive"; + maShadingShift.disabled = true; + maShadingShiftSlider.disabled = true; + } else { + maMaterialData.shadingShiftIsActive = true; + maShadingShiftIsActive.className = "uiMaterialAssistant-active"; + maShadingShift.disabled = false; + maShadingShiftSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maShadingShiftMapIsActive.onclick = function() { + if (maMaterialData.shadingShiftMapIsActive) { + maMaterialData.shadingShiftMapIsActive = false; + maShadingShiftMapIsActive.className = "uiMaterialAssistant-inactive"; + maShadingShiftMap.disabled = true; + } else { + maMaterialData.shadingShiftMapIsActive = true; + maShadingShiftMapIsActive.className = "uiMaterialAssistant-active"; + maShadingShiftMap.disabled = false; + if (maMaterialData.shadingShiftMap === undefined) { + maMaterialData.shadingShiftMap = ""; + } + } + maGenerateJsonAndSave(); + }; + + maShadingShiftSlider.oninput = function() { + maShadingShift.value = maShadingShiftSlider.value/1000; + maMaterialData.shadingShift = parseFloat(maShadingShift.value); + maGenerateJsonAndSave(); + }; + + maShadingShiftMap.oninput = function() { + maMaterialData.shadingShiftMap = maShadingShiftMap.value; + maGenerateJsonAndSave(); + }; + + maShadingToonyIsActive.onclick = function() { + if (maMaterialData.shadingToonyIsActive) { + maMaterialData.shadingToonyIsActive = false; + maShadingToonyIsActive.className = "uiMaterialAssistant-inactive"; + maShadingToony.disabled = true; + maShadingToonySlider.disabled = true; + } else { + maMaterialData.shadingToonyIsActive = true; + maShadingToonyIsActive.className = "uiMaterialAssistant-active"; + maShadingToony.disabled = false; + maShadingToonySlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maShadingToonySlider.oninput = function() { + maShadingToony.value = maShadingToonySlider.value/1000; + maMaterialData.shadingToony = parseFloat(maShadingToony.value); + maGenerateJsonAndSave(); + }; + +/* ################# Not supported Yet, but the code is ready ######################### + + maOutlineWidthModeIsActive.onclick = function() { + if (maMaterialData.outlineWidthModeIsActive) { + maMaterialData.outlineWidthModeIsActive = false; + maOutlineWidthModeIsActive.className = "uiMaterialAssistant-inactive"; + maOutlineWidthModeNone.disabled = true; + maOutlineWidthModeWorld.disabled = true; + maOutlineWidthModeScreen.disabled = true; + } else { + maMaterialData.outlineWidthModeIsActive = true; + maOutlineWidthModeIsActive.className = "uiMaterialAssistant-active"; + maOutlineWidthModeNone.disabled = false; + maOutlineWidthModeWorld.disabled = false; + maOutlineWidthModeScreen.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maOutlineWidthModeNone.oninput = function() { + maMaterialData.outlineWidthMode = maOutlineWidthModeNone.value; + maGenerateJsonAndSave(); + }; + + maOutlineWidthModeWorld.oninput = function() { + maMaterialData.outlineWidthMode = maOutlineWidthModeWorld.value; + maGenerateJsonAndSave(); + }; + + maOutlineWidthModeScreen.oninput = function() { + maMaterialData.outlineWidthMode = maOutlineWidthModeScreen.value; + maGenerateJsonAndSave(); + }; + + maOutlineWidthIsActive.onclick = function() { + if (maMaterialData.outlineWidthIsActive) { + maMaterialData.outlineWidthIsActive = false; + maOutlineWidthIsActive.className = "uiMaterialAssistant-inactive"; + maOutlineWidth.disabled = true; + maOutlineWidthSlider.disabled = true; + } else { + maMaterialData.outlineWidthIsActive = true; + maOutlineWidthIsActive.className = "uiMaterialAssistant-active"; + maOutlineWidth.disabled = false; + maOutlineWidthSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maOutlineWidthSlider.oninput = function() { + maOutlineWidth.value = maOutlineWidthSlider.value/1000; + maMaterialData.outlineWidth = parseFloat(maOutlineWidth.value); + maGenerateJsonAndSave(); + }; + + maOutlineIsActive.onclick = function() { + if (maMaterialData.outlineIsActive) { + maMaterialData.outlineIsActive = false; + maOutlineIsActive.className = "uiMaterialAssistant-inactive"; + maOutlineColorPicker.style.pointerEvents = 'none'; + maOutlineColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.outlineIsActive = true; + maOutlineIsActive.className = "uiMaterialAssistant-active"; + maOutlineColorPicker.style.pointerEvents = 'auto'; + maOutlineColorPicker.style.backgroundColor = maGetRGB(maMaterialData.outline); + } + maGenerateJsonAndSave(); + }; +//################################################################ +*/ + + maUvAnimationMaskMapIsActive.onclick = function() { + if (maMaterialData.uvAnimationMaskMapIsActive) { + maMaterialData.uvAnimationMaskMapIsActive = false; + maUvAnimationMaskMapIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationMaskMap.disabled = true; + } else { + maMaterialData.uvAnimationMaskMapIsActive = true; + maUvAnimationMaskMapIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationMaskMap.disabled = false; + if (maMaterialData.uvAnimationMaskMap === undefined) { + maMaterialData.uvAnimationMaskMap = ""; + } + } + maGenerateJsonAndSave(); + }; + + maUvAnimationMaskMap.oninput = function() { + maMaterialData.uvAnimationMaskMap = maUvAnimationMaskMap.value; + maGenerateJsonAndSave(); + }; + + maUvAnimationScrollXSpeedIsActive.onclick = function() { + if (maMaterialData.uvAnimationScrollXSpeedIsActive) { + maMaterialData.uvAnimationScrollXSpeedIsActive = false; + maUvAnimationScrollXSpeedIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationScrollXSpeed.disabled = true; + maUvAnimationScrollXSpeedSlider.disabled = true; + } else { + maMaterialData.uvAnimationScrollXSpeedIsActive = true; + maUvAnimationScrollXSpeedIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationScrollXSpeed.disabled = false; + maUvAnimationScrollXSpeedSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maUvAnimationScrollXSpeedSlider.oninput = function() { + maUvAnimationScrollXSpeed.value = maUvAnimationScrollXSpeedSlider.value/1000; + maMaterialData.uvAnimationScrollXSpeed = parseFloat(maUvAnimationScrollXSpeed.value); + maGenerateJsonAndSave(); + }; + + maUvAnimationScrollYSpeedIsActive.onclick = function() { + if (maMaterialData.uvAnimationScrollYSpeedIsActive) { + maMaterialData.uvAnimationScrollYSpeedIsActive = false; + maUvAnimationScrollYSpeedIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationScrollYSpeed.disabled = true; + maUvAnimationScrollYSpeedSlider.disabled = true; + } else { + maMaterialData.uvAnimationScrollYSpeedIsActive = true; + maUvAnimationScrollYSpeedIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationScrollYSpeed.disabled = false; + maUvAnimationScrollYSpeedSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maUvAnimationScrollYSpeedSlider.oninput = function() { + maUvAnimationScrollYSpeed.value = maUvAnimationScrollYSpeedSlider.value/1000; + maMaterialData.uvAnimationScrollYSpeed = parseFloat(maUvAnimationScrollYSpeed.value); + maGenerateJsonAndSave(); + }; + + maUvAnimationRotationSpeedIsActive.onclick = function() { + if (maMaterialData.uvAnimationRotationSpeedIsActive) { + maMaterialData.uvAnimationRotationSpeedIsActive = false; + maUvAnimationRotationSpeedIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationRotationSpeed.disabled = true; + maUvAnimationRotationSpeedSlider.disabled = true; + } else { + maMaterialData.uvAnimationRotationSpeedIsActive = true; + maUvAnimationRotationSpeedIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationRotationSpeed.disabled = false; + maUvAnimationRotationSpeedSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + + maUvAnimationRotationSpeedSlider.oninput = function() { + maUvAnimationRotationSpeed.value = maUvAnimationRotationSpeedSlider.value/1000; + maMaterialData.uvAnimationRotationSpeed = parseFloat(maUvAnimationRotationSpeed.value); + maGenerateJsonAndSave(); + }; + + maProcedural.oninput = function() { + let testJsonData; + if (maProcedural.value === "") { + maAddProceduralTemplate.disabled = false; + } else { + try { + testJsonData = JSON.parse(maProcedural.value); + } catch (e) { + maProcedural.style.color = "#ff0000"; + return; + } + } + maProcedural.style.color = "#000000"; + maMaterialData.procedural = maProcedural.value; + maGenerateJsonAndSave(); + }; + maAddProceduralTemplate.onclick = function() { + if (maMaterialData.procedural === "") { + let template = { + "version": 3, + "fragmentShaderURL": "", + "uniforms": {}, + "channels": [] + }; + maProcedural.value = JSON.stringify(template, null, 4); + maAddProceduralTemplate.disabled = true; + maProcedural.oninput(); + } + }; maCullFaceModeBack.oninput = function() { maMaterialData.cullFaceMode = maCullFaceModeBack.value; maGenerateJsonAndSave(); @@ -338,6 +948,22 @@ function initiateMaUi() { maGenerateJsonAndSave(); }; + maModelHifiPbr.oninput = function() { + maMaterialData.model = maModelHifiPbr.value; + maFieldContextualDisplayer(); + maGenerateJsonAndSave(); + }; + maModelVrmMtoon.oninput = function() { + maMaterialData.model = maModelVrmMtoon.value; + maFieldContextualDisplayer(); + maGenerateJsonAndSave(); + }; + maModelHifiShaderSimple.oninput = function() { + maMaterialData.model = maModelHifiShaderSimple.value; + maFieldContextualDisplayer(); + maGenerateJsonAndSave(); + }; + var maAlbedoColorPickerID = "#ma-albedo-colorPicker"; maAlbedoColorPickerSel = $(maAlbedoColorPickerID).colpick({ colorScheme: 'dark', @@ -389,27 +1015,157 @@ function initiateMaUi() { } } }); + + var maShadeColorPickerID = "#ma-shade-colorPicker"; + maShadeColorPickerSel = $(maShadeColorPickerID).colpick({ + colorScheme: 'dark', + layout: 'rgbhex', + color: '000000', + submit: false, + onShow: function(colpick) { + $(maShadeColorPickerID).colpickSetColor({ + "r": maMaterialData.shade[0] * 255, + "g": maMaterialData.shade[1] * 255, + "b": maMaterialData.shade[2] * 255, + }); + $(maShadeColorPickerID).attr('active', 'true'); + }, + onHide: function(colpick) { + $(maShadeColorPickerID).attr('active', 'false'); + }, + onChange: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + if ($(maShadeColorPickerID).attr('active') === 'true') { + maMaterialData.shade = [(rgb.r/255), (rgb.g/255), (rgb.b/255)]; + maGenerateJsonAndSave(); + } + } + }); + + var maMatcapColorPickerID = "#ma-matcap-colorPicker"; + maMatcapColorPickerSel = $(maMatcapColorPickerID).colpick({ + colorScheme: 'dark', + layout: 'rgbhex', + color: '000000', + submit: false, + onShow: function(colpick) { + $(maMatcapColorPickerID).colpickSetColor({ + "r": maMaterialData.matcap[0] * 255, + "g": maMaterialData.matcap[1] * 255, + "b": maMaterialData.matcap[2] * 255, + }); + $(maMatcapColorPickerID).attr('active', 'true'); + }, + onHide: function(colpick) { + $(maMatcapColorPickerID).attr('active', 'false'); + }, + onChange: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + if ($(maMatcapColorPickerID).attr('active') === 'true') { + maMaterialData.matcap = [(rgb.r/255), (rgb.g/255), (rgb.b/255)]; + maGenerateJsonAndSave(); + } + } + }); + + var maParametricRimColorPickerID = "#ma-parametricRim-colorPicker"; + maParametricRimColorPickerSel = $(maParametricRimColorPickerID).colpick({ + colorScheme: 'dark', + layout: 'rgbhex', + color: '000000', + submit: false, + onShow: function(colpick) { + $(maParametricRimColorPickerID).colpickSetColor({ + "r": maMaterialData.parametricRim[0] * 255, + "g": maMaterialData.parametricRim[1] * 255, + "b": maMaterialData.parametricRim[2] * 255, + }); + $(maParametricRimColorPickerID).attr('active', 'true'); + }, + onHide: function(colpick) { + $(maParametricRimColorPickerID).attr('active', 'false'); + }, + onChange: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + if ($(maParametricRimColorPickerID).attr('active') === 'true') { + maMaterialData.parametricRim = [(rgb.r/255), (rgb.g/255), (rgb.b/255)]; + maGenerateJsonAndSave(); + } + } + }); + +/* ############# Not supported yet, but the code is ready ######################### + + var maOutlineColorPickerID = "#ma-outline-colorPicker"; + maOutlineColorPickerSel = $(maOutlineColorPickerID).colpick({ + colorScheme: 'dark', + layout: 'rgbhex', + color: '000000', + submit: false, + onShow: function(colpick) { + $(maOutlineColorPickerID).colpickSetColor({ + "r": maMaterialData.outline[0] * 255, + "g": maMaterialData.outline[1] * 255, + "b": maMaterialData.outline[2] * 255, + }); + $(maOutlineColorPickerID).attr('active', 'true'); + }, + onHide: function(colpick) { + $(maOutlineColorPickerID).attr('active', 'false'); + }, + onChange: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + if ($(maOutlineColorPickerID).attr('active') === 'true') { + maMaterialData.outline = [(rgb.r/255), (rgb.g/255), (rgb.b/255)]; + maGenerateJsonAndSave(); + } + } + }); +//############################################################################## +*/ + } function loadDataInMaUi(materialDataPropertyValue) { var entityMaterialData, materialDefinition; - try { - entityMaterialData = JSON.parse(materialDataPropertyValue); - } - catch(e) { + var mapToUse; + + if (materialDataPropertyValue === "" || materialDataPropertyValue === "{}") { entityMaterialData = { "materials":{} }; + } else { + try { + entityMaterialData = JSON.parse(materialDataPropertyValue); + } + catch(e) { + entityMaterialData = { + "materials":{} + }; + } } - + if (entityMaterialData.materials.length === undefined) { materialDefinition = entityMaterialData.materials; } else { materialDefinition = entityMaterialData.materials[0]; } - //MODEL (value other than "hifi_pbr" are not supposed to get the button, so we can assume.) - maMaterialData.model === "hifi_pbr"; + //MODEL + maMaterialData.model = materialDefinition.model || DEFAULT_MODEL; + switch (maMaterialData.model) { + case "hifi_pbr": + maModelHifiPbr.checked = true; + break; + case "vrm_mtoon": + maModelVrmMtoon.checked = true; + break; + case "hifi_shader_simple": + maModelHifiShaderSimple.checked = true; + break; + default: + alert("ERROR: model = '" + maMaterialData.model + "'. Something has been broken in the code."); + } //NAME if (materialDefinition.name !== undefined) { @@ -440,7 +1196,9 @@ function loadDataInMaUi(materialDataPropertyValue) { maAlbedoColorPicker.style.backgroundColor = maGetRGB(maMaterialData.albedo); //ALBEDO MAP - if (materialDefinition.defaultFallthrough === true && materialDefinition.albedoMap === undefined) { + if (materialDefinition.defaultFallthrough === true + && materialDefinition.albedoMap === undefined + && (materialDefinition.model === "hifi_pbr" || materialDefinition.model === "vrm_mtoon" )) { maMaterialData.albedoMapIsActive = false; maAlbedoMapIsActive.className = "uiMaterialAssistant-inactive"; maAlbedoMap.disabled = true; @@ -458,20 +1216,44 @@ function loadDataInMaUi(materialDataPropertyValue) { maAlbedoMap.value = maMaterialData.albedoMap; //METALLIC + if (materialDefinition.metallicMap !== undefined && materialDefinition.specularMap !== undefined) { + if (JSON.stringify(materialDefinition).indexOf("metallicMap") > JSON.stringify(materialDefinition).indexOf("specularMap")) { + delete materialDefinition.specularMap; + mapToUse = materialDefinition.metallicMap; + maUseSpecular.checked = false; + } else { + delete materialDefinition.metallicMap; + mapToUse = materialDefinition.specularMap; + maUseSpecular.checked = true; + } + } else if (materialDefinition.metallicMap === undefined && materialDefinition.specularMap === undefined) { + mapToUse = materialDefinition.metallicMap; + maUseSpecular.checked = false; + } else if (materialDefinition.specularMap === undefined) { + mapToUse = materialDefinition.metallicMap; + maUseSpecular.checked = false; + } else { + mapToUse = materialDefinition.specularMap; + maUseSpecular.checked = true; + } + if (materialDefinition.defaultFallthrough === true && materialDefinition.metallic === undefined - && materialDefinition.metallicMap === undefined) { + && mapToUse === undefined + && materialDefinition.model === "hifi_pbr") { maMaterialData.metallicIsActive = false; maMetallicIsActive.className = "uiMaterialAssistant-inactive"; maMetallic.disabled = true; maMetallicSlider.disabled = true; maMetallicMap.disabled = true; + maUseSpecular.disabled = true; } else { maMaterialData.metallicIsActive = true; maMetallicIsActive.className = "uiMaterialAssistant-active"; maMetallic.disabled = false; maMetallicSlider.disabled = false; maMetallicMap.disabled = false; + maUseSpecular.disabled = false; } if (materialDefinition.metallic !== undefined) { @@ -482,28 +1264,53 @@ function loadDataInMaUi(materialDataPropertyValue) { maMetallic.value = maMaterialData.metallic; maMetallicSlider.value = Math.floor(maMaterialData.metallic * 1000); - if (materialDefinition.metallicMap !== undefined) { - maMaterialData.metallicMap = materialDefinition.metallicMap; + if (mapToUse !== undefined) { + maMaterialData.metallicMap = mapToUse; } else { maMaterialData.metallicMap = ""; } maMetallicMap.value = maMaterialData.metallicMap; + maMaterialData.useSpecular = maUseSpecular.checked; //ROUGHNESS + if (materialDefinition.roughnessMap !== undefined && materialDefinition.glossMap !== undefined) { + if (JSON.stringify(materialDefinition).indexOf("roughnessMap") > JSON.stringify(materialDefinition).indexOf("glossMap")) { + delete materialDefinition.glossMap; + mapToUse = materialDefinition.roughnessMap; + maUseGloss.checked = false; + } else { + delete materialDefinition.roughnessMap; + mapToUse = materialDefinition.glossMap; + maUseGloss.checked = true; + } + } else if (materialDefinition.roughnessMap === undefined && materialDefinition.glossMap === undefined) { + mapToUse = materialDefinition.roughnessMap; + maUseGloss.checked = false; + } else if (materialDefinition.glossMap === undefined) { + mapToUse = materialDefinition.roughnessMap; + maUseGloss.checked = false; + } else { + mapToUse = materialDefinition.glossMap; + maUseGloss.checked = true; + } + if (materialDefinition.defaultFallthrough === true && materialDefinition.roughness === undefined - && materialDefinition.roughnessMap === undefined) { + && mapToUse === undefined + && materialDefinition.model === "hifi_pbr") { maMaterialData.roughnessIsActive = false; maRoughnessIsActive.className = "uiMaterialAssistant-inactive"; maRoughness.disabled = true; maRoughnessSlider.disabled = true; maRoughnessMap.disabled = true; + maUseGloss.disabled = true; } else { maMaterialData.roughnessIsActive = true; maRoughnessIsActive.className = "uiMaterialAssistant-active"; maRoughness.disabled = false; maRoughnessSlider.disabled = false; maRoughnessMap.disabled = false; + maUseGloss.disabled = false; } if (materialDefinition.roughness !== undefined) { @@ -514,30 +1321,57 @@ function loadDataInMaUi(materialDataPropertyValue) { maRoughness.value = maMaterialData.roughness; maRoughnessSlider.value = Math.floor(maMaterialData.roughness * 1000); - if (materialDefinition.roughnessMap !== undefined) { - maMaterialData.roughnessMap = materialDefinition.roughnessMap; + if (mapToUse !== undefined) { + maMaterialData.roughnessMap = mapToUse; } else { maMaterialData.roughnessMap = ""; } maRoughnessMap.value = maMaterialData.roughnessMap; + maMaterialData.useGloss = maUseGloss.checked; //NORMAL MAP - if (materialDefinition.defaultFallthrough === true && materialDefinition.normalMap === undefined) { + if (materialDefinition.normalMap !== undefined && materialDefinition.bumpMap !== undefined) { + if (JSON.stringify(materialDefinition).indexOf("normalMap") > JSON.stringify(materialDefinition).indexOf("bumpMap")) { + delete materialDefinition.bumpMap; + mapToUse = materialDefinition.normalMap; + maUseBump.checked = false; + } else { + delete materialDefinition.normalMap; + mapToUse = materialDefinition.bumpMap; + maUseBump.checked = true; + } + } else if (materialDefinition.normalMap === undefined && materialDefinition.bumpMap === undefined) { + mapToUse = materialDefinition.normalMap; + maUseBump.checked = false; + } else if (materialDefinition.bumpMap === undefined) { + mapToUse = materialDefinition.normalMap; + maUseBump.checked = false; + } else { + mapToUse = materialDefinition.bumpMap; + maUseBump.checked = true; + } + + if (materialDefinition.defaultFallthrough === true && + mapToUse === undefined && + (materialDefinition.model === "hifi_pbr" || materialDefinition.model === "vrm_mtoon")) { maMaterialData.normalMapIsActive = false; maNormalMapIsActive.className = "uiMaterialAssistant-inactive"; maNormalMap.disabled = true; + maUseBump.disabled = true; } else { maMaterialData.normalMapIsActive = true; maNormalMapIsActive.className = "uiMaterialAssistant-active"; maNormalMap.disabled = false; + maUseBump.disabled = false; } - if (materialDefinition.normalMap !== undefined) { - maMaterialData.normalMap = materialDefinition.normalMap; + if (mapToUse !== undefined) { + maMaterialData.normalMap = mapToUse; } else { maMaterialData.normalMap = ""; } maNormalMap.value = maMaterialData.normalMap; + maMaterialData.useBump = maUseBump.checked; //OPACITY if (materialDefinition.defaultFallthrough === true @@ -602,7 +1436,8 @@ function loadDataInMaUi(materialDataPropertyValue) { //EMISSIVE if (materialDefinition.defaultFallthrough === true && materialDefinition.emissive === undefined - && materialDefinition.emissiveMap === undefined) { + && materialDefinition.emissiveMap === undefined + && (materialDefinition.model === "hifi_pbr" || materialDefinition.model === "vrm_mtoon")) { maMaterialData.emissiveIsActive = false; maEmissiveIsActive.className = "uiMaterialAssistant-inactive"; maBloom.disabled = true; @@ -649,7 +1484,8 @@ function loadDataInMaUi(materialDataPropertyValue) { //SCATTERING if (materialDefinition.defaultFallthrough === true && materialDefinition.scattering === undefined - && materialDefinition.scatteringMap === undefined) { + && materialDefinition.scatteringMap === undefined + && materialDefinition.model === "hifi_pbr") { maMaterialData.scatteringIsActive = false; maScatteringIsActive.className = "uiMaterialAssistant-inactive"; maScattering.disabled = true; @@ -679,7 +1515,8 @@ function loadDataInMaUi(materialDataPropertyValue) { maScatteringMap.value = maMaterialData.scatteringMap; //OCCLUSION MAP - if (materialDefinition.defaultFallthrough === true && materialDefinition.occlusionMap === undefined) { + if (materialDefinition.defaultFallthrough === true && materialDefinition.occlusionMap === undefined + && materialDefinition.model === "hifi_pbr") { maMaterialData.occlusionMapIsActive = false; maOcclusionMapIsActive.className = "uiMaterialAssistant-inactive"; maOcclusionMap.disabled = true; @@ -695,6 +1532,468 @@ function loadDataInMaUi(materialDataPropertyValue) { maMaterialData.occlusionMap = ""; } maOcclusionMap.value = maMaterialData.occlusionMap; + + //LIGHT MAP + if (materialDefinition.defaultFallthrough === true && + materialDefinition.lightMap === undefined && + materialDefinition.model === "hifi_pbr") { + maMaterialData.lightMapIsActive = false; + maLightMapIsActive.className = "uiMaterialAssistant-inactive"; + maLightMap.disabled = true; + } else { + maMaterialData.lightMapIsActive = true; + maLightMapIsActive.className = "uiMaterialAssistant-active"; + maLightMap.disabled = false; + } + + if (materialDefinition.lightMap !== undefined) { + maMaterialData.lightMap = materialDefinition.lightMap; + } else { + maMaterialData.lightMap = ""; + } + maLightMap.value = maMaterialData.lightMap; + + //SHADE + if (materialDefinition.defaultFallthrough === true && materialDefinition.shade === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.shadeIsActive = false; + maShadeIsActive.className = "uiMaterialAssistant-inactive"; + maShadeColorPicker.style.pointerEvents = 'none'; + maShadeColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.shadeIsActive = true; + maShadeIsActive.className = "uiMaterialAssistant-active"; + maShadeColorPicker.style.pointerEvents = 'auto'; + maShadeColorPicker.style.backgroundColor = maGetRGB(maMaterialData.shade); + } + + if (materialDefinition.shade !== undefined) { + maMaterialData.shade = materialDefinition.shade; + } else { + maMaterialData.shade = DEFAULT_SHADE; + } + maShadeColorPicker.style.backgroundColor = maGetRGB(maMaterialData.shade); + + //SHADE MAP + if (materialDefinition.defaultFallthrough === true + && materialDefinition.shadeMap === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.shadeMapIsActive = false; + maShadeMapIsActive.className = "uiMaterialAssistant-inactive"; + maShadeMap.disabled = true; + } else { + maMaterialData.shadeMapIsActive = true; + maShadeMapIsActive.className = "uiMaterialAssistant-active"; + maShadeMap.disabled = false; + } + + if (materialDefinition.shadeMap !== undefined) { + maMaterialData.shadeMap = materialDefinition.shadeMap; + } else { + maMaterialData.shadeMap = ""; + } + maShadeMap.value = maMaterialData.shadeMap; + + //MATCAP + if (materialDefinition.defaultFallthrough === true && materialDefinition.matcap === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.matcapIsActive = false; + maMatcapIsActive.className = "uiMaterialAssistant-inactive"; + maMatcapColorPicker.style.pointerEvents = 'none'; + maMatcapColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.matcapIsActive = true; + maMatcapIsActive.className = "uiMaterialAssistant-active"; + maMatcapColorPicker.style.pointerEvents = 'auto'; + maMatcapColorPicker.style.backgroundColor = maGetRGB(maMaterialData.matcap); + } + + if (materialDefinition.matcap !== undefined) { + maMaterialData.matcap = materialDefinition.matcap; + } else { + maMaterialData.matcap = DEFAULT_MATCAP; + } + maMatcapColorPicker.style.backgroundColor = maGetRGB(maMaterialData.matcap); + + //MATCAP MAP + if (materialDefinition.defaultFallthrough === true + && materialDefinition.matcapMap === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.matcapMapIsActive = false; + maMatcapMapIsActive.className = "uiMaterialAssistant-inactive"; + maMatcapMap.disabled = true; + } else { + maMaterialData.matcapMapIsActive = true; + maMatcapMapIsActive.className = "uiMaterialAssistant-active"; + maMatcapMap.disabled = false; + } + + if (materialDefinition.matcapMap !== undefined) { + maMaterialData.matcapMap = materialDefinition.matcapMap; + } else { + maMaterialData.matcapMap = ""; + } + maMatcapMap.value = maMaterialData.matcapMap; + + //SHADING SHIFT + if (materialDefinition.defaultFallthrough === true + && materialDefinition.shadingShift === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.shadingShiftIsActive = false; + maShadingShiftIsActive.className = "uiMaterialAssistant-inactive"; + maShadingShift.disabled = true; + maShadingShiftSlider.disabled = true; + } else { + maMaterialData.shadingShiftIsActive = true; + maShadingShiftIsActive.className = "uiMaterialAssistant-active"; + maShadingShift.disabled = false; + maShadingShiftSlider.disabled = false; + } + + if (materialDefinition.shadingShift !== undefined) { + maMaterialData.shadingShift = materialDefinition.shadingShift; + } else { + maMaterialData.shadingShift = DEFAULT_SHADING_SHIFT; + } + maShadingShift.value = maMaterialData.shadingShift; + maShadingShiftSlider.value = Math.floor(maMaterialData.shadingShift * 1000); + + //SHADING SHIFT MAP + if (materialDefinition.defaultFallthrough === true + && materialDefinition.shadingShiftMap === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.shadingShiftMapIsActive = false; + maShadingShiftMapIsActive.className = "uiMaterialAssistant-inactive"; + maShadingShiftMap.disabled = true; + } else { + maMaterialData.shadingShiftMapIsActive = true; + maShadingShiftMapIsActive.className = "uiMaterialAssistant-active"; + maShadingShiftMap.disabled = false; + } + + if (materialDefinition.shadingShiftMap !== undefined) { + maMaterialData.shadingShiftMap = materialDefinition.shadingShiftMap; + } else { + maMaterialData.shadingShiftMap = ""; + } + maShadingShiftMap.value = maMaterialData.shadingShiftMap; + + //SHADING TOONY + if (materialDefinition.defaultFallthrough === true + && materialDefinition.shadingToony === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.shadingToonyIsActive = false; + maShadingToonyIsActive.className = "uiMaterialAssistant-inactive"; + maShadingToony.disabled = true; + maShadingToonySlider.disabled = true; + } else { + maMaterialData.shadingToonyIsActive = true; + maShadingToonyIsActive.className = "uiMaterialAssistant-active"; + maShadingToony.disabled = false; + maShadingToonySlider.disabled = false; + } + + if (materialDefinition.shadingToony !== undefined) { + maMaterialData.shadingToony = materialDefinition.shadingToony; + } else { + maMaterialData.shadingToony = DEFAULT_SHADING_TOONY; + } + maShadingToony.value = maMaterialData.shadingToony; + maShadingToonySlider.value = Math.floor(maMaterialData.shadingToony * 1000); + + //PARAMETRIC RIM + if (materialDefinition.defaultFallthrough === true && materialDefinition.parametricRim === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.parametricRimIsActive = false; + maParametricRimIsActive.className = "uiMaterialAssistant-inactive"; + maParametricRimColorPicker.style.pointerEvents = 'none'; + maParametricRimColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.parametricRimIsActive = true; + maParametricRimIsActive.className = "uiMaterialAssistant-active"; + maParametricRimColorPicker.style.pointerEvents = 'auto'; + maParametricRimColorPicker.style.backgroundColor = maGetRGB(maMaterialData.parametricRim); + } + + if (materialDefinition.parametricRim !== undefined) { + maMaterialData.parametricRim = materialDefinition.parametricRim; + } else { + maMaterialData.parametricRim = DEFAULT_PARAMETRIC_RIM; + } + maParametricRimColorPicker.style.backgroundColor = maGetRGB(maMaterialData.parametricRim); + + //RIM MAP + if (materialDefinition.defaultFallthrough === true + && materialDefinition.rimMap === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.rimMapIsActive = false; + maRimMapIsActive.className = "uiMaterialAssistant-inactive"; + maRimMap.disabled = true; + } else { + maMaterialData.rimMapIsActive = true; + maRimMapIsActive.className = "uiMaterialAssistant-active"; + maRimMap.disabled = false; + } + + if (materialDefinition.rimMap !== undefined) { + maMaterialData.rimMap = materialDefinition.rimMap; + } else { + maMaterialData.rimMap = ""; + } + maRimMap.value = maMaterialData.rimMap; + + //RIM LIGHTING MIX + if (materialDefinition.defaultFallthrough === true + && materialDefinition.rimLightingMix === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.rimLightingMixIsActive = false; + maRimLightingMixIsActive.className = "uiMaterialAssistant-inactive"; + maRimLightingMix.disabled = true; + maRimLightingMixSlider.disabled = true; + } else { + maMaterialData.rimLightingMixIsActive = true; + maRimLightingMixIsActive.className = "uiMaterialAssistant-active"; + maRimLightingMix.disabled = false; + maRimLightingMixSlider.disabled = false; + } + + if (materialDefinition.rimLightingMix !== undefined) { + maMaterialData.rimLightingMix = materialDefinition.rimLightingMix; + } else { + maMaterialData.rimLightingMix = DEFAULT_RIM_LIGHTING_MIX; + } + maRimLightingMix.value = maMaterialData.rimLightingMix; + maRimLightingMixSlider.value = Math.floor(maMaterialData.rimLightingMix * 1000); + + //PARAMETRIC RIM FRESNEL POWER + if (materialDefinition.defaultFallthrough === true + && materialDefinition.parametricRimFresnelPower === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.parametricRimFresnelPowerIsActive = false; + maParametricRimFresnelPowerIsActive.className = "uiMaterialAssistant-inactive"; + maParametricRimFresnelPower.disabled = true; + maParametricRimFresnelPowerSlider.disabled = true; + } else { + maMaterialData.parametricRimFresnelPowerIsActive = true; + maParametricRimFresnelPowerIsActive.className = "uiMaterialAssistant-active"; + maParametricRimFresnelPower.disabled = false; + maParametricRimFresnelPowerSlider.disabled = false; + } + + if (materialDefinition.parametricRimFresnelPower !== undefined) { + maMaterialData.parametricRimFresnelPower = materialDefinition.parametricRimFresnelPower; + } else { + maMaterialData.parametricRimFresnelPower = DEFAULT_PARAMETRIC_RIM_FRESNEL_POWER; + } + maParametricRimFresnelPower.value = maMaterialData.parametricRimFresnelPower; + maParametricRimFresnelPowerSlider.value = Math.floor(maMaterialData.parametricRimFresnelPower * 1000); + + //PARAMETRIC RIM LIFT + if (materialDefinition.defaultFallthrough === true + && materialDefinition.parametricRimLift === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.parametricRimLiftIsActive = false; + maParametricRimLiftIsActive.className = "uiMaterialAssistant-inactive"; + maParametricRimLift.disabled = true; + maParametricRimLiftSlider.disabled = true; + } else { + maMaterialData.parametricRimLiftIsActive = true; + maParametricRimLiftIsActive.className = "uiMaterialAssistant-active"; + maParametricRimLift.disabled = false; + maParametricRimLiftSlider.disabled = false; + } + + if (materialDefinition.parametricRimLift !== undefined) { + maMaterialData.parametricRimLift = materialDefinition.parametricRimLift; + } else { + maMaterialData.parametricRimLift = DEFAULT_PARAMETRIC_RIM_LIFT; + } + maParametricRimLift.value = maMaterialData.parametricRimLift; + maParametricRimLiftSlider.value = Math.floor(maMaterialData.parametricRimLift * 1000); + +/* ######## Not supported yet, but the code is ready ######################################### + //OUTLINE WIDTH MODE + if (materialDefinition.defaultFallthrough === true + && materialDefinition.outlineWidthMode === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.outlineWidthModeIsActive = false; + maOutlineWidthModeIsActive.className = "uiMaterialAssistant-inactive"; + maOutlineWidthModeNone.disabled = true; + maOutlineWidthModeWorld.disabled = true; + maOutlineWidthModeScreen.disabled = true; + } else { + maMaterialData.outlineWidthModeIsActive = true; + maOutlineWidthModeIsActive.className = "uiMaterialAssistant-active"; + maOutlineWidthModeNone.disabled = false; + maOutlineWidthModeWorld.disabled = false; + maOutlineWidthModeScreen.disabled = false; + } + + if (materialDefinition.outlineWidthMode !== undefined) { + maMaterialData.outlineWidthMode = materialDefinition.outlineWidthMode; + } else { + maMaterialData.outlineWidthMode = DEFAULT_OUTLINE_WIDTH_MODE; + } + + switch (maMaterialData.outlineWidthMode) { + case "none": + maOutlineWidthModeNone.checked = true; + break; + case "worldCoordinates": + maOutlineWidthModeWorld.checked = true; + break; + case "screenCoordinates": + maOutlineWidthModeScreen.checked = true; + break; + default: + alert("ERROR: outlineWidthMode = '" + maMaterialData.outlineWidthMode + "'. Something has been broken in the code."); + } + + //OUTLINE WIDTH + if (materialDefinition.defaultFallthrough === true + && materialDefinition.outlineWidth === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.outlineWidthIsActive = false; + maOutlineWidthIsActive.className = "uiMaterialAssistant-inactive"; + maOutlineWidth.disabled = true; + maOutlineWidthSlider.disabled = true; + } else { + maMaterialData.outlineWidthIsActive = true; + maOutlineWidthIsActive.className = "uiMaterialAssistant-active"; + maOutlineWidth.disabled = false; + maOutlineWidthSlider.disabled = false; + } + + if (materialDefinition.outlineWidth !== undefined) { + maMaterialData.outlineWidth = materialDefinition.outlineWidth; + } else { + maMaterialData.outlineWidth = DEFAULT_OUTLINE_WIDTH; + } + maOutlineWidth.value = maMaterialData.outlineWidth; + maOutlineWidthSlider.value = Math.floor(maMaterialData.outlineWidth * 1000); + + //OUTLINE + if (materialDefinition.defaultFallthrough === true && materialDefinition.outline === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.outlineIsActive = false; + maOutlineIsActive.className = "uiMaterialAssistant-inactive"; + maOutlineColorPicker.style.pointerEvents = 'none'; + maOutlineColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.outlineIsActive = true; + maOutlineIsActive.className = "uiMaterialAssistant-active"; + maOutlineColorPicker.style.pointerEvents = 'auto'; + maOutlineColorPicker.style.backgroundColor = maGetRGB(maMaterialData.outline); + } + + if (materialDefinition.outline !== undefined) { + maMaterialData.outline = materialDefinition.outline; + } else { + maMaterialData.outline = DEFAULT_OUTLINE; + } + maOutlineColorPicker.style.backgroundColor = maGetRGB(maMaterialData.outline); + +//############################################################## +*/ + + //UV ANIMATION MASK MAP + if (materialDefinition.defaultFallthrough === true + && materialDefinition.uvAnimationMaskMap === undefined + && materialDefinition.model === "vrm_mtoon" ) { + maMaterialData.uvAnimationMaskMapIsActive = false; + maUvAnimationMaskMapIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationMaskMap.disabled = true; + } else { + maMaterialData.uvAnimationMaskMapIsActive = true; + maUvAnimationMaskMapIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationMaskMap.disabled = false; + } + + if (materialDefinition.uvAnimationMaskMap !== undefined) { + maMaterialData.uvAnimationMaskMap = materialDefinition.uvAnimationMaskMap; + } else { + maMaterialData.uvAnimationMaskMap = ""; + } + maUvAnimationMaskMap.value = maMaterialData.uvAnimationMaskMap; + + //UV ANIMATION SCROLL X SPEED + if (materialDefinition.defaultFallthrough === true + && materialDefinition.uvAnimationScrollXSpeed === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.uvAnimationScrollXSpeedIsActive = false; + maUvAnimationScrollXSpeedIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationScrollXSpeed.disabled = true; + maUvAnimationScrollXSpeedSlider.disabled = true; + } else { + maMaterialData.uvAnimationScrollXSpeedIsActive = true; + maUvAnimationScrollXSpeedIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationScrollXSpeed.disabled = false; + maUvAnimationScrollXSpeedSlider.disabled = false; + } + + if (materialDefinition.uvAnimationScrollXSpeed !== undefined) { + maMaterialData.uvAnimationScrollXSpeed = materialDefinition.uvAnimationScrollXSpeed; + } else { + maMaterialData.uvAnimationScrollXSpeed = DEFAULT_UV_ANIMATION_SCROLL_X_SPEED; + } + maUvAnimationScrollXSpeed.value = maMaterialData.uvAnimationScrollXSpeed; + maUvAnimationScrollXSpeedSlider.value = Math.floor(maMaterialData.uvAnimationScrollXSpeed * 1000); + + //UV ANIMATION SCROLL Y SPEED + if (materialDefinition.defaultFallthrough === true + && materialDefinition.uvAnimationScrollYSpeed === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.uvAnimationScrollYSpeedIsActive = false; + maUvAnimationScrollYSpeedIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationScrollYSpeed.disabled = true; + maUvAnimationScrollYSpeedSlider.disabled = true; + } else { + maMaterialData.uvAnimationScrollYSpeedIsActive = true; + maUvAnimationScrollYSpeedIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationScrollYSpeed.disabled = false; + maUvAnimationScrollYSpeedSlider.disabled = false; + } + + if (materialDefinition.uvAnimationScrollYSpeed !== undefined) { + maMaterialData.uvAnimationScrollYSpeed = materialDefinition.uvAnimationScrollYSpeed; + } else { + maMaterialData.uvAnimationScrollYSpeed = DEFAULT_UV_ANIMATION_SCROLL_Y_SPEED; + } + maUvAnimationScrollYSpeed.value = maMaterialData.uvAnimationScrollYSpeed; + maUvAnimationScrollYSpeedSlider.value = Math.floor(maMaterialData.uvAnimationScrollYSpeed * 1000); + + //UV ANIMATION ROTATION SPEED + if (materialDefinition.defaultFallthrough === true + && materialDefinition.uvAnimationRotationSpeed === undefined + && materialDefinition.model === "vrm_mtoon") { + maMaterialData.uvAnimationRotationSpeedIsActive = false; + maUvAnimationRotationSpeedIsActive.className = "uiMaterialAssistant-inactive"; + maUvAnimationRotationSpeed.disabled = true; + maUvAnimationRotationSpeedSlider.disabled = true; + } else { + maMaterialData.uvAnimationRotationSpeedIsActive = true; + maUvAnimationRotationSpeedIsActive.className = "uiMaterialAssistant-active"; + maUvAnimationRotationSpeed.disabled = false; + maUvAnimationRotationSpeedSlider.disabled = false; + } + + if (materialDefinition.uvAnimationRotationSpeed !== undefined) { + maMaterialData.uvAnimationRotationSpeed = materialDefinition.uvAnimationRotationSpeed; + } else { + maMaterialData.uvAnimationRotationSpeed = DEFAULT_UV_ANIMATION_ROTATION_SPEED; + } + maUvAnimationRotationSpeed.value = maMaterialData.uvAnimationRotationSpeed; + maUvAnimationRotationSpeedSlider.value = Math.floor(maMaterialData.uvAnimationRotationSpeed * 1000); + + //PROCEDURAL + if (materialDefinition.procedural !== undefined) { + maMaterialData.procedural = JSON.stringify(materialDefinition.procedural, null, 4); + maAddProceduralTemplate.disabled = true; + } else { + maMaterialData.procedural = ""; + maAddProceduralTemplate.disabled = false; + } + maProcedural.value = maMaterialData.procedural; //CULL FACE MODE if (materialDefinition.cullFaceMode !== undefined) { @@ -715,134 +2014,438 @@ function loadDataInMaUi(materialDataPropertyValue) { default: alert("ERROR: cullFaceMode = '" + maMaterialData.cullFaceMode + "'. Something has been broken in the code."); } + + maFieldContextualDisplayer(); +} + +function maFieldContextualDisplayer() { + if (maMaterialData.model === "hifi_pbr") { + document.getElementById("maContainerAlbedo").style.display = "block"; + document.getElementById("maContainerAlbedoMap").style.display = "block"; + document.getElementById("maContainerMetallic").style.display = "block"; + document.getElementById("maContainerRoughness").style.display = "block"; + document.getElementById("maContainerNormalMap").style.display = "block"; + document.getElementById("maContainerOpacity").style.display = "block"; + document.getElementById("maContainerOpacityMap").style.display = "block"; + document.getElementById("maContainerEmissive").style.display = "block"; + document.getElementById("maContainerEmissiveMap").style.display = "block"; + document.getElementById("maContainerUnlit").style.display = "block"; + document.getElementById("maContainerScattering").style.display = "block"; + document.getElementById("maContainerOcclusionMap").style.display = "block"; + document.getElementById("maContainerLightMap").style.display = "block"; + document.getElementById("maContainerMtoon").style.display = "none"; + document.getElementById("maContainerShaderSimple").style.display = "none"; + } else if (maMaterialData.model === "vrm_mtoon") { + document.getElementById("maContainerAlbedo").style.display = "block"; + document.getElementById("maContainerAlbedoMap").style.display = "block"; + document.getElementById("maContainerMetallic").style.display = "none"; + document.getElementById("maContainerRoughness").style.display = "none"; + document.getElementById("maContainerNormalMap").style.display = "block"; + document.getElementById("maContainerOpacity").style.display = "block"; + document.getElementById("maContainerOpacityMap").style.display = "block"; + document.getElementById("maContainerEmissive").style.display = "block"; + document.getElementById("maContainerEmissiveMap").style.display = "block"; + document.getElementById("maContainerUnlit").style.display = "none"; + document.getElementById("maContainerScattering").style.display = "none"; + document.getElementById("maContainerOcclusionMap").style.display = "none"; + document.getElementById("maContainerLightMap").style.display = "none"; + document.getElementById("maContainerMtoon").style.display = "block"; + document.getElementById("maContainerShaderSimple").style.display = "none"; + } else if (maMaterialData.model === "hifi_shader_simple") { + document.getElementById("maContainerAlbedo").style.display = "block"; + document.getElementById("maContainerAlbedoMap").style.display = "none"; + document.getElementById("maContainerMetallic").style.display = "none"; + document.getElementById("maContainerRoughness").style.display = "none"; + document.getElementById("maContainerNormalMap").style.display = "none"; + document.getElementById("maContainerOpacity").style.display = "block"; + document.getElementById("maContainerOpacityMap").style.display = "none"; + document.getElementById("maContainerEmissive").style.display = "none"; + document.getElementById("maContainerEmissiveMap").style.display = "none"; + document.getElementById("maContainerUnlit").style.display = "none"; + document.getElementById("maContainerScattering").style.display = "none"; + document.getElementById("maContainerOcclusionMap").style.display = "none"; + document.getElementById("maContainerLightMap").style.display = "none"; + document.getElementById("maContainerMtoon").style.display = "none"; + document.getElementById("maContainerShaderSimple").style.display = "block"; + } } function maGenerateJsonAndSave() { var newMaterial = {}; var defaultFallthrough = false; + //MODEL + newMaterial.model = maMaterialData.model; + //NAME if (maMaterialData.name != "") { newMaterial.name = maMaterialData.name; } - //ALBEDO & ALBEDOMAP + //ALBEDO if (maMaterialData.albedoIsActive) { newMaterial.albedo = maMaterialData.albedo; - if (maMaterialData.albedoMap !== "") { - newMaterial.albedoMap = maMaterialData.albedoMap; - } } else { defaultFallthrough = true; } - //METALLIC & METALLICMAP - if (maMaterialData.metallicIsActive) { - if (maMaterialData.metallicMap === "") { - newMaterial.metallic = maMaterialData.metallic; + + if (maMaterialData.model === "hifi_pbr") { + + //ALBEDOMAP + if (maMaterialData.albedoMapIsActive) { + newMaterial.albedoMap = maMaterialData.albedoMap || ""; } else { - newMaterial.metallicMap = maMaterialData.metallicMap; + defaultFallthrough = true; } - } else { - defaultFallthrough = true; - } - - //ROUGHNESS & ROUGHNESSMAP - if (maMaterialData.roughnessIsActive) { - if (maMaterialData.roughnessMap === "") { - newMaterial.roughness = maMaterialData.roughness; + + //METALLIC & METALLICMAP + if (maMaterialData.metallicIsActive) { + if (maMaterialData.metallicMap === "") { + newMaterial.metallic = maMaterialData.metallic; + } else { + if (maMaterialData.useSpecular) { + newMaterial.specularMap = maMaterialData.metallicMap; + } else { + newMaterial.metallicMap = maMaterialData.metallicMap; + } + } } else { - newMaterial.roughnessMap = maMaterialData.roughnessMap; + defaultFallthrough = true; } - } else { - defaultFallthrough = true; - } - - //NORMAL MAP - if (maMaterialData.normalMapIsActive) { - if (maMaterialData.normalMap !== "") { - newMaterial.normalMap = maMaterialData.normalMap; - } - } else { - defaultFallthrough = true; - } - - //OPACITY - if (maMaterialData.opacityIsActive) { - switch (maMaterialData.opacityMapMode) { - case "OPACITY_MAP_OPAQUE": - newMaterial.opacity = maMaterialData.opacity; - break; - case "OPACITY_MAP_MASK": - newMaterial.opacityMapMode = maMaterialData.opacityMapMode; - newMaterial.opacityMap = maMaterialData.albedoMap; - newMaterial.opacityCutoff = maMaterialData.opacityCutoff; - break; - case "OPACITY_MAP_BLEND": - newMaterial.opacityMapMode = maMaterialData.opacityMapMode; - newMaterial.opacityMap = maMaterialData.albedoMap; - break; - default: - alert("ERROR: opacityMapMode = '" + maMaterialData.opacityMapMode + "'. Something has been broken in the code."); - } - } else { - defaultFallthrough = true; - } - - //EMISSIVE - if (maMaterialData.emissiveIsActive) { - if (maMaterialData.emissiveMap === "") { - newMaterial.emissive = scaleEmissiveByBloomFactor(maMaterialData.emissive, maMaterialData.bloom); + + //ROUGHNESS & ROUGHNESSMAP + if (maMaterialData.roughnessIsActive) { + if (maMaterialData.roughnessMap === "") { + newMaterial.roughness = maMaterialData.roughness; + } else { + if (maMaterialData.useGloss) { + newMaterial.glossMap = maMaterialData.roughnessMap; + } else { + newMaterial.roughnessMap = maMaterialData.roughnessMap; + } + } } else { - newMaterial.emissiveMap = maMaterialData.emissiveMap; - } - } else { - defaultFallthrough = true; - } + defaultFallthrough = true; + } - //UNLIT - if (maMaterialData.unlit) { - newMaterial.unlit = maMaterialData.unlit; - } - - //SCATTERING - if (maMaterialData.scatteringIsActive) { - if (maMaterialData.scatteringMap === "") { - newMaterial.scattering = maMaterialData.scattering; + //NORMAL MAP + if (maMaterialData.normalMapIsActive) { + if (maMaterialData.useBump) { + newMaterial.bumpMap = maMaterialData.normalMap || ""; + } else { + newMaterial.normalMap = maMaterialData.normalMap || ""; + } } else { - newMaterial.scatteringMap = maMaterialData.scatteringMap; + defaultFallthrough = true; } - } else { - defaultFallthrough = true; - } - - //OCCLUSION MAP - if (maMaterialData.occlusionMapIsActive) { - if (maMaterialData.occlusionMap !== "") { - newMaterial.occlusionMap = maMaterialData.occlusionMap; + + //OPACITY + if (maMaterialData.opacityIsActive) { + switch (maMaterialData.opacityMapMode) { + case "OPACITY_MAP_OPAQUE": + newMaterial.opacity = maMaterialData.opacity; + break; + case "OPACITY_MAP_MASK": + newMaterial.opacityMapMode = maMaterialData.opacityMapMode; + newMaterial.opacityMap = maMaterialData.albedoMap; + newMaterial.opacityCutoff = maMaterialData.opacityCutoff; + break; + case "OPACITY_MAP_BLEND": + newMaterial.opacityMapMode = maMaterialData.opacityMapMode; + newMaterial.opacityMap = maMaterialData.albedoMap; + break; + default: + alert("ERROR: opacityMapMode = '" + maMaterialData.opacityMapMode + "'. Something has been broken in the code."); + } + } else { + defaultFallthrough = true; } - } else { - defaultFallthrough = true; + + //EMISSIVE + if (maMaterialData.emissiveIsActive) { + if (maMaterialData.emissiveMap === "") { + newMaterial.emissive = scaleEmissiveByBloomFactor(maMaterialData.emissive, maMaterialData.bloom); + } else { + newMaterial.emissiveMap = maMaterialData.emissiveMap; + } + } else { + defaultFallthrough = true; + } + + //UNLIT + if (maMaterialData.unlit) { + newMaterial.unlit = maMaterialData.unlit; + } + + //SCATTERING + if (maMaterialData.scatteringIsActive) { + if (maMaterialData.scatteringMap === "") { + newMaterial.scattering = maMaterialData.scattering; + } else { + newMaterial.scatteringMap = maMaterialData.scatteringMap; + } + } else { + defaultFallthrough = true; + } + + //OCCLUSION MAP + if (maMaterialData.occlusionMapIsActive) { + newMaterial.occlusionMap = maMaterialData.occlusionMap || ""; + } else { + defaultFallthrough = true; + } + + //LIGHT MAP + if (maMaterialData.lightMapIsActive) { + newMaterial.lightMap = maMaterialData.lightMap || ""; + } else { + defaultFallthrough = true; + } + + } else if (maMaterialData.model === "vrm_mtoon") { + //ALBEDOMAP + if (maMaterialData.albedoMapIsActive) { + newMaterial.albedoMap = maMaterialData.albedoMap || ""; + } else { + defaultFallthrough = true; + } + + //NORMAL MAP + if (maMaterialData.normalMapIsActive) { + if (maMaterialData.useBump) { + newMaterial.bumpMap = maMaterialData.normalMap || ""; + } else { + newMaterial.normalMap = maMaterialData.normalMap || ""; + } + } else { + defaultFallthrough = true; + } + + //EMISSIVE + if (maMaterialData.emissiveIsActive) { + if (maMaterialData.emissiveMap === "") { + newMaterial.emissive = scaleEmissiveByBloomFactor(maMaterialData.emissive, maMaterialData.bloom); + } else { + newMaterial.emissiveMap = maMaterialData.emissiveMap; + } + } else { + defaultFallthrough = true; + } + + //OPACITY + if (maMaterialData.opacityIsActive) { + switch (maMaterialData.opacityMapMode) { + case "OPACITY_MAP_OPAQUE": + newMaterial.opacity = maMaterialData.opacity; + break; + case "OPACITY_MAP_MASK": + newMaterial.opacityMapMode = maMaterialData.opacityMapMode; + newMaterial.opacityMap = maMaterialData.albedoMap; + newMaterial.opacityCutoff = maMaterialData.opacityCutoff; + break; + case "OPACITY_MAP_BLEND": + newMaterial.opacityMapMode = maMaterialData.opacityMapMode; + newMaterial.opacityMap = maMaterialData.albedoMap; + break; + default: + alert("ERROR: opacityMapMode = '" + maMaterialData.opacityMapMode + "'. Something has been broken in the code."); + } + } else { + defaultFallthrough = true; + } + + //SHADE + if (maMaterialData.shadeIsActive) { + newMaterial.shade = maMaterialData.shade; + } else { + defaultFallthrough = true; + } + + //SHADEMAP + if (maMaterialData.shadeMapIsActive) { + newMaterial.shadeMap = maMaterialData.shadeMap || ""; + } else { + defaultFallthrough = true; + } + + //MATCAP + if (maMaterialData.matcapIsActive) { + newMaterial.matcap = maMaterialData.matcap; + } else { + defaultFallthrough = true; + } + + //MATCAPMAP + if (maMaterialData.matcapMapIsActive) { + newMaterial.matcapMap = maMaterialData.matcapMap || ""; + } else { + defaultFallthrough = true; + } + //SHADING SHIFT + if (maMaterialData.shadingShiftIsActive) { + newMaterial.shadingShift = maMaterialData.shadingShift; + } else { + defaultFallthrough = true; + } + + //SHADING SHIFT MAP + if (maMaterialData.shadingShiftMapIsActive) { + newMaterial.shadingShiftMap = maMaterialData.shadingShiftMap || ""; + } else { + defaultFallthrough = true; + } + + //SHADING TOONY + if (maMaterialData.shadingToonyIsActive) { + newMaterial.shadingToony = maMaterialData.shadingToony; + } else { + defaultFallthrough = true; + } + + //PARAMETRIC RIM + if (maMaterialData.parametricRimIsActive) { + newMaterial.parametricRim = maMaterialData.parametricRim; + } else { + defaultFallthrough = true; + } + + //RIM MAP + if (maMaterialData.rimMapIsActive) { + newMaterial.rimMap = maMaterialData.rimMap || ""; + } else { + defaultFallthrough = true; + } + + //RIM LIGHTING MIX + if (maMaterialData.rimLightingMixIsActive) { + newMaterial.rimLightingMix = maMaterialData.rimLightingMix; + } else { + defaultFallthrough = true; + } + + //PARAMETRIC RIM FRESNEL POWER + if (maMaterialData.parametricRimFresnelPowerIsActive) { + newMaterial.parametricRimFresnelPower = maMaterialData.parametricRimFresnelPower; + } else { + defaultFallthrough = true; + } + + //PARAMETRIC RIM LIFT + if (maMaterialData.parametricRimLiftIsActive) { + newMaterial.parametricRimLift = maMaterialData.parametricRimLift; + } else { + defaultFallthrough = true; + } +/* ###################### Not yet supported but ready for it... ############################# + + //OUTLINE WIDTH MODE + if (maMaterialData.outlineWidthModeIsActive) { + newMaterial.outlineWidthMode = maMaterialData.outlineWidthMode; + } else { + defaultFallthrough = true; + } + + //OUTLINE WIDTH + if (maMaterialData.outlineWidthIsActive) { + newMaterial.outlineWidth = maMaterialData.outlineWidth; + } else { + defaultFallthrough = true; + } + + //OUTLINE + if (maMaterialData.outlineIsActive) { + newMaterial.outline = maMaterialData.outline; + } else { + defaultFallthrough = true; + } + + if (newMaterial.outlineWidthMode === "none") { + delete newMaterial.outlineWidth; + delete newMaterial.outline; + } + + //##################################################################################### +*/ + //UV ANIMATION MASK MAP + if (maMaterialData.uvAnimationMaskMapIsActive) { + newMaterial.uvAnimationMaskMap = maMaterialData.uvAnimationMaskMap || ""; + } else { + defaultFallthrough = true; + } + + //UV ANIMATION SCROLL X SPEED + if (maMaterialData.uvAnimationScrollXSpeedIsActive) { + newMaterial.uvAnimationScrollXSpeed = maMaterialData.uvAnimationScrollXSpeed; + } else { + defaultFallthrough = true; + } + + //UV ANIMATION SCROLL Y SPEED + if (maMaterialData.uvAnimationScrollYSpeedIsActive) { + newMaterial.uvAnimationScrollYSpeed = maMaterialData.uvAnimationScrollYSpeed; + } else { + defaultFallthrough = true; + } + + //UV ANIMATION ROTATION SPEED + if (maMaterialData.uvAnimationRotationSpeedIsActive) { + newMaterial.uvAnimationRotationSpeed = maMaterialData.uvAnimationRotationSpeed; + } else { + defaultFallthrough = true; + } + + } else if (maMaterialData.model === "hifi_shader_simple") { + //OPACITY + if (maMaterialData.opacityIsActive) { + newMaterial.opacity = maMaterialData.opacity; + } else { + defaultFallthrough = true; + } + + //PROCEDURAL + + if ( maMaterialData.procedural === "") { + maAddProceduralTemplate.disabled = false; + } else { + newMaterial.procedural = JSON.parse(maMaterialData.procedural); + maAddProceduralTemplate.disabled = true; + } + } //CULL FACE MODE newMaterial.cullFaceMode = maMaterialData.cullFaceMode; - //MODEL - newMaterial.model = maMaterialData.model; - //defaultFallthrough if (defaultFallthrough) { newMaterial.defaultFallthrough = true; } - + + //Remove the empty map when defaultFallthrough is false + if (!defaultFallthrough) { + if (newMaterial.albedoMap === "") {delete newMaterial.albedoMap; } + if (newMaterial.normalMap === "") {delete newMaterial.normalMap; } + if (newMaterial.bumpMap === "") {delete newMaterial.bumpMap; } + if (newMaterial.occlusionMap === "") {delete newMaterial.occlusionMap; } + if (newMaterial.lightMap === "") {delete newMaterial.lightMap; } + if (newMaterial.shadeMap === "") {delete newMaterial.shadeMap; } + if (newMaterial.matcapMap === "") {delete newMaterial.matcapMap; } + if (newMaterial.shadingShiftMap === "") {delete newMaterial.shadingShiftMap; } + if (newMaterial.rimMap === "") {delete newMaterial.rimMap; } + if (newMaterial.uvAnimationMaskMap === "") {delete newMaterial.uvAnimationMaskMap; } +/* ############## Not yet supported, but the code is ready (commented) ################### + if (newMaterial.outlineWidthMode === "none") {delete newMaterial.outlineWidthMode; } +//############################################################################################ */ + } + //insert newMaterial to materialData var materialDataForUpdate = { "materialVersion": 1, "materials": [] }; materialDataForUpdate.materials.push(newMaterial); - + //save to property EventBridge.emitWebEvent( JSON.stringify({ @@ -912,10 +2515,13 @@ function maGetMaterialDataAssistantAvailability(materialData) { materialDataJSON = materialData; materialDataString = JSON.stringify(materialData); } - if (getPropertyInputElement("materialURL").value === "materialData" && materialDataString.indexOf("hifi_shader_simple") === -1 && - materialDataString.indexOf("glossMap") === -1 && materialDataString.indexOf("specularMap") === -1 && - materialDataString.indexOf("bumpMap") === -1 && materialDataString.indexOf("lightMap") === -1 && - materialDataString.indexOf("texCoordTransform0") === -1 && materialDataString.indexOf("texCoordTransform1") === -1 && + + if (getPropertyInputElement("materialURL").value === "materialData" && + materialDataString.indexOf("outlineWidthMode") === -1 && //<=== ##### REMOVE THIS LINE WHEN YOU REACTIVATE OUTINE BLOCK (commented in the code) ##### + materialDataString.indexOf("outlineWidth") === -1 && //<=== ##### REMOVE THIS LINE WHEN YOU REACTIVATE OUTINE BLOCK (commented in the code) ##### + materialDataString.indexOf("outline") === -1 && //<=== ##### REMOVE THIS LINE WHEN YOU REACTIVATE OUTINE BLOCK (commented in the code) ##### + materialDataString.indexOf("texCoordTransform0") === -1 && + materialDataString.indexOf("texCoordTransform1") === -1 && (materialDataJSON.materials === undefined || materialDataJSON.materials.length <= 1 || typeof materialDataJSON.materials === "object")) { showMaterialAssistantButton(); } else { From a987ab0e656cee6cb801dff87b3ea6d5f07074e3 Mon Sep 17 00:00:00 2001 From: Alezia Kurdis <60075796+AleziaKurdis@users.noreply.github.com> Date: Sun, 21 Jul 2024 22:35:27 -0400 Subject: [PATCH 15/29] Support MTOON in Material Assistant Support MTOON in Material Assistant --- .../html/entityProperties.html | 407 ++++++++++++------ 1 file changed, 287 insertions(+), 120 deletions(-) diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index a85e3b00ef..3375493f46 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -5,7 +5,7 @@ // Created by Ryan Huffman on 13 Nov 2014 // Copyright 2014 High Fidelity, Inc. // Copyright 2020 Vircadia contributors. -// Copyright 2022 Overte e.V. +// Copyright 2022-2024 Overte e.V. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html @@ -63,131 +63,298 @@