mirror of
https://github.com/overte-org/overte.git
synced 2025-04-08 07:12:40 +02:00
Merge pull request #14696 from thoys/feat/create/showZonesInCreate
MS20292 - [CreateApp] Make it easier to see zones while you're editing them
This commit is contained in:
commit
c95b681092
5 changed files with 353 additions and 2 deletions
73
scripts/system/assets/images/icon-zone.svg
Normal file
73
scripts/system/assets/images/icon-zone.svg
Normal file
|
@ -0,0 +1,73 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
viewBox="0 0 512 512"
|
||||
style="enable-background:new 0 0 512 512;"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="icon-zone.svg"><metadata
|
||||
id="metadata4211"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs4209" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2560"
|
||||
inkscape:window-height="1377"
|
||||
id="namedview4207"
|
||||
showgrid="false"
|
||||
inkscape:zoom="2"
|
||||
inkscape:cx="228.01796"
|
||||
inkscape:cy="376.88605"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g4191" /><style
|
||||
type="text/css"
|
||||
id="style4189">
|
||||
.st0{fill:none;stroke:#000000;stroke-width:18;stroke-miterlimit:10;}
|
||||
.st1{fill:none;stroke:#000000;stroke-width:18;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
.st2{fill:none;stroke:#000000;stroke-width:19;stroke-linecap:round;stroke-miterlimit:10;}
|
||||
</style><g
|
||||
id="g4191"><path
|
||||
d="M 380.7,139.8 C 378,133.2 371.5,129 364.4,129 l -72.4,0 0,34 29.9,0 -162.9,163.1 0,-36.1 -36,0 0,79 0.006,0.024 c 0.1,2 0.5,4.1 1.3,5.9 C 127.00564,381.52397 134.7,386 141.8,386 l 83.2,0 0,-35 -40.8,0 161.8,-161.3 0,25.3 36.125,0.125 -0.19692,-62.65758 C 382.08839,148.14645 382.4,144 380.7,139.8 Z"
|
||||
id="path4193"
|
||||
style="fill:#333333;fill-opacity:1"
|
||||
inkscape:connector-curvature="0"
|
||||
sodipodi:nodetypes="cscccccccccscccccccc" /><path
|
||||
d="M338.4,437.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0 C348.1,459.3,338.4,449.6,338.4,437.6z M266.9,437.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0 c0,12-9.7,21.7-21.7,21.7l0,0C276.6,459.3,266.9,449.6,266.9,437.6z M195.4,437.6c0-12,9.7-21.7,21.7-21.7l0,0 c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C205.1,459.3,195.4,449.6,195.4,437.6z M123.9,437.6 c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C133.6,459.3,123.9,449.6,123.9,437.6z"
|
||||
id="path4195"
|
||||
style="fill:#333333;fill-opacity:1" /><path
|
||||
d="M74.1,459.3c-5.7,0-11.3-2.3-15.4-6.4c-4-4-6.4-9.6-6.4-15.3c0-5.7,2.3-11.3,6.4-15.3c4-4,9.6-6.4,15.4-6.4 c5.7,0,11.3,2.3,15.3,6.4c4,4,6.4,9.6,6.4,15.3c0,5.7-2.3,11.3-6.4,15.3C85.4,457,79.8,459.3,74.1,459.3z"
|
||||
id="path4197"
|
||||
style="fill:#333333;fill-opacity:1" /><path
|
||||
d="M52.4,366.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0 C62.1,387.8,52.4,378,52.4,366.1z M52.4,294.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7 l0,0C62.1,316.3,52.4,306.5,52.4,294.6z M52.4,223.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0 c0,12-9.7,21.7-21.7,21.7l0,0C62.1,244.8,52.4,235,52.4,223.1z M52.4,151.5c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7 l0,0c0,12-9.7,21.7-21.7,21.7l0,0C62.1,173.2,52.4,163.5,52.4,151.5z"
|
||||
id="path4199"
|
||||
style="fill:#333333;fill-opacity:1" /><path
|
||||
d="M338.4,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0 C348.1,101.7,338.4,92,338.4,80z M266.9,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0 C276.6,101.7,266.9,92,266.9,80z M195.4,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0 C205.1,101.7,195.4,92,195.4,80z M123.9,80c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0 C133.6,101.7,123.9,92,123.9,80z"
|
||||
id="path4201"
|
||||
style="fill:#333333;fill-opacity:1" /><path
|
||||
d="M431.6,101.7c-5.7,0-11.3-2.3-15.3-6.4c-4-4-6.4-9.6-6.4-15.3c0-5.7,2.3-11.3,6.4-15.3c4-4,9.6-6.4,15.3-6.4 s11.3,2.3,15.3,6.4c4,4,6.4,9.6,6.4,15.3c0,5.7-2.3,11.3-6.4,15.3C442.9,99.4,437.4,101.7,431.6,101.7z"
|
||||
id="path4203"
|
||||
style="fill:#333333;fill-opacity:1" /><path
|
||||
d="M409.9,366.1c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0 C419.7,387.8,409.9,378.1,409.9,366.1z M409.9,294.6c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0 c0,12-9.7,21.7-21.7,21.7l0,0C419.7,316.3,409.9,306.5,409.9,294.6z M409.9,223.1c0-12,9.7-21.7,21.7-21.7l0,0 c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C419.7,244.7,409.9,235,409.9,223.1z M409.9,151.5 c0-12,9.7-21.7,21.7-21.7l0,0c12,0,21.7,9.7,21.7,21.7l0,0c0,12-9.7,21.7-21.7,21.7l0,0C419.7,173.2,409.9,163.5,409.9,151.5z"
|
||||
id="path4205"
|
||||
style="fill:#333333;fill-opacity:1" /></g></svg>
|
After Width: | Height: | Size: 5.3 KiB |
13
scripts/system/assets/images/materials/GridPattern.json
Normal file
13
scripts/system/assets/images/materials/GridPattern.json
Normal file
|
@ -0,0 +1,13 @@
|
|||
{
|
||||
"materialVersion": 1,
|
||||
"materials": {
|
||||
"albedo": [
|
||||
0.0,
|
||||
0.0,
|
||||
7.0
|
||||
],
|
||||
"unlit": true,
|
||||
"opacity": 0.4,
|
||||
"albedoMap": "GridPattern.png"
|
||||
}
|
||||
}
|
BIN
scripts/system/assets/images/materials/GridPattern.png
Normal file
BIN
scripts/system/assets/images/materials/GridPattern.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
|
@ -82,13 +82,18 @@ var selectionManager = SelectionManager;
|
|||
var PARTICLE_SYSTEM_URL = Script.resolvePath("assets/images/icon-particles.svg");
|
||||
var POINT_LIGHT_URL = Script.resolvePath("assets/images/icon-point-light.svg");
|
||||
var SPOT_LIGHT_URL = Script.resolvePath("assets/images/icon-spot-light.svg");
|
||||
var ZONE_URL = Script.resolvePath("assets/images/icon-zone.svg");
|
||||
|
||||
var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect'], function(entityID) {
|
||||
var entityIconOverlayManager = new EntityIconOverlayManager(['Light', 'ParticleEffect', 'Zone'], function(entityID) {
|
||||
var properties = Entities.getEntityProperties(entityID, ['type', 'isSpotlight']);
|
||||
if (properties.type === 'Light') {
|
||||
return {
|
||||
url: properties.isSpotlight ? SPOT_LIGHT_URL : POINT_LIGHT_URL,
|
||||
};
|
||||
} else if (properties.type === 'Zone') {
|
||||
return {
|
||||
url: ZONE_URL,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
url: PARTICLE_SYSTEM_URL,
|
||||
|
@ -106,11 +111,15 @@ var gridTool = new GridTool({
|
|||
});
|
||||
gridTool.setVisible(false);
|
||||
|
||||
var EntityShapeVisualizer = Script.require('./modules/entityShapeVisualizer.js');
|
||||
var entityShapeVisualizer = new EntityShapeVisualizer(["Zone"]);
|
||||
|
||||
var entityListTool = new EntityListTool(shouldUseEditTabletApp);
|
||||
|
||||
selectionManager.addEventListener(function () {
|
||||
selectionDisplay.updateHandles();
|
||||
entityIconOverlayManager.updatePositions();
|
||||
entityShapeVisualizer.setEntities(selectionManager.selections);
|
||||
});
|
||||
|
||||
var DEGREES_TO_RADIANS = Math.PI / 180.0;
|
||||
|
@ -836,7 +845,7 @@ var toolBar = (function () {
|
|||
dialogWindow.fromQml.connect(fromQml);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
addButton("newModelButton", createNewEntityDialogButtonCallback("Model"));
|
||||
|
||||
|
@ -1492,6 +1501,7 @@ Script.scriptEnding.connect(function () {
|
|||
cleanupModelMenus();
|
||||
tooltip.cleanup();
|
||||
selectionDisplay.cleanup();
|
||||
entityShapeVisualizer.cleanup();
|
||||
Entities.setLightsArePickable(originalLightsArePickable);
|
||||
|
||||
Overlays.deleteOverlay(importingSVOImageOverlay);
|
||||
|
|
255
scripts/system/modules/entityShapeVisualizer.js
Normal file
255
scripts/system/modules/entityShapeVisualizer.js
Normal file
|
@ -0,0 +1,255 @@
|
|||
"use strict";
|
||||
|
||||
// entityShapeVisualizer.js
|
||||
//
|
||||
// Created by Thijs Wenker on 1/11/19
|
||||
//
|
||||
// Copyright 2019 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var SHAPETYPE_TO_SHAPE = {
|
||||
"box": "Cube",
|
||||
"ellipsoid": "Sphere",
|
||||
"cylinder-y": "Cylinder",
|
||||
};
|
||||
|
||||
var REQUESTED_ENTITY_SHAPE_PROPERTIES = [
|
||||
'type', 'shapeType', 'compoundShapeURL', 'localDimensions'
|
||||
];
|
||||
|
||||
function getEntityShapePropertiesForType(properties) {
|
||||
switch (properties.type) {
|
||||
case "Zone":
|
||||
if (SHAPETYPE_TO_SHAPE[properties.shapeType]) {
|
||||
return {
|
||||
type: "Shape",
|
||||
shape: SHAPETYPE_TO_SHAPE[properties.shapeType],
|
||||
localDimensions: properties.localDimensions
|
||||
};
|
||||
} else if (properties.shapeType === "compound") {
|
||||
return {
|
||||
type: "Model",
|
||||
modelURL: properties.compoundShapeURL,
|
||||
localDimensions: properties.localDimensions
|
||||
};
|
||||
} else if (properties.shapeType === "sphere") {
|
||||
var sphereDiameter = Math.max(properties.localDimensions.x, properties.localDimensions.y,
|
||||
properties.localDimensions.z);
|
||||
return {
|
||||
type: "Sphere",
|
||||
modelURL: properties.compoundShapeURL,
|
||||
localDimensions: {x: sphereDiameter, y: sphereDiameter, z: sphereDiameter}
|
||||
};
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Default properties
|
||||
return {
|
||||
type: "Shape",
|
||||
shape: "Cube",
|
||||
localDimensions: properties.localDimensions
|
||||
};
|
||||
}
|
||||
|
||||
function deepEqual(a, b) {
|
||||
if (a === b) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (typeof(a) !== "object" || typeof(b) !== "object") {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Object.keys(a).length !== Object.keys(b).length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (var property in a) {
|
||||
if (!a.hasOwnProperty(property)) {
|
||||
continue;
|
||||
}
|
||||
if (!b.hasOwnProperty(property)) {
|
||||
return false;
|
||||
}
|
||||
if (!deepEqual(a[property], b[property])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of property names which are different in comparison.
|
||||
* @param propertiesA
|
||||
* @param propertiesB
|
||||
* @returns {Array} - array of different property names
|
||||
*/
|
||||
function compareEntityProperties(propertiesA, propertiesB) {
|
||||
var differentProperties = [],
|
||||
property;
|
||||
|
||||
for (property in propertiesA) {
|
||||
if (!propertiesA.hasOwnProperty(property)) {
|
||||
continue;
|
||||
}
|
||||
if (!propertiesB.hasOwnProperty(property) || !deepEqual(propertiesA[property], propertiesB[property])) {
|
||||
differentProperties.push(property);
|
||||
}
|
||||
}
|
||||
for (property in propertiesB) {
|
||||
if (!propertiesB.hasOwnProperty(property)) {
|
||||
continue;
|
||||
}
|
||||
if (!propertiesA.hasOwnProperty(property)) {
|
||||
differentProperties.push(property);
|
||||
}
|
||||
}
|
||||
|
||||
return differentProperties;
|
||||
}
|
||||
|
||||
function deepCopy(v) {
|
||||
return JSON.parse(JSON.stringify(v));
|
||||
}
|
||||
|
||||
function EntityShape(entityID) {
|
||||
this.entityID = entityID;
|
||||
var propertiesForType = getEntityShapePropertiesForType(Entities.getEntityProperties(entityID, REQUESTED_ENTITY_SHAPE_PROPERTIES));
|
||||
|
||||
this.previousPropertiesForType = propertiesForType;
|
||||
|
||||
this.initialize(propertiesForType);
|
||||
}
|
||||
|
||||
EntityShape.prototype = {
|
||||
initialize: function(properties) {
|
||||
// Create new instance of JS object:
|
||||
var overlayProperties = deepCopy(properties);
|
||||
|
||||
overlayProperties.localPosition = Vec3.ZERO;
|
||||
overlayProperties.localRotation = Quat.IDENTITY;
|
||||
overlayProperties.canCastShadows = false;
|
||||
overlayProperties.parentID = this.entityID;
|
||||
overlayProperties.collisionless = true;
|
||||
this.entity = Entities.addEntity(overlayProperties, "local");
|
||||
var PROJECTED_MATERIALS = false;
|
||||
this.materialEntity = Entities.addEntity({
|
||||
type: "Material",
|
||||
localPosition: Vec3.ZERO,
|
||||
localRotation: Quat.IDENTITY,
|
||||
localDimensions: properties.localDimensions,
|
||||
parentID: this.entity,
|
||||
priority: 1,
|
||||
materialMappingMode: PROJECTED_MATERIALS ? "projected" : "uv",
|
||||
materialURL: Script.resolvePath("../assets/images/materials/GridPattern.json"),
|
||||
}, "local");
|
||||
},
|
||||
update: function() {
|
||||
var propertiesForType = getEntityShapePropertiesForType(Entities.getEntityProperties(this.entityID, REQUESTED_ENTITY_SHAPE_PROPERTIES));
|
||||
|
||||
var difference = compareEntityProperties(propertiesForType, this.previousPropertiesForType);
|
||||
|
||||
if (deepEqual(difference, ['localDimensions'])) {
|
||||
this.previousPropertiesForType = propertiesForType;
|
||||
Entities.editEntity(this.entity, {
|
||||
localDimensions: propertiesForType.localDimensions,
|
||||
});
|
||||
} else if (difference.length > 0) {
|
||||
this.previousPropertiesForType = propertiesForType;
|
||||
this.clear();
|
||||
this.initialize(propertiesForType);
|
||||
}
|
||||
},
|
||||
clear: function() {
|
||||
Entities.deleteEntity(this.materialEntity);
|
||||
Entities.deleteEntity(this.entity);
|
||||
}
|
||||
};
|
||||
|
||||
function EntityShapeVisualizer(visualizedTypes) {
|
||||
this.acceptedEntities = [];
|
||||
this.ignoredEntities = [];
|
||||
this.entityShapes = {};
|
||||
|
||||
this.visualizedTypes = visualizedTypes;
|
||||
}
|
||||
|
||||
EntityShapeVisualizer.prototype = {
|
||||
addEntity: function(entityID) {
|
||||
if (this.entityShapes[entityID]) {
|
||||
return;
|
||||
}
|
||||
this.entityShapes[entityID] = new EntityShape(entityID);
|
||||
|
||||
},
|
||||
updateEntity: function(entityID) {
|
||||
if (!this.entityShapes[entityID]) {
|
||||
return;
|
||||
}
|
||||
this.entityShapes[entityID].update();
|
||||
},
|
||||
removeEntity: function(entityID) {
|
||||
if (!this.entityShapes[entityID]) {
|
||||
return;
|
||||
}
|
||||
this.entityShapes[entityID].clear();
|
||||
delete this.entityShapes[entityID];
|
||||
},
|
||||
cleanup: function() {
|
||||
Object.keys(this.entityShapes).forEach(function(entityID) {
|
||||
this.entityShapes[entityID].clear();
|
||||
}, this);
|
||||
this.entityShapes = {};
|
||||
},
|
||||
setEntities: function(entities) {
|
||||
var qualifiedEntities = entities.filter(function(entityID) {
|
||||
if (this.acceptedEntities.indexOf(entityID) !== -1) {
|
||||
return true;
|
||||
}
|
||||
if (this.ignoredEntities.indexOf(entityID) !== -1) {
|
||||
return false;
|
||||
}
|
||||
if (this.visualizedTypes.indexOf(Entities.getEntityProperties(entityID, "type").type) !== -1) {
|
||||
this.acceptedEntities.push(entityID);
|
||||
return true;
|
||||
}
|
||||
this.ignoredEntities.push(entityID);
|
||||
return false;
|
||||
}, this);
|
||||
|
||||
|
||||
var newEntries = [];
|
||||
var updateEntries = [];
|
||||
|
||||
var currentEntries = Object.keys(this.entityShapes);
|
||||
qualifiedEntities.forEach(function(entityID) {
|
||||
if (currentEntries.indexOf(entityID) !== -1) {
|
||||
updateEntries.push(entityID);
|
||||
} else {
|
||||
newEntries.push(entityID);
|
||||
}
|
||||
});
|
||||
|
||||
var deleteEntries = currentEntries.filter(function(entityID) {
|
||||
return updateEntries.indexOf(entityID) === -1;
|
||||
});
|
||||
|
||||
deleteEntries.forEach(function(entityID) {
|
||||
this.removeEntity(entityID);
|
||||
}, this);
|
||||
|
||||
updateEntries.forEach(function(entityID) {
|
||||
this.updateEntity(entityID);
|
||||
}, this);
|
||||
|
||||
newEntries.forEach(function(entityID) {
|
||||
this.addEntity(entityID);
|
||||
}, this);
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = EntityShapeVisualizer;
|
Loading…
Reference in a new issue