#include #include #include #include #include #include "../../EditorMode/AEEditorEvents.h" #include "SceneEditOps.h" #include "SceneEditor3DEvents.h" #include "SceneEditHistory.h" namespace AtomicEditor { SceneEditHistory::SceneEditHistory(Context* context, Scene* scene) : Object(context), scene_(scene), locked_(false) { SubscribeToEvent(E_HISTORYNODEADDED, HANDLER(SceneEditHistory, HandleHistoryNodeAdded)); SubscribeToEvent(E_HISTORYNODEREMOVED, HANDLER(SceneEditHistory, HandleHistoryNodeRemoved)); SubscribeToEvent(E_HISTORYNODECHANGED, HANDLER(SceneEditHistory, HandleHistoryNodeChanged)); SubscribeToEvent(E_HISTORYCOMPONENTCHANGED, HANDLER(SceneEditHistory, HandleHistoryComponentChanged)); SubscribeToEvent(E_EDITORACTIVENODECHANGE, HANDLER(SceneEditHistory, HandleEditorActiveNodeChange)); } SceneEditHistory::~SceneEditHistory() { } void SceneEditHistory::AddUndoOp(SceneHistoryOp* op) { undoHistory_.Push(op); // adding a new undo op invalids redos for (unsigned i = 0; i < redoHistory_.Size(); i++) { delete redoHistory_[i]; } redoHistory_.Clear(); if (activeNode_.NotNull()) { if (op->type_ == SCENEHISTORYOP_NODECHANGED) { activeNodeCurrentState_.Clear(); activeNode_->Animatable::Save(activeNodeCurrentState_); activeNodeCurrentState_.Seek(0); } if (op->type_ == SCENEHISTORYOP_COMPONENTCHANGED) { ComponentChangedOp* ccop = (ComponentChangedOp*) op; currentComponentStates_[ccop->component_].Clear(); ccop->component_->Animatable::Save(currentComponentStates_[ccop->component_]); currentComponentStates_[ccop->component_].Seek(0); } } } void SceneEditHistory::HandleHistoryNodeAdded(StringHash eventType, VariantMap& eventData) { if (locked_) return; Scene* scene = static_cast(eventData[HistoryNodeAdded::P_SCENE].GetPtr()); if (scene != scene_) return; Node* node = static_cast(eventData[HistoryNodeAdded::P_NODE].GetPtr()); NodeAddedOp* op = new NodeAddedOp(node); AddUndoOp(op); } void SceneEditHistory::HandleHistoryNodeChanged(StringHash eventType, VariantMap& eventData) { if (locked_) return; Scene* scene = static_cast(eventData[HistoryNodeChanged::P_SCENE].GetPtr()); if (scene != scene_) return; Node* node = static_cast(eventData[HistoryNodeChanged::P_NODE].GetPtr()); NodeChangedOp* op = new NodeChangedOp(node, activeNodeCurrentState_); if (activeNodeCurrentState_.GetSize() != op->newState_.GetSize() || memcmp(activeNodeCurrentState_.GetData(), op->newState_.GetData(), op->newState_.GetSize())) { activeNodeCurrentState_ = op->newState_; AddUndoOp(op); } else { delete op; } } void SceneEditHistory::HandleHistoryNodeRemoved(StringHash eventType, VariantMap& eventData) { if (locked_) return; } void SceneEditHistory::HandleEditorActiveNodeChange(StringHash eventType, VariantMap& eventData) { Node* node = static_cast(eventData[EditorActiveNodeChange::P_NODE].GetPtr()); if (activeNode_ == node) return; activeNode_ = node; activeNodeCurrentState_.Clear(); currentComponentStates_.Clear(); if (activeNode_.Null()) return; node->Animatable::Save(activeNodeCurrentState_); activeNodeCurrentState_.Seek(0); const Vector >& comps = activeNode_->GetComponents(); for (unsigned i = 0; i < comps.Size(); i++) { comps[i]->Animatable::Save(currentComponentStates_[comps[i]]); currentComponentStates_[comps[i]].Seek(0); } } void SceneEditHistory::HandleHistoryComponentChanged(StringHash eventType, VariantMap& eventData) { if (locked_) return; Component* component = static_cast(eventData[HistoryComponentChanged::P_COMPONENT].GetPtr()); if (!component || component->GetNode() != activeNode_) return; assert(currentComponentStates_.Contains(component)); ComponentChangedOp* op = new ComponentChangedOp(component, currentComponentStates_[component]); if (currentComponentStates_[component].GetSize() != op->newState_.GetSize() || memcmp(currentComponentStates_[component].GetData(), op->newState_.GetData(), op->newState_.GetSize())) { activeNodeCurrentState_ = op->newState_; AddUndoOp(op); } else { delete op; } } void SceneEditHistory::BeginUndoRedo() { //VariantMap evData; //evData[SceneUndoRedoBegin::P_SCENE] = scene_; //SendEvent(E_SCENEUNDOREDOBEGIN, evData); } void SceneEditHistory::EndUndoRedo() { //VariantMap evData; //evData[SceneUndoRedoEnd::P_SCENE] = scene_; //SendEvent(E_SCENEUNDOREDOEND, evData); } void SceneEditHistory::Undo() { if (!undoHistory_.Size()) return; SceneHistoryOp* op = undoHistory_.Back(); undoHistory_.Pop(); op->Undo(); VariantMap eventData; if (op->type_ == SCENEHISTORYOP_NODECHANGED) { NodeChangedOp* ncop = (NodeChangedOp*) op; eventData[HistoryNodeChangedUndoRedo::P_NODE] = ncop->node_; ncop->node_->SendEvent(E_HISTORYNODECHANGEDUNDOREDO, eventData); } else if (op->type_ == SCENEHISTORYOP_COMPONENTCHANGED) { ComponentChangedOp* ccop = (ComponentChangedOp*) op; eventData[HistoryComponentChangedUndoRedo::P_COMPONENT] = ccop->component_; ccop->component_->SendEvent(E_HISTORYCOMPONENTCHANGEDUNDOREDO, eventData); } redoHistory_.Push(op); } void SceneEditHistory::Redo() { if (!redoHistory_.Size()) return; SceneHistoryOp* op = redoHistory_.Back(); redoHistory_.Pop(); op->Redo(); undoHistory_.Push(op); VariantMap eventData; if (op->type_ == SCENEHISTORYOP_NODECHANGED) { NodeChangedOp* ncop = (NodeChangedOp*) op; eventData[HistoryNodeChangedUndoRedo::P_NODE] = ncop->node_; ncop->node_->SendEvent(E_HISTORYNODECHANGEDUNDOREDO, eventData); } else if (op->type_ == SCENEHISTORYOP_COMPONENTCHANGED) { ComponentChangedOp* ccop = (ComponentChangedOp*) op; eventData[HistoryComponentChangedUndoRedo::P_COMPONENT] = ccop->component_; ccop->component_->SendEvent(E_HISTORYCOMPONENTCHANGEDUNDOREDO, eventData); } } }