Merge pull request #14745 from sabrina-shanman/material-inspector

(case 20748) Add material inspector to Luci.js
This commit is contained in:
Shannon Romano 2019-01-25 17:35:07 -08:00 committed by GitHub
commit 1584311689
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 257 additions and 10 deletions

View file

@ -14,7 +14,6 @@ import QtQuick.Layouts 1.3
import stylesUit 1.0
import controlsUit 1.0 as HifiControls
import "configSlider"
import "../lib/jet/qml" as Jet
Rectangle {
HifiConstants { id: hifi;}
@ -249,12 +248,6 @@ Rectangle {
checked: render.mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"]
onCheckedChanged: { render.mainViewTask.getConfig("DrawOverlayHUDOpaqueBounds")["enabled"] = checked }
}
HifiControls.CheckBox {
boxSize: 20
text: "Transparents in HUD"
checked: render.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"]
onCheckedChanged: { render.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] = checked }
}
}
Column {
@ -277,6 +270,12 @@ Rectangle {
checked: render.mainViewTask.getConfig("DrawZones")["enabled"]
onCheckedChanged: { render.mainViewTask.getConfig("ZoneRenderer")["enabled"] = checked; render.mainViewTask.getConfig("DrawZones")["enabled"] = checked; }
}
HifiControls.CheckBox {
boxSize: 20
text: "Transparents in HUD"
checked: render.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"]
onCheckedChanged: { render.mainViewTask.getConfig("DrawOverlayHUDTransparentBounds")["enabled"] = checked }
}
}
}
Separator {}
@ -303,5 +302,13 @@ Rectangle {
}
}
}
Row {
HifiControls.Button {
text: "Material"
onClicked: {
sendToScript({method: "openMaterialInspectorView"});
}
}
}
}
}

View file

@ -12,6 +12,8 @@
(function() {
var AppUi = Script.require('appUi');
var MaterialInspector = Script.require('./materialInspector.js');
var moveDebugCursor = false;
var onMousePressEvent = function (e) {
@ -41,11 +43,12 @@
Render.getConfig("RenderMainView").getConfig("DebugDeferredBuffer").size = { x: nx, y: ny, z: 1.0, w: 1.0 };
}
function Page(title, qmlurl, width, height) {
function Page(title, qmlurl, width, height, handleWindowFunc) {
this.title = title;
this.qml = qmlurl;
this.width = width;
this.height = height;
this.handleWindowFunc = handleWindowFunc;
this.window;
@ -73,8 +76,10 @@
presentationMode: Desktop.PresentationMode.NATIVE,
size: {x: this.width, y: this.height}
});
this.handleWindowFunc(this.window);
this.window.closed.connect(function () {
that.killView();
this.handleWindowFunc(undefined);
});
}
};
@ -84,8 +89,12 @@
this._pages = {};
};
Pages.prototype.addPage = function (command, title, qmlurl, width, height) {
this._pages[command] = new Page(title, qmlurl, width, height);
Pages.prototype.addPage = function (command, title, qmlurl, width, height, handleWindowFunc) {
if (handleWindowFunc === undefined) {
// Workaround for bad linter
handleWindowFunc = function(window){};
}
this._pages[command] = new Page(title, qmlurl, width, height, handleWindowFunc);
};
Pages.prototype.open = function (command) {
@ -110,6 +119,7 @@
pages.addPage('openEngineView', 'Render Engine', 'engineInspector.qml', 300, 400);
pages.addPage('openEngineLODView', 'Render LOD', 'lod.qml', 300, 400);
pages.addPage('openCullInspectorView', 'Cull Inspector', 'culling.qml', 300, 400);
pages.addPage('openMaterialInspectorView', 'Material Inspector', 'materialInspector.qml', 300, 400, MaterialInspector.setWindow);
function fromQml(message) {
if (pages.open(message.method)) {

View file

@ -0,0 +1,165 @@
//
// 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
};

View file

@ -0,0 +1,65 @@
//
// materialInspector.qml
//
// Created by Sabrina Shanman on 2019-01-16
// 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
//
import QtQuick 2.7
import QtQuick.Controls 2.3 as Original
import QtQuick.Layouts 1.3
import stylesUit 1.0
import controlsUit 1.0 as HifiControls
Rectangle {
HifiConstants { id: hifi;}
color: Qt.rgba(hifi.colors.baseGray.r, hifi.colors.baseGray.g, hifi.colors.baseGray.b, 0.8);
id: root;
function fromScript(message) {
switch (message.method) {
case "setObjectInfo":
entityIDInfo.text = "Type: " + message.params.type + "\nID: " + message.params.id + "\nMesh Part: " + message.params.meshPart;
break;
case "setMaterialJSON":
materialJSONText.text = message.params.materialJSONText;
break;
}
}
Rectangle {
id: entityIDContainer
height: 52
width: root.width
color: Qt.rgba(root.color.r * 0.7, root.color.g * 0.7, root.color.b * 0.7, 0.8);
TextEdit {
id: entityIDInfo
text: "Type: Unknown\nID: None\nMesh Part: Unknown"
font.pointSize: 9
color: "#FFFFFF"
readOnly: true
selectByMouse: true
}
}
Original.ScrollView {
anchors.top: entityIDContainer.bottom
height: root.height - entityIDContainer.height
width: root.width
clip: true
Original.ScrollBar.horizontal.policy: Original.ScrollBar.AlwaysOff
TextEdit {
id: materialJSONText
text: "Click an object to get material JSON"
width: root.width
font.pointSize: 10
color: "#FFFFFF"
readOnly: true
selectByMouse: true
wrapMode: Text.WordWrap
}
}
}