community-apps/applications/materialDataCreator/materialDataCreator.html
Alezia Kurdis e0f9ee048d
Rebranding for Overte
Rebranding for Overte
Addition of a new feature to copy .fst formated material data.
2022-02-07 22:54:45 -05:00

659 lines
No EOL
36 KiB
HTML

<!doctype html>
<!--
// materialDataCreator.html
//
// Created by Alezia Kurdis, April 12th, 2020.
// Copyright 2020 Vircadia and contributors.
// Copyright 2022 Overte e.V.
//
// A tool to generate materialData.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
-->
<html>
<head>
<meta charset="utf-8">
<title>Material Data Creator</title>
<link href="color-picker.min.css" rel="stylesheet">
<style>
.color-picker.no-alpha .color-picker\:a {
display: none;
}
textarea.output {
width: 98%;
max-height: 100%;
}
div.info{
background-color: #AAAAAA;
padding: 5px;
margin: 0px 0px 6px 0px;
font-family: arial,sans-serif, helvetica;
font-weight: 600;
text-decoration: none;
font-size: 13px;
color:#000000;
}
div.group{
background-color: #2e3745;
border: 2px solid #aaaaaa;
padding: 5px;
margin: 0px 0px 6px 0px;
font-family: arial,sans-serif, helvetica;
font-weight: 600;
text-decoration: none;
font-size: 13px;
color:#ffffff;
}
font.Explain{
font-family: arial,sans-serif, helvetica;
font-weight: 500;
text-decoration: Italic;
font-size: 10px;
color:#8ad5ff;
}
font.label{
font-family: arial,sans-serif, helvetica;
font-weight: 600;
text-decoration: none;
font-size: 12px;
color:#fff2d0;
}
body{
background-color: #4c4d5c;
font-family: arial,sans-serif, helvetica;
font-weight: 600;
text-decoration: none;
font-size: 12px;
color:#000000;
margin: 0px;
border-collapse: collapse;
}
img.demo{
background-color: #AAAAAA;
}
img.save{
background-color: #dfd093;
}
img.reset{
background-color: #d16c64;
}
img.studio{
background-color: #c6dcb6;
}
td.title {
text-align: center;
font-family: arial,sans-serif, helvetica;
font-weight: 700;
text-decoration: none;
font-size: 20px;
color:#ffffff;
}
input.copybtn {
font-family: arial,sans-serif, helvetica;
font-weight: 800;
text-decoration: none;
font-size: 11px;
padding: 2px;
}
#helpOverlay {
position: fixed;
display: none;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #4c4d5c;
color: #ffffff;
padding: 10px;
z-index: 2;
cursor: pointer;
}
</style>
<script src='jquery.min.js'></script>
<script src="color-picker.min.js"></script>
<script>
var material = {
"name": "untitled",
"albedo": "#ffffff",
"metallic": 0.001,
"roughness": 1.0,
"opacity": 1,
"emissive": "#000000",
"bloom": 1,
"scattering": 0,
"unlit": false,
"albedoMap": "",
"metallicMap": "",
"roughnessMap": "",
"normalMap": "",
"opacityMap": "DO NOT USE",
"opacityCutoff": 0.5,
"emissiveMap": "",
"scatteringMap": "",
"occlusionMap": "",
"cullFaceMode": "CULL_BACK",
"defaultFallthrough": false
};
function resetMaterial() {
material = {
"name": "untitled",
"albedo": "#ffffff",
"metallic": 0.001,
"roughness": 1.0,
"opacity": 1,
"emissive": "#000000",
"bloom": 1,
"scattering": 0,
"unlit": false,
"albedoMap": "",
"metallicMap": "",
"roughnessMap": "",
"normalMap": "",
"opacityMap": "DO NOT USE",
"opacityCutoff": 0.5,
"emissiveMap": "",
"scatteringMap": "",
"occlusionMap": "",
"cullFaceMode": "CULL_BACK",
"defaultFallthrough": false
};
document.materialEditor.reset();
document.materialEditor.name.value = "untitled";
document.materialEditor.albedo.value = "#ffffff";
document.materialEditor.metallic.value = 1;
document.materialEditor.metallic_value.value = 0.001;
document.materialEditor.roughness.value = 500;
document.materialEditor.roughness_value.value = 1.0;
document.materialEditor.opacity.value = 1000;
document.materialEditor.opacity_value.value = 1;
document.materialEditor.emissive.value = "#000000";
document.materialEditor.bloom.value = 100;
document.materialEditor.bloom_value.value = 1;
document.materialEditor.scattering.value = 0;
document.materialEditor.scattering_value.value = 0;
document.materialEditor.unlit.checked = false;
document.materialEditor.albedoMap.value = "";
document.materialEditor.metallicMap.value = "";
document.materialEditor.roughnessMap.value = "";
document.materialEditor.normalMap.value = "";
document.materialEditor.opacityMap.value = "DO NOT USE";
document.materialEditor.opacityCutoff.value = 0.5;
document.materialEditor.emissiveMap.value = "";
document.materialEditor.scatteringMap.value = "";
document.materialEditor.occlusionMap.value = "";
document.materialEditor.cullFaceMode.value = "CULL_BACK";
document.materialEditor.defaultFallthrough.checked = false;
generateMaterialJSON();
}
function loadMaterial() {
document.materialEditor.name.value = material.name;
document.materialEditor.albedo.value = material.albedo;
document.materialEditor.albedo.style.backgroundColor = material.albedo;
document.materialEditor.albedo.style.color = material.albedo;
document.materialEditor.metallic.value = material.metallic * 1000;
document.materialEditor.metallic_value.value = material.metallic;
document.materialEditor.roughness.value = material.roughness * 1000;
document.materialEditor.roughness_value.value = material.roughness;
document.materialEditor.opacity.value = material.opacity * 1000;
document.materialEditor.opacity_value.value = material.opacity;
document.materialEditor.emissive.value = material.emissive;
document.materialEditor.emissive.style.backgroundColor = material.emissive;
document.materialEditor.emissive.style.color = material.emissive;
document.materialEditor.bloom.value = material.bloom * 100;
document.materialEditor.bloom_value.value = material.bloom;
document.materialEditor.scattering.value = material.scattering * 1000;
document.materialEditor.scattering_value.value = material.scattering;
document.materialEditor.unlit.checked = material.unlit;
document.materialEditor.albedoMap.value = material.albedoMap;
document.materialEditor.metallicMap.value = material.metallicMap;
document.materialEditor.roughnessMap.value = material.roughnessMap;
document.materialEditor.normalMap.value = material.normalMap;
document.materialEditor.opacityMap.value = material.opacityMap;
document.materialEditor.opacityCutoff.value = material.opacityCutoff * 1000;
document.materialEditor.opacityCutoff_value.value = material.opacityCutoff;
document.materialEditor.emissiveMap.value = material.emissiveMap;
document.materialEditor.scatteringMap.value = material.scatteringMap;
document.materialEditor.occlusionMap.value = material.occlusionMap;
document.materialEditor.cullFaceMode.value = material.cullFaceMode;
document.materialEditor.defaultFallthrough.value = material.defaultFallthrough;
}
function save( attribute, valueContainer) {
if (attribute === "metallic" || attribute === "roughness" || attribute === "opacity" || attribute === "opacityCutoff" || attribute === "scattering" ) {
material[attribute] = valueContainer.value/1000;
} else {
if (attribute === "bloom") {
material[attribute] = valueContainer.value/100;
} else {
if (attribute === "unlit") {
material[attribute] = valueContainer.checked;
} else {
if (attribute === "defaultFallthrough") {
material[attribute] = valueContainer.checked;
} else {
material[attribute] = valueContainer.value;
}
}
}
}
document.materialEditor.metallic_value.value = (document.materialEditor.metallic.value/1000);
document.materialEditor.roughness_value.value = (document.materialEditor.roughness.value/1000);
document.materialEditor.opacity_value.value = (document.materialEditor.opacity.value/1000);
document.materialEditor.opacityCutoff_value.value = (document.materialEditor.opacityCutoff.value/1000);
document.materialEditor.bloom_value.value = (document.materialEditor.bloom.value/100);
document.materialEditor.scattering_value.value = (document.materialEditor.scattering.value/1000);
generateMaterialJSON();
}
function hexToRgb(str, factor) {
// Note to user, for normal color, used a factor of 1.
if ( /^#([0-9a-f]{3}|[0-9a-f]{6})$/ig.test(str) ) {
var hex = str.substr(1);
hex = hex.length == 3 ? hex.replace(/(.)/g, '$1$1') : hex;
var rgb = parseInt(hex, 16);
var r = (rgb >> 16) & 255;
var g = (rgb >> 8) & 255;
var b = rgb & 255;
return "[" + (r/255*factor) + ", " + (g/255*factor) +", " + (b/255*factor) + "]";
}
return false;
}
function generateMaterialJSON() {
var materialData = "";
var fstMaterialData = "";
materialData += '{' + "\n";
materialData += ' "materialVersion": 1,' + "\n";
materialData += ' "materials": [' + "\n";
materialData += ' {' + "\n";
fstMaterialData += '{"mat::' + material.name.escapeJSON() + '": {"materials":[{ "name": "' + material.name.escapeJSON() + '"';
if (material.name !== "") {
materialData += ' "name": "' + material.name.escapeJSON() + '",' + "\n";
}
materialData += ' "albedo": ' + hexToRgb(material.albedo, 1) + ',' + "\n";
fstMaterialData += ', "albedo": ' + hexToRgb(material.albedo, 1);
if (material.metallicMap === "") {
materialData += ' "metallic": ' + material.metallic + ',' + "\n";
fstMaterialData += ', "metallic": ' + material.metallic;
}
if (material.roughnessMap === "" && material.roughness !== 1.0) {
materialData += ' "roughness": ' + material.roughness + ',' + "\n";
fstMaterialData += ', "roughness": ' + material.roughness;
}
if (material.opacityMap === "DO NOT USE" && material.opacity !== 1.0) {
materialData += ' "opacity": ' + material.opacity + ',' + "\n";
fstMaterialData += ', "opacity": ' + material.opacity;
}
if (material.emissive !== "#000000") {
materialData += ' "emissive": ' + hexToRgb(material.emissive, material.bloom) + ',' + "\n";
fstMaterialData += ', "emissive": ' + hexToRgb(material.emissive, material.bloom);
}
if (material.scatteringMap === "" && material.scattering !== 0) {
materialData += ' "scattering": ' + material.scattering + ',' + "\n";
fstMaterialData += ', "scattering": ' + material.scattering;
}
if (material.unlit === true) {
materialData += ' "unlit": ' + material.unlit + ',' + "\n";
fstMaterialData += ', "unlit": ' + material.unlit;
}
if (material.normalMap !== "") {
materialData += ' "normalMap": "' + material.normalMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "normalMap": "' + material.normalMap.escapeJSON() + '"';
}
if (material.albedoMap !== "") {
materialData += ' "albedoMap": "' + material.albedoMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "albedoMap": "' + material.albedoMap.escapeJSON() + '"';
}
if (material.metallicMap !== "") {
materialData += ' "metallicMap": "' + material.metallicMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "metallicMap": "' + material.metallicMap.escapeJSON() + '"';
}
if (material.roughnessMap !== "") {
materialData += ' "roughnessMap": "' + material.roughnessMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "roughnessMap": "' + material.roughnessMap.escapeJSON() + '"';
}
if (material.opacityMap === "OPACITY_MAP_MASK" || material.opacityMap === "OPACITY_MAP_BLEND") {
materialData += ' "opacityMap": "' + material.albedoMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "opacityMap": "' + material.albedoMap.escapeJSON() + '"';
materialData += ' "opacityMapMode": "' + material.opacityMap + '",' + "\n";
fstMaterialData += ', "opacityMapMode": "' + material.opacityMap + '"';
if (material.opacityMap === "OPACITY_MAP_MASK") {
materialData += ' "opacityCutoff": ' + material.opacityCutoff + ',' + "\n";
fstMaterialData += ', "opacityCutoff": ' + material.opacityCutoff;
}
}
if (material.emissiveMap !== "") {
materialData += ' "emissiveMap": "' + material.emissiveMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "emissiveMap": "' + material.emissiveMap.escapeJSON() + '"';
}
if (material.scatteringMap !== "") {
materialData += ' "scatteringMap": "' + material.scatteringMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "scatteringMap": "' + material.scatteringMap.escapeJSON() + '"';
}
if (material.occlusionMap !== "") {
materialData += ' "occlusionMap": "' + material.occlusionMap.escapeJSON() + '",' + "\n";
fstMaterialData += ', "occlusionMap": "' + material.occlusionMap.escapeJSON() + '"';
}
materialData += ' "cullFaceMode": "' + material.cullFaceMode + '",' + "\n";
fstMaterialData += ', "cullFaceMode": "' + material.cullFaceMode + '"';
if (material.defaultFallthrough === true) {
materialData += ' "defaultFallthrough": ' + material.defaultFallthrough + ',' + "\n";
fstMaterialData += ', "defaultFallthrough": ' + material.defaultFallthrough;
}
materialData += ' "model": "hifi_pbr"' + "\n";
fstMaterialData += ', "model": "hifi_pbr"';
materialData += ' }' + "\n";
materialData += ' ]' + "\n";
materialData += '}';
fstMaterialData += '}]}}';
document.materialEditor.output.value = materialData;
document.materialEditor.fstoutput.value = fstMaterialData;
var message = {
"channel": channel,
"action": "updateMaterialData",
"materialData": materialData,
"materialRecord": material
};
EventBridge.emitWebEvent(JSON.stringify(message));
}
String.prototype.escapeJSON = function() {
var result = "";
for (var i = 0; i < this.length; i++) {
var ch = this[i];
switch (ch)
{
case "\\": ch = "\\\\"; break;
//case "\'": ch = "\\'"; break;
case "\"": ch = '\\"'; break;
//case "\&": ch = "\\&"; break;
case "\t": ch = "\\t"; break;
case "\n": ch = "\\n"; break;
case "\r": ch = "\\r"; break;
case "\b": ch = "\\b"; break;
case "\f": ch = "\\f"; break;
case "\v": ch = "\\v"; break;
default: break;
}
result += ch;
}
return result;
};
var channel = "materialDataCreator.ak.overte";
function copyToClipboard(data) {
var $temp = $("<input>");
$("body").append($temp);
$temp.val(data).select();
document.execCommand("copy");
$temp.remove();
}
function demo(shape) {
var message = {
"channel": channel,
"action": "changeDemoShape",
"shape": shape
};
EventBridge.emitWebEvent(JSON.stringify(message));
}
function exportAsJson() {
var message = {
"channel": channel,
"action": "exportMaterialAsJson"
};
EventBridge.emitWebEvent(JSON.stringify(message));
}
function createMaterialEntity() {
var message = {
"channel": channel,
"action": "createMaterialEntity"
};
EventBridge.emitWebEvent(JSON.stringify(message));
}
function teleportToServerless() {
var message = {
"channel": channel,
"action": "teleportToServerless"
};
EventBridge.emitWebEvent(JSON.stringify(message));
}
function toggleDayNight() {
var message = {
"channel": channel,
"action": "toggleDayNight"
};
EventBridge.emitWebEvent(JSON.stringify(message));
}
</script>
</head>
<body>
<form name='materialEditor' id='materialEditor'>
<table style= 'width: 100%;'><tr><td style= 'width: 90%;'>
<div class='header'>
<table style= 'width: 100%;'><tr>
<td class='title' colspan='10'>MATERIAL DATA CREATOR<br>&nbsp;</td>
<td style= 'width: 10%; vertical-align: top;'><a href='#' onclick='helpOn();'><img src="images/help.png"></a></td>
</tr><tr>
<td style= 'width: 10%;'><a href='#' onclick='demo("cube");'><img class='demo' src="images/demo_cube.png"></a></td>
<td style= 'width: 10%;'><a href='#' onclick='demo("sphere");'><img class='demo' src="images/demo_sphere.png"></a></td>
<td style= 'width: 10%;'><a href='#' onclick='demo("teapot");'><img class='demo' src="images/demo_teapot.png"></a></td>
<td style= 'width: 10%;'><a href='#' onclick='demo("brand");'><img class='demo' src="images/demo_brand.png"></a></td>
<td style= 'width: 5%;'>&nbsp;</td>
<td style= 'width: 10%;'><a href='#' onclick='teleportToServerless();'><img class='studio' src="images/studio.png"></a></td>
<td style= 'width: 10%;'><a href='#' onclick='toggleDayNight();'><img class='studio' src="images/toggle_day_night.png"></a></td>
<td style= 'width: 5%;'>&nbsp;</td>
<td style= 'width: 10%;'><a href='#' onclick='resetMaterial();'><img class='reset' src="images/reset.png"></a></td>
<td style= 'width: 10%;'><a href='#' onclick='exportAsJson();'><img class='save' src="images/save_as_json.png"></a></td>
<td style= 'width: 10%;'><a href='#' onclick='createMaterialEntity();'><img class='save' src="images/create_material_entity.png"></a></td>
</tr></table>
</div>
<div class='info'>
<table style= 'width: 100%;'><tr><td>Name:</td><td style= 'width: 100%;'><input name = 'name' type = 'text' style= 'width: 100%;' oninput="save('name', this);"></td></tr></table>
</div>
<div class='group'>
<font class='label'>Albedo (Color):</font> <input name = 'albedo' type = 'text' value="#ffffff"><br>
<font class='label'>Albedo Map (RGB) URL:</font> <input name = 'albedoMap' type = 'text' style= 'width:100%;' oninput="save('albedoMap', this);"><br>
<font class = 'Explain'>The Albedo (Color) can be used to tint the texture of the Albedo Map.</font>
</div>
<div class='group'>
<font class='label'>Metallic:</font> <input name = 'metallic_value' readonly type = 'text' size = '5'><br>
<input type="range" style="width:100%;" min="1" max="1000" value="1" class="slider" name = 'metallic' id = 'metallic' oninput="save('metallic', this); document.materialEditor.metallic_value.value = (this.value/1000);"><br>
<table style='width:100%'><tr><td style='width: 15%; text-align: left;'><font class = 'Explain'>|&lt; Nonmetal</font></td><td style='width: 15%; text-align: left;'><font class = 'Explain'>| Hair</font></td><td style='width: 60%; text-align: left;'><font class = 'Explain'>| Chitin</font></td><td style='width: 10%; text-align: right;'><font class = 'Explain'>Metal &gt;|</font></td></tr></table>
<font class='label'>Metallic Map (Grayscale) URL:</font> <input name = 'metallicMap' type = 'text' style= 'width:100%;' oninput="save('metallicMap', this);">
</div>
<div class='group'>
<font class='label'>Roughness:</font> <input name = 'roughness_value' readonly type = 'text' size = '5'><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'roughness' id = 'roughness' oninput="save('roughness', this); document.materialEditor.roughness_value.value = (this.value/1000);"><br>
<table style='width:100%'><tr><td style='width: 50%; text-align: left;'><font class = 'Explain'>|&lt; Glossy, polished, lustrous</font></td><td style='width: 50%; text-align: right;'><font class = 'Explain'>Unpolished, mat, rough &gt;|</font></td></tr></table>
<font class='label'>Roughness Map (Grayscale) URL:</font> <input name = 'roughnessMap' type = 'text' style= 'width:100%;' oninput="save('roughnessMap', this);">
</div>
<div class='group'>
<font class='label'>Normal Map URL:</font> <input name = 'normalMap' type = 'text' style= 'width:100%;' oninput="save('normalMap', this);">
</div>
<div class='group'>
<font class='label'>Opacity:</font> <input name = 'opacity_value' readonly type = 'text' size = '5'><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'opacity' id = 'opacity' oninput="save('opacity', this); document.materialEditor.opacity_value.value = (document.materialEditor.opacity.value/1000);"><br>
<table style='width:100%'><tr><td style='width: 50%; text-align: left;'><font class = 'Explain'>|&lt; Transparent</font></td><td style='width: 50%; text-align: right;'><font class = 'Explain'>Opaque &gt;|</font></td></tr></table>
<br>
<font class='label'>Opacity Map Mode:</font><br>
<input type="radio" checked name = 'opacityMap' value = 'DO NOT USE' oninput="save('opacityMap', this);">Do not used&nbsp;&nbsp;&nbsp;
<input type="radio" name = 'opacityMap' value = 'OPACITY_MAP_MASK' oninput="save('opacityMap', this);">Cut off mask&nbsp;&nbsp;&nbsp;
<input type="radio" name = 'opacityMap' value = 'OPACITY_MAP_BLEND' oninput="save('opacityMap', this);">Blend<br>
<font class='Explain'>Note: For an opacity map, the alpha layer of the Albedo Map will be used. 'Blend' mode will used the alpha value to determine the opacity of a pixel. 'Cut off mask' mode will use the 'Cut off threshold' to determine if a pixel will be opaque or transparent, based on the alpha value from the map.</font><br><br>
<font class='label'>Cut Off Threshold:</font> <input name = 'opacityCutoff_value' readonly type = 'text' size = '5'><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'opacityCutoff' id = 'opacityCutoff' oninput="save('opacityCutoff', this); document.materialEditor.opacityCutoff_value.value = (document.materialEditor.opacityCutoff.value/1000);"><br>
<table style='width:100%'><tr><td style='width: 50%; text-align: left;'><font class = 'Explain'>|&lt; Transparent</font></td><td style='width: 50%; text-align: right;'><font class = 'Explain'>Opaque &gt;|</font></td></tr></table>
</div>
<div class='group'>
<table style="width:100%;"><tr><td><font class='label'>Emissive:</font> <input name = 'emissive' type = 'text' value = '#000000'>
</td><td>
<font class='label'>Unlit:</font> <input type="checkbox" name = 'unlit' oninput="save('unlit', this);">
</td></tr></table>
<font class='label'>Bloom Factor:</font> <input name = 'bloom_value' readonly type = 'text' size = '5'><br>
<input type="range" style="width:100%;" min="100" max="900" value="100" class="slider" name = 'bloom' id = 'bloom' oninput="save('bloom', this); document.materialEditor.bloom_value.value = (this.value/100);"><br>
<font class='label'>Emissive Map (RGB) URL:</font> <input name = 'emissiveMap' type = 'text' style= 'width:100%;' oninput="save('emissiveMap', this);">
</div>
<div class='group'>
<font class='label'>Scattering:</font> <input name = 'scattering_value' readonly type = 'text' size = '5'><br>
<input type="range" style="width:100%;" min="0" max="1000" value="0" class="slider" name = 'scattering' id = 'scattering' oninput="save('scattering', this); document.materialEditor.scattering_value.value = (this.value/1000);"><br>
<font class='label'>Scattering Map (Grayscale) URL:</font> <input name = 'scatteringMap' type = 'text' style= 'width:100%;' oninput="save('scatteringMap', this);">
</div>
<div class='group'>
<font class='label'>Occlusion Map (Grayscale) URL:</font> <input name = 'occlusionMap' type = 'text' style= 'width:100%;' oninput="save('occlusionMap', this);">
</div>
<div class='group'>
<font class='label'>Material displayed on surface: </font><br>
<input type="radio" checked name = 'cullFaceMode' value = 'CULL_BACK' oninput="save('cullFaceMode', this);">Outside&nbsp;&nbsp;&nbsp;
<input type="radio" name = 'cullFaceMode' value = 'CULL_FRONT' oninput="save('cullFaceMode', this);">Inside&nbsp;&nbsp;&nbsp;
<input type="radio" name = 'cullFaceMode' value = 'CULL_NONE' oninput="save('cullFaceMode', this);">Both<br>
</div>
<div class='group'>
<font class='label'>Keep other existing material's properties: </font><br>
<font class='label'>defaultFallthrough:</font> <input type="checkbox" name = 'defaultFallthrough' oninput="save('defaultFallthrough', this);">
</div>
<input type='button' class = 'copybtn' name='copy' value = 'Copy' onclick='copyToClipboard(document.materialEditor.output.value);'><br>
<textarea name='output' id='output' rows = '21' class='output'></textarea>
<br><br>
<input type='button' class = 'copybtn' name='copy-fst' value = 'Copy for .fst materialMap array' onclick='copyToClipboard(document.materialEditor.fstoutput.value);'><br>
<textarea name='fstoutput' id='fstoutput' rows = '6' class='output'></textarea>
</td><td style=' background-image: url("images/trottoire.png"); background-repeat: repeat;'>&nbsp;</td></tr></table>
</form>
<script>
//Color Pickers functions
var picker = new CP(document.materialEditor.albedo);
picker.self.classList.add('no-alpha');
picker.on('change', function(r, g, b) {
this.source.value = this.color(r, g, b, 1);
this.source.style.backgroundColor = this.color(r, g, b, 1);
this.source.style.color = this.color(r, g, b, 1);
material.albedo = this.color(r, g, b, 1);
generateMaterialJSON();
});
var pickerEmissive = new CP(document.materialEditor.emissive);
pickerEmissive.self.classList.add('no-alpha');
pickerEmissive.on('change', function(r, g, b) {
this.source.value = this.color(r, g, b, 1);
this.source.style.backgroundColor = this.color(r, g, b, 1);
this.source.style.color = this.color(r, g, b, 1);
material.emissive = this.color(r, g, b, 1);
generateMaterialJSON();
});
EventBridge.scriptEventReceived.connect(function (message) {
var messageObj = JSON.parse(message);
if (messageObj.channel === channel) {
if (messageObj.action === "initializeMaterial") {
if (messageObj.material !== undefined) {
material = messageObj.material;
}
loadMaterial();
generateMaterialJSON();
}
}
});
function helpOn() {
document.getElementById("helpOverlay").style.display = "block";
}
function helpOff() {
document.getElementById("helpOverlay").style.display = "none";
}
</script>
<div id="helpOverlay" onclick="helpOff();">
<div style='text-align:right; font-size:14px; color:#999999; width:95%;'>&#10006;</div><br><br>
<div style='width:95%;'>
<img class='demo' src="images/demo_cube.png"> <img class='demo' src="images/demo_sphere.png">
<img class='demo' src="images/demo_teapot.png"> <img class='demo' src="images/demo_brand.png"><br>
You can use these buttons to change the shape of the demonstration entity.
<br><hr>
<img class='studio' src="images/studio.png"><br>
You can use this button to teleport yourself to a serverless environment preconfigured with a consistent "ambientLight".
<br><hr>
<img class='studio' src="images/toggle_day_night.png"><br>
You can use this button to toggle between day and night in the serverless preconfigured environment.
<br><hr>
<img class='reset' src="images/reset.png"><br>
This button resets the material data to a new blank material.
<br><hr>
<img class='save' src="images/save_as_json.png"><br>
You can use this button to export the material data as a .json file. Such a .json file can be used in a material entity. It's mainly useful when you plan to reuse the same material for many entities. Using a .json file can simplify the update of a material used on many entities.
<br><hr>
<img class='save' src="images/create_material_entity.png"><br>
This button generates a Material entity from the specified material data. (Ready to be used.)
<br><hr>
</div>
</div>
</body>
</html>