Merge pull request #15325 from dback2/dynamicMaterialTargetProperties

Case 20738: add dynamic multiselect for material target property
This commit is contained in:
Ryan Huffman 2019-04-05 17:55:26 -07:00 committed by GitHub
commit aff80dec26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 218 additions and 66 deletions

View file

@ -2522,7 +2522,19 @@ var PropertiesTool = function (opts) {
type: 'propertyRangeReply',
propertyRanges: propertyRanges,
});
}
} else if (data.type === "materialTargetRequest") {
var properties = Entities.getEntityProperties(data.entityID, ["type", "parentID"]);
var parentModel = properties.parentID !== Uuid.NULL &&
Entities.getEntityProperties(properties.parentID, ["type"]).type === "Model";
var parentModelData;
if (properties.type === "Material" && parentModel) {
parentModelData = Graphics.getModel(properties.parentID);
}
emitScriptEvent({
type: 'materialTargetReply',
materialTargetData: parentModelData,
});
}
};
HMD.displayModeChanged.connect(function() {

View file

@ -861,10 +861,16 @@ span.indented {
.multiselect-options input[type=checkbox]:checked + label {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg==');
}
.multiselect-options input[type=checkbox]:checked + label:hover {
.multiselect-options input[type=checkbox]:checked + label:hover {
background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACwAAAAsCAYAAAAehFoBAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAB3RJTUUH4goSADMveELP9QAAABl0RVh0Q29tbWVudABDcmVhdGVkIHdpdGggR0lNUFeBDhcAAAIqSURBVFjD7ZmxkqowFIb/7GwJPfT6APZib+9QC33o4QGghz70vIC9sfcBsE966bPNWlxnlQTDRWc4JUT4hpPz5SQSAAofFF/4sJiBx47v+wun04m8E+B6vVbzlJiBZ2CLIYRQQgj1EcBCCEUpRRRF4Jyrtwa+Xq+glEJKia7rkKYpGGPqbYHzPFdSyn+uMcZ6oScBZowpzvmje0jTVHVd9x7ATdMoxtjTMZxzUErV5MDn81mVZak1No7jab+wEEKlaaoNGwQBmQz4pq9H8/IeNo5jMmnRpWmKeyP8FZvN5insfwEuy1JdLpfecb7vI8uy3tb2Szelu91ONU1jtP9jjKmmabRgq6qC4zh2VrpbSsuy1FqNdPUFAK7roqoqeJ6ntXH4Mk1pn9gBoG1bbX1lWaYN2wv8KKWcc+z3+z+7LFv6MgY+Ho9PUyqlBKUUbduqe33pGKFPX0bAQgiV53nvj6WUiKIIt2K0qS/tXTMAEELguq6W6H/nOQ6Hg1V9GX1hz/NIXdckCALtB7Vta1VfxnPYcRwURUEeNSGmYaqvwVqL45gkSfIysKm+Xlo4wjAkdV3D9/1BLxmir5d7ieVySaqqMoYOw3CwEV5ufkyLcbVaIUkSq2d1xt2abjH6vo+iKKwfLA5uL58Vow19jdIPPyrGoiisGGGUBv6+GJMkwWKxGO2M+dvGQ36LEZxztd1uRz0Qt7ZFchwHY8NOelQ1NAjm/+lm4M8G/gH2zx33BSr7jAAAAABJRU5ErkJggg==');
}
.dynamic-multiselect {
position: relative;
top: 6px;
padding-bottom: 6px;
}
div.refresh {
box-sizing: border-box;
padding-right: 44px;

View file

@ -701,23 +701,10 @@ const GROUPS = [
propertyID: "materialData",
},
{
label: "Select Submesh",
type: "bool",
propertyID: "selectSubmesh",
},
{
label: "Submesh to Replace",
type: "number-draggable",
min: 0,
step: 1,
propertyID: "submeshToReplace",
indentedLabel: true,
},
{
label: "Material to Replace",
type: "string",
propertyID: "materialNameToReplace",
indentedLabel: true,
label: "Material Target",
type: "dynamic-multiselect",
propertyUpdate: materialTargetPropertyUpdate,
propertyID: "parentMaterialName",
},
{
label: "Priority",
@ -1639,6 +1626,8 @@ function getPropertyInputElement(propertyID) {
return { red: property.elNumberR.elInput, green: property.elNumberG.elInput, blue: property.elNumberB.elInput };
case 'icon':
return property.elLabel;
case 'dynamic-multiselect':
return property.elDivOptions;
default:
return undefined;
}
@ -1761,6 +1750,10 @@ function resetProperties() {
property.elInput.imageLoad(property.elInput.value);
break;
}
case 'dynamic-multiselect': {
resetDynamicMultiselectProperty(property.elDivOptions);
break;
}
}
let showPropertyRules = properties[propertyID].showPropertyRules;
@ -2437,7 +2430,7 @@ function createTextureProperty(property, elProperty) {
return elResult;
}
function createButtonsProperty(property, elProperty, elLabel) {
function createButtonsProperty(property, elProperty) {
let elementID = property.elementID;
let propertyData = property.data;
@ -2450,6 +2443,43 @@ function createButtonsProperty(property, elProperty, elLabel) {
return elProperty;
}
function createDynamicMultiselectProperty(property, elProperty) {
let elementID = property.elementID;
let propertyData = property.data;
elProperty.className = "dynamic-multiselect";
let elDivOptions = document.createElement('div');
elDivOptions.setAttribute("id", elementID + "-options");
elDivOptions.style = "overflow-y:scroll;max-height:160px;"
let elDivButtons = document.createElement('div');
elDivButtons.setAttribute("id", elDivOptions.getAttribute("id") + "-buttons");
let elLabel = document.createElement('label');
elLabel.innerText = "No Options";
elDivOptions.appendChild(elLabel);
let buttons = [ { id: "selectAll", label: "Select All", className: "black", onClick: selectAllMaterialTarget },
{ id: "clearAll", label: "Clear All", className: "black", onClick: clearAllMaterialTarget } ];
addButtons(elDivButtons, elementID, buttons, false);
elProperty.appendChild(elDivOptions);
elProperty.appendChild(elDivButtons);
return elDivOptions;
}
function resetDynamicMultiselectProperty(elDivOptions) {
let elInputs = elDivOptions.getElementsByTagName("input");
while (elInputs.length > 0) {
let elDivOption = elInputs[0].parentNode;
elDivOption.parentNode.removeChild(elDivOption);
}
elDivOptions.firstChild.style.display = "block"; // show "No Options" text
elDivOptions.parentNode.lastChild.style.display = "none"; // hide Select/Clear all buttons
}
function createTupleNumberInput(property, subLabel) {
let propertyElementID = property.elementID;
let propertyData = property.data;
@ -2573,6 +2603,10 @@ function createProperty(propertyData, propertyElementID, propertyName, propertyI
property.elProperty = createButtonsProperty(property, elProperty);
break;
}
case 'dynamic-multiselect': {
property.elDivOptions = createDynamicMultiselectProperty(property, elProperty);
break;
}
case 'placeholder':
case 'sub-header': {
break;
@ -3109,7 +3143,7 @@ function setDropdownValue(event) {
/**
* TEXTAREA / PARENT MATERIAL NAME FUNCTIONS
* TEXTAREA FUNCTIONS
*/
function setTextareaScrolling(element) {
@ -3117,16 +3151,140 @@ function setTextareaScrolling(element) {
element.setAttribute("scrolling", isScrolling ? "true" : "false");
}
function showParentMaterialNameBox(number, elNumber, elString) {
if (number) {
$('#property-submeshToReplace').parent().show();
$('#property-materialNameToReplace').parent().hide();
elString.value = "";
} else {
$('#property-materialNameToReplace').parent().show();
$('#property-submeshToReplace').parent().hide();
elNumber.value = 0;
/**
* MATERIAL TARGET FUNCTIONS
*/
function setMaterialTargetData(materialTargetData) {
let elDivOptions = getPropertyInputElement("parentMaterialName");
resetDynamicMultiselectProperty(elDivOptions);
if (materialTargetData === undefined) {
return;
}
elDivOptions.firstChild.style.display = "none"; // hide "No Options" text
elDivOptions.parentNode.lastChild.style.display = "block"; // show Select/Clear all buttons
let numMeshes = materialTargetData.numMeshes;
for (let i = 0; i < numMeshes; ++i) {
addMaterialTarget(elDivOptions, i, false);
}
let materialNames = materialTargetData.materialNames;
let materialNamesAdded = [];
for (let i = 0; i < materialNames.length; ++i) {
let materialName = materialNames[i];
if (materialNamesAdded.indexOf(materialName) === -1) {
addMaterialTarget(elDivOptions, materialName, true);
materialNamesAdded.push(materialName);
}
}
materialTargetPropertyUpdate(elDivOptions.propertyValue);
}
function addMaterialTarget(elDivOptions, targetID, isMaterialName) {
let elementID = elDivOptions.getAttribute("id");
elementID += isMaterialName ? "-material-" : "-mesh-";
elementID += targetID;
let elDiv = document.createElement('div');
elDiv.className = "materialTargetDiv";
elDiv.onclick = onToggleMaterialTarget;
elDivOptions.appendChild(elDiv);
let elInput = document.createElement('input');
elInput.className = "materialTargetInput";
elInput.setAttribute("type", "checkbox");
elInput.setAttribute("id", elementID);
elInput.setAttribute("targetID", targetID);
elInput.setAttribute("isMaterialName", isMaterialName);
elDiv.appendChild(elInput);
let elLabel = document.createElement('label');
elLabel.setAttribute("for", elementID);
elLabel.innerText = isMaterialName ? "Material " + targetID : "Mesh Index " + targetID;
elDiv.appendChild(elLabel);
return elDiv;
}
function onToggleMaterialTarget(event) {
let elTarget = event.target;
if (elTarget instanceof HTMLInputElement) {
sendMaterialTargetProperty();
}
event.stopPropagation();
}
function setAllMaterialTargetInputs(checked) {
let elDivOptions = getPropertyInputElement("parentMaterialName");
let elInputs = elDivOptions.getElementsByClassName("materialTargetInput");
for (let i = 0; i < elInputs.length; ++i) {
elInputs[i].checked = checked;
}
}
function selectAllMaterialTarget() {
setAllMaterialTargetInputs(true);
sendMaterialTargetProperty();
}
function clearAllMaterialTarget() {
setAllMaterialTargetInputs(false);
sendMaterialTargetProperty();
}
function sendMaterialTargetProperty() {
let elDivOptions = getPropertyInputElement("parentMaterialName");
let elInputs = elDivOptions.getElementsByClassName("materialTargetInput");
let materialTargetList = "";
for (let i = 0; i < elInputs.length; ++i) {
let elInput = elInputs[i];
if (elInput.checked) {
let targetID = elInput.getAttribute("targetID");
if (elInput.getAttribute("isMaterialName") === "true") {
materialTargetList += "mat::" + targetID + ",";
} else {
materialTargetList += targetID + ",";
}
}
}
if (materialTargetList !== "") {
materialTargetList = materialTargetList.substring(0, materialTargetList.length - 1);
materialTargetList = "[" + materialTargetList + "]";
}
updateProperty("parentMaterialName", materialTargetList, false);
}
function materialTargetPropertyUpdate(propertyValue) {
let elDivOptions = getPropertyInputElement("parentMaterialName");
let elInputs = elDivOptions.getElementsByClassName("materialTargetInput");
if (propertyValue.charAt(0) === '[') {
propertyValue = propertyValue.substring(1, propertyValue.length);
}
if (propertyValue.charAt(propertyValue.length - 1) === ']') {
propertyValue = propertyValue.substring(0, propertyValue.length - 1);
}
let materialTargets = propertyValue.split(",");
for (let i = 0; i < elInputs.length; ++i) {
let elInput = elInputs[i];
let targetID = elInput.getAttribute("targetID");
let materialTargetName = targetID;
if (elInput.getAttribute("isMaterialName") === "true") {
materialTargetName = "mat::" + targetID;
}
elInput.checked = materialTargets.indexOf(materialTargetName) >= 0;
}
elDivOptions.propertyValue = propertyValue;
}
@ -3555,6 +3713,12 @@ function loaded() {
property.elInput.imageLoad(property.elInput.value);
break;
}
case 'dynamic-multiselect': {
if (property.data.propertyUpdate) {
property.data.propertyUpdate(propertyValue);
}
break;
}
}
let showPropertyRules = property.showPropertyRules;
@ -3568,22 +3732,6 @@ function loaded() {
}
updateVisibleSpaceModeProperties();
if (selectedEntityProperties.type === "Material") {
let elParentMaterialNameString = getPropertyInputElement("materialNameToReplace");
let elParentMaterialNameNumber = getPropertyInputElement("submeshToReplace");
let elParentMaterialNameCheckbox = getPropertyInputElement("selectSubmesh");
let parentMaterialName = selectedEntityProperties.parentMaterialName;
if (parentMaterialName.startsWith(MATERIAL_PREFIX_STRING)) {
elParentMaterialNameString.value = parentMaterialName.replace(MATERIAL_PREFIX_STRING, "");
showParentMaterialNameBox(false, elParentMaterialNameNumber, elParentMaterialNameString);
elParentMaterialNameCheckbox.checked = false;
} else {
elParentMaterialNameNumber.value = parseInt(parentMaterialName);
showParentMaterialNameBox(true, elParentMaterialNameNumber, elParentMaterialNameString);
elParentMaterialNameCheckbox.checked = true;
}
}
let json = null;
try {
@ -3631,6 +3779,10 @@ function loaded() {
hideMaterialDataSaved();
}
if (hasSelectedEntityChanged && selectedEntityProperties.type === "Material") {
EventBridge.emitWebEvent(JSON.stringify({ type: 'materialTargetRequest', entityID: selectedEntityProperties.id }));
}
let activeElement = document.activeElement;
if (doSelectElement && typeof activeElement.select !== "undefined") {
activeElement.select();
@ -3680,6 +3832,8 @@ function loaded() {
}
}
}
} else if (data.type === 'materialTargetReply') {
setMaterialTargetData(data.materialTargetData);
}
});
@ -3749,26 +3903,6 @@ function loaded() {
elDiv.insertBefore(elMaterialDataEditor, elMaterialData);
elDiv.insertBefore(elMaterialDataEditorStatus, elMaterialData);
// Special Property Callbacks
let elParentMaterialNameString = getPropertyInputElement("materialNameToReplace");
let elParentMaterialNameNumber = getPropertyInputElement("submeshToReplace");
let elParentMaterialNameCheckbox = getPropertyInputElement("selectSubmesh");
elParentMaterialNameString.addEventListener('change', function () {
updateProperty("parentMaterialName", MATERIAL_PREFIX_STRING + this.value, false);
});
elParentMaterialNameNumber.addEventListener('change', function () {
updateProperty("parentMaterialName", this.value, false);
});
elParentMaterialNameCheckbox.addEventListener('change', function () {
if (this.checked) {
updateProperty("parentMaterialName", elParentMaterialNameNumber.value, false);
showParentMaterialNameBox(true, elParentMaterialNameNumber, elParentMaterialNameString);
} else {
updateProperty("parentMaterialName", MATERIAL_PREFIX_STRING + elParentMaterialNameString.value, false);
showParentMaterialNameBox(false, elParentMaterialNameNumber, elParentMaterialNameString);
}
});
// Collapsible sections
let elCollapsible = document.getElementsByClassName("collapse-icon");