//----------------------------------------------------------------------------- // Copyright (c) 2012 GarageGames, LLC // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to // deal in the Software without restriction, including without limitation the // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or // sell copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS // IN THE SOFTWARE. //----------------------------------------------------------------------------- #include "platform/platform.h" #include "forest/editor/forestUndo.h" #include "forest/forestDataFile.h" #include "forest/editor/forestEditorCtrl.h" ForestUndoAction::ForestUndoAction( const Resource &data, ForestEditorCtrl *editor, const char *description ) : UndoAction( description ), mEditor( editor ), mData( data ) { } ForestCreateUndoAction::ForestCreateUndoAction( const Resource &data, ForestEditorCtrl *editor ) : ForestUndoAction( data, editor, "Create Forest Items" ) { } void ForestCreateUndoAction::addItem( ForestItemData *data, const Point3F &position, F32 rotation, F32 scale ) { const ForestItem &item = mData->addItem( data, position, rotation, scale ); mItems.push_back( item ); // We store the datablock ID rather than the actual pointer // since the pointer could go bad. SimObjectId dataId = item.getData()->getId(); mItems.last().setData( (ForestItemData*)(uintptr_t)dataId ); } void ForestCreateUndoAction::redo() { for ( U32 i = 0; i < mItems.size(); i++ ) { const ForestItem &item = mItems[i]; // Not 64bit safe! // We store the datablock ID rather than the actual pointer // since the pointer could go bad. ForestItemData *data; if ( !Sim::findObject( (SimObjectId)(uintptr_t)(item.getData()), data ) ) { Con::errorf( "ForestCreateUndoAction::redo() - ForestItemData for item to restore does not seem to exist. Undo stack may be hosed." ); continue; } mData->addItem( item.getKey(), data, item.getTransform(), item.getScale() ); } mEditor->onUndoAction(); } void ForestCreateUndoAction::undo() { for ( S32 i = mItems.size()-1; i >= 0; i-- ) { const ForestItem &item = mItems[i]; mData->removeItem( item.getKey(), item.getPosition() ); } mEditor->onUndoAction(); } ForestDeleteUndoAction::ForestDeleteUndoAction( const Resource &data, ForestEditorCtrl *editor ) : ForestUndoAction( data, editor, "Delete Forest Items" ) { } void ForestDeleteUndoAction::removeItem( const ForestItem &item ) { // Not 64bit safe! // We store the datablock ID rather than the actual pointer // since the pointer could go bad. SimObjectId dataId = item.getData()->getId(); mItems.push_back( item ); mItems.last().setData( (ForestItemData*)(uintptr_t)dataId ); mData->removeItem( item.getKey(), item.getPosition() ); } void ForestDeleteUndoAction::removeItem( const Vector &itemList ) { for ( S32 i = 0; i < itemList.size(); i++ ) removeItem( itemList[i] ); } void ForestDeleteUndoAction::redo() { for ( U32 i = 0; i < mItems.size(); i++ ) { const ForestItem &item = mItems[i]; mData->removeItem( item.getKey(), item.getPosition() ); } mEditor->onUndoAction(); } void ForestDeleteUndoAction::undo() { for ( S32 i = mItems.size()-1; i >= 0; i-- ) { const ForestItem &item = mItems[i]; // We store the datablock ID rather than the actual pointer // since the pointer could go bad. ForestItemData *data; if ( !Sim::findObject( (SimObjectId)(uintptr_t)(item.getData()), data ) ) { Con::errorf( "ForestDeleteUndoAction::undo() - ForestItemData for item to restore does not seem to exist. Undo stack may be hosed." ); continue; } mData->addItem( item.getKey(), data, item.getTransform(), item.getScale() ); } mEditor->onUndoAction(); } ForestUpdateAction::ForestUpdateAction( const Resource &data, ForestEditorCtrl *editor ) : ForestUndoAction( data, editor, "Update Forest Items" ) { } void ForestUpdateAction::saveItem( const ForestItem &item ) { // We just store the current state... we undo it later. mItems.push_back( item ); // We store the datablock ID rather than the actual pointer // since the pointer could go bad. SimObjectId dataId = item.getData()->getId(); mItems.last().setData( (ForestItemData*)(uintptr_t)dataId ); } void ForestUpdateAction::_swapState() { Vector prevItems = mItems; mItems.clear(); for ( U32 i=0; i < prevItems.size(); i++ ) { const ForestItem &item = prevItems[i]; // Save the current state so we can reverse this swap. // // Note that we do 'not' want the const ref returned by findItem // because when we call updateItem below we would lose our copy // of the items state before the call. // ForestItem newItem = mData->findItem( item.getKey() ); if ( !newItem.isValid() ) { Con::errorf( "ForestUpdateAction::_swapState() - saved item no longer exists. Undo stack may be hosed." ); continue; } // Not 64bit safe! // We store the datablock ID rather than the actual pointer // since the pointer could go bad. ForestItemData *data; if ( !Sim::findObject( (SimObjectId)(uintptr_t)(item.getData()), data ) ) { Con::errorf( "ForestUpdateAction::_swapState() - ForestItemData for item to restore does not seem to exist. Undo stack may be hosed." ); continue; } // Now revert to the old state. mData->updateItem( item.getKey(), item.getPosition(), data, item.getTransform(), item.getScale() ); // Save the state before this swap for the next swap. newItem.setData( (ForestItemData*)(uintptr_t)data->getId() ); mItems.push_back( newItem ); } mEditor->onUndoAction(); }