Distinguish properly between intersected and root entities

This commit is contained in:
David Rowe 2017-08-12 14:56:22 +12:00
parent 2bf0ea1dff
commit 541402b559
2 changed files with 80 additions and 50 deletions

View file

@ -16,7 +16,7 @@ Selection = function (side) {
"use strict";
var selection = [],
selectedEntityID = null,
intersectedEntityID = null,
rootEntityID = null,
rootPosition,
rootOrientation,
@ -65,12 +65,14 @@ Selection = function (side) {
}
}
function select(entityID) {
function select(intersectionEntityID) {
var entityProperties,
PARENT_PROPERTIES = ["parentID", "position", "rotation", "dymamic", "collisionless"];
intersectedEntityID = intersectionEntityID;
// Find root parent.
rootEntityID = Entities.rootOf(entityID);
rootEntityID = Entities.rootOf(intersectedEntityID);
// Selection position and orientation is that of the root entity.
entityProperties = Entities.getEntityProperties(rootEntityID, PARENT_PROPERTIES);
@ -80,8 +82,10 @@ Selection = function (side) {
// Find all children.
selection = [];
traverseEntityTree(rootEntityID, selection);
}
selectedEntityID = entityID;
function getIntersectedEntityID() {
return intersectedEntityID;
}
function getRootEntityID() {
@ -263,7 +267,7 @@ Selection = function (side) {
}
function finishDirectScaling() {
select(selectedEntityID); // Refresh.
select(intersectedEntityID); // Refresh.
}
function startHandleScaling() {
@ -296,19 +300,23 @@ Selection = function (side) {
}
function finishHandleScaling() {
select(selectedEntityID); // Refresh.
select(intersectedEntityID); // Refresh.
}
function cloneEntities() {
var parentIDIndexes = [],
intersectedEntityIndex = 0,
parentID,
properties,
i,
j,
length;
// Map parent IDs.
// Map parent IDs; find intersectedEntityID's index.
for (i = 1, length = selection.length; i < length; i += 1) {
if (selection[i].id === intersectedEntityID) {
intersectedEntityIndex = i;
}
parentID = selection[i].parentID;
for (j = 0; j < i; j += 1) {
if (parentID === selection[j].id) {
@ -327,6 +335,7 @@ Selection = function (side) {
selection[i].id = Entities.addEntity(properties);
}
intersectedEntityID = selection[intersectedEntityIndex].id;
rootEntityID = selection[0].id;
}
@ -410,7 +419,7 @@ Selection = function (side) {
function clear() {
selection = [];
selectedEntityID = null;
intersectedEntityID = null;
rootEntityID = null;
}
@ -429,6 +438,7 @@ Selection = function (side) {
select: select,
selection: getSelection,
count: count,
intersectedEntityID: getIntersectedEntityID,
rootEntityID: getRootEntityID,
boundingBox: getBoundingBox,
getPositionAndOrientation: getPositionAndOrientation,

View file

@ -337,7 +337,8 @@
// State machine.
STATE_MACHINE,
highlightedEntityID = null, // Root entity of highlighted entity set.
intersectedEntityID = null, // Intersected entity of highlighted entity set.
rootEntityID = null, // Root entity of highlighted entity set.
wasScaleTool = false,
isOtherEditorEditingEntityID = false,
isTriggerClicked = false,
@ -408,18 +409,22 @@
return handles.isHandle(overlayID);
}
function isEditing(rootEntityID) {
// rootEntityID is an optional parameter.
function isEditing(aRootEntityID) {
// aRootEntityID is an optional parameter.
return editorState > EDITOR_HIGHLIGHTING
&& (rootEntityID === undefined || rootEntityID === selection.rootEntityID());
&& (aRootEntityID === undefined || aRootEntityID === rootEntityID);
}
function isScaling() {
return editorState === EDITOR_DIRECT_SCALING || editorState === EDITOR_HANDLE_SCALING;
}
function rootEntityID() {
return selection.rootEntityID();
function getIntersectedEntityID() {
return intersectedEntityID;
}
function getRootEntityID() {
return rootEntityID;
}
@ -634,6 +639,8 @@
function enterEditorSearching() {
selection.clear();
intersectedEntityID = null;
rootEntityID = null;
hoveredOverlayID = intersection.overlayID;
otherEditor.hoverHandle(hoveredOverlayID);
}
@ -650,21 +657,21 @@
}
function enterEditorHighlighting() {
selection.select(highlightedEntityID);
if (toolSelected !== TOOL_SCALE || !otherEditor.isEditing(highlightedEntityID)) {
selection.select(intersectedEntityID);
if (toolSelected !== TOOL_SCALE || !otherEditor.isEditing(rootEntityID)) {
highlights.display(intersection.handIntersected, selection.selection(),
toolSelected === TOOL_SCALE || otherEditor.isEditing(highlightedEntityID)
toolSelected === TOOL_SCALE || otherEditor.isEditing(rootEntityID)
? highlights.SCALE_COLOR : highlights.HIGHLIGHT_COLOR);
}
isOtherEditorEditingEntityID = otherEditor.isEditing(highlightedEntityID);
isOtherEditorEditingEntityID = otherEditor.isEditing(rootEntityID);
wasScaleTool = toolSelected === TOOL_SCALE;
}
function updateEditorHighlighting() {
selection.select(highlightedEntityID);
if (toolSelected !== TOOL_SCALE || !otherEditor.isEditing(highlightedEntityID)) {
selection.select(intersectedEntityID);
if (toolSelected !== TOOL_SCALE || !otherEditor.isEditing(rootEntityID)) {
highlights.display(intersection.handIntersected, selection.selection(),
toolSelected === TOOL_SCALE || otherEditor.isEditing(highlightedEntityID)
toolSelected === TOOL_SCALE || otherEditor.isEditing(rootEntityID)
? highlights.SCALE_COLOR : highlights.HIGHLIGHT_COLOR);
} else {
highlights.clear();
@ -678,23 +685,23 @@
}
function enterEditorGrabbing() {
selection.select(highlightedEntityID); // For when transitioning from EDITOR_SEARCHING.
selection.select(intersectedEntityID); // For when transitioning from EDITOR_SEARCHING.
if (intersection.laserIntersected) {
laser.setLength(laser.length());
} else {
laser.disable();
}
if (toolSelected === TOOL_SCALE) {
handles.display(highlightedEntityID, selection.boundingBox(), selection.count() > 1);
handles.display(rootEntityID, selection.boundingBox(), selection.count() > 1);
}
startEditing();
wasScaleTool = toolSelected === TOOL_SCALE;
}
function updateEditorGrabbing() {
selection.select(highlightedEntityID);
selection.select(intersectedEntityID);
if (toolSelected === TOOL_SCALE) {
handles.display(highlightedEntityID, selection.boundingBox(), selection.count() > 1);
handles.display(rootEntityID, selection.boundingBox(), selection.count() > 1);
} else {
handles.clear();
}
@ -708,7 +715,7 @@
}
function enterEditorDirectScaling() {
selection.select(highlightedEntityID); // In case need to transition to EDITOR_GRABBING.
selection.select(intersectedEntityID); // In case need to transition to EDITOR_GRABBING.
isScalingWithHand = intersection.handIntersected;
if (intersection.laserIntersected) {
laser.setLength(laser.length());
@ -729,7 +736,7 @@
}
function enterEditorHandleScaling() {
selection.select(highlightedEntityID); // In case need to transition to EDITOR_GRABBING.
selection.select(intersectedEntityID); // In case need to transition to EDITOR_GRABBING.
isScalingWithHand = intersection.handIntersected;
if (intersection.laserIntersected) {
laser.setLength(laser.length());
@ -750,9 +757,11 @@
}
function enterEditorCloning() {
selection.select(highlightedEntityID); // For when transitioning from EDITOR_SEARCHING.
selection.select(intersectedEntityID); // For when transitioning from EDITOR_SEARCHING.
selection.cloneEntities();
highlightedEntityID = selection.rootEntityID();
intersectedEntityID = selection.intersectedEntityID();
rootEntityID = selection.rootEntityID();
intersectedEntityID = rootEntityID;
}
function exitEditorCloning() {
@ -760,7 +769,7 @@
}
function enterEditorGrouping() {
if (!grouping.includes(highlightedEntityID)) {
if (!grouping.includes(rootEntityID)) {
highlights.display(false, selection.selection(), highlights.GROUP_COLOR);
}
grouping.toggle(selection.selection());
@ -869,16 +878,19 @@
setState(EDITOR_IDLE);
} else if (intersection.overlayID && !wasTriggerClicked && isTriggerClicked
&& otherEditor.isHandle(intersection.overlayID)) {
highlightedEntityID = otherEditor.rootEntityID();
intersectedEntityID = otherEditor.intersectedEntityID();
rootEntityID = otherEditor.rootEntityID();
setState(EDITOR_HANDLE_SCALING);
} else if (intersection.entityID && intersection.editableEntity
&& (wasTriggerClicked || !isTriggerClicked) && !isAutoGrab) {
highlightedEntityID = Entities.rootOf(intersection.entityID);
intersectedEntityID = intersection.entityID;
rootEntityID = Entities.rootOf(intersectedEntityID);
setState(EDITOR_HIGHLIGHTING);
} else if (intersection.entityID && intersection.editableEntity
&& (!wasTriggerClicked || isAutoGrab) && isTriggerClicked) {
highlightedEntityID = Entities.rootOf(intersection.entityID);
if (otherEditor.isEditing(highlightedEntityID)) {
intersectedEntityID = intersection.entityID;
rootEntityID = Entities.rootOf(intersectedEntityID);
if (otherEditor.isEditing(rootEntityID)) {
if (toolSelected !== TOOL_SCALE) {
setState(EDITOR_DIRECT_SCALING);
}
@ -917,16 +929,17 @@
if (hand.valid()
&& intersection.entityID && intersection.editableEntity
&& !(!wasTriggerClicked && isTriggerClicked
&& (!otherEditor.isEditing(highlightedEntityID) || toolSelected !== TOOL_SCALE))
&& (!otherEditor.isEditing(rootEntityID) || toolSelected !== TOOL_SCALE))
&& !(!wasTriggerClicked && isTriggerClicked && intersection.overlayID
&& otherEditor.isHandle(intersection.overlayID))) {
// No transition.
doUpdateState = false;
if (otherEditor.isEditing(highlightedEntityID) !== isOtherEditorEditingEntityID) {
if (otherEditor.isEditing(rootEntityID) !== isOtherEditorEditingEntityID) {
doUpdateState = true;
}
if (Entities.rootOf(intersection.entityID) !== highlightedEntityID) {
highlightedEntityID = Entities.rootOf(intersection.entityID);
if (Entities.rootOf(intersection.entityID) !== rootEntityID) {
intersectedEntityID = intersection.entityID;
rootEntityID = Entities.rootOf(intersectedEntityID);
doUpdateState = true;
}
if ((toolSelected === TOOL_SCALE) !== wasScaleTool) {
@ -943,11 +956,13 @@
setState(EDITOR_IDLE);
} else if (intersection.overlayID && !wasTriggerClicked && isTriggerClicked
&& otherEditor.isHandle(intersection.overlayID)) {
highlightedEntityID = otherEditor.rootEntityID();
intersectedEntityID = otherEditor.intersectedEntityID();
rootEntityID = otherEditor.rootEntityID();
setState(EDITOR_HANDLE_SCALING);
} else if (intersection.entityID && intersection.editableEntity && !wasTriggerClicked && isTriggerClicked) {
highlightedEntityID = Entities.rootOf(intersection.entityID); // May be a different entityID.
if (otherEditor.isEditing(highlightedEntityID)) {
intersectedEntityID = intersection.entityID; // May be a different entityID.
rootEntityID = Entities.rootOf(intersectedEntityID);
if (otherEditor.isEditing(rootEntityID)) {
if (toolSelected !== TOOL_SCALE) {
setState(EDITOR_DIRECT_SCALING);
} else {
@ -998,7 +1013,8 @@
setState(EDITOR_IDLE);
} else if (!isTriggerClicked) {
if (intersection.entityID && intersection.editableEntity) {
highlightedEntityID = Entities.rootOf(intersection.entityID);
intersectedEntityID = intersection.entityID;
rootEntityID = Entities.rootOf(intersectedEntityID);
setState(EDITOR_HIGHLIGHTING);
} else {
setState(EDITOR_SEARCHING);
@ -1014,7 +1030,7 @@
break;
case EDITOR_DIRECT_SCALING:
if (hand.valid() && isTriggerClicked
&& (otherEditor.isEditing(highlightedEntityID) || otherEditor.isHandle(intersection.overlayID))) {
&& (otherEditor.isEditing(rootEntityID) || otherEditor.isHandle(intersection.overlayID))) {
// Don't test for intersection.intersected because when scaling with handles intersection may lag behind.
// Don't test toolSelected === TOOL_SCALE because this is a UI element and so not able to be changed while
// scaling with two hands.
@ -1029,10 +1045,11 @@
if (!intersection.entityID || !intersection.editableEntity) {
setState(EDITOR_SEARCHING);
} else {
highlightedEntityID = Entities.rootOf(intersection.entityID);
intersectedEntityID = intersection.entityID;
rootEntityID = Entities.rootOf(intersectedEntityID);
setState(EDITOR_HIGHLIGHTING);
}
} else if (!otherEditor.isEditing(highlightedEntityID)) {
} else if (!otherEditor.isEditing(rootEntityID)) {
// Grab highlightEntityID that was scaling and has already been set.
setState(EDITOR_GRABBING);
} else {
@ -1040,7 +1057,7 @@
}
break;
case EDITOR_HANDLE_SCALING:
if (hand.valid() && isTriggerClicked && otherEditor.isEditing(highlightedEntityID)) {
if (hand.valid() && isTriggerClicked && otherEditor.isEditing(rootEntityID)) {
// Don't test for intersection.intersected because when scaling with handles intersection may lag behind.
// Don't test toolSelected === TOOL_SCALE because this is a UI element and so not able to be changed while
// scaling with two hands.
@ -1055,10 +1072,11 @@
if (!intersection.entityID || !intersection.editableEntity) {
setState(EDITOR_SEARCHING);
} else {
highlightedEntityID = Entities.rootOf(intersection.entityID);
intersectedEntityID = intersection.entityID;
rootEntityID = Entities.rootOf(intersectedEntityID);
setState(EDITOR_HIGHLIGHTING);
}
} else if (!otherEditor.isEditing(highlightedEntityID)) {
} else if (!otherEditor.isEditing(rootEntityID)) {
// Grab highlightEntityID that was scaling and has already been set.
setState(EDITOR_GRABBING);
} else {
@ -1073,7 +1091,8 @@
setState(EDITOR_IDLE);
} else if (!isTriggerClicked) {
if (intersection.entityID && intersection.editableEntity) {
highlightedEntityID = Entities.rootOf(intersection.entityID);
intersectedEntityID = intersection.entityID;
rootEntityID = Entities.rootOf(intersectedEntityID);
setState(EDITOR_HIGHLIGHTING);
} else {
setState(EDITOR_SEARCHING);
@ -1150,7 +1169,8 @@
isHandle: isHandle,
isEditing: isEditing,
isScaling: isScaling,
rootEntityID: rootEntityID,
intersectedEntityID: getIntersectedEntityID,
rootEntityID: getRootEntityID,
startDirectScaling: startDirectScaling,
updateDirectScaling: updateDirectScaling,
stopDirectScaling: stopDirectScaling,