mirror of
https://github.com/Armored-Dragon/overte.git
synced 2025-03-11 16:13:16 +01:00
More work on Undo/Redo
This commit is contained in:
parent
d7b3c8b8fa
commit
d213cd7840
8 changed files with 190 additions and 21 deletions
|
@ -911,7 +911,6 @@ function mousePressEvent(event) {
|
|||
}
|
||||
|
||||
voxelDetails = calculateVoxelFromIntersection(intersection,"add");
|
||||
Voxels.eraseVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s);
|
||||
Voxels.setVoxel(voxelDetails.x, voxelDetails.y, voxelDetails.z, voxelDetails.s,
|
||||
newColor.red, newColor.green, newColor.blue);
|
||||
lastVoxelPosition = { x: voxelDetails.x, y: voxelDetails.y, z: voxelDetails.z };
|
||||
|
|
|
@ -3274,6 +3274,7 @@ void Application::loadScript(const QString& scriptName) {
|
|||
// we can use the same ones from the application.
|
||||
scriptEngine->getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender);
|
||||
scriptEngine->getVoxelsScriptingInterface()->setVoxelTree(_voxels.getTree());
|
||||
scriptEngine->getVoxelsScriptingInterface()->setUndoStack(&_undoStack);
|
||||
scriptEngine->getParticlesScriptingInterface()->setPacketSender(&_particleEditSender);
|
||||
scriptEngine->getParticlesScriptingInterface()->setParticleTree(_particles.getTree());
|
||||
|
||||
|
|
|
@ -161,14 +161,15 @@ Menu::Menu() :
|
|||
|
||||
|
||||
QMenu* editMenu = addMenu("Edit");
|
||||
|
||||
QUndoStack* undoStack = Application::getInstance()->getUndoStack();
|
||||
QAction* undoAction = undoStack->createUndoAction(editMenu);
|
||||
undoAction->setShortcut(Qt::CTRL | Qt::Key_Z);
|
||||
addActionToQMenuAndActionHash(editMenu, undoAction);
|
||||
|
||||
QAction* redoAction = undoStack->createRedoAction(editMenu);
|
||||
|
||||
addActionToQMenuAndActionHash(editMenu,
|
||||
undoAction);
|
||||
addActionToQMenuAndActionHash(editMenu,
|
||||
redoAction);
|
||||
redoAction->setShortcut(Qt::CTRL | Qt::SHIFT | Qt::Key_Z);
|
||||
addActionToQMenuAndActionHash(editMenu, redoAction);
|
||||
|
||||
addActionToQMenuAndActionHash(editMenu,
|
||||
MenuOption::Preferences,
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
//
|
||||
//
|
||||
// VoxelTree.h
|
||||
// hifi
|
||||
//
|
||||
|
@ -14,6 +14,7 @@
|
|||
#include "VoxelTreeElement.h"
|
||||
#include "VoxelEditPacketSender.h"
|
||||
|
||||
class QUndoStack;
|
||||
class ReadCodeColorBufferToTreeArgs;
|
||||
|
||||
class VoxelTree : public Octree {
|
||||
|
@ -44,6 +45,8 @@ public:
|
|||
virtual bool handlesEditPacketType(PacketType packetType) const;
|
||||
virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength,
|
||||
const unsigned char* editData, int maxLength, const SharedNodePointer& node);
|
||||
|
||||
void setUndoStack(QUndoStack* undoStack) { _undoStack = undoStack; }
|
||||
|
||||
private:
|
||||
// helper functions for nudgeSubTree
|
||||
|
@ -52,6 +55,8 @@ private:
|
|||
void nudgeLeaf(VoxelTreeElement* element, void* extraData);
|
||||
void chunkifyLeaf(VoxelTreeElement* element);
|
||||
void readCodeColorBufferToTreeRecursion(VoxelTreeElement* node, ReadCodeColorBufferToTreeArgs& args);
|
||||
|
||||
QUndoStack* _undoStack;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__VoxelTree__) */
|
||||
|
|
64
libraries/voxels/src/VoxelTreeCommands.cpp
Normal file
64
libraries/voxels/src/VoxelTreeCommands.cpp
Normal file
|
@ -0,0 +1,64 @@
|
|||
//
|
||||
// VoxelTreeCommands.cpp
|
||||
// hifi
|
||||
//
|
||||
// Created by Clement on 4/4/14.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
//
|
||||
|
||||
#include "VoxelTree.h"
|
||||
|
||||
#include "VoxelTreeCommands.h"
|
||||
|
||||
AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender, QUndoCommand* parent) :
|
||||
QUndoCommand("Add Voxel", parent),
|
||||
_tree(tree),
|
||||
_packetSender(packetSender),
|
||||
_voxel(voxel)
|
||||
{
|
||||
}
|
||||
|
||||
void AddVoxelCommand::redo() {
|
||||
if (_tree) {
|
||||
_tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue);
|
||||
}
|
||||
if (_packetSender) {
|
||||
_packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel);
|
||||
}
|
||||
}
|
||||
|
||||
void AddVoxelCommand::undo() {
|
||||
if (_tree) {
|
||||
_tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s);
|
||||
}
|
||||
if (_packetSender) {
|
||||
_packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel);
|
||||
}
|
||||
}
|
||||
|
||||
DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender, QUndoCommand* parent) :
|
||||
QUndoCommand("Delete Voxel", parent),
|
||||
_tree(tree),
|
||||
_packetSender(packetSender),
|
||||
_voxel(voxel)
|
||||
{
|
||||
}
|
||||
|
||||
void DeleteVoxelCommand::redo() {
|
||||
if (_tree) {
|
||||
_tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s);
|
||||
}
|
||||
if (_packetSender) {
|
||||
_packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel);
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteVoxelCommand::undo() {
|
||||
if (_tree) {
|
||||
_tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue);
|
||||
}
|
||||
if (_packetSender) {
|
||||
_packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel);
|
||||
}
|
||||
}
|
46
libraries/voxels/src/VoxelTreeCommands.h
Normal file
46
libraries/voxels/src/VoxelTreeCommands.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
//
|
||||
// VoxelTreeCommands.h
|
||||
// hifi
|
||||
//
|
||||
// Created by Clement on 4/4/14.
|
||||
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#ifndef __hifi__VoxelTreeCommands__
|
||||
#define __hifi__VoxelTreeCommands__
|
||||
|
||||
#include <QRgb>
|
||||
#include <QUndoCommand>
|
||||
|
||||
#include "VoxelDetail.h"
|
||||
#include "VoxelEditPacketSender.h"
|
||||
|
||||
class VoxelTree;
|
||||
|
||||
class AddVoxelCommand : public QUndoCommand {
|
||||
public:
|
||||
AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL);
|
||||
|
||||
virtual void redo();
|
||||
virtual void undo();
|
||||
|
||||
private:
|
||||
VoxelTree* _tree;
|
||||
VoxelEditPacketSender* _packetSender;
|
||||
VoxelDetail _voxel;
|
||||
};
|
||||
|
||||
class DeleteVoxelCommand : public QUndoCommand {
|
||||
public:
|
||||
DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL);
|
||||
|
||||
virtual void redo();
|
||||
virtual void undo();
|
||||
|
||||
private:
|
||||
VoxelTree* _tree;
|
||||
VoxelEditPacketSender* _packetSender;
|
||||
VoxelDetail _voxel;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__VoxelTreeCommands__) */
|
|
@ -6,6 +6,8 @@
|
|||
// Copyright (c) 2013 HighFidelity, Inc. All rights reserved.
|
||||
//
|
||||
|
||||
#include "VoxelTreeCommands.h"
|
||||
|
||||
#include "VoxelsScriptingInterface.h"
|
||||
|
||||
void VoxelsScriptingInterface::queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails) {
|
||||
|
@ -37,17 +39,24 @@ VoxelDetail VoxelsScriptingInterface::getVoxelAt(float x, float y, float z, floa
|
|||
}
|
||||
|
||||
void VoxelsScriptingInterface::setVoxelNonDestructive(float x, float y, float z, float scale,
|
||||
uchar red, uchar green, uchar blue) {
|
||||
uchar red, uchar green, uchar blue) {
|
||||
// setup a VoxelDetail struct with the data
|
||||
VoxelDetail addVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE,
|
||||
VoxelDetail addVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE, red, green, blue};
|
||||
|
||||
// queue the add packet
|
||||
queueVoxelAdd(PacketTypeVoxelSet, addVoxelDetail);
|
||||
|
||||
// handle the local tree also...
|
||||
if (_tree) {
|
||||
_tree->createVoxel(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, red, green, blue, false);
|
||||
if (_undoStack) {
|
||||
AddVoxelCommand* command = new AddVoxelCommand(_tree,
|
||||
addVoxelDetail,
|
||||
getVoxelPacketSender());
|
||||
_undoStack->push(command);
|
||||
} else {
|
||||
// queue the add packet
|
||||
queueVoxelAdd(PacketTypeVoxelSet, addVoxelDetail);
|
||||
_tree->createVoxel(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, red, green, blue, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -57,26 +66,68 @@ void VoxelsScriptingInterface::setVoxel(float x, float y, float z, float scale,
|
|||
VoxelDetail addVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE, red, green, blue};
|
||||
|
||||
// queue the destructive add
|
||||
queueVoxelAdd(PacketTypeVoxelSetDestructive, addVoxelDetail);
|
||||
|
||||
// handle the local tree also...
|
||||
if (_tree) {
|
||||
_tree->createVoxel(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, red, green, blue, true);
|
||||
if (_undoStack) {
|
||||
AddVoxelCommand* addCommand = new AddVoxelCommand(_tree,
|
||||
addVoxelDetail,
|
||||
getVoxelPacketSender());
|
||||
|
||||
VoxelTreeElement* deleteVoxelElement = _tree->getVoxelAt(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s);
|
||||
if (deleteVoxelElement) {
|
||||
nodeColor color;
|
||||
memcpy(&color, &deleteVoxelElement->getColor(), sizeof(nodeColor));
|
||||
VoxelDetail deleteVoxelDetail = {addVoxelDetail.x,
|
||||
addVoxelDetail.y,
|
||||
addVoxelDetail.z,
|
||||
addVoxelDetail.s,
|
||||
color[0],
|
||||
color[1],
|
||||
color[2]};
|
||||
DeleteVoxelCommand* delCommand = new DeleteVoxelCommand(_tree,
|
||||
deleteVoxelDetail,
|
||||
getVoxelPacketSender());
|
||||
_undoStack->beginMacro(addCommand->text());
|
||||
qDebug() << "Macro";
|
||||
_undoStack->push(delCommand);
|
||||
_undoStack->push(addCommand);
|
||||
_undoStack->endMacro();
|
||||
} else {
|
||||
_undoStack->push(addCommand);
|
||||
}
|
||||
} else {
|
||||
// queue the destructive add
|
||||
queueVoxelAdd(PacketTypeVoxelSetDestructive, addVoxelDetail);
|
||||
_tree->createVoxel(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s, red, green, blue, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void VoxelsScriptingInterface::eraseVoxel(float x, float y, float z, float scale) {
|
||||
|
||||
// setup a VoxelDetail struct with data
|
||||
VoxelDetail deleteVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE, 0, 0, 0};
|
||||
VoxelDetail deleteVoxelDetail = {x / (float)TREE_SCALE, y / (float)TREE_SCALE, z / (float)TREE_SCALE,
|
||||
scale / (float)TREE_SCALE};
|
||||
|
||||
getVoxelPacketSender()->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &deleteVoxelDetail);
|
||||
|
||||
// handle the local tree also...
|
||||
if (_tree) {
|
||||
_tree->deleteVoxelAt(deleteVoxelDetail.x, deleteVoxelDetail.y, deleteVoxelDetail.z, deleteVoxelDetail.s);
|
||||
VoxelTreeElement* deleteVoxelElement = _tree->getVoxelAt(deleteVoxelDetail.x, deleteVoxelDetail.y, deleteVoxelDetail.z, deleteVoxelDetail.s);
|
||||
if (deleteVoxelElement) {
|
||||
deleteVoxelDetail.red = deleteVoxelElement->getColor()[0];
|
||||
deleteVoxelDetail.green = deleteVoxelElement->getColor()[1];
|
||||
deleteVoxelDetail.blue = deleteVoxelElement->getColor()[2];
|
||||
}
|
||||
|
||||
if (_undoStack) {
|
||||
DeleteVoxelCommand* command = new DeleteVoxelCommand(_tree,
|
||||
deleteVoxelDetail,
|
||||
getVoxelPacketSender());
|
||||
_undoStack->push(command);
|
||||
} else {
|
||||
getVoxelPacketSender()->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &deleteVoxelDetail);
|
||||
_tree->deleteVoxelAt(deleteVoxelDetail.x, deleteVoxelDetail.y, deleteVoxelDetail.z, deleteVoxelDetail.s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -22,12 +22,13 @@
|
|||
class VoxelsScriptingInterface : public OctreeScriptingInterface {
|
||||
Q_OBJECT
|
||||
public:
|
||||
VoxelsScriptingInterface() : _tree(NULL) {};
|
||||
VoxelsScriptingInterface() : _tree(NULL), _undoStack(NULL) {};
|
||||
VoxelEditPacketSender* getVoxelPacketSender() { return (VoxelEditPacketSender*)getPacketSender(); }
|
||||
|
||||
virtual NodeType_t getServerNodeType() const { return NodeType::VoxelServer; }
|
||||
virtual OctreeEditPacketSender* createPacketSender() { return new VoxelEditPacketSender(); }
|
||||
void setVoxelTree(VoxelTree* tree) { _tree = tree; }
|
||||
void setUndoStack(QUndoStack* undoStack) { _undoStack = undoStack; }
|
||||
|
||||
public slots:
|
||||
|
||||
|
@ -79,6 +80,7 @@ public slots:
|
|||
private:
|
||||
void queueVoxelAdd(PacketType addPacketType, VoxelDetail& addVoxelDetails);
|
||||
VoxelTree* _tree;
|
||||
QUndoStack* _undoStack;
|
||||
};
|
||||
|
||||
#endif /* defined(__hifi__VoxelsScriptingInterface__) */
|
||||
|
|
Loading…
Reference in a new issue