// // materialInspector.js // // Created by Sabrina Shanman on 2019-01-17 // Copyright 2019 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html // "use strict"; var activeWindow; // Adapted from Samuel G's material painting script function getTopMaterial(multiMaterial) { // For non-models: multiMaterial[0] will be the top material // For models, multiMaterial[0] is the base material, and multiMaterial[1] is the highest priority applied material if (multiMaterial.length > 1) { if (multiMaterial[1].priority > multiMaterial[0].priority) { return multiMaterial[1]; } } return multiMaterial[0]; } function updateMaterial(type, id, meshPart) { var mesh = Graphics.getModel(id); var meshPartString = meshPart.toString(); if (!mesh) { return; } var materials = mesh.materialLayers; if (!materials[meshPartString] || materials[meshPartString].length <= 0) { return; } var topMaterial = getTopMaterial(materials[meshPartString]); var materialJSONText = JSON.stringify({ materialVersion: 1, materials: topMaterial.material }, null, 2); toQml({method: "setObjectInfo", params: {id: id, type: type, meshPart: meshPart}}); toQml({method: "setMaterialJSON", params: {materialJSONText: materialJSONText}}); } // Adapted from Samuel G's material painting script function getHoveredMaterialLocation(event) { var pickRay = Camera.computePickRay(event.x, event.y); var closest; var id; var type = "Entity"; var avatar = AvatarManager.findRayIntersection(pickRay); var entity = Entities.findRayIntersection(pickRay, true); var overlay = Overlays.findRayIntersection(pickRay, true); closest = entity; id = entity.entityID; if (avatar.intersects && avatar.distance < closest.distance) { closest = avatar; id = avatar.avatarID; type = "Avatar"; } else if (overlay.intersects && overlay.distance < closest.distance) { closest = overlay; id = overlay.overlayID; type = "Overlay"; } if (closest.intersects) { return { type: type, id: id, meshPart: (closest.extraInfo.shapeID ? closest.extraInfo.shapeID : 0) }; } else { return undefined; } } var pressedID; var pressedMeshPart; function mousePressEvent(event) { if (!event.isLeftButton) { return; } var result = getHoveredMaterialLocation(event); if (result !== undefined) { pressedID = result.id; pressedMeshPart = result.meshPart; } } function mouseReleaseEvent(event) { if (!event.isLeftButton) { return; } var result = getHoveredMaterialLocation(event); if (result !== undefined && result.id === pressedID && result.meshPart === pressedMeshPart) { updateMaterial(result.type, result.id, result.meshPart); setSelectedObject(result.id, result.type); } } function killWindow() { setWindow(undefined); } function toQml(message) { if (activeWindow === undefined) { return; // Shouldn't happen } activeWindow.sendToQml(message); } function fromQml(message) { // No cases currently } var SELECT_LIST = "luci_materialInspector_SelectionList"; Selection.enableListHighlight(SELECT_LIST, { outlineUnoccludedColor: { red: 255, green: 255, blue: 255 } }); function setSelectedObject(id, type) { Selection.clearSelectedItemsList(SELECT_LIST); if (id !== undefined && !Uuid.isNull(id)) { Selection.addToSelectedItemsList(SELECT_LIST, type.toLowerCase(), id); } } function setWindow(window) { if (activeWindow !== undefined) { setSelectedObject(Uuid.NULL, ""); activeWindow.closed.disconnect(killWindow); activeWindow.fromQml.disconnect(fromQml); Controller.mousePressEvent.disconnect(mousePressEvent); Controller.mouseReleaseEvent.disconnect(mouseReleaseEvent); activeWindow.close(); } if (window !== undefined) { window.closed.connect(killWindow); window.fromQml.connect(fromQml); Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); } activeWindow = window; } function cleanup() { setWindow(undefined); Selection.disableListHighlight(SELECT_LIST); } Script.scriptEnding.connect(cleanup); module.exports = { setWindow: setWindow };