diff --git a/scripts/system/create/entityProperties/html/entityProperties.html b/scripts/system/create/entityProperties/html/entityProperties.html index eef1c338291..a85e3b00efb 100644 --- a/scripts/system/create/entityProperties/html/entityProperties.html +++ b/scripts/system/create/entityProperties/html/entityProperties.html @@ -5,6 +5,7 @@ // Created by Ryan Huffman on 13 Nov 2014 // Copyright 2014 High Fidelity, Inc. // Copyright 2020 Vircadia contributors. +// Copyright 2022 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 @@ -17,7 +18,8 @@ - + + @@ -29,7 +31,8 @@ - + +
@@ -59,5 +62,137 @@
+ + diff --git a/scripts/system/create/entityProperties/html/js/entityProperties.js b/scripts/system/create/entityProperties/html/js/entityProperties.js index 20da2012507..3b8f218ff3f 100644 --- a/scripts/system/create/entityProperties/html/js/entityProperties.js +++ b/scripts/system/create/entityProperties/html/js/entityProperties.js @@ -878,9 +878,10 @@ const GROUPS = [ { label: "Material Data", type: "textarea", - buttons: [ { id: "clear", label: "Clear Material Data", className: "red", onClick: clearMaterialData }, - { id: "edit", label: "Edit as JSON", className: "blue", onClick: newJSONMaterialEditor }, - { id: "save", label: "Save Material Data", className: "black", onClick: saveMaterialData } ], + buttons: [ { id: "materialAssistant", label: "Assistant...", className: "secondary_blue blue", onClick: openMaterialAssistant }, + { id: "clear", label: "Clear Material", className: "secondary_red red", onClick: clearMaterialData }, + { id: "edit", label: "Edit as JSON", className: "secondary", onClick: newJSONMaterialEditor }, + { id: "save", label: "Save Material", className: "secondary", onClick: saveMaterialData }], propertyID: "materialData", }, { @@ -2498,8 +2499,7 @@ function createStringProperty(property, elProperty) { elInput.addEventListener('change', createEmitTextPropertyUpdateFunction(property)); - if (propertyData. - onChange !== undefined) { + if (propertyData.onChange !== undefined) { elInput.addEventListener('change', propertyData.onChange); } @@ -3580,6 +3580,21 @@ function saveMaterialData() { saveJSONMaterialData(true); } +function openMaterialAssistant() { + if (materialEditor === null) { + loadDataInMaUi({}); + } else { + loadDataInMaUi(materialEditor.getText()); + } + $('#uiMaterialAssistant').show(); + $('#properties-list').hide(); +} + +function closeMaterialAssistant() { + $('#uiMaterialAssistant').hide(); + $('#properties-list').show(); +} + /** * @param {boolean} noUpdate - don't update the UI, but do send a property update. * @param {Set.} [entityIDsToUpdate] - Entity IDs to update materialData for. @@ -3611,6 +3626,8 @@ function setMaterialDataFromEditor(noUpdate, entityIDsToUpdate) { } else { updateProperty('materialData', text, false); } + + maGetMaterialDataAssistantAvailability(text); } let materialEditor = null; @@ -3669,6 +3686,14 @@ function hideMaterialDataSaved() { $('#property-materialData-saved').hide(); } +function showMaterialAssistantButton() { + $('#property-materialData-button-materialAssistant').show(); +} + +function hideMaterialAssistantButton() { + $('#property-materialData-button-materialAssistant').hide(); +} + function setMaterialEditorJSON(json) { materialEditor.set(json); if (materialEditor.hasOwnProperty('expandAll')) { @@ -4145,6 +4170,7 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { const multipleSelections = currentSelections.length > 1; const hasSelectedEntityChanged = !areSetsEqual(selectedEntityIDs, previouslySelectedEntityIDs); + closeMaterialAssistant(); requestZoneList(); if (selections.length === 0) { @@ -4446,20 +4472,20 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { let materialDataMultiValue = getMultiplePropertyValue("materialData"); let materialDataTextArea = getPropertyInputElement("materialData"); - let materialJson = null; + let materialJSON = null; if (!materialDataMultiValue.isMultiDiffValue) { try { - materialJson = JSON.parse(materialDataMultiValue.value); + materialJSON = JSON.parse(materialDataMultiValue.value); } catch (e) { } } - if (materialJson !== null && !lockedMultiValue.isMultiDiffValue && !lockedMultiValue.value) { + if (materialJSON !== null && !lockedMultiValue.isMultiDiffValue && !lockedMultiValue.value) { if (materialEditor === null) { createJSONMaterialEditor(); } materialDataTextArea.classList.remove('multi-diff'); - setMaterialEditorJSON(materialJson); + setMaterialEditorJSON(materialJSON); showSaveMaterialDataButton(); hideMaterialDataTextArea(); hideNewJSONMaterialEditorButton(); @@ -4475,6 +4501,8 @@ function handleEntitySelectionUpdate(selections, isPropertiesToolUpdate) { hideMaterialDataSaved(); } + maGetMaterialDataAssistantAvailability(materialJSON); + if (hasSelectedEntityChanged && selections.length === 1 && entityTypes[0] === "Material") { requestMaterialTarget(); } diff --git a/scripts/system/create/entityProperties/html/js/materialAssistant.js b/scripts/system/create/entityProperties/html/js/materialAssistant.js new file mode 100644 index 00000000000..02af601330d --- /dev/null +++ b/scripts/system/create/entityProperties/html/js/materialAssistant.js @@ -0,0 +1,924 @@ +// materialAssistant.js +// +// Created by Alezia Kurdis on May 19th, 2022. +// Copyright 2022 Vircadia contributors. +// Copyright 2022 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 + +let maMaterialData = {}; + +let maClose, + maName, + maAlbedoIsActive, + maAlbedoColorPicker, + maAlbedoColorPickerSel, + maAlbedoMapIsActive, + maAlbedoMap, + maMetallicIsActive, + maMetallic, + maMetallicSlider, + maMetallicMap, + maRoughnessIsActive, + maRoughness, + maRoughnessSlider, + maRoughnessMap, + maNormalMapIsActive, + maNormalMap, + maOpacityIsActive, + maOpacity, + maOpacitySlider, + maOpacityMapModeDont, + maOpacityMapModeMask, + maOpacityMapModeBlend, + maOpacityCutoff, + maOpacityCutoffSlider, + maEmissiveIsActive, + maEmissiveColorPicker, + maEmissiveColorPickerSel, + maBloom, + maBloomSlider, + maUnlit, + maEmissiveMap, + maScatteringIsActive, + maScattering, + maScatteringSlider, + maScatteringMap, + maOcclusionMapIsActive, + maOcclusionMap, + maCullFaceModeBack, + maCullFaceModeFront, + maCullFaceModeNone; + +let DEFAULT_ALBEDO = [1,1,1]; +let DEFAULT_EMISSIVE = [0,0,0]; +let DEFAULT_BLOOM_FACTOR = 1; +let DEFAULT_ROUGHNESS = 0.9; +let DEFAULT_METALLIC_FOR_MA_UI = 0.001; +let DEFAULT_METALLIC = 0; +let DEFAULT_OPACITY = 1; +let DEFAULT_OPACITY_CUTOFF = 0.5; +let DEFAULT_SCATTERING = 0; + +function initiateMaUi() { + maClose = document.getElementById("uiMaterialAssistant-closeButton"); + maName = document.getElementById("ma-name"); + maAlbedoIsActive = document.getElementById("ma-albedo-isActive"); + maAlbedoColorPicker = document.getElementById("ma-albedo-colorPicker"); + maAlbedoMapIsActive = document.getElementById("ma-albedoMap-isActive"); + maAlbedoMap = document.getElementById("ma-albedoMap"); + maMetallicIsActive = document.getElementById("ma-metallic-isActive"); + maMetallic = document.getElementById("ma-metallic"); + maMetallicSlider = document.getElementById("ma-metallic-slider"); + maMetallicMap = document.getElementById("ma-metallicMap"); + maRoughnessIsActive = document.getElementById("ma-roughness-isActive"); + maRoughness = document.getElementById("ma-roughness"); + maRoughnessSlider = document.getElementById("ma-roughness-slider"); + maRoughnessMap = document.getElementById("ma-roughnessMap"); + maNormalMapIsActive = document.getElementById("ma-normalMap-isActive"); + maNormalMap = document.getElementById("ma-normalMap"); + maOpacityIsActive = document.getElementById("ma-opacity-isActive"); + maOpacity = document.getElementById("ma-opacity"); + maOpacitySlider = document.getElementById("ma-opacity-slider"); + maOpacityMapModeDont = document.getElementById("ma-opacityMapMode-dont"); + maOpacityMapModeMask = document.getElementById("ma-opacityMapMode-mask"); + maOpacityMapModeBlend = document.getElementById("ma-opacityMapMode-blend"); + maOpacityCutoff = document.getElementById("ma-opacityCutoff"); + maOpacityCutoffSlider = document.getElementById("ma-opacityCutoff-slider"); + maEmissiveIsActive = document.getElementById("ma-emissive-isActive"); + maEmissiveColorPicker = document.getElementById("ma-emissive-colorPicker"); + maBloom = document.getElementById("ma-bloom"); + maBloomSlider = document.getElementById("ma-bloom-slider"); + maUnlit = document.getElementById("ma-unlit"); + maEmissiveMap = document.getElementById("ma-emissiveMap"); + maScatteringIsActive = document.getElementById("ma-scattering-isActive"); + maScattering = document.getElementById("ma-scattering"); + maScatteringSlider = document.getElementById("ma-scattering-slider"); + maScatteringMap = document.getElementById("ma-scatteringMap"); + maOcclusionMapIsActive = document.getElementById("ma-occlusionMap-isActive"); + maOcclusionMap = document.getElementById("ma-occlusionMap"); + maCullFaceModeBack = document.getElementById("ma-cullFaceMode-back"); + maCullFaceModeFront = document.getElementById("ma-cullFaceMode-front"); + maCullFaceModeNone = document.getElementById("ma-cullFaceMode-none"); + + maClose.onclick = function() { + closeMaterialAssistant(); + }; + maAlbedoIsActive.onclick = function() { + if (maMaterialData.albedoIsActive) { + maMaterialData.albedoIsActive = false; + maAlbedoIsActive.className = "uiMaterialAssistant-inactive"; + maAlbedoColorPicker.style.pointerEvents = 'none'; + maAlbedoColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.albedoIsActive = true; + maAlbedoIsActive.className = "uiMaterialAssistant-active"; + maAlbedoColorPicker.style.pointerEvents = 'auto'; + maAlbedoColorPicker.style.backgroundColor = maGetRGB(maMaterialData.albedo); + } + maGenerateJsonAndSave(); + }; + maAlbedoMapIsActive.onclick = function() { + if (maMaterialData.albedoMapIsActive) { + maMaterialData.albedoMapIsActive = false; + maAlbedoMapIsActive.className = "uiMaterialAssistant-inactive"; + maAlbedoMap.disabled = true; + } else { + maMaterialData.albedoMapIsActive = true; + maAlbedoMapIsActive.className = "uiMaterialAssistant-active"; + maAlbedoMap.disabled = false; + } + maGenerateJsonAndSave(); + }; + maMetallicIsActive.onclick = function() { + if (maMaterialData.metallicIsActive) { + maMaterialData.metallicIsActive = false; + maMetallicIsActive.className = "uiMaterialAssistant-inactive"; + maMetallic.disabled = true; + maMetallicSlider.disabled = true; + maMetallicMap.disabled = true; + } else { + maMaterialData.metallicIsActive = true; + maMetallicIsActive.className = "uiMaterialAssistant-active"; + maMetallic.disabled = false; + maMetallicSlider.disabled = false; + maMetallicMap.disabled = false; + } + maGenerateJsonAndSave(); + }; + maRoughnessIsActive.onclick = function() { + if (maMaterialData.roughnessIsActive) { + maMaterialData.roughnessIsActive = false; + maRoughnessIsActive.className = "uiMaterialAssistant-inactive"; + maRoughness.disabled = true; + maRoughnessSlider.disabled = true; + maRoughnessMap.disabled = true; + } else { + maMaterialData.roughnessIsActive = true; + maRoughnessIsActive.className = "uiMaterialAssistant-active"; + maRoughness.disabled = false; + maRoughnessSlider.disabled = false; + maRoughnessMap.disabled = false; + } + maGenerateJsonAndSave(); + }; + maNormalMapIsActive.onclick = function() { + if (maMaterialData.normalMapIsActive) { + maMaterialData.normalMapIsActive = false; + maNormalMapIsActive.className = "uiMaterialAssistant-inactive"; + maNormalMap.disabled = true; + } else { + maMaterialData.normalMapIsActive = true; + maNormalMapIsActive.className = "uiMaterialAssistant-active"; + maNormalMap.disabled = false; + } + maGenerateJsonAndSave(); + }; + maOpacityIsActive.onclick = function() { + if (maMaterialData.opacityIsActive) { + maMaterialData.opacityIsActive = false; + maOpacityIsActive.className = "uiMaterialAssistant-inactive"; + maOpacity.disabled = true; + maOpacitySlider.disabled = true; + maOpacityMapModeDont.disabled = true; + maOpacityMapModeMask.disabled = true; + maOpacityMapModeBlend.disabled = true; + maOpacityCutoff.disabled = true; + maOpacityCutoffSlider.disabled = true; + } else { + maMaterialData.opacityIsActive = true; + maOpacityIsActive.className = "uiMaterialAssistant-active"; + maOpacity.disabled = false; + maOpacitySlider.disabled = false; + maOpacityMapModeDont.disabled = false; + maOpacityMapModeMask.disabled = false; + maOpacityMapModeBlend.disabled = false; + maOpacityCutoff.disabled = false; + maOpacityCutoffSlider.disabled = false; + } + maGenerateJsonAndSave(); + }; + maEmissiveIsActive.onclick = function() { + if (maMaterialData.emissiveIsActive) { + maMaterialData.emissiveIsActive = false; + maEmissiveIsActive.className = "uiMaterialAssistant-inactive"; + maBloom.disabled = true; + maBloomSlider.disabled = true; + maEmissiveMap.disabled = true; + maEmissiveColorPicker.style.pointerEvents = 'none'; + maEmissiveColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.emissiveIsActive = true; + maEmissiveIsActive.className = "uiMaterialAssistant-active"; + maBloom.disabled = false; + maBloomSlider.disabled = false; + maEmissiveMap.disabled = false; + maEmissiveColorPicker.style.pointerEvents = 'auto'; + maEmissiveColorPicker.style.backgroundColor = maGetRGB(maMaterialData.emissive); + } + maGenerateJsonAndSave(); + }; + maScatteringIsActive.onclick = function() { + if (maMaterialData.scatteringIsActive) { + maMaterialData.scatteringIsActive = false; + maScatteringIsActive.className = "uiMaterialAssistant-inactive"; + maScattering.disabled = true; + maScatteringSlider.disabled = true; + maScatteringMap.disabled = true; + } else { + maMaterialData.scatteringIsActive = true; + maScatteringIsActive.className = "uiMaterialAssistant-active"; + maScattering.disabled = false; + maScatteringSlider.disabled = false; + maScatteringMap.disabled = false; + } + maGenerateJsonAndSave(); + }; + maOcclusionMapIsActive.onclick = function() { + if (maMaterialData.occlusionMapIsActive) { + maMaterialData.occlusionMapIsActive = false; + maOcclusionMapIsActive.className = "uiMaterialAssistant-inactive"; + maOcclusionMap.disabled = true; + } else { + maMaterialData.occlusionMapIsActive = true; + maOcclusionMapIsActive.className = "uiMaterialAssistant-active"; + maOcclusionMap.disabled = false; + } + maGenerateJsonAndSave(); + }; + maName.oninput = function() { + maMaterialData.name = maName.value; + maGenerateJsonAndSave(); + }; + maAlbedoMap.oninput = function() { + maMaterialData.albedoMap = maAlbedoMap.value; + maGenerateJsonAndSave(); + }; + maMetallicSlider.oninput = function() { + maMetallic.value = maMetallicSlider.value/1000; + maMaterialData.metallic = parseFloat(maMetallic.value); + maGenerateJsonAndSave(); + }; + maMetallicMap.oninput = function() { + maMaterialData.metallicMap = maMetallicMap.value; + maGenerateJsonAndSave(); + }; + maRoughnessSlider.oninput = function() { + maRoughness.value = maRoughnessSlider.value/1000; + maMaterialData.roughness = parseFloat(maRoughness.value); + maGenerateJsonAndSave(); + }; + maRoughnessMap.oninput = function() { + maMaterialData.roughnessMap = maRoughnessMap.value; + maGenerateJsonAndSave(); + }; + maNormalMap.oninput = function() { + maMaterialData.normalMap = maNormalMap.value; + maGenerateJsonAndSave(); + }; + maOpacitySlider.oninput = function() { + maOpacity.value = maOpacitySlider.value/1000; + maMaterialData.opacity = parseFloat(maOpacity.value); + maGenerateJsonAndSave(); + }; + maOpacityMapModeDont.oninput = function() { + maMaterialData.opacityMapMode = maOpacityMapModeDont.value; + maGenerateJsonAndSave(); + }; + maOpacityMapModeMask.oninput = function() { + maMaterialData.opacityMapMode = maOpacityMapModeMask.value; + maGenerateJsonAndSave(); + }; + maOpacityMapModeBlend.oninput = function() { + maMaterialData.opacityMapMode = maOpacityMapModeBlend.value; + maGenerateJsonAndSave(); + }; + maOpacityCutoffSlider.oninput = function() { + maOpacityCutoff.value = maOpacityCutoffSlider.value/1000; + maMaterialData.opacityCutoff = parseFloat(maOpacityCutoff.value); + maGenerateJsonAndSave(); + }; + maBloomSlider.oninput = function() { + maBloom.value = maBloomSlider.value/100; + maMaterialData.bloom = parseFloat(maBloom.value); + maGenerateJsonAndSave(); + }; + maUnlit.oninput = function() { + maMaterialData.unlit = maUnlit.checked; + maGenerateJsonAndSave(); + }; + maEmissiveMap.oninput = function() { + maMaterialData.emissiveMap = maEmissiveMap.value; + maGenerateJsonAndSave(); + }; + maScatteringSlider.oninput = function() { + maScattering.value = maScatteringSlider.value/1000; + maMaterialData.scattering = parseFloat(maScattering.value); + maGenerateJsonAndSave(); + }; + maScatteringMap.oninput = function() { + maMaterialData.scatteringMap = maScatteringMap.value; + maGenerateJsonAndSave(); + }; + maOcclusionMap.oninput = function() { + maMaterialData.occlusionMap = maOcclusionMap.value; + maGenerateJsonAndSave(); + }; + maCullFaceModeBack.oninput = function() { + maMaterialData.cullFaceMode = maCullFaceModeBack.value; + maGenerateJsonAndSave(); + }; + maCullFaceModeFront.oninput = function() { + maMaterialData.cullFaceMode = maCullFaceModeFront.value; + maGenerateJsonAndSave(); + }; + maCullFaceModeNone.oninput = function() { + maMaterialData.cullFaceMode = maCullFaceModeNone.value; + maGenerateJsonAndSave(); + }; + + var maAlbedoColorPickerID = "#ma-albedo-colorPicker"; + maAlbedoColorPickerSel = $(maAlbedoColorPickerID).colpick({ + colorScheme: 'dark', + layout: 'rgbhex', + color: '000000', + submit: false, + onShow: function(colpick) { + $(maAlbedoColorPickerID).colpickSetColor({ + "r": maMaterialData.albedo[0] * 255, + "g": maMaterialData.albedo[1] * 255, + "b": maMaterialData.albedo[2] * 255, + }); + $(maAlbedoColorPickerID).attr('active', 'true'); + }, + onHide: function(colpick) { + $(maAlbedoColorPickerID).attr('active', 'false'); + }, + onChange: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + if ($(maAlbedoColorPickerID).attr('active') === 'true') { + maMaterialData.albedo = [(rgb.r/255), (rgb.g/255), (rgb.b/255)]; + maGenerateJsonAndSave(); + } + } + }); + + var maEmissiveColorPickerID = "#ma-emissive-colorPicker"; + maEmissiveColorPickerSel = $(maEmissiveColorPickerID).colpick({ + colorScheme: 'dark', + layout: 'rgbhex', + color: '000000', + submit: false, + onShow: function(colpick) { + $(maEmissiveColorPickerID).colpickSetColor({ + "r": maMaterialData.emissive[0] * 255, + "g": maMaterialData.emissive[1] * 255, + "b": maMaterialData.emissive[2] * 255, + }); + $(maEmissiveColorPickerID).attr('active', 'true'); + }, + onHide: function(colpick) { + $(maEmissiveColorPickerID).attr('active', 'false'); + }, + onChange: function(hsb, hex, rgb, el) { + $(el).css('background-color', '#' + hex); + if ($(maEmissiveColorPickerID).attr('active') === 'true') { + maMaterialData.emissive = [(rgb.r/255), (rgb.g/255), (rgb.b/255)]; + maGenerateJsonAndSave(); + } + } + }); +} + +function loadDataInMaUi(materialDataPropertyValue) { + var entityMaterialData, materialDefinition; + 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"; + + //NAME + if (materialDefinition.name !== undefined) { + maMaterialData.name = materialDefinition.name; + } else { + maMaterialData.name = ""; + } + maName.value = maMaterialData.name; + + //ALBEDO + if (materialDefinition.defaultFallthrough === true && materialDefinition.albedo === undefined) { + maMaterialData.albedoIsActive = false; + maAlbedoIsActive.className = "uiMaterialAssistant-inactive"; + maAlbedoColorPicker.style.pointerEvents = 'none'; + maAlbedoColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.albedoIsActive = true; + maAlbedoIsActive.className = "uiMaterialAssistant-active"; + maAlbedoColorPicker.style.pointerEvents = 'auto'; + maAlbedoColorPicker.style.backgroundColor = maGetRGB(maMaterialData.albedo); + } + + if (materialDefinition.albedo !== undefined) { + maMaterialData.albedo = materialDefinition.albedo; + } else { + maMaterialData.albedo = DEFAULT_ALBEDO; + } + maAlbedoColorPicker.style.backgroundColor = maGetRGB(maMaterialData.albedo); + + //ALBEDO MAP + if (materialDefinition.defaultFallthrough === true && materialDefinition.albedoMap === undefined) { + maMaterialData.albedoMapIsActive = false; + maAlbedoMapIsActive.className = "uiMaterialAssistant-inactive"; + maAlbedoMap.disabled = true; + } else { + maMaterialData.albedoMapIsActive = true; + maAlbedoMapIsActive.className = "uiMaterialAssistant-active"; + maAlbedoMap.disabled = false; + } + + if (materialDefinition.albedoMap !== undefined) { + maMaterialData.albedoMap = materialDefinition.albedoMap; + } else { + maMaterialData.albedoMap = ""; + } + maAlbedoMap.value = maMaterialData.albedoMap; + + //METALLIC + if (materialDefinition.defaultFallthrough === true + && materialDefinition.metallic === undefined + && materialDefinition.metallicMap === undefined) { + maMaterialData.metallicIsActive = false; + maMetallicIsActive.className = "uiMaterialAssistant-inactive"; + maMetallic.disabled = true; + maMetallicSlider.disabled = true; + maMetallicMap.disabled = true; + } else { + maMaterialData.metallicIsActive = true; + maMetallicIsActive.className = "uiMaterialAssistant-active"; + maMetallic.disabled = false; + maMetallicSlider.disabled = false; + maMetallicMap.disabled = false; + } + + if (materialDefinition.metallic !== undefined) { + maMaterialData.metallic = materialDefinition.metallic; + } else { + maMaterialData.metallic = DEFAULT_METALLIC_FOR_MA_UI; + } + maMetallic.value = maMaterialData.metallic; + maMetallicSlider.value = Math.floor(maMaterialData.metallic * 1000); + + if (materialDefinition.metallicMap !== undefined) { + maMaterialData.metallicMap = materialDefinition.metallicMap; + } else { + maMaterialData.metallicMap = ""; + } + maMetallicMap.value = maMaterialData.metallicMap; + + //ROUGHNESS + if (materialDefinition.defaultFallthrough === true + && materialDefinition.roughness === undefined + && materialDefinition.roughnessMap === undefined) { + maMaterialData.roughnessIsActive = false; + maRoughnessIsActive.className = "uiMaterialAssistant-inactive"; + maRoughness.disabled = true; + maRoughnessSlider.disabled = true; + maRoughnessMap.disabled = true; + } else { + maMaterialData.roughnessIsActive = true; + maRoughnessIsActive.className = "uiMaterialAssistant-active"; + maRoughness.disabled = false; + maRoughnessSlider.disabled = false; + maRoughnessMap.disabled = false; + } + + if (materialDefinition.roughness !== undefined) { + maMaterialData.roughness = materialDefinition.roughness; + } else { + maMaterialData.roughness = DEFAULT_ROUGHNESS; + } + maRoughness.value = maMaterialData.roughness; + maRoughnessSlider.value = Math.floor(maMaterialData.roughness * 1000); + + if (materialDefinition.roughnessMap !== undefined) { + maMaterialData.roughnessMap = materialDefinition.roughnessMap; + } else { + maMaterialData.roughnessMap = ""; + } + maRoughnessMap.value = maMaterialData.roughnessMap; + + //NORMAL MAP + if (materialDefinition.defaultFallthrough === true && materialDefinition.normalMap === undefined) { + maMaterialData.normalMapIsActive = false; + maNormalMapIsActive.className = "uiMaterialAssistant-inactive"; + maNormalMap.disabled = true; + } else { + maMaterialData.normalMapIsActive = true; + maNormalMapIsActive.className = "uiMaterialAssistant-active"; + maNormalMap.disabled = false; + } + + if (materialDefinition.normalMap !== undefined) { + maMaterialData.normalMap = materialDefinition.normalMap; + } else { + maMaterialData.normalMap = ""; + } + maNormalMap.value = maMaterialData.normalMap; + + //OPACITY + if (materialDefinition.defaultFallthrough === true + && materialDefinition.opacity === undefined + && materialDefinition.opacityMapMode === undefined) { + maMaterialData.opacityIsActive = false; + maOpacityIsActive.className = "uiMaterialAssistant-inactive"; + maOpacity.disabled = true; + maOpacitySlider.disabled = true; + maOpacityMapModeDont.disabled = true; + maOpacityMapModeMask.disabled = true; + maOpacityMapModeBlend.disabled = true; + maOpacityCutoff.disabled = true; + maOpacityCutoffSlider.disabled = true; + } else { + maMaterialData.opacityIsActive = true; + maOpacityIsActive.className = "uiMaterialAssistant-active"; + maOpacity.disabled = false; + maOpacitySlider.disabled = false; + maOpacityMapModeDont.disabled = false; + maOpacityMapModeMask.disabled = false; + maOpacityMapModeBlend.disabled = false; + maOpacityCutoff.disabled = false; + maOpacityCutoffSlider.disabled = false; + } + + if (materialDefinition.opacity !== undefined) { + maMaterialData.opacity = materialDefinition.opacity; + } else { + maMaterialData.opacity = DEFAULT_OPACITY; + } + maOpacity.value = maMaterialData.opacity; + maOpacitySlider.value = Math.floor(maMaterialData.opacity * 1000); + + if (materialDefinition.opacityMapMode !== undefined) { + maMaterialData.opacityMapMode = materialDefinition.opacityMapMode; + } else { + maMaterialData.opacityMapMode = "OPACITY_MAP_OPAQUE"; + } + switch (maMaterialData.opacityMapMode) { + case "OPACITY_MAP_OPAQUE": + maOpacityMapModeDont.checked = true; + break; + case "OPACITY_MAP_MASK": + maOpacityMapModeMask.checked = true; + break; + case "OPACITY_MAP_BLEND": + maOpacityMapModeBlend.checked = true; + break; + default: + alert("ERROR: opacityMapMode = '" + maMaterialData.opacityMapMode + "'. Something has been broken in the code."); + } + + if (materialDefinition.opacityCutoff !== undefined) { + maMaterialData.opacityCutoff = materialDefinition.opacityCutoff; + } else { + maMaterialData.opacityCutoff = DEFAULT_OPACITY_CUTOFF; + } + maOpacityCutoff.value = maMaterialData.opacityCutoff; + maOpacityCutoffSlider.value = Math.floor(maMaterialData.opacityCutoff * 1000); + + //EMISSIVE + if (materialDefinition.defaultFallthrough === true + && materialDefinition.emissive === undefined + && materialDefinition.emissiveMap === undefined) { + maMaterialData.emissiveIsActive = false; + maEmissiveIsActive.className = "uiMaterialAssistant-inactive"; + maBloom.disabled = true; + maBloomSlider.disabled = true; + maEmissiveMap.disabled = true; + maEmissiveColorPicker.style.pointerEvents = 'none'; + maEmissiveColorPicker.style.backgroundColor = "#555555"; + } else { + maMaterialData.emissiveIsActive = true; + maEmissiveIsActive.className = "uiMaterialAssistant-active"; + maBloom.disabled = false; + maBloomSlider.disabled = false; + maEmissiveMap.disabled = false; + maEmissiveColorPicker.style.pointerEvents = 'auto'; + maEmissiveColorPicker.style.backgroundColor = maGetRGB(maMaterialData.emissive); + } + + if (materialDefinition.emissive !== undefined) { + maMaterialData.emissive = maGetColorValueFromEmissive(materialDefinition.emissive); + maMaterialData.bloom = maGetBloomFactorFromEmissive(materialDefinition.emissive); + } else { + maMaterialData.emissive = DEFAULT_EMISSIVE; + maMaterialData.bloom = DEFAULT_BLOOM_FACTOR; + } + maEmissiveColorPicker.style.backgroundColor = maGetRGB(maMaterialData.emissive); + maBloom.value = maMaterialData.bloom; + maBloomSlider.value = Math.floor(maMaterialData.bloom * 100); + + if (materialDefinition.emissiveMap !== undefined) { + maMaterialData.emissiveMap = materialDefinition.emissiveMap; + } else { + maMaterialData.emissiveMap = ""; + } + maEmissiveMap.value = maMaterialData.emissiveMap; + + //UNLIT + if (materialDefinition.unlit !== undefined) { + maMaterialData.unlit = materialDefinition.unlit; + } else { + maMaterialData.unlit = false; + } + maUnlit.checked = maMaterialData.unlit; + + //SCATTERING + if (materialDefinition.defaultFallthrough === true + && materialDefinition.scattering === undefined + && materialDefinition.scatteringMap === undefined) { + maMaterialData.scatteringIsActive = false; + maScatteringIsActive.className = "uiMaterialAssistant-inactive"; + maScattering.disabled = true; + maScatteringSlider.disabled = true; + maScatteringMap.disabled = true; + } else { + maMaterialData.scatteringIsActive = true; + maScatteringIsActive.className = "uiMaterialAssistant-active"; + maScattering.disabled = false; + maScatteringSlider.disabled = false; + maScatteringMap.disabled = false; + } + + if (materialDefinition.scattering !== undefined) { + maMaterialData.scattering = materialDefinition.scattering; + } else { + maMaterialData.scattering = DEFAULT_SCATTERING; + } + maScattering.value = maMaterialData.scattering; + maScatteringSlider.value = Math.floor(maMaterialData.scattering * 1000); + + if (materialDefinition.scatteringMap !== undefined) { + maMaterialData.scatteringMap = materialDefinition.scatteringMap; + } else { + maMaterialData.scatteringMap = ""; + } + maScatteringMap.value = maMaterialData.scatteringMap; + + //OCCLUSION MAP + if (materialDefinition.defaultFallthrough === true && materialDefinition.occlusionMap === undefined) { + maMaterialData.occlusionMapIsActive = false; + maOcclusionMapIsActive.className = "uiMaterialAssistant-inactive"; + maOcclusionMap.disabled = true; + } else { + maMaterialData.occlusionMapIsActive = true; + maOcclusionMapIsActive.className = "uiMaterialAssistant-active"; + maOcclusionMap.disabled = false; + } + + if (materialDefinition.occlusionMap !== undefined) { + maMaterialData.occlusionMap = materialDefinition.occlusionMap; + } else { + maMaterialData.occlusionMap = ""; + } + maOcclusionMap.value = maMaterialData.occlusionMap; + + //CULL FACE MODE + if (materialDefinition.cullFaceMode !== undefined) { + maMaterialData.cullFaceMode = materialDefinition.cullFaceMode; + } else { + maMaterialData.cullFaceMode = "CULL_BACK"; + } + switch (maMaterialData.cullFaceMode) { + case "CULL_BACK": + maCullFaceModeBack.checked = true; + break; + case "CULL_FRONT": + maCullFaceModeFront.checked = true; + break; + case "CULL_NONE": + maCullFaceModeNone.checked = true; + break; + default: + alert("ERROR: cullFaceMode = '" + maMaterialData.cullFaceMode + "'. Something has been broken in the code."); + } +} + +function maGenerateJsonAndSave() { + var newMaterial = {}; + var defaultFallthrough = false; + + //NAME + if (maMaterialData.name != "") { + newMaterial.name = maMaterialData.name; + } + + //ALBEDO & ALBEDOMAP + 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; + } else { + newMaterial.metallicMap = maMaterialData.metallicMap; + } + } else { + defaultFallthrough = true; + } + + //ROUGHNESS & ROUGHNESSMAP + if (maMaterialData.roughnessIsActive) { + if (maMaterialData.roughnessMap === "") { + newMaterial.roughness = maMaterialData.roughness; + } else { + newMaterial.roughnessMap = maMaterialData.roughnessMap; + } + } 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); + } 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) { + if (maMaterialData.occlusionMap !== "") { + newMaterial.occlusionMap = maMaterialData.occlusionMap; + } + } else { + defaultFallthrough = true; + } + + //CULL FACE MODE + newMaterial.cullFaceMode = maMaterialData.cullFaceMode; + + //MODEL + newMaterial.model = maMaterialData.model; + + //defaultFallthrough + if (defaultFallthrough) { + newMaterial.defaultFallthrough = true; + } + + //insert newMaterial to materialData + var materialDataForUpdate = { + "materialVersion": 1, + "materials": [] + }; + materialDataForUpdate.materials.push(newMaterial); + + //save to property + EventBridge.emitWebEvent( + JSON.stringify({ + ids: [...selectedEntityIDs], + type: "saveMaterialData", + properties: { + materialData: JSON.stringify(materialDataForUpdate) + } + }) + ); + materialEditor.set(materialDataForUpdate); +} + +function maGetColorValueFromEmissive(colorArray) { + if (Array.isArray(colorArray)) { + var max = maGetHighestValue(colorArray); + if (max > 1) { + var normalizer = 1/max; + return [colorArray[0] * normalizer, colorArray[1] * normalizer, colorArray[2] * normalizer]; + } else { + return colorArray; + } + } else { + return [0,0,0]; + } +} + +function maGetBloomFactorFromEmissive(colorArray) { + if (Array.isArray(colorArray)) { + return maGetHighestValue(colorArray); + } else { + return 1; + } +} + +function maGetHighestValue(colorArray) { + var highest = colorArray[0]; + for (var i = 0; i < colorArray.length; i++) { + if (colorArray[i] > highest) { + highest = colorArray[i]; + } + } + return highest; +} + +function scaleEmissiveByBloomFactor(colorArray, bloomFactor) { + return [colorArray[0] * bloomFactor, colorArray[1] * bloomFactor, colorArray[2] * bloomFactor]; +} + +function maGetRGB(colorArray){ + if (colorArray === undefined) { + return "#000000"; + } else { + return "rgb(" + Math.floor(colorArray[0] * 255) + ", " + Math.floor(colorArray[1] * 255) + ", " + Math.floor(colorArray[2] * 255) + ")"; + } +} + +/** + * @param {string or object} materialData - json of the materialData as a string or as an object. + */ +function maGetMaterialDataAssistantAvailability(materialData) { + var materialDataJSON, materialDataString; + if (typeof materialData === "string") { + materialDataJSON = JSON.parse(materialData); + materialDataString = materialData; + } else { + 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 && + (materialDataJSON.materials === undefined || materialDataJSON.materials.length <= 1 || typeof materialDataJSON.materials === "object")) { + showMaterialAssistantButton(); + } else { + hideMaterialAssistantButton(); + } +} diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css index 1f2539206ca..70696abdabc 100644 --- a/scripts/system/html/css/edit-style.css +++ b/scripts/system/html/css/edit-style.css @@ -496,6 +496,22 @@ input[type=button].secondary_red, button.hifi-edit-button.secondary_red { background: linear-gradient(#d42043 20%, #94132e 100%); cursor: pointer; } +input[type=button].secondary_blue, button.hifi-edit-button.secondary_blue { + font-family: Raleway-Bold; + font-size: 10px; + text-transform: uppercase; + vertical-align: top; + height: 18px; + min-width: 60px; + padding: 0 14px; + margin-right: 6px; + border-radius: 4px; + border: none; + color: #fff; + background-color: #1080b8; + background: linear-gradient(#00b4ef 20%, #1080b8 100%); + cursor: pointer; +} input[type=button]:enabled:hover, button.hifi-edit-button:enabled:hover { background: linear-gradient(#000, #000); border: none; diff --git a/scripts/system/html/css/img/sidewalk.png b/scripts/system/html/css/img/sidewalk.png new file mode 100644 index 00000000000..8db0adc2d48 Binary files /dev/null and b/scripts/system/html/css/img/sidewalk.png differ diff --git a/scripts/system/html/css/materialAssistant.css b/scripts/system/html/css/materialAssistant.css new file mode 100644 index 00000000000..9944baf73f3 --- /dev/null +++ b/scripts/system/html/css/materialAssistant.css @@ -0,0 +1,223 @@ +/* +// materialAssistant.css +// +// Created by Alezia Kurdis on May 17th, 2022. +// Copyright 2022 Vircadia contributors. +// Copyright 2022 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 +*/ + +#uiMaterialAssistant { + position: fixed; + display: none; + width: 100%; + top: 0px; + left: 0px; + right: 0px; + bottom: 0px; + border: 0px; + padding: 0px; + background-color: #404040; + z-index: 2; + border-collapse: collapse; + overflow-y: scroll; +} + +#uiMaterialAssistant-headerContainer { + width: 98%; + text-align: right; + padding: 6px; + display: flex; +} + +#uiMaterialAssistant-closeButton { + font-family: Raleway-Bold; + font-size: 18px; + text-align: center; + border: 0px; + padding: 6px; + color: #FFFFFF; +} + +#uiMaterialAssistant-sidewalk { + width: 100%; + background-image: url("img/sidewalk.png"); + background-repeat: repeat; +} + +#uiMaterialAssistant-formContainer { + background-color: #404040; + width: 90%; + padding: 2px; +} + +div.uiMaterialAssistant-group{ + background-color: #2E2E2E; + border: 2px solid #aaaaaa; + padding: 5px; + margin: 0px 0px 6px 0px; + font-family: Raleway-SemiBold; + text-decoration: none; + font-size: 13px; + color: #ffffff; +} + +font.uiMaterialAssistant-Explain{ + background-color: #2E2E2E; + font-family: Raleway-Regular; + text-decoration: Italic; + font-size: 10px; + color: #8ad5ff; +} + +font.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; +} + +input[type=range].uiMaterialAssistant-slider { + margin: 10px 0; + width: 100%; + background-color: #2E2E2E; +} + +input[type=range].uiMaterialAssistant-slider:focus { + outline: none; +} + +input[type=range].uiMaterialAssistant-slider::-webkit-slider-runnable-track { + width: 100%; + height: 6px; + cursor: pointer; + animate: 0.2s; + box-shadow: 0px 0px 0px #000000; + background: #ffffff; + border-radius: 0px; + border: 0px solid #000000; +} + +input[type=range].uiMaterialAssistant-slider:disabled::-webkit-slider-runnable-track { + background: #555555; + border: 0px solid #333333; +} + +input[type=range].uiMaterialAssistant-slider::-webkit-slider-thumb { + box-shadow: 1px 1px 1px #000000; + border: 1px solid #000000; + height: 22px; + width: 12px; + border-radius: 10px; + background: #FFFFFF; + cursor: pointer; + -webkit-appearance: none; + margin-top: -8.5px; +} + +input[type=range].uiMaterialAssistant-slider:disabled::-webkit-slider-thumb { + box-shadow: 1px 1px 1px #000000; + border: 1px solid #333333; + height: 22px; + width: 12px; + border-radius: 10px; + background: #555555; +} + +input[type=range].uiMaterialAssistant-slider:focus::-webkit-slider-runnable-track { + background: #ffffff; +} + +input[type=text].uiMaterialAssistant-input { + background-color: #ffffff; + border: 1px solid #000000; + font-family: FiraSans-SemiBold; + font-size: 14px; + width: auto; + height: auto; + padding: 3px; + margin: 3px 0px 3px 0px; + color: #000000; +} + +input[type=text].uiMaterialAssistant-input:disabled { + background-color: #555555; + color: #888888; +} +input[type=radio].uiMaterialAssistant-radio { + width: 16px; + height: 16px; + margin: 2px; + padding: 3px; +} + +input[type=radio].uiMaterialAssistant-radio:focus { + outline: none; +} + +input[type=checkbox].uiMaterialAssistant-checkbox { + width: 16px; + height: 16px; + margin: 2px; + padding: 3px; + display: block; + text-align: left; +} + +input[type=checkbox].uiMaterialAssistant-checkbox:focus { + outline: none; +} + +button.uiMaterialAssistant-active { + width: 12px; + height: 12px; + margin: 0px; + padding: 0px; + border: 1px solid #000000; + background-color: #00FF00; +} + +button.uiMaterialAssistant-active:hover { + background-color: #33FF33; + border: 1px solid #ffffff; +} + +button.uiMaterialAssistant-active:focus { + outline: none; +} + +button.uiMaterialAssistant-inactive { + width: 12px; + height: 12px; + margin: 0px; + padding: 0px; + border: 1px solid #000000; + background-color: #555555; +} + +button.uiMaterialAssistant-inactive:hover { + background-color: #777777; + border: 1px solid #ffffff; +} + +button.uiMaterialAssistant-inactive:focus { + outline: none; +} + +div.uiMaterialAssistant-color-picker { + background-color: #000000; + border: 1px solid #AAAAAA; + width: 120px; + height: 30px; +}