mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-05 06:36:21 +02:00
Add undo/redo for physics
This commit is contained in:
parent
709e7e7d90
commit
18ce5ba30f
2 changed files with 77 additions and 0 deletions
|
@ -48,6 +48,27 @@ History = (function () {
|
|||
MAX_HISTORY_ITEMS = 100,
|
||||
undoPosition = -1; // The next history item to undo; the next history item to redo = undoIndex + 1.
|
||||
|
||||
function doKick(entityID) {
|
||||
var properties,
|
||||
NO_KICK_ENTITY_TYPES = ["Text", "Web"], // These entities don't respond to gravity so don't kick them.
|
||||
DYNAMIC_VELOCITY_THRESHOLD = 0.05, // See EntityMotionState.cpp DYNAMIC_LINEAR_VELOCITY_THRESHOLD
|
||||
DYNAMIC_VELOCITY_KICK = { x: 0, y: 0.1, z: 0 };
|
||||
|
||||
properties = Entities.getEntityProperties(entityID, ["type", "dynamic", "gravity", "velocity"]);
|
||||
if (NO_KICK_ENTITY_TYPES.indexOf(properties.type) === -1 && properties.dynamic
|
||||
&& Vec3.length(properties.gravity) > 0 && Vec3.length(properties.velocity) < DYNAMIC_VELOCITY_THRESHOLD) {
|
||||
Entities.editEntity(entityID, { velocity: DYNAMIC_VELOCITY_KICK });
|
||||
}
|
||||
}
|
||||
|
||||
function kickPhysics(entityID) {
|
||||
// Gives entities a small kick to start off physics, if necessary.
|
||||
var KICK_DELAY = 500; // ms
|
||||
|
||||
// Give physics a chance to catch up. Avoids some erratic behavior.
|
||||
Script.setTimeout(function () { doKick(entityID); }, KICK_DELAY);
|
||||
}
|
||||
|
||||
function push(undoData, redoData) {
|
||||
// Wipe any redo history after current undo position.
|
||||
if (undoPosition < history.length - 1) {
|
||||
|
@ -118,6 +139,9 @@ History = (function () {
|
|||
if (undoData.setProperties) {
|
||||
for (i = 0, length = undoData.setProperties.length; i < length; i += 1) {
|
||||
Entities.editEntity(undoData.setProperties[i].entityID, undoData.setProperties[i].properties);
|
||||
if (undoData.setProperties[i].properties.gravity) {
|
||||
kickPhysics(undoData.setProperties[i].entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,6 +175,9 @@ History = (function () {
|
|||
if (redoData.setProperties) {
|
||||
for (i = 0, length = redoData.setProperties.length; i < length; i += 1) {
|
||||
Entities.editEntity(redoData.setProperties[i].entityID, redoData.setProperties[i].properties);
|
||||
if (redoData.setProperties[i].properties.gravity) {
|
||||
kickPhysics(redoData.setProperties[i].entityID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -652,6 +652,9 @@ Selection = function (side) {
|
|||
// - Requires child entities to be collisionless, otherwise the entity tree can become self-propelled.
|
||||
// See also: Groups.group() and ungroup().
|
||||
var properties,
|
||||
property,
|
||||
undoData = [],
|
||||
redoData = [],
|
||||
i,
|
||||
length;
|
||||
|
||||
|
@ -661,14 +664,61 @@ Selection = function (side) {
|
|||
collisionless: physicsProperties.dynamic || physicsProperties.collisionless
|
||||
};
|
||||
for (i = 1, length = selection.length; i < length; i += 1) {
|
||||
undoData.push({
|
||||
entityID: selection[i].id,
|
||||
properties: {
|
||||
dynamic: selection[i].dynamic,
|
||||
collisionless: selection[i].collisionless
|
||||
}
|
||||
});
|
||||
Entities.editEntity(selection[i].id, properties);
|
||||
undoData.push({
|
||||
entityID: selection[i].id,
|
||||
properties: properties
|
||||
});
|
||||
}
|
||||
|
||||
// Undo data.
|
||||
properties = {
|
||||
position: selection[0].position,
|
||||
rotation: selection[0].rotation,
|
||||
velocity: Vec3.ZERO,
|
||||
angularVelocity: Vec3.ZERO
|
||||
};
|
||||
for (property in physicsProperties) {
|
||||
if (physicsProperties.hasOwnProperty(property)) {
|
||||
properties[property] = selectionProperties[0].properties[property];
|
||||
}
|
||||
}
|
||||
if (properties.userData === undefined) {
|
||||
properties.userData = "";
|
||||
}
|
||||
undoData.push({
|
||||
entityID: selection[0].id,
|
||||
properties: properties
|
||||
});
|
||||
|
||||
// Set root per physicsProperties.
|
||||
properties = Object.clone(physicsProperties);
|
||||
properties.userData = updatePhysicsUserData(selection[intersectedEntityIndex].userData, physicsProperties.userData);
|
||||
Entities.editEntity(rootEntityID, properties);
|
||||
|
||||
// Redo data.
|
||||
properties.position = selection[0].position;
|
||||
properties.rotation = selection[0].rotation;
|
||||
properties.velocity = Vec3.ZERO;
|
||||
properties.angularVelocity = Vec3.ZERO;
|
||||
redoData.push({
|
||||
entityID: selection[0].id,
|
||||
properties: properties
|
||||
});
|
||||
|
||||
// Add history entry.
|
||||
History.push(
|
||||
{ setProperties: undoData },
|
||||
{ setProperties: redoData }
|
||||
);
|
||||
|
||||
// Kick off physics if necessary.
|
||||
if (physicsProperties.dynamic) {
|
||||
kickPhysics(rootEntityID);
|
||||
|
|
Loading…
Reference in a new issue