mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 01:24:03 +02:00
Merge pull request #3678 from huffman/entity-tool-fixes
Entity tool updates and fixes
This commit is contained in:
commit
caecf473ff
4 changed files with 416 additions and 239 deletions
|
@ -19,10 +19,15 @@ SPACE_WORLD = "world";
|
|||
SelectionManager = (function() {
|
||||
var that = {};
|
||||
|
||||
var PENDING_SELECTION_CHECK_INTERVAL = 50;
|
||||
|
||||
that.savedProperties = {};
|
||||
|
||||
that.eventListener = null;
|
||||
that.selections = [];
|
||||
// These are selections that don't have a known ID yet
|
||||
that.pendingSelections = [];
|
||||
var pendingSelectionTimer = null;
|
||||
|
||||
that.localRotation = Quat.fromPitchYawRollDegrees(0, 0, 0);
|
||||
that.localPosition = { x: 0, y: 0, z: 0 };
|
||||
|
@ -45,11 +50,58 @@ SelectionManager = (function() {
|
|||
that.eventListener = func;
|
||||
};
|
||||
|
||||
that.hasSelection = function() {
|
||||
return that.selections.length > 0;
|
||||
};
|
||||
|
||||
that.setSelections = function(entityIDs) {
|
||||
that.selections = [];
|
||||
for (var i = 0; i < entityIDs.length; i++) {
|
||||
var entityID = entityIDs[i];
|
||||
if (entityID.isKnownID) {
|
||||
that.selections.push(entityID);
|
||||
} else {
|
||||
that.pendingSelections.push(entityID);
|
||||
if (pendingSelectionTimer == null) {
|
||||
pendingSelectionTimer = Script.setInterval(that._checkPendingSelections, PENDING_SELECTION_CHECK_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
that._update();
|
||||
};
|
||||
|
||||
that._checkPendingSelections = function() {
|
||||
for (var i = 0; i < that.pendingSelections.length; i++) {
|
||||
var entityID = that.pendingSelections[i];
|
||||
var newEntityID = Entities.identifyEntity(entityID);
|
||||
if (newEntityID.isKnownID) {
|
||||
that.pendingSelections.splice(i, 1);
|
||||
that.addEntity(newEntityID);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
if (that.pendingSelections.length == 0) {
|
||||
Script.clearInterval(pendingSelectionTimer);
|
||||
pendingSelectionTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
that.addEntity = function(entityID) {
|
||||
print("Adding: " + entityID.id);
|
||||
var idx = that.selections.indexOf(entityID);
|
||||
if (idx == -1) {
|
||||
that.selections.push(entityID);
|
||||
if (entityID.isKnownID) {
|
||||
var idx = that.selections.indexOf(entityID);
|
||||
if (idx == -1) {
|
||||
that.selections.push(entityID);
|
||||
}
|
||||
} else {
|
||||
var idx = that.pendingSelections.indexOf(entityID);
|
||||
if (idx == -1) {
|
||||
that.pendingSelections.push(entityID);
|
||||
if (pendingSelectionTimer == null) {
|
||||
pendingSelectionTimer = Script.setInterval(that._checkPendingSelections, PENDING_SELECTION_CHECK_INTERVAL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
that._update();
|
||||
|
@ -61,11 +113,22 @@ SelectionManager = (function() {
|
|||
that.selections.splice(idx, 1);
|
||||
}
|
||||
|
||||
var idx = that.pendingSelections.indexOf(entityID);
|
||||
if (idx >= 0) {
|
||||
that.pendingSelections.splice(idx, 1);
|
||||
}
|
||||
|
||||
that._update();
|
||||
};
|
||||
|
||||
that.clearSelections = function() {
|
||||
that.selections = [];
|
||||
that.pendingSelections = [];
|
||||
|
||||
if (pendingSelectionTimer !== null) {
|
||||
Script.clearInterval(pendingSelectionTimer);
|
||||
pendingSelectionTimer = null;
|
||||
}
|
||||
|
||||
that._update();
|
||||
};
|
||||
|
@ -77,8 +140,6 @@ SelectionManager = (function() {
|
|||
that.worldDimensions = null;
|
||||
that.worldPosition = null;
|
||||
} else if (that.selections.length == 1) {
|
||||
SelectionDisplay.setSpaceMode(SPACE_LOCAL);
|
||||
|
||||
var properties = Entities.getEntityProperties(that.selections[0]);
|
||||
that.localDimensions = properties.dimensions;
|
||||
that.localPosition = properties.position;
|
||||
|
@ -86,10 +147,9 @@ SelectionManager = (function() {
|
|||
|
||||
that.worldDimensions = properties.boundingBox.dimensions;
|
||||
that.worldPosition = properties.boundingBox.center;
|
||||
} else {
|
||||
// For 1+ selections we can only modify selections in world space
|
||||
SelectionDisplay.setSpaceMode(SPACE_WORLD);
|
||||
|
||||
SelectionDisplay.setSpaceMode(SPACE_LOCAL);
|
||||
} else {
|
||||
that.localRotation = null;
|
||||
that.localDimensions = null;
|
||||
that.localPosition = null;
|
||||
|
@ -122,6 +182,9 @@ SelectionManager = (function() {
|
|||
y: brn.y + (that.worldDimensions.y / 2),
|
||||
z: brn.z + (that.worldDimensions.z / 2),
|
||||
};
|
||||
|
||||
// For 1+ selections we can only modify selections in world space
|
||||
SelectionDisplay.setSpaceMode(SPACE_WORLD);
|
||||
}
|
||||
|
||||
if (that.eventListener) {
|
||||
|
@ -600,7 +663,7 @@ SelectionDisplay = (function () {
|
|||
currentSelection = entityID;
|
||||
entitySelected = true;
|
||||
|
||||
lastCameraPosition = Camera.getPosition();
|
||||
// lastCameraPosition = Camera.getPosition();
|
||||
lastCameraOrientation = Camera.getOrientation();
|
||||
|
||||
if (event !== false) {
|
||||
|
@ -623,10 +686,15 @@ SelectionDisplay = (function () {
|
|||
|
||||
}
|
||||
|
||||
Entities.editEntity(entityID, { localRenderAlpha: 0.1 });
|
||||
Overlays.editOverlay(highlightBox, { visible: false });
|
||||
|
||||
that.updateHandles();
|
||||
}
|
||||
|
||||
that.updateRotationHandles = function() {
|
||||
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
||||
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
||||
innerRadius = diagonal;
|
||||
outerRadius = diagonal * 1.15;
|
||||
var innerActive = false;
|
||||
var innerAlpha = 0.2;
|
||||
var outerAlpha = 0.2;
|
||||
|
@ -637,22 +705,18 @@ SelectionDisplay = (function () {
|
|||
}
|
||||
|
||||
var rotateHandleOffset = 0.05;
|
||||
var grabberMoveUpOffset = 0.1;
|
||||
|
||||
var top, far, left, bottom, near, right, boundsCenter, objectCenter, BLN, BRN, BLF, TLN, TRN, TLF, TRF;
|
||||
|
||||
// objectCenter = { x: properties.position.x, y: properties.position.y, z: properties.position.z };
|
||||
|
||||
var dimensions;
|
||||
var dimensions, rotation;
|
||||
if (spaceMode == SPACE_LOCAL) {
|
||||
objectCenter = SelectionManager.localPosition;
|
||||
dimensions = SelectionManager.localDimensions;
|
||||
rotation = SelectionManager.localRotation;
|
||||
} else {
|
||||
objectCenter = SelectionManager.worldPosition;
|
||||
dimensions = SelectionManager.worldDimensions;
|
||||
rotation = SelectionManager.worldRotation;
|
||||
}
|
||||
objectCenter = SelectionManager.worldPosition;
|
||||
dimensions = SelectionManager.worldDimensions;
|
||||
var position = objectCenter;
|
||||
|
||||
top = objectCenter.y + (dimensions.y / 2);
|
||||
far = objectCenter.z + (dimensions.z / 2);
|
||||
|
@ -662,7 +726,6 @@ SelectionDisplay = (function () {
|
|||
near = objectCenter.z - (dimensions.z / 2);
|
||||
right = objectCenter.x - (dimensions.x / 2);
|
||||
|
||||
// boundsCenter = { x: properties.boundingBox.center.x, y: properties.boundingBox.center.y, z: properties.boundingBox.center.z };
|
||||
boundsCenter = objectCenter;
|
||||
|
||||
var yawCorner;
|
||||
|
@ -812,10 +875,12 @@ SelectionDisplay = (function () {
|
|||
}
|
||||
|
||||
var rotateHandlesVisible = true;
|
||||
var rotationOverlaysVisible = false;
|
||||
var translateHandlesVisible = true;
|
||||
var stretchHandlesVisible = true;
|
||||
var selectionBoxVisible = true;
|
||||
if (mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL" || mode == "TRANSLATE_X in case they Z") {
|
||||
rotationOverlaysVisible = true;
|
||||
rotateHandlesVisible = false;
|
||||
translateHandlesVisible = false;
|
||||
stretchHandlesVisible = false;
|
||||
|
@ -828,77 +893,33 @@ SelectionDisplay = (function () {
|
|||
rotateHandlesVisible = false;
|
||||
translateHandlesVisible = false;
|
||||
}
|
||||
|
||||
Overlays.editOverlay(highlightBox, { visible: false });
|
||||
|
||||
var dimensions, rotation, position;
|
||||
if (spaceMode == SPACE_LOCAL) {
|
||||
rotation = SelectionManager.localRotation;
|
||||
dimensions = SelectionManager.localDimensions;
|
||||
position = SelectionManager.localPosition;
|
||||
} else {
|
||||
rotation = SelectionManager.worldRotation;
|
||||
dimensions = SelectionManager.worldDimensions;
|
||||
position = SelectionManager.worldPosition;
|
||||
}
|
||||
|
||||
Overlays.editOverlay(grabberMoveUp, { visible: translateHandlesVisible, position: { x: boundsCenter.x, y: top + grabberMoveUpOffset, z: boundsCenter.z } });
|
||||
|
||||
that.updateHandles();
|
||||
|
||||
var rotation = SelectionManager.worldRotation;
|
||||
var dimensions = SelectionManager.worldDimensions;
|
||||
var position = SelectionManager.worldPosition;
|
||||
|
||||
Overlays.editOverlay(baseOfEntityProjectionOverlay,
|
||||
{
|
||||
visible: true,
|
||||
solid:true,
|
||||
lineWidth: 2.0,
|
||||
position: { x: properties.position.x,
|
||||
position: { x: position.x,
|
||||
y: 0,
|
||||
z: properties.position.z },
|
||||
z: position.z },
|
||||
|
||||
dimensions: { x: properties.dimensions.x, y: properties.dimensions.z },
|
||||
rotation: properties.rotation,
|
||||
dimensions: { x: dimensions.x, y: 0, z: dimensions.z },
|
||||
rotation: rotation,
|
||||
});
|
||||
|
||||
|
||||
Overlays.editOverlay(rotateOverlayTarget, { visible: false });
|
||||
|
||||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: false,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
alpha: innerAlpha
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: false,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
alpha: outerAlpha,
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: false,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateZeroOverlay, { visible: false });
|
||||
Overlays.editOverlay(rotateCurrentOverlay, { visible: false });
|
||||
Overlays.editOverlay(rotateOverlayTarget, { visible: rotationOverlaysVisible });
|
||||
Overlays.editOverlay(rotateZeroOverlay, { visible: rotationOverlaysVisible });
|
||||
Overlays.editOverlay(rotateCurrentOverlay, { visible: rotationOverlaysVisible });
|
||||
|
||||
// TODO: we have not implemented the rotating handle/controls yet... so for now, these handles are hidden
|
||||
Overlays.editOverlay(yawHandle, { visible: rotateHandlesVisible, position: yawCorner, rotation: yawHandleRotation});
|
||||
Overlays.editOverlay(pitchHandle, { visible: rotateHandlesVisible, position: pitchCorner, rotation: pitchHandleRotation});
|
||||
Overlays.editOverlay(rollHandle, { visible: rotateHandlesVisible, position: rollCorner, rotation: rollHandleRotation});
|
||||
|
||||
Entities.editEntity(entityID, { localRenderAlpha: 0.1 });
|
||||
};
|
||||
|
||||
that.setSpaceMode = function(newSpaceMode) {
|
||||
|
@ -931,6 +952,8 @@ SelectionDisplay = (function () {
|
|||
return;
|
||||
}
|
||||
|
||||
that.updateRotationHandles();
|
||||
|
||||
var rotation, dimensions, position;
|
||||
|
||||
if (spaceMode == SPACE_LOCAL) {
|
||||
|
@ -945,12 +968,14 @@ SelectionDisplay = (function () {
|
|||
|
||||
var halfDimensions = Vec3.multiply(0.5, dimensions);
|
||||
|
||||
left = -halfDimensions.x;
|
||||
right = halfDimensions.x;
|
||||
top = halfDimensions.y;
|
||||
bottom = -halfDimensions.y;
|
||||
var left = -halfDimensions.x;
|
||||
var right = halfDimensions.x;
|
||||
var top = halfDimensions.y;
|
||||
var bottom = -halfDimensions.y;
|
||||
var front = far = halfDimensions.z;
|
||||
near = -halfDimensions.z;
|
||||
var near = -halfDimensions.z;
|
||||
|
||||
var worldTop = SelectionManager.worldDimensions.y / 2;
|
||||
|
||||
var LBN = { x: left, y: bottom, z: near };
|
||||
var RBN = { x: right, y: bottom, z: near };
|
||||
|
@ -1060,7 +1085,7 @@ SelectionDisplay = (function () {
|
|||
position: position,
|
||||
dimensions: dimensions,
|
||||
rotation: rotation,
|
||||
visible: true,
|
||||
visible: !(mode == "ROTATE_YAW" || mode == "ROTATE_PITCH" || mode == "ROTATE_ROLL"),
|
||||
});
|
||||
|
||||
Overlays.editOverlay(grabberEdgeTR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeTR });
|
||||
|
@ -1076,6 +1101,8 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(grabberEdgeFR, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFR });
|
||||
Overlays.editOverlay(grabberEdgeFL, { visible: stretchHandlesVisible, rotation: rotation, position: EdgeFL });
|
||||
|
||||
var grabberMoveUpOffset = 0.1;
|
||||
Overlays.editOverlay(grabberMoveUp, { visible: activeTool == null || mode == "TRANSLATE_UP_DOWN", position: { x: position.x, y: position.y + worldTop + grabberMoveUpOffset, z: position.z } });
|
||||
};
|
||||
|
||||
that.setOverlaysVisible = function(isVisible) {
|
||||
|
@ -1094,47 +1121,10 @@ SelectionDisplay = (function () {
|
|||
entitySelected = false;
|
||||
};
|
||||
|
||||
function applyEntityProperties(data) {
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
var entityID = data[i].entityID;
|
||||
var properties = data[i].properties;
|
||||
Entities.editEntity(entityID, properties);
|
||||
}
|
||||
selectionManager._update();
|
||||
};
|
||||
|
||||
// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the
|
||||
// redo command, and the saved properties for the undo command.
|
||||
function pushCommandForSelections() {
|
||||
var undoData = [];
|
||||
var redoData = [];
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
var currentProperties = Entities.getEntityProperties(entityID);
|
||||
undoData.push({
|
||||
entityID: entityID,
|
||||
properties: {
|
||||
position: initialProperties.position,
|
||||
rotation: initialProperties.rotation,
|
||||
dimensions: initialProperties.dimensions,
|
||||
},
|
||||
});
|
||||
redoData.push({
|
||||
entityID: entityID,
|
||||
properties: {
|
||||
position: currentProperties.position,
|
||||
rotation: currentProperties.rotation,
|
||||
dimensions: currentProperties.dimensions,
|
||||
},
|
||||
});
|
||||
}
|
||||
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
|
||||
}
|
||||
|
||||
var initialXZPick = null;
|
||||
var isConstrained = false;
|
||||
var startPosition = null;
|
||||
var duplicatedEntityIDs = null;
|
||||
var translateXZTool = {
|
||||
mode: 'TRANSLATE_XZ',
|
||||
onBegin: function(event) {
|
||||
|
@ -1149,43 +1139,32 @@ SelectionDisplay = (function () {
|
|||
// copy of the selected entities and move the _original_ entities, not
|
||||
// the new ones.
|
||||
if (event.isAlt) {
|
||||
duplicatedEntityIDs = [];
|
||||
for (var otherEntityID in SelectionManager.savedProperties) {
|
||||
var properties = SelectionManager.savedProperties[otherEntityID];
|
||||
var entityID = Entities.addEntity(properties);
|
||||
duplicatedEntityIDs.push({
|
||||
entityID: entityID,
|
||||
properties: properties,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
duplicatedEntityIDs = null;
|
||||
}
|
||||
|
||||
isConstrained = false;
|
||||
},
|
||||
onEnd: function(event, reason) {
|
||||
if (reason == 'cancel') {
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
Entities.editEntity(entityID, initialProperties);
|
||||
}
|
||||
} else {
|
||||
pushCommandForSelections();
|
||||
}
|
||||
pushCommandForSelections(duplicatedEntityIDs);
|
||||
|
||||
Overlays.editOverlay(xRailOverlay, { visible: false });
|
||||
Overlays.editOverlay(zRailOverlay, { visible: false });
|
||||
},
|
||||
onMove: function(event) {
|
||||
if (!entitySelected || mode !== "TRANSLATE_XZ") {
|
||||
return; // not allowed
|
||||
}
|
||||
|
||||
pickRay = Camera.computePickRay(event.x, event.y);
|
||||
|
||||
// translate mode left/right based on view toward entity
|
||||
var newIntersection = rayPlaneIntersection(pickRay,
|
||||
selectedEntityPropertiesOriginalPosition,
|
||||
Quat.getFront(lastCameraOrientation));
|
||||
|
||||
var vector = Vec3.subtract(newIntersection, lastPlaneIntersection);
|
||||
var pick = rayPlaneIntersection(pickRay, SelectionManager.worldPosition, { x: 0, y: 1, z: 0 });
|
||||
var vector = Vec3.subtract(pick, initialXZPick);
|
||||
// initialXZPick = pick;
|
||||
|
||||
// If shifted, constrain to one axis
|
||||
if (event.isShifted) {
|
||||
|
@ -1222,7 +1201,6 @@ SelectionDisplay = (function () {
|
|||
if (wantDebug) {
|
||||
print("translateXZ... ");
|
||||
Vec3.print(" lastPlaneIntersection:", lastPlaneIntersection);
|
||||
Vec3.print(" newIntersection:", newIntersection);
|
||||
Vec3.print(" vector:", vector);
|
||||
Vec3.print(" newPosition:", properties.position);
|
||||
Vec3.print(" newPosition:", newPosition);
|
||||
|
@ -1239,22 +1217,28 @@ SelectionDisplay = (function () {
|
|||
mode: "TRANSLATE_UP_DOWN",
|
||||
onBegin: function(event) {
|
||||
SelectionManager.saveProperties();
|
||||
},
|
||||
onEnd: function(event, reason) {
|
||||
if (reason == 'cancel') {
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
Entities.editEntity(entityID, initialProperties);
|
||||
|
||||
// Duplicate entities if alt is pressed. This will make a
|
||||
// copy of the selected entities and move the _original_ entities, not
|
||||
// the new ones.
|
||||
if (event.isAlt) {
|
||||
duplicatedEntityIDs = [];
|
||||
for (var otherEntityID in SelectionManager.savedProperties) {
|
||||
var properties = SelectionManager.savedProperties[otherEntityID];
|
||||
var entityID = Entities.addEntity(properties);
|
||||
duplicatedEntityIDs.push({
|
||||
entityID: entityID,
|
||||
properties: properties,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
pushCommandForSelections();
|
||||
duplicatedEntityIDs = null;
|
||||
}
|
||||
},
|
||||
onEnd: function(event, reason) {
|
||||
pushCommandForSelections(duplicatedEntityIDs);
|
||||
},
|
||||
onMove: function(event) {
|
||||
if (!entitySelected || mode !== "TRANSLATE_UP_DOWN") {
|
||||
return; // not allowed
|
||||
}
|
||||
pickRay = Camera.computePickRay(event.x, event.y);
|
||||
|
||||
// translate mode left/right based on view toward entity
|
||||
|
@ -1403,21 +1387,10 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(yRailOverlay, { visible: false });
|
||||
Overlays.editOverlay(zRailOverlay, { visible: false });
|
||||
|
||||
if (reason == 'cancel') {
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
Entities.editEntity(entityID, initialProperties);
|
||||
}
|
||||
} else {
|
||||
pushCommandForSelections();
|
||||
}
|
||||
pushCommandForSelections();
|
||||
};
|
||||
|
||||
var onMove = function(event) {
|
||||
if (!entitySelected || mode !== stretchMode) {
|
||||
return; // not allowed
|
||||
}
|
||||
var proportional = spaceMode == SPACE_WORLD || event.isShifted;
|
||||
|
||||
var position, dimensions, rotation;
|
||||
|
@ -1510,14 +1483,6 @@ SelectionDisplay = (function () {
|
|||
};
|
||||
};
|
||||
|
||||
that.cancelTool = function() {
|
||||
if (activeTool) {
|
||||
activeTool.onEnd(null, 'cancel');
|
||||
activeTool = null;
|
||||
SelectionManager._update();
|
||||
}
|
||||
};
|
||||
|
||||
function addStretchTool(overlay, mode, pivot, direction) {
|
||||
if (!pivot) {
|
||||
pivot = Vec3.multiply(-1, direction);
|
||||
|
@ -1563,23 +1528,49 @@ SelectionDisplay = (function () {
|
|||
onBegin: function(event) {
|
||||
SelectionManager.saveProperties();
|
||||
initialPosition = SelectionManager.worldPosition;
|
||||
|
||||
// Size the overlays to the current selection size
|
||||
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
||||
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
||||
innerRadius = diagonal;
|
||||
outerRadius = diagonal * 1.15;
|
||||
var innerAlpha = 0.2;
|
||||
var outerAlpha = 0.2;
|
||||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
alpha: innerAlpha
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
alpha: outerAlpha,
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
});
|
||||
},
|
||||
onEnd: function(event, reason) {
|
||||
if (reason == 'cancel') {
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
Entities.editEntity(entityID, initialProperties);
|
||||
}
|
||||
} else {
|
||||
pushCommandForSelections();
|
||||
}
|
||||
Overlays.editOverlay(rotateOverlayInner, { visible: false });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { visible: false });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { visible: false });
|
||||
|
||||
pushCommandForSelections();
|
||||
},
|
||||
onMove: function(event) {
|
||||
if (!entitySelected || mode !== "ROTATE_YAW") {
|
||||
return; // not allowed
|
||||
}
|
||||
|
||||
var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems");
|
||||
|
||||
if (debug) {
|
||||
|
@ -1591,9 +1582,6 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false});
|
||||
Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false });
|
||||
Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false });
|
||||
Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true });
|
||||
|
||||
var result = Overlays.findRayIntersection(pickRay);
|
||||
|
||||
|
@ -1611,6 +1599,7 @@ SelectionDisplay = (function () {
|
|||
|
||||
var distanceFromCenter = Vec3.distance(center, result.intersection);
|
||||
var snapToInner = false;
|
||||
// var innerRadius = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
||||
if (distanceFromCenter < innerRadius) {
|
||||
angleFromZero = Math.floor(angleFromZero/innerSnapAngle) * innerSnapAngle;
|
||||
snapToInner = true;
|
||||
|
@ -1671,22 +1660,49 @@ SelectionDisplay = (function () {
|
|||
onBegin: function(event) {
|
||||
SelectionManager.saveProperties();
|
||||
initialPosition = SelectionManager.worldPosition;
|
||||
|
||||
// Size the overlays to the current selection size
|
||||
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
||||
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
||||
var innerRadius = diagonal;
|
||||
var outerRadius = diagonal * 1.15;
|
||||
var innerAlpha = 0.2;
|
||||
var outerAlpha = 0.2;
|
||||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
alpha: innerAlpha
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
alpha: outerAlpha,
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
});
|
||||
},
|
||||
onEnd: function(event, reason) {
|
||||
if (reason == 'cancel') {
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
Entities.editEntity(entityID, initialProperties);
|
||||
}
|
||||
} else {
|
||||
pushCommandForSelections();
|
||||
}
|
||||
Overlays.editOverlay(rotateOverlayInner, { visible: false });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { visible: false });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { visible: false });
|
||||
|
||||
pushCommandForSelections();
|
||||
},
|
||||
onMove: function(event) {
|
||||
if (!entitySelected || mode !== "ROTATE_PITCH") {
|
||||
return; // not allowed
|
||||
}
|
||||
var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems");
|
||||
|
||||
if (debug) {
|
||||
|
@ -1698,9 +1714,6 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false});
|
||||
Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false });
|
||||
Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false });
|
||||
Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true });
|
||||
var result = Overlays.findRayIntersection(pickRay);
|
||||
|
||||
if (debug) {
|
||||
|
@ -1777,22 +1790,49 @@ SelectionDisplay = (function () {
|
|||
onBegin: function(event) {
|
||||
SelectionManager.saveProperties();
|
||||
initialPosition = SelectionManager.worldPosition;
|
||||
|
||||
// Size the overlays to the current selection size
|
||||
var diagonal = (Vec3.length(selectionManager.worldDimensions) / 2) * 1.1;
|
||||
var halfDimensions = Vec3.multiply(selectionManager.worldDimensions, 0.5);
|
||||
var innerRadius = diagonal;
|
||||
var outerRadius = diagonal * 1.15;
|
||||
var innerAlpha = 0.2;
|
||||
var outerAlpha = 0.2;
|
||||
Overlays.editOverlay(rotateOverlayInner,
|
||||
{
|
||||
visible: true,
|
||||
size: innerRadius,
|
||||
innerRadius: 0.9,
|
||||
alpha: innerAlpha
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayOuter,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius,
|
||||
innerRadius: 0.9,
|
||||
startAt: 0,
|
||||
endAt: 360,
|
||||
alpha: outerAlpha,
|
||||
});
|
||||
|
||||
Overlays.editOverlay(rotateOverlayCurrent,
|
||||
{
|
||||
visible: true,
|
||||
size: outerRadius,
|
||||
startAt: 0,
|
||||
endAt: 0,
|
||||
innerRadius: 0.9,
|
||||
});
|
||||
},
|
||||
onEnd: function(event, reason) {
|
||||
if (reason == 'cancel') {
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
Entities.editEntity(entityID, initialProperties);
|
||||
}
|
||||
} else {
|
||||
pushCommandForSelections();
|
||||
}
|
||||
Overlays.editOverlay(rotateOverlayInner, { visible: false });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { visible: false });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { visible: false });
|
||||
|
||||
pushCommandForSelections();
|
||||
},
|
||||
onMove: function(event) {
|
||||
if (!entitySelected || mode !== "ROTATE_ROLL") {
|
||||
return; // not allowed
|
||||
}
|
||||
var debug = Menu.isOptionChecked("Debug Ryans Rotation Problems");
|
||||
|
||||
if (debug) {
|
||||
|
@ -1804,9 +1844,6 @@ SelectionDisplay = (function () {
|
|||
Overlays.editOverlay(selectionBox, { ignoreRayIntersection: true, visible: false});
|
||||
Overlays.editOverlay(baseOfEntityProjectionOverlay, { ignoreRayIntersection: true, visible: false });
|
||||
Overlays.editOverlay(rotateOverlayTarget, { ignoreRayIntersection: false });
|
||||
Overlays.editOverlay(rotateOverlayInner, { ignoreRayIntersection: true });
|
||||
Overlays.editOverlay(rotateOverlayOuter, { ignoreRayIntersection: true });
|
||||
Overlays.editOverlay(rotateOverlayCurrent, { ignoreRayIntersection: true });
|
||||
var result = Overlays.findRayIntersection(pickRay);
|
||||
|
||||
if (debug) {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
|
||||
// newEditEntities.js
|
||||
// examples
|
||||
//
|
||||
|
@ -282,7 +282,7 @@ var toolBar = (function () {
|
|||
toggleNewModelButton(false);
|
||||
|
||||
file = Window.browse("Select your model file ...",
|
||||
Settings.getValue("LastModelUploadLocation").path(),
|
||||
Settings.getValue("LastModelUploadLocation").path(),
|
||||
"Model files (*.fst *.fbx)");
|
||||
//"Model files (*.fst *.fbx *.svo)");
|
||||
if (file !== null) {
|
||||
|
@ -305,7 +305,7 @@ var toolBar = (function () {
|
|||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
Entities.addEntity({
|
||||
Entities.addEntity({
|
||||
type: "Box",
|
||||
position: position,
|
||||
dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION },
|
||||
|
@ -322,7 +322,7 @@ var toolBar = (function () {
|
|||
var position = Vec3.sum(MyAvatar.position, Vec3.multiply(Quat.getFront(MyAvatar.orientation), SPAWN_DISTANCE));
|
||||
|
||||
if (position.x > 0 && position.y > 0 && position.z > 0) {
|
||||
Entities.addEntity({
|
||||
Entities.addEntity({
|
||||
type: "Sphere",
|
||||
position: position,
|
||||
dimensions: { x: DEFAULT_DIMENSION, y: DEFAULT_DIMENSION, z: DEFAULT_DIMENSION },
|
||||
|
@ -468,7 +468,7 @@ function mousePressEvent(event) {
|
|||
|
||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(), properties.position)) * 180 / 3.14;
|
||||
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
|
||||
&& (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||
|
||||
if (0 < x && sizeOK) {
|
||||
|
@ -502,7 +502,7 @@ function mousePressEvent(event) {
|
|||
w: selectedEntityProperties.rotation.w,
|
||||
};
|
||||
selectedEntityProperties.glowLevel = 0.0;
|
||||
|
||||
|
||||
print("Clicked on " + selectedEntityID.id + " " + entitySelected);
|
||||
tooltip.updateText(selectedEntityProperties);
|
||||
tooltip.show(true);
|
||||
|
@ -516,7 +516,7 @@ function mouseMoveEvent(event) {
|
|||
if (!isActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// allow the selectionDisplay and cameraManager to handle the event first, if it doesn't handle it, then do our own thing
|
||||
if (selectionDisplay.mouseMoveEvent(event) || cameraManager.mouseMoveEvent(event)) {
|
||||
return;
|
||||
|
@ -531,11 +531,11 @@ function mouseMoveEvent(event) {
|
|||
}
|
||||
|
||||
var halfDiagonal = Vec3.length(entityIntersection.properties.dimensions) / 2.0;
|
||||
|
||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(),
|
||||
|
||||
var angularSize = 2 * Math.atan(halfDiagonal / Vec3.distance(Camera.getPosition(),
|
||||
entityIntersection.properties.position)) * 180 / 3.14;
|
||||
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
|
||||
var sizeOK = (allowLargeModels || angularSize < MAX_ANGULAR_SIZE)
|
||||
&& (allowSmallModels || angularSize > MIN_ANGULAR_SIZE);
|
||||
|
||||
if (entityIntersection.entityID.isKnownID && sizeOK) {
|
||||
|
@ -545,7 +545,7 @@ function mouseMoveEvent(event) {
|
|||
highlightedEntityID = entityIntersection.entityID;
|
||||
selectionDisplay.highlightSelectable(entityIntersection.entityID);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -585,9 +585,9 @@ function setupModelMenus() {
|
|||
}
|
||||
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Paste Models", shortcutKey: "CTRL+META+V", afterItem: "Edit Properties..." });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Large Models", shortcutKey: "CTRL+META+L",
|
||||
afterItem: "Paste Models", isCheckable: true });
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S",
|
||||
Menu.addMenuItem({ menuName: "Edit", menuItemName: "Allow Select Small Models", shortcutKey: "CTRL+META+S",
|
||||
afterItem: "Allow Select Large Models", isCheckable: true });
|
||||
|
||||
Menu.addMenuItem({ menuName: "File", menuItemName: "Models", isSeparator: true, beforeItem: "Settings" });
|
||||
|
@ -641,14 +641,24 @@ function handeMenuEvent(menuItem) {
|
|||
} else if (menuItem == "Allow Select Large Models") {
|
||||
allowLargeModels = Menu.isOptionChecked("Allow Select Large Models");
|
||||
} else if (menuItem == "Delete") {
|
||||
if (entitySelected) {
|
||||
if (SelectionManager.hasSelection()) {
|
||||
print(" Delete Entity.... selectedEntityID="+ selectedEntityID);
|
||||
SelectionManager.saveProperties();
|
||||
var savedProperties = [];
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
Entities.deleteEntity(selectionManager.selections[i]);
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
SelectionManager.savedProperties[entityID.id];
|
||||
savedProperties.push({
|
||||
entityID: entityID,
|
||||
properties: initialProperties
|
||||
});
|
||||
Entities.deleteEntity(entityID);
|
||||
}
|
||||
SelectionManager.clearSelections();
|
||||
pushCommandForSelections([], savedProperties);
|
||||
selectionDisplay.unselect(selectedEntityID);
|
||||
entitySelected = false;
|
||||
selectionManager.clearSelections();
|
||||
} else {
|
||||
print(" Delete Entity.... not holding...");
|
||||
}
|
||||
|
@ -658,15 +668,16 @@ function handeMenuEvent(menuItem) {
|
|||
editModelID = -1;
|
||||
if (selectionManager.selections.length == 1) {
|
||||
print(" Edit Properties.... selectedEntityID="+ selectedEntityID);
|
||||
editModelID = selectedEntityID;
|
||||
editModelID = selectionManager.selections[0];
|
||||
} else {
|
||||
print(" Edit Properties.... not holding...");
|
||||
}
|
||||
if (editModelID != -1) {
|
||||
print(" Edit Properties.... about to edit properties...");
|
||||
entityPropertyDialogBox.openDialog(editModelID);
|
||||
selectionManager._update();
|
||||
}
|
||||
|
||||
|
||||
} else if (menuItem == "Paste Models") {
|
||||
modelImporter.paste();
|
||||
} else if (menuItem == "Export Models") {
|
||||
|
@ -694,8 +705,6 @@ Controller.keyReleaseEvent.connect(function (event) {
|
|||
handeMenuEvent("Delete");
|
||||
} else if (event.text == "TAB") {
|
||||
selectionDisplay.toggleSpaceMode();
|
||||
} else if (event.text == "ESC") {
|
||||
selectionDisplay.cancelTool();
|
||||
} else if (event.text == "f") {
|
||||
if (entitySelected) {
|
||||
// Get latest properties
|
||||
|
@ -706,8 +715,130 @@ Controller.keyReleaseEvent.connect(function (event) {
|
|||
if (isActive) {
|
||||
cameraManager.enable();
|
||||
}
|
||||
} else {
|
||||
var delta = null;
|
||||
|
||||
if (event.text == 'UP') {
|
||||
if (event.isControl || event.isAlt) {
|
||||
delta = { x: 0, y: 1, z: 0 };
|
||||
} else {
|
||||
delta = { x: 0, y: 0, z: -1 };
|
||||
}
|
||||
} else if (event.text == 'DOWN') {
|
||||
if (event.isControl || event.isAlt) {
|
||||
delta = { x: 0, y: -1, z: 0 };
|
||||
} else {
|
||||
delta = { x: 0, y: 0, z: 1 };
|
||||
}
|
||||
} else if (event.text == 'LEFT') {
|
||||
delta = { x: -1, y: 0, z: 0 };
|
||||
} else if (event.text == 'RIGHT') {
|
||||
delta = { x: 1, y: 0, z: 0 };
|
||||
}
|
||||
|
||||
if (delta != null) {
|
||||
// Adjust delta so that movements are relative to the current camera orientation
|
||||
var lookDirection = Quat.getFront(Camera.getOrientation());
|
||||
lookDirection.z *= -1;
|
||||
|
||||
var angle = Math.atan2(lookDirection.z, lookDirection.x);
|
||||
angle -= (Math.PI / 4);
|
||||
|
||||
var rotation = Math.floor(angle / (Math.PI / 2)) * (Math.PI / 2);
|
||||
var rotator = Quat.fromPitchYawRollRadians(0, rotation, 0);
|
||||
|
||||
delta = Vec3.multiplyQbyV(rotator, delta);
|
||||
|
||||
SelectionManager.saveProperties();
|
||||
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
var entityID = selectionManager.selections[i];
|
||||
var properties = Entities.getEntityProperties(entityID);
|
||||
Entities.editEntity(entityID, {
|
||||
position: Vec3.sum(properties.position, delta)
|
||||
});
|
||||
}
|
||||
|
||||
pushCommandForSelections();
|
||||
|
||||
selectionManager._update();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// When an entity has been deleted we need a way to "undo" this deletion. Because it's not currently
|
||||
// possible to create an entity with a specific id, earlier undo commands to the deleted entity
|
||||
// will fail if there isn't a way to find the new entity id.
|
||||
DELETED_ENTITY_MAP = {
|
||||
}
|
||||
|
||||
function applyEntityProperties(data) {
|
||||
var properties = data.setProperties;
|
||||
var selectedEntityIDs = [];
|
||||
for (var i = 0; i < properties.length; i++) {
|
||||
var entityID = properties[i].entityID;
|
||||
if (DELETED_ENTITY_MAP[entityID.id] !== undefined) {
|
||||
entityID = DELETED_ENTITY_MAP[entityID.id];
|
||||
}
|
||||
Entities.editEntity(entityID, properties[i].properties);
|
||||
selectedEntityIDs.push(entityID);
|
||||
}
|
||||
for (var i = 0; i < data.createEntities.length; i++) {
|
||||
var entityID = data.createEntities[i].entityID;
|
||||
var properties = data.createEntities[i].properties;
|
||||
var newEntityID = Entities.addEntity(properties);
|
||||
DELETED_ENTITY_MAP[entityID.id] = newEntityID;
|
||||
print(newEntityID.isKnownID);
|
||||
if (data.selectCreated) {
|
||||
selectedEntityIDs.push(newEntityID);
|
||||
}
|
||||
}
|
||||
for (var i = 0; i < data.deleteEntities.length; i++) {
|
||||
var entityID = data.deleteEntities[i].entityID;
|
||||
if (DELETED_ENTITY_MAP[entityID.id] !== undefined) {
|
||||
entityID = DELETED_ENTITY_MAP[entityID.id];
|
||||
}
|
||||
Entities.deleteEntity(entityID);
|
||||
}
|
||||
|
||||
selectionManager.setSelections(selectedEntityIDs);
|
||||
};
|
||||
|
||||
// For currently selected entities, push a command to the UndoStack that uses the current entity properties for the
|
||||
// redo command, and the saved properties for the undo command. Also, include create and delete entity data.
|
||||
function pushCommandForSelections(createdEntityData, deletedEntityData) {
|
||||
var undoData = {
|
||||
setProperties: [],
|
||||
createEntities: deletedEntityData || [],
|
||||
deleteEntities: createdEntityData || [],
|
||||
selectCreated: true,
|
||||
};
|
||||
var redoData = {
|
||||
setProperties: [],
|
||||
createEntities: createdEntityData || [],
|
||||
deleteEntities: deletedEntityData || [],
|
||||
selectCreated: false,
|
||||
};
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var entityID = SelectionManager.selections[i];
|
||||
var initialProperties = SelectionManager.savedProperties[entityID.id];
|
||||
var currentProperties = Entities.getEntityProperties(entityID);
|
||||
undoData.setProperties.push({
|
||||
entityID: entityID,
|
||||
properties: {
|
||||
position: initialProperties.position,
|
||||
rotation: initialProperties.rotation,
|
||||
dimensions: initialProperties.dimensions,
|
||||
},
|
||||
});
|
||||
redoData.setProperties.push({
|
||||
entityID: entityID,
|
||||
properties: {
|
||||
position: currentProperties.position,
|
||||
rotation: currentProperties.rotation,
|
||||
dimensions: currentProperties.dimensions,
|
||||
},
|
||||
});
|
||||
}
|
||||
UndoStack.pushCommand(applyEntityProperties, undoData, applyEntityProperties, redoData);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ void UndoStackScriptingInterface::pushCommand(QScriptValue undoFunction, QScript
|
|||
|
||||
ScriptUndoCommand::ScriptUndoCommand(QScriptValue undoFunction, QScriptValue undoData,
|
||||
QScriptValue redoFunction, QScriptValue redoData) :
|
||||
_hasRedone(false),
|
||||
_undoFunction(undoFunction),
|
||||
_undoData(undoData),
|
||||
_redoFunction(redoFunction),
|
||||
|
@ -41,7 +42,15 @@ void ScriptUndoCommand::undo() {
|
|||
}
|
||||
|
||||
void ScriptUndoCommand::redo() {
|
||||
QMetaObject::invokeMethod(this, "doRedo");
|
||||
// QUndoStack will call `redo()` when adding a command to the stack. This
|
||||
// makes it difficult to work with commands that span a period of time - for instance,
|
||||
// the entity duplicate + move command that duplicates an entity and then moves it.
|
||||
// A better implementation might be to properly implement `mergeWith()` and `id()`
|
||||
// so that the two actions in the example would be merged.
|
||||
if (_hasRedone) {
|
||||
QMetaObject::invokeMethod(this, "doRedo");
|
||||
}
|
||||
_hasRedone = true;
|
||||
}
|
||||
|
||||
void ScriptUndoCommand::doUndo() {
|
||||
|
@ -50,7 +59,6 @@ void ScriptUndoCommand::doUndo() {
|
|||
_undoFunction.call(QScriptValue(), args);
|
||||
}
|
||||
|
||||
|
||||
void ScriptUndoCommand::doRedo() {
|
||||
QScriptValueList args;
|
||||
args << _redoData;
|
||||
|
|
|
@ -43,6 +43,7 @@ public slots:
|
|||
void doRedo();
|
||||
|
||||
private:
|
||||
bool _hasRedone;
|
||||
QScriptValue _undoFunction;
|
||||
QScriptValue _undoData;
|
||||
QScriptValue _redoFunction;
|
||||
|
|
Loading…
Reference in a new issue