Torque3D Documentation / _generateds / simObjectMemento.cpp

simObjectMemento.cpp

Engine/source/console/simObjectMemento.cpp

More...

Detailed Description

  1
  2//-----------------------------------------------------------------------------
  3// Copyright (c) 2012 GarageGames, LLC
  4//
  5// Permission is hereby granted, free of charge, to any person obtaining a copy
  6// of this software and associated documentation files (the "Software"), to
  7// deal in the Software without restriction, including without limitation the
  8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9// sell copies of the Software, and to permit persons to whom the Software is
 10// furnished to do so, subject to the following conditions:
 11//
 12// The above copyright notice and this permission notice shall be included in
 13// all copies or substantial portions of the Software.
 14//
 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
 21// IN THE SOFTWARE.
 22//-----------------------------------------------------------------------------
 23
 24#include "platform/platform.h"
 25#include "console/simObjectMemento.h"
 26
 27#include "console/simObject.h"
 28#include "console/simDatablock.h"
 29#include "core/stream/memStream.h"
 30
 31
 32SimObjectMemento::SimObjectMemento()
 33   : mState( NULL ),
 34      mIsDatablock( false )
 35{
 36}
 37
 38SimObjectMemento::~SimObjectMemento()
 39{
 40   dFree( mState );
 41}
 42
 43void SimObjectMemento::save( SimObject *object )
 44{
 45   // Cleanup any existing state data.
 46   dFree( mState );
 47   mObjectName = String::EmptyString;
 48
 49   // Use a stream to save the state.
 50   MemStream stream( 256 );
 51
 52   U32 writeFlags = 0;
 53   SimDataBlock* db = dynamic_cast<SimDataBlock*>(object);
 54   if( !db )
 55      stream.write( sizeof( "return " ) - 1, "return " );
 56   else
 57   {
 58      mIsDatablock = true;
 59
 60      // Cull the datablock name from the output so that
 61      // we can easily replace it in case the datablock's name
 62      // is already taken when we call restore().  We can't use the same
 63      // setup as with non-datablock classes as the return semantics
 64      // are not the same.
 65
 66      writeFlags |= SimObject::NoName;
 67   }
 68   
 69   object->write( stream, 0, writeFlags );
 70   stream.write( (UTF8)0 );
 71
 72   // Steal the data away from the stream.
 73   mState = (UTF8*)stream.takeBuffer();
 74   mObjectName = object->getName();
 75}
 76
 77SimObject *SimObjectMemento::restore() const
 78{
 79   // Make sure we have data to restore.
 80   if ( !mState )
 81      return NULL;
 82
 83   // TODO: We could potentially make this faster by
 84   // caching the CodeBlock generated from the string
 85
 86   SimObject* object;
 87   if( !mIsDatablock )
 88   {
 89      // Set the redefine behavior to automatically giving
 90      // the new objects unique names.  This will restore the
 91      // old names if they are still available or give reasonable
 92      // approximations if not.
 93
 94      const char* oldRedefineBehavior = Con::getVariable( "$Con::redefineBehavior" );
 95      Con::setVariable( "$Con::redefineBehavior", "renameNew" );
 96
 97      // Read the object.
 98
 99      const UTF8* result = Con::evaluate( mState );
100
101      // Restore the redefine behavior.
102
103      Con::setVariable( "$Con::redefineBehavior", oldRedefineBehavior );
104
105      if ( !result || !result[ 0 ] )
106         return NULL;
107
108      // Look up the object.
109
110      U32 objectId = dAtoi( result );
111      object = Sim::findObject( objectId );
112   }
113   else
114   {
115      String objectName = mObjectName;
116
117      // For datablocks, it's getting a little complicated.  Datablock definitions cannot be used
118      // as expressions and thus we can't get to the datablock object we create by using the
119      // Con::evaluate() return value.  Instead, we need to rely on the object name.  However, if
120      // the name is already taken and needs to be changed, we need to manually do that.  To complicate
121      // this further, we cannot rely on automatic renaming since then we don't know by what name
122      // the newly created object actually goes.  So what we do is we alter the source text snapshot
123      // and substitute a name in case the old object name is actually taken now.
124
125      char* tempBuffer;
126      if( !Sim::findObject( objectName ) )
127         tempBuffer = mState;
128      else
129      {
130         String uniqueName = Sim::getUniqueName( objectName );
131         U32 uniqueNameLen = uniqueName.length();
132
133         char* pLeftParen = dStrchr( mState, '(' );
134         if( pLeftParen == NULL )
135            return NULL;
136         U32 numCharsToLeftParen = pLeftParen - mState;
137
138         dsize_t tempBufferLen = dStrlen(mState) + uniqueNameLen + 1;
139         tempBuffer = ( char* ) dMalloc( tempBufferLen );
140         dMemcpy( tempBuffer, mState, numCharsToLeftParen );
141         dMemcpy( &tempBuffer[ numCharsToLeftParen ], uniqueName, uniqueNameLen );
142         dStrcpy( &tempBuffer[ numCharsToLeftParen + uniqueNameLen ], &mState[ numCharsToLeftParen ], tempBufferLen - numCharsToLeftParen - uniqueNameLen );
143      }
144
145      Con::evaluate( tempBuffer );
146
147      if( tempBuffer != mState )
148         dFree( tempBuffer );
149
150      if( objectName == String::EmptyString )
151         return NULL;
152
153      object = Sim::findObject( objectName );
154   }
155
156   return object;
157}
158