diff --git a/scripts/system/assets/data/createAppTooltips.json b/scripts/system/assets/data/createAppTooltips.json
index 5572779d46..720d4537ee 100644
--- a/scripts/system/assets/data/createAppTooltips.json
+++ b/scripts/system/assets/data/createAppTooltips.json
@@ -294,12 +294,21 @@
"position": {
"tooltip": "The global position of this entity."
},
+ "localPosition": {
+ "tooltip": "The local position of this entity."
+ },
"rotation": {
- "tooltip": "The rotation of the entity with respect to world coordinates."
+ "tooltip": "The global rotation of this entity."
+ },
+ "localRotation": {
+ "tooltip": "The local rotation of this entity."
},
"dimensions": {
"tooltip": "The global dimensions of this entity."
},
+ "localDimensions": {
+ "tooltip": "The local dimensions of this entity."
+ },
"scale": {
"tooltip": "The global scaling of this entity.",
"skipJSProperty": true
@@ -398,13 +407,13 @@
"userData": {
"tooltip": "Used to store extra data about the entity in JSON format."
},
- "velocity": {
+ "localVelocity": {
"tooltip": "The linear velocity vector of the entity. The velocity at which this entity moves forward in space."
},
"damping": {
"tooltip": "The linear damping to slow down the linear velocity of an entity over time."
},
- "angularVelocity": {
+ "localAngularVelocity": {
"tooltip": "The angular velocity of the entity in rad/s with respect to its axes, about its pivot point."
},
"angularDamping": {
diff --git a/scripts/system/edit.js b/scripts/system/edit.js
index c8811bd603..38f9c5ea34 100644
--- a/scripts/system/edit.js
+++ b/scripts/system/edit.js
@@ -2261,9 +2261,17 @@ var PropertiesTool = function (opts) {
});
}
+ that.setSpaceMode = function(spaceMode) {
+ emitScriptEvent({
+ type: 'setSpaceMode',
+ spaceMode: spaceMode
+ })
+ };
+
function updateSelections(selectionUpdated) {
var data = {
- type: 'update'
+ type: 'update',
+ spaceMode: selectionDisplay.getSpaceMode()
};
if (selectionUpdated) {
@@ -2293,6 +2301,9 @@ var PropertiesTool = function (opts) {
if (entity.properties.rotation !== undefined) {
entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation);
}
+ if (entity.properties.localRotation !== undefined) {
+ entity.properties.localRotation = Quat.safeEulerAngles(entity.properties.localRotation);
+ }
if (entity.properties.emitOrientation !== undefined) {
entity.properties.emitOrientation = Quat.safeEulerAngles(entity.properties.emitOrientation);
}
@@ -2329,12 +2340,15 @@ var PropertiesTool = function (opts) {
} else if (data.properties) {
if (data.properties.dynamic === false) {
// this object is leaving dynamic, so we zero its velocities
- data.properties.velocity = Vec3.ZERO;
- data.properties.angularVelocity = Vec3.ZERO;
+ data.properties.localVelocity = Vec3.ZERO;
+ data.properties.localAngularVelocity = Vec3.ZERO;
}
if (data.properties.rotation !== undefined) {
data.properties.rotation = Quat.fromVec3Degrees(data.properties.rotation);
}
+ if (data.properties.localRotation !== undefined) {
+ data.properties.localRotation = Quat.fromVec3Degrees(data.properties.localRotation);
+ }
if (data.properties.emitOrientation !== undefined) {
data.properties.emitOrientation = Quat.fromVec3Degrees(data.properties.emitOrientation);
}
@@ -2725,4 +2739,10 @@ entityListTool.webView.webEventReceived.connect(function(data) {
}
});
+
+selectionDisplay.onSpaceModeChange = function(spaceMode) {
+ entityListTool.setSpaceMode(spaceMode);
+ propertiesTool.setSpaceMode(spaceMode);
+};
+
}()); // END LOCAL_SCOPE
diff --git a/scripts/system/html/css/edit-style.css b/scripts/system/html/css/edit-style.css
index 7d2350e1c8..941a9ec171 100644
--- a/scripts/system/html/css/edit-style.css
+++ b/scripts/system/html/css/edit-style.css
@@ -222,7 +222,7 @@ input::-webkit-input-placeholder {
font-style: italic;
}
-input:focus, textarea:focus {
+input:focus, textarea:focus, button:focus {
color: #fff;
background-color: #000;
outline: 1px solid #00b4ef;
@@ -340,7 +340,7 @@ input.no-spin::-webkit-inner-spin-button {
padding-right: 12px;
}
-input[type=button] {
+input[type=button], button.hifi-edit-button {
font-family: Raleway-Bold;
font-size: 13px;
text-transform: uppercase;
@@ -357,7 +357,7 @@ input[type=button] {
cursor: pointer;
}
-input[type=button].glyph {
+input[type=button].glyph, button.hifi-edit-button.glyph {
font-family: HiFi-Glyphs;
font-size: 20px;
text-transform: none;
@@ -365,58 +365,58 @@ input[type=button].glyph {
padding: 0;
}
-input[type=button].red {
+input[type=button].red, button.hifi-edit-button.red {
color: #fff;
background-color: #94132e;
background: linear-gradient(#d42043 20%, #94132e 100%);
}
-input[type=button].blue {
+input[type=button].blue, button.hifi-edit-button.blue {
color: #fff;
background-color: #1080b8;
background: linear-gradient(#00b4ef 20%, #1080b8 100%);
}
-input[type=button].white {
+input[type=button].white, button.hifi-edit-button.white {
color: #121212;
background-color: #afafaf;
background: linear-gradient(#fff 20%, #afafaf 100%);
}
-input[type=button]:enabled:hover {
+input[type=button]:enabled:hover, button.hifi-edit-button:enabled:hover {
background: linear-gradient(#000, #000);
border: none;
}
-input[type=button].red:enabled:hover {
+input[type=button].red:enabled:hover, button.hifi-edit-button.red:enabled:hover {
background: linear-gradient(#d42043, #d42043);
border: none;
}
-input[type=button].blue:enabled:hover {
+input[type=button].blue:enabled:hover, button.hifi-edit-button.blue:enabled:hover {
background: linear-gradient(#00b4ef, #00b4ef);
border: none;
}
-input[type=button].white:enabled:hover {
+input[type=button].white:enabled:hover, button.hifi-edit-button.white:enabled:hover {
background: linear-gradient(#fff, #fff);
border: none;
}
-input[type=button]:active {
+input[type=button]:active, button.hifi-edit-button:active {
background: linear-gradient(#343434, #343434);
}
-input[type=button].red:active {
+input[type=button].red:active, button.hifi-edit-button.red:active {
background: linear-gradient(#94132e, #94132e);
}
-input[type=button].blue:active {
+input[type=button].blue:active, button.hifi-edit-button.blue:active {
background: linear-gradient(#1080b8, #1080b8);
}
-input[type=button].white:active {
+input[type=button].white:active, button.hifi-edit-button.white:active {
background: linear-gradient(#afafaf, #afafaf);
}
-input[type=button]:disabled {
+input[type=button]:disabled, button.hifi-edit-button:disabled {
color: #252525;
background: linear-gradient(#575757 20%, #252525 100%);
}
-input[type=button][pressed=pressed] {
+input[type=button][pressed=pressed], button.hifi-edit-button[pressed=pressed] {
color: #00b4ef;
}
@@ -1620,3 +1620,21 @@ input.rename-entity {
bottom: 0;
margin-top: 5px;
}
+
+#toggle-space-mode::before {
+ font-family: HiFi-Glyphs;
+ font-size: 20px;
+ text-transform: none;
+ min-width: 32px;
+ padding-right: 4px;
+ vertical-align: middle;
+}
+
+#toggle-space-mode.space-mode-local::before {
+ content: "m";
+}
+
+#toggle-space-mode.space-mode-world::before {
+ content: "\e02c";
+}
+
diff --git a/scripts/system/html/entityList.html b/scripts/system/html/entityList.html
index 2e7ac58ac1..062847bcb6 100644
--- a/scripts/system/html/entityList.html
+++ b/scripts/system/html/entityList.html
@@ -9,6 +9,7 @@
-->
+
diff --git a/scripts/system/html/js/entityList.js b/scripts/system/html/js/entityList.js
index 41c957c4fa..315e313ae6 100644
--- a/scripts/system/html/js/entityList.js
+++ b/scripts/system/html/js/entityList.js
@@ -149,6 +149,7 @@ function loaded() {
elSelectedEntitiesCount = document.getElementById("selected-entities-count");
elVisibleEntitiesCount = document.getElementById("visible-entities-count");
elNoEntitiesMessage = document.getElementById("no-entities");
+ elToggleSpaceMode = document.getElementById('toggle-space-mode');
document.body.onclick = onBodyClick;
document.getElementById("entity-name").onclick = function() {
@@ -205,6 +206,10 @@ function loaded() {
elDelete.onclick = function() {
EventBridge.emitWebEvent(JSON.stringify({ type: 'delete' }));
};
+ elToggleSpaceMode.onclick = function() {
+ EventBridge.emitWebEvent(JSON.stringify({ type: 'toggleSpaceMode' }));
+ };
+
elFilterTypeSelectBox.onclick = onToggleTypeDropdown;
elFilterSearch.onkeyup = refreshEntityList;
elFilterSearch.onsearch = refreshEntityList;
@@ -646,6 +651,8 @@ function loaded() {
}
}
+ elToggleSpaceMode.disabled = selectedIDs.length > 1;
+
refreshFooter();
return notFound;
@@ -827,6 +834,16 @@ function loaded() {
entityList.resize();
event.stopPropagation();
}
+
+ function setSpaceMode(spaceMode) {
+ if (spaceMode === "local") {
+ elToggleSpaceMode.className = "space-mode-local hifi-edit-button";
+ elToggleSpaceMode.innerText = "Local";
+ } else {
+ elToggleSpaceMode.className = "space-mode-world hifi-edit-button";
+ elToggleSpaceMode.innerText = "World";
+ }
+ }
document.addEventListener("keydown", function (keyDownEvent) {
if (keyDownEvent.target.nodeName === "INPUT") {
@@ -866,12 +883,15 @@ function loaded() {
updateSelectedEntities(data.selectedIDs, true);
}
}
+ setSpaceMode(data.spaceMode);
});
} else if (data.type === "removeEntities" && data.deletedIDs !== undefined && data.selectedIDs !== undefined) {
removeEntities(data.deletedIDs);
updateSelectedEntities(data.selectedIDs, true);
} else if (data.type === "deleted" && data.ids) {
removeEntities(data.ids);
+ } else if (data.type === "setSpaceMode") {
+ setSpaceMode(data.spaceMode);
}
});
}
diff --git a/scripts/system/html/js/entityProperties.js b/scripts/system/html/js/entityProperties.js
index b66d7e19c6..f2c84d2f36 100644
--- a/scripts/system/html/js/entityProperties.js
+++ b/scripts/system/html/js/entityProperties.js
@@ -31,6 +31,12 @@ const DEGREES_TO_RADIANS = Math.PI / 180.0;
const NO_SELECTION = "No selection";
+const PROPERTY_SPACE_MODE = {
+ ALL: 0,
+ LOCAL: 1,
+ WORLD: 2
+};
+
const GROUPS = [
{
id: "base",
@@ -662,7 +668,7 @@ const GROUPS = [
propertyID: "speedSpread",
},
{
- label: "Emit Dimension",
+ label: "Emit Dimensions",
type: "vec3",
vec3Type: "xyz",
min: 0,
@@ -957,6 +963,17 @@ const GROUPS = [
subLabels: [ "x", "y", "z" ],
unit: "m",
propertyID: "position",
+ spaceMode: PROPERTY_SPACE_MODE.WORLD,
+ },
+ {
+ label: "Local Position",
+ type: "vec3",
+ vec3Type: "xyz",
+ decimals: 4,
+ subLabels: [ "x", "y", "z" ],
+ unit: "m",
+ propertyID: "localPosition",
+ spaceMode: PROPERTY_SPACE_MODE.LOCAL,
},
{
label: "Rotation",
@@ -967,9 +984,21 @@ const GROUPS = [
subLabels: [ "pitch", "yaw", "roll" ],
unit: "deg",
propertyID: "rotation",
+ spaceMode: PROPERTY_SPACE_MODE.WORLD,
},
{
- label: "Dimension",
+ label: "Local Rotation",
+ type: "vec3",
+ vec3Type: "pyr",
+ step: 0.1,
+ decimals: 4,
+ subLabels: [ "pitch", "yaw", "roll" ],
+ unit: "deg",
+ propertyID: "localRotation",
+ spaceMode: PROPERTY_SPACE_MODE.LOCAL,
+ },
+ {
+ label: "Dimensions",
type: "vec3",
vec3Type: "xyz",
min: 0,
@@ -978,6 +1007,19 @@ const GROUPS = [
subLabels: [ "x", "y", "z" ],
unit: "m",
propertyID: "dimensions",
+ spaceMode: PROPERTY_SPACE_MODE.WORLD,
+ },
+ {
+ label: "Local Dimensions",
+ type: "vec3",
+ vec3Type: "xyz",
+ min: 0,
+ step: 0.1,
+ decimals: 4,
+ subLabels: [ "x", "y", "z" ],
+ unit: "m",
+ propertyID: "localDimensions",
+ spaceMode: PROPERTY_SPACE_MODE.LOCAL,
},
{
label: "Scale",
@@ -1174,7 +1216,7 @@ const GROUPS = [
decimals: 4,
subLabels: [ "x", "y", "z" ],
unit: "m/s",
- propertyID: "velocity",
+ propertyID: "localVelocity",
},
{
label: "Linear Damping",
@@ -1190,7 +1232,7 @@ const GROUPS = [
decimals: 4,
subLabels: [ "pitch", "yaw", "roll" ],
unit: "deg/s",
- propertyID: "angularVelocity",
+ propertyID: "localAngularVelocity",
},
{
label: "Angular Damping",
@@ -1317,6 +1359,7 @@ var particlePropertyUpdates = {};
var selectedEntityProperties;
var lastEntityID = null;
var createAppTooltip = new CreateAppTooltip();
+let currentSpaceMode = PROPERTY_SPACE_MODE.LOCAL;
function debugPrint(message) {
EventBridge.emitWebEvent(
@@ -2666,7 +2709,17 @@ function showParentMaterialNameBox(number, elNumber, elString) {
}
}
-
+function updateVisibleSpaceModeProperties() {
+ for (let propertyID in properties) {
+ if (properties.hasOwnProperty(propertyID)) {
+ let property = properties[propertyID];
+ let propertySpaceMode = property.spaceMode;
+ if (propertySpaceMode !== PROPERTY_SPACE_MODE.ALL) {
+ showPropertyElement(propertyID, propertySpaceMode === currentSpaceMode);
+ }
+ }
+ }
+}
function loaded() {
openEventBridge(function() {
@@ -2700,6 +2753,7 @@ function loaded() {
let propertyType = propertyData.type;
let propertyID = propertyData.propertyID;
let propertyName = propertyData.propertyName !== undefined ? propertyData.propertyName : propertyID;
+ let propertySpaceMode = propertyData.spaceMode !== undefined ? propertyData.spaceMode : PROPERTY_SPACE_MODE.ALL;
let propertyElementID = "property-" + propertyID;
propertyElementID = propertyElementID.replace('.', '-');
@@ -2746,7 +2800,8 @@ function loaded() {
elementID: propertyElementID,
name: propertyName,
isParticleProperty: group.id.includes("particles"),
- elProperty: elProperty
+ elProperty,
+ spaceMode: propertySpaceMode,
};
properties[propertyID] = property;
@@ -2840,6 +2895,8 @@ function loaded() {
elGroups[group.id] = elGroup;
});
+
+ updateVisibleSpaceModeProperties();
if (window.EventBridge !== undefined) {
EventBridge.scriptEventReceived.connect(function(data) {
@@ -2860,6 +2917,9 @@ function loaded() {
elServerScriptStatus.innerText = NOT_RUNNING_SCRIPT_STATUS;
}
} else if (data.type === "update" && data.selections) {
+ if (data.spaceMode !== undefined) {
+ currentSpaceMode = data.spaceMode === "local" ? PROPERTY_SPACE_MODE.LOCAL : PROPERTY_SPACE_MODE.WORLD;
+ }
if (data.selections.length === 0) {
if (lastEntityID !== null) {
if (editor !== null) {
@@ -3082,7 +3142,9 @@ function loaded() {
}
}
}
-
+
+ updateVisibleSpaceModeProperties();
+
if (selectedEntityProperties.type === "Image") {
let imageLink = JSON.parse(selectedEntityProperties.textures)["tex.picture"];
getPropertyInputElement("image").value = imageLink;
@@ -3167,6 +3229,9 @@ function loaded() {
createAppTooltip.setTooltipData(data.tooltips);
} else if (data.type === 'hmdActiveChanged') {
createAppTooltip.setIsEnabled(!data.hmdActive);
+ } else if (data.type === 'setSpaceMode') {
+ currentSpaceMode = data.spaceMode === "local" ? PROPERTY_SPACE_MODE.LOCAL : PROPERTY_SPACE_MODE.WORLD;
+ updateVisibleSpaceModeProperties();
}
});
diff --git a/scripts/system/libraries/entityList.js b/scripts/system/libraries/entityList.js
index 585820d32f..c47e8045d6 100644
--- a/scripts/system/libraries/entityList.js
+++ b/scripts/system/libraries/entityList.js
@@ -115,6 +115,13 @@ EntityListTool = function(shouldUseEditTabletApp) {
});
});
+ that.setSpaceMode = function(spaceMode) {
+ emitJSONScriptEvent({
+ type: 'setSpaceMode',
+ spaceMode: spaceMode
+ });
+ };
+
that.clearEntityList = function() {
emitJSONScriptEvent({
type: 'clearEntityList'
@@ -200,6 +207,7 @@ EntityListTool = function(shouldUseEditTabletApp) {
type: "update",
entities: entities,
selectedIDs: selectedIDs,
+ spaceMode: SelectionDisplay.getSpaceMode(),
});
});
};
@@ -288,6 +296,8 @@ EntityListTool = function(shouldUseEditTabletApp) {
Entities.editEntity(data.entityID, {name: data.name});
// make sure that the name also gets updated in the properties window
SelectionManager._update();
+ } else if (data.type === "toggleSpaceMode") {
+ SelectionDisplay.toggleSpaceMode();
}
};
diff --git a/scripts/system/libraries/entitySelectionTool.js b/scripts/system/libraries/entitySelectionTool.js
index 3bb36d632e..b0b1740821 100644
--- a/scripts/system/libraries/entitySelectionTool.js
+++ b/scripts/system/libraries/entitySelectionTool.js
@@ -500,7 +500,7 @@ SelectionManager = (function() {
that.entityType = properties.type;
if (selectionUpdated) {
- SelectionDisplay.setSpaceMode(SPACE_LOCAL);
+ SelectionDisplay.useDesiredSpaceMode();
}
} else {
properties = Entities.getEntityProperties(that.selections[0], ['type', 'boundingBox']);
@@ -537,7 +537,7 @@ SelectionManager = (function() {
};
// For 1+ selections we can only modify selections in world space
- SelectionDisplay.setSpaceMode(SPACE_WORLD);
+ SelectionDisplay.setSpaceMode(SPACE_WORLD, false);
}
for (var j = 0; j < listeners.length; j++) {
@@ -651,6 +651,8 @@ SelectionDisplay = (function() {
};
var spaceMode = SPACE_LOCAL;
+ var desiredSpaceMode = SPACE_LOCAL;
+
var overlayNames = [];
var lastControllerPoses = [
getControllerWorldLocation(Controller.Standard.LeftHand, true),
@@ -1400,8 +1402,21 @@ SelectionDisplay = (function() {
that.updateHandles();
};
+
+ /**
+ * This callback is used for spaceMode changes.
+ * @callback spaceModeChangedCallback
+ * @param {string} spaceMode
+ */
+
+ /**
+ * set this property with a callback to keep track of spaceMode changes.
+ * @type {spaceModeChangedCallback}
+ */
+ that.onSpaceModeChange = null;
+
// FUNCTION: SET SPACE MODE
- that.setSpaceMode = function(newSpaceMode) {
+ that.setSpaceMode = function(newSpaceMode, isDesiredChange) {
var wantDebug = false;
if (wantDebug) {
print("======> SetSpaceMode called. ========");
@@ -1411,7 +1426,15 @@ SelectionDisplay = (function() {
if (wantDebug) {
print(" Updating SpaceMode From: " + spaceMode + " To: " + newSpaceMode);
}
+ if (isDesiredChange) {
+ desiredSpaceMode = newSpaceMode;
+ }
spaceMode = newSpaceMode;
+
+ if (that.onSpaceModeChange !== null) {
+ that.onSpaceModeChange(newSpaceMode);
+ }
+
that.updateHandles();
} else if (wantDebug) {
print("WARNING: entitySelectionTool.setSpaceMode - Can't update SpaceMode. CurrentMode: " +
@@ -1437,14 +1460,36 @@ SelectionDisplay = (function() {
if (wantDebug) {
print("PreToggle: " + spaceMode);
}
- spaceMode = (spaceMode === SPACE_LOCAL) ? SPACE_WORLD : SPACE_LOCAL;
- that.updateHandles();
+ that.setSpaceMode((spaceMode === SPACE_LOCAL) ? SPACE_WORLD : SPACE_LOCAL, true);
if (wantDebug) {
print("PostToggle: " + spaceMode);
print("======== ToggleSpaceMode called. <=========");
}
};
+ /**
+ * Switches the display mode back to the set desired display mode
+ */
+ that.useDesiredSpaceMode = function() {
+ var wantDebug = false;
+ if (wantDebug) {
+ print("========> UseDesiredSpaceMode called. =========");
+ }
+ that.setSpaceMode(desiredSpaceMode, false);
+ if (wantDebug) {
+ print("PostToggle: " + spaceMode);
+ print("======== UseDesiredSpaceMode called. <=========");
+ }
+ };
+
+ /**
+ * Get the currently set SpaceMode
+ * @returns {string} spaceMode
+ */
+ that.getSpaceMode = function() {
+ return spaceMode;
+ };
+
function addHandleTool(overlay, tool) {
handleTools[overlay] = tool;
return tool;