Removed old/unfinished replay code.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@10898 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
parent
bce6113fd7
commit
f190652fb0
@ -321,15 +321,6 @@ supertuxkart_SOURCES = \
|
||||
race/race_manager.hpp \
|
||||
replay/replay.cpp \
|
||||
replay/replay.hpp \
|
||||
replay/replay_base.cpp \
|
||||
replay/replay_base.hpp \
|
||||
replay/replay_buffer_tpl.hpp \
|
||||
replay/replay_buffers.cpp \
|
||||
replay/replay_buffers.hpp \
|
||||
replay/replay_player.cpp \
|
||||
replay/replay_player.hpp \
|
||||
replay/replay_recorder.cpp \
|
||||
replay/replay_recorder.hpp \
|
||||
states_screens/credits.cpp \
|
||||
states_screens/credits.hpp \
|
||||
states_screens/dialogs/add_device_dialog.cpp \
|
||||
|
@ -1112,22 +1112,6 @@
|
||||
RelativePath="..\..\replay\replay.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_base.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_buffers.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_player.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_recorder.cpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="io"
|
||||
@ -2226,26 +2210,6 @@
|
||||
RelativePath="..\..\replay\replay.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_base.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_buffer_tpl.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_buffers.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_player.hpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\replay\replay_recorder.hpp"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="io"
|
||||
|
@ -1,3 +0,0 @@
|
||||
Those files are an unfinished attempt from Mai Semder
|
||||
and are not used atm - they are left in case that
|
||||
someone wants implement a replay mode.
|
@ -1,47 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
#include "replay/replay_base.hpp"
|
||||
|
||||
|
||||
const std::string ReplayBase::REPLAY_FOLDER = "replay";
|
||||
const std::string ReplayBase::REPLAY_FILE_EXTENSION_HUMAN_READABLE = "rph";
|
||||
const std::string ReplayBase::REPLAY_FILE_EXTENSION_BINARY = "rpb";
|
||||
|
||||
|
||||
ReplayBase::ReplayBase()
|
||||
: m_ReplayBuffers()
|
||||
{
|
||||
}
|
||||
|
||||
ReplayBase::~ReplayBase()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ReplayBase::destroy()
|
||||
{
|
||||
m_ReplayBuffers.destroy();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
@ -1,75 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_REPLAYBASE_HPP
|
||||
#define HEADER_REPLAYBASE_HPP
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "replay/replay_buffers.hpp"
|
||||
|
||||
|
||||
// the data stored for each kart in each frame
|
||||
struct ReplayKartState
|
||||
{
|
||||
sgCoord position;
|
||||
};
|
||||
// the data stored for each frame
|
||||
struct ReplayFrame
|
||||
{
|
||||
// absolute time of frame
|
||||
float time;
|
||||
// for each kart in frame, points to continious block
|
||||
// in Buffers::m_pp_blocks_kart_states with m_number_karts items
|
||||
ReplayKartState *p_kart_states;
|
||||
};
|
||||
|
||||
|
||||
class ReplayBase
|
||||
{
|
||||
public:
|
||||
static const std::string REPLAY_FOLDER;
|
||||
static const std::string REPLAY_FILE_EXTENSION_HUMAN_READABLE;
|
||||
static const std::string REPLAY_FILE_EXTENSION_BINARY;
|
||||
|
||||
public:
|
||||
|
||||
ReplayBase();
|
||||
virtual ~ReplayBase();
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
bool saveReplayHumanReadable( FILE *fd ) const { return m_ReplayBuffers.saveReplayHumanReadable( fd ); }
|
||||
|
||||
private:
|
||||
|
||||
protected:
|
||||
ReplayBuffers m_ReplayBuffers;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
||||
|
||||
#endif // HEADER_REPLAYBASE_HPP
|
||||
|
@ -1,327 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_REPLAYBUFFERTPL_HPP
|
||||
#define HEADER_REPLAYBUFFERTPL_HPP
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
|
||||
#include <new>
|
||||
|
||||
// needed for MSVC-memory-leak-checks
|
||||
#if defined( REPLAY_UNIT_TEST ) && defined( _MSC_VER )
|
||||
# ifdef _DEBUG
|
||||
# ifndef _DBG_NEW
|
||||
# include <crtdbg.h>
|
||||
inline void* __operator_new(size_t __n) { return ::operator
|
||||
new(__n,_NORMAL_BLOCK,__FILE__,__LINE__); }
|
||||
inline void* _cdecl operator new(size_t __n,const char* __fname,
|
||||
int __line) {
|
||||
return ::operator new(__n,_NORMAL_BLOCK,__fname,__line); }
|
||||
inline void _cdecl operator delete(void* __p,const char*,int)
|
||||
{ ::operator delete(__p);}
|
||||
# define _DBG_NEW new(__FILE__,__LINE__)
|
||||
# define new _DBG_NEW
|
||||
# endif // _DBG_NEW
|
||||
# else
|
||||
# define __operator_new(__n) operator new(__n)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
template<typename T> class ReplayBufferArray;
|
||||
|
||||
template<typename T>
|
||||
class ReplayBuffer
|
||||
{
|
||||
friend class ReplayBufferArray<T>;
|
||||
|
||||
public:
|
||||
ReplayBuffer() : m_pp_blocks(NULL),m_number_blocks(0),m_block_size(0),
|
||||
m_number_objects_used(0),m_healthy(true) {}
|
||||
~ReplayBuffer() { destroy(); }
|
||||
|
||||
private:
|
||||
ReplayBuffer( ReplayBuffer<T> const &c );
|
||||
ReplayBuffer<T> const &operator=( ReplayBuffer<T> const &c );
|
||||
|
||||
public:
|
||||
bool init( size_t number_preallocated_objects );
|
||||
void destroy();
|
||||
// this is false, if a reallocation failed
|
||||
bool isHealthy() const { return m_healthy; }
|
||||
// returns a new *free* object, allocated memory if necessary
|
||||
T* getNewObject();
|
||||
// returs object at given position, like usual array access,
|
||||
// does not allocate memory, index must be < getNumberObjectsUsed()
|
||||
T const* getObjectAt( size_t index ) const;
|
||||
T* getObjectAt( size_t index );
|
||||
size_t getNumberObjectsUsed() const
|
||||
{ return m_number_objects_used; }
|
||||
size_t getNumberBlocks() const { return m_number_blocks; }
|
||||
|
||||
private:
|
||||
// adds a new block of objects to m_pp_blocks with a size of m_block_size
|
||||
bool addNewBlock();
|
||||
// helper to make sure healthy bit is set, if new fails
|
||||
template<typename TT>
|
||||
TT* buffer_new_array( size_t n )
|
||||
{
|
||||
#if defined( REPLAY_UNIT_TEST ) && defined( _MSC_VER )
|
||||
// the msvc-debug-new macros didnt like nothrow
|
||||
TT *p = new TT[ n ];
|
||||
#else
|
||||
TT *p = new(std::nothrow) TT[ n ];
|
||||
#endif
|
||||
m_healthy = (NULL != p );
|
||||
return p;
|
||||
}
|
||||
|
||||
private:
|
||||
T **m_pp_blocks;
|
||||
// number of allocated blocks. we start with 1 for recording
|
||||
// for showing a replay-file it is 1
|
||||
size_t m_number_blocks;
|
||||
// size of all blocks
|
||||
size_t m_block_size;
|
||||
// number of used objects
|
||||
size_t m_number_objects_used;
|
||||
// this flag indicates, that, if any reallocation happedened, it failed
|
||||
// then recordings is blocked
|
||||
bool m_healthy;
|
||||
};
|
||||
|
||||
|
||||
// does the same as ReplayBuffer<T>, but it returns an array of objects,
|
||||
// rather than just one object ..
|
||||
template<typename T>
|
||||
class ReplayBufferArray
|
||||
{
|
||||
public:
|
||||
ReplayBufferArray() : m_Buffer(), m_array_size(0) {}
|
||||
~ReplayBufferArray() { destroy(); }
|
||||
|
||||
void destroy();
|
||||
bool init( size_t number_preallocated_arrays,
|
||||
size_t array_size );
|
||||
// returns a new *free* array of objects with size of 2nd param in init
|
||||
T* getNewArray();
|
||||
// returs objects at given position, like usual array access,
|
||||
// does not allocate memory
|
||||
T const* getArrayAt( size_t index ) const
|
||||
{ assert( m_array_size );
|
||||
return m_Buffer.getObjectAt( m_array_size * index ); }
|
||||
T* getArrayAt( size_t index )
|
||||
{ assert( m_array_size );
|
||||
return m_Buffer.getObjectAt( m_array_size * index ); }
|
||||
size_t getNumberArraysUsed() const
|
||||
{ return m_Buffer.getNumberObjectsUsed() / m_array_size; }
|
||||
size_t getNumberBlocks() const
|
||||
{ return m_Buffer.getNumberBlocks(); }
|
||||
bool isHealthy() const
|
||||
{ return m_Buffer.isHealthy(); }
|
||||
|
||||
private:
|
||||
ReplayBuffer<T> m_Buffer;
|
||||
size_t m_array_size;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
bool ReplayBuffer<T>::init( size_t number_preallocated_objects )
|
||||
{
|
||||
// make sure *clean* usage
|
||||
assert( !m_pp_blocks );
|
||||
assert( number_preallocated_objects );
|
||||
m_block_size = number_preallocated_objects;
|
||||
|
||||
if( !addNewBlock() ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void ReplayBuffer<T>::destroy()
|
||||
{
|
||||
size_t tmp;
|
||||
if( m_pp_blocks )
|
||||
{
|
||||
for( tmp = 0; tmp < m_number_blocks; ++tmp ) delete[] m_pp_blocks[tmp];
|
||||
delete[] m_pp_blocks; m_pp_blocks = NULL;
|
||||
m_number_blocks = 0;
|
||||
m_block_size = 0;
|
||||
m_number_objects_used = 0;
|
||||
m_healthy = true;
|
||||
}
|
||||
}
|
||||
|
||||
// returns a new *free* frame to be used to store the current frame-data into
|
||||
// it used to *record* the replay
|
||||
template<typename T>
|
||||
T* ReplayBuffer<T>::getNewObject()
|
||||
{
|
||||
// make sure initialization was called properly
|
||||
assert( m_pp_blocks );
|
||||
assert( m_number_blocks );
|
||||
|
||||
if( !m_healthy ) return NULL;
|
||||
|
||||
// check, if we need a new block
|
||||
if( m_number_objects_used == (m_block_size*m_number_blocks) )
|
||||
{
|
||||
// we need a new block
|
||||
if( !addNewBlock() ) return NULL;
|
||||
}
|
||||
|
||||
// get current frame
|
||||
T* block_current = m_pp_blocks[ m_number_blocks-1 ];
|
||||
size_t new_in_block_idx = m_number_objects_used % m_block_size;
|
||||
T* current = block_current + new_in_block_idx;
|
||||
|
||||
++m_number_objects_used;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
// returs frame at given position from replay data
|
||||
// used to *show* the replay
|
||||
template<typename T>
|
||||
T const* ReplayBuffer<T>::getObjectAt( size_t index ) const
|
||||
{
|
||||
// make sure initialization was called properly
|
||||
assert( m_pp_blocks );
|
||||
assert( m_number_blocks );
|
||||
assert( index < m_number_objects_used );
|
||||
assert( (index / m_block_size) < m_number_blocks );
|
||||
|
||||
T const* block = m_pp_blocks[ index / m_block_size ];
|
||||
return block + (index % m_block_size);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* ReplayBuffer<T>::getObjectAt( size_t index )
|
||||
{
|
||||
// make sure initialization was called properly
|
||||
assert( m_pp_blocks );
|
||||
assert( m_number_blocks );
|
||||
assert( index < m_number_objects_used );
|
||||
assert( (index / m_block_size) < m_number_blocks );
|
||||
|
||||
T* block = m_pp_blocks[ index / m_block_size ];
|
||||
return block + (index % m_block_size);
|
||||
}
|
||||
|
||||
// adds a new block of objects to m_pp_blocks with a size of m_block_size
|
||||
template<typename T>
|
||||
bool ReplayBuffer<T>::addNewBlock()
|
||||
{
|
||||
assert( m_block_size );
|
||||
|
||||
if( !m_healthy ) return false;
|
||||
|
||||
size_t number_blocks_new = m_number_blocks + 1;
|
||||
|
||||
T **pp_blocks_old = m_pp_blocks;
|
||||
m_pp_blocks = buffer_new_array<T*>( number_blocks_new );
|
||||
if( !m_pp_blocks )
|
||||
{
|
||||
// put back old blocks
|
||||
m_pp_blocks = pp_blocks_old;
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy old block pointers .. note: we dont copy the objects,
|
||||
// only the pointers, to blocks of objects, which is supposed
|
||||
// to be a very small number .. 2 is probably never reached
|
||||
size_t tmp;
|
||||
for( tmp = 0; tmp < m_number_blocks; ++tmp )
|
||||
m_pp_blocks[tmp] = pp_blocks_old[tmp];
|
||||
|
||||
// create new objects at new block position
|
||||
m_pp_blocks[m_number_blocks] = buffer_new_array<T>( m_block_size );
|
||||
if( !m_pp_blocks[m_number_blocks] )
|
||||
{
|
||||
// delete and put back old blocks
|
||||
delete[] m_pp_blocks;
|
||||
m_pp_blocks = pp_blocks_old;
|
||||
return false;
|
||||
}
|
||||
|
||||
// everything went fine, we got new arrays of objects
|
||||
delete[] pp_blocks_old; pp_blocks_old = NULL;
|
||||
|
||||
++m_number_blocks;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
void ReplayBufferArray<T>::destroy()
|
||||
{
|
||||
m_Buffer.destroy();
|
||||
m_array_size = 0;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool ReplayBufferArray<T>::init( size_t number_preallocated_arrays,
|
||||
size_t array_size )
|
||||
{
|
||||
assert( number_preallocated_arrays );
|
||||
assert( array_size );
|
||||
m_array_size = array_size;
|
||||
return m_Buffer.init( number_preallocated_arrays * array_size );
|
||||
}
|
||||
|
||||
// returns a new *free* array of objects
|
||||
template<typename T>
|
||||
T* ReplayBufferArray<T>::getNewArray()
|
||||
{
|
||||
if( !isHealthy() ) return NULL;
|
||||
|
||||
// check, if we need a new block
|
||||
if( m_Buffer.m_number_objects_used ==
|
||||
(m_Buffer.m_block_size*m_Buffer.m_number_blocks) )
|
||||
{
|
||||
// we need a new block
|
||||
if( !m_Buffer.addNewBlock() ) return NULL;
|
||||
}
|
||||
|
||||
// get current frame
|
||||
T* block_current = m_Buffer.m_pp_blocks[ m_Buffer.m_number_blocks-1 ];
|
||||
size_t new_in_block_idx =
|
||||
m_Buffer.m_number_objects_used % m_Buffer.m_block_size;
|
||||
T* current = block_current + new_in_block_idx;
|
||||
|
||||
assert( (current + m_array_size) <= (m_Buffer
|
||||
.m_pp_blocks[ m_Buffer.m_number_blocks-1 ]
|
||||
+ m_Buffer.m_block_size) );
|
||||
|
||||
m_Buffer.m_number_objects_used += m_array_size;
|
||||
|
||||
return current;
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
||||
|
||||
#endif // HEADER_REPLAYBUFFERTPL_HPP
|
||||
|
@ -1,175 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
#include "replay/replay_buffers.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "replay/replay_base.hpp"
|
||||
|
||||
#define REPLAY_SAVE_STATISTIC
|
||||
|
||||
ReplayBuffers::ReplayBuffers()
|
||||
: m_number_karts(0),
|
||||
m_BufferFrame(),
|
||||
m_BufferKartState()
|
||||
{
|
||||
}
|
||||
|
||||
ReplayBuffers::~ReplayBuffers()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ReplayBuffers::destroy()
|
||||
{
|
||||
m_BufferFrame.destroy();
|
||||
m_BufferKartState.destroy();
|
||||
m_number_karts = 0;
|
||||
}
|
||||
|
||||
bool ReplayBuffers::init( unsigned int number_karts,
|
||||
size_t number_preallocated_frames )
|
||||
{
|
||||
m_number_karts = number_karts;
|
||||
|
||||
if( !m_BufferFrame.init( number_preallocated_frames ) ) return false;
|
||||
if( !m_BufferKartState.init( number_preallocated_frames, number_karts ) ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ReplayFrame*
|
||||
ReplayBuffers::getNewFrame()
|
||||
{
|
||||
// make sure initialization was called properly
|
||||
assert( m_BufferFrame.getNumberObjectsUsed() == m_BufferKartState.getNumberArraysUsed() );
|
||||
|
||||
if( !isHealthy() ) return NULL;
|
||||
|
||||
ReplayFrame* frame = m_BufferFrame.getNewObject();
|
||||
if( !frame ) return NULL;
|
||||
|
||||
// get current karts-array
|
||||
ReplayKartState* karts_array = m_BufferKartState.getNewArray();
|
||||
if( !karts_array ) return NULL;
|
||||
|
||||
frame->p_kart_states = karts_array;
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
bool ReplayBuffers::saveReplayHumanReadable( FILE *fd ) const
|
||||
{
|
||||
if( !isHealthy() ) return false;
|
||||
|
||||
if( fprintf( fd, "frames: %u\n", getNumberFrames() ) < 1 ) return false;
|
||||
|
||||
#ifdef REPLAY_SAVE_STATISTIC
|
||||
float time_step_min = 9999999.0f, time_step_max = 0.0f, time_last;
|
||||
#endif
|
||||
|
||||
unsigned int frame_idx, kart_idx;
|
||||
ReplayFrame const *frame;
|
||||
ReplayKartState const *kart;
|
||||
for( frame_idx = 0; frame_idx < getNumberFrames(); ++frame_idx )
|
||||
{
|
||||
frame = getFrameAt( frame_idx );
|
||||
if( fprintf( fd, "frame %u time %f\n", frame_idx, frame->time ) < 1 ) return false;
|
||||
|
||||
for( kart_idx = 0; kart_idx < m_number_karts; ++kart_idx )
|
||||
{
|
||||
kart = frame->p_kart_states + kart_idx;
|
||||
|
||||
if( fprintf( fd, "\tkart %u: %f,%f,%f,%f,%f,%f\n", kart_idx,
|
||||
kart->position.xyz[0], kart->position.xyz[1], kart->position.xyz[2],
|
||||
kart->position.hpr[0], kart->position.hpr[1], kart->position.hpr[2] ) < 1 ) return false;
|
||||
}
|
||||
|
||||
#ifdef REPLAY_SAVE_STATISTIC
|
||||
if( frame_idx )
|
||||
{
|
||||
float diff = frame->time - time_last;
|
||||
if( diff < time_step_min ) time_step_min = diff;
|
||||
if( diff > time_step_max ) time_step_max = diff;
|
||||
}
|
||||
time_last = frame->time;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef REPLAY_SAVE_STATISTIC
|
||||
float time_step_avg;
|
||||
if( getNumberFrames() > 1 )
|
||||
{
|
||||
time_step_avg = time_last / ( getNumberFrames() - 1 );
|
||||
}
|
||||
else
|
||||
{
|
||||
time_step_avg = -1.0f;
|
||||
}
|
||||
fprintf( fd, "\n# statistic time-steps:\n# \tmin: %f\n# \tmax: %f\n# \tavg: %f\n", time_step_min, time_step_max, time_step_avg );
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReplayBuffers::loadReplayHumanReadable( FILE *fd, unsigned int number_karts )
|
||||
{
|
||||
size_t frames;
|
||||
if( fscanf( fd, "frames: %u\n", &frames ) != 1 ) return false;
|
||||
|
||||
if( !init( number_karts, frames ) ) return false;
|
||||
|
||||
assert( m_number_karts );
|
||||
unsigned int frame_idx, kart_idx, tmp;
|
||||
ReplayFrame *frame;
|
||||
ReplayKartState *kart;
|
||||
for( frame_idx = 0; frame_idx < frames; ++frame_idx )
|
||||
{
|
||||
// if we are here, it cant fail, since enough objects have to be allocated above
|
||||
frame = getNewFrame();
|
||||
assert( frame );
|
||||
|
||||
if( fscanf( fd, "frame %u time %f\n", &tmp, &frame->time ) != 2 ) return false;
|
||||
|
||||
for( kart_idx = 0; kart_idx < m_number_karts; ++kart_idx )
|
||||
{
|
||||
kart = frame->p_kart_states + kart_idx;
|
||||
|
||||
if( fscanf( fd, "\tkart %u: %f,%f,%f,%f,%f,%f\n", &tmp,
|
||||
&kart->position.xyz[0], &kart->position.xyz[1], &kart->position.xyz[2],
|
||||
&kart->position.hpr[0], &kart->position.hpr[1], &kart->position.hpr[2] ) != 7 ) return false;
|
||||
}
|
||||
}
|
||||
|
||||
assert( frames == getNumberFrames() );
|
||||
assert( m_BufferFrame.getNumberObjectsUsed() == getNumberFrames() );
|
||||
assert( m_BufferKartState.getNumberArraysUsed() == getNumberFrames() );
|
||||
|
||||
// there should be no reallocation ..
|
||||
assert( m_BufferFrame.getNumberBlocks() == 1 );
|
||||
assert( m_BufferKartState.getNumberBlocks() == 1 );
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
@ -1,77 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_REPLAYBUFFERS_HPP
|
||||
#define HEADER_REPLAYBUFFERS_HPP
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
|
||||
#include <cstdio>
|
||||
|
||||
#include "replay/replay_buffer_tpl.hpp"
|
||||
|
||||
struct ReplayKartState;
|
||||
struct ReplayFrame;
|
||||
|
||||
|
||||
// the worker-class .. administrates the memory-usage with no copy of
|
||||
// previous replay-items when reallocation needed if buffers are full
|
||||
class ReplayBuffers
|
||||
{
|
||||
public:
|
||||
|
||||
ReplayBuffers();
|
||||
~ReplayBuffers();
|
||||
|
||||
bool init( unsigned int number_karts,
|
||||
size_t number_preallocated_frames );
|
||||
void destroy();
|
||||
|
||||
// returns a new *free* frame to be used to store the current frame-data into it
|
||||
// used to *record* the replay
|
||||
ReplayFrame* getNewFrame();
|
||||
|
||||
// returs frame at given position from replay data
|
||||
// used to *show* the replay
|
||||
// if frame_index >= num_frames -> returns NULL
|
||||
ReplayFrame const* getFrameAt( size_t frame_index ) const { return m_BufferFrame.getObjectAt( frame_index ); }
|
||||
|
||||
size_t getNumberFrames() const { return m_BufferFrame.getNumberObjectsUsed(); }
|
||||
unsigned int getNumberKarts() const { return m_number_karts; }
|
||||
|
||||
bool saveReplayHumanReadable( FILE *fd ) const;
|
||||
bool loadReplayHumanReadable( FILE *fd, unsigned int number_karts );
|
||||
|
||||
private:
|
||||
bool isHealthy() const { return m_BufferFrame.isHealthy() && m_BufferKartState.isHealthy(); }
|
||||
|
||||
private:
|
||||
typedef ReplayBuffer<ReplayFrame> BufferFrame;
|
||||
typedef ReplayBufferArray<ReplayKartState> BufferKartState;
|
||||
|
||||
unsigned int m_number_karts;
|
||||
BufferFrame m_BufferFrame;
|
||||
BufferKartState m_BufferKartState;
|
||||
};
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
||||
|
||||
#endif // HEADER_REPLAYBUFFERS_HPP
|
||||
|
@ -1,186 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
#include "replay/replay_player.hpp"
|
||||
|
||||
#include "karts/kart_properties_manager.hpp"
|
||||
#include "karts/kart_properties.hpp"
|
||||
|
||||
|
||||
ReplayKart::ReplayKart()
|
||||
: m_kart_properties(NULL), m_model(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
ReplayKart::~ReplayKart()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ReplayKart::destroy()
|
||||
{
|
||||
m_kart_properties = NULL;
|
||||
}
|
||||
|
||||
bool ReplayKart::init( const std::string &strKartIdent )
|
||||
{
|
||||
assert( !m_kart_properties );
|
||||
|
||||
m_model = new ssgTransform();
|
||||
m_model->ref();
|
||||
|
||||
m_kart_properties = kart_properties_manager->getKart( strKartIdent );
|
||||
if( NULL == m_kart_properties ) return false;
|
||||
|
||||
ssgEntity *obj = m_kart_properties->getModel();
|
||||
assert( obj );
|
||||
// Optimize the model, this can't be done while loading the model
|
||||
// because it seems that it removes the name of the wheels or something
|
||||
// else needed to load the wheels as a separate object.
|
||||
ssgFlatten(obj);
|
||||
|
||||
ssgRangeSelector *lod = new ssgRangeSelector;
|
||||
|
||||
float r [ 2 ] = { -10.0f, 100.0f } ;
|
||||
lod -> addKid ( obj ) ;
|
||||
lod -> setRanges ( r, 2 ) ;
|
||||
|
||||
m_model -> addKid ( lod ) ;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
ReplayPlayer::ReplayPlayer()
|
||||
: ReplayBase(), m_current_frame_index(-1)
|
||||
{
|
||||
}
|
||||
|
||||
ReplayPlayer::~ReplayPlayer()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ReplayPlayer::destroy()
|
||||
{
|
||||
m_current_frame_index = -1;
|
||||
m_Karts.clear();
|
||||
ReplayBase::destroy();
|
||||
}
|
||||
|
||||
bool ReplayPlayer::loadReplayHumanReadable( FILE *fd )
|
||||
{
|
||||
destroy();
|
||||
|
||||
bool blnRet = false;
|
||||
int intTemp;
|
||||
char buff[1000];
|
||||
size_t number_karts;
|
||||
if( fscanf( fd, "Version: %s\n", buff ) != 1 ) return false;
|
||||
if( fscanf( fd, "numkarts: %u\n", &number_karts ) != 1 ) return false;
|
||||
if( fscanf( fd, "numplayers: %s\n", buff ) != 1 ) return false;
|
||||
if( fscanf( fd, "difficulty: %s\n", buff ) != 1 ) return false;
|
||||
if( fscanf( fd, "track: %s\n", buff ) != 1 ) return false;
|
||||
for( size_t k = 0; k < number_karts; ++k )
|
||||
{
|
||||
if( fscanf( fd, "model %d: %s\n", &intTemp, buff ) != 2 ) return false;
|
||||
|
||||
m_Karts.resize( m_Karts.size() + 1 );
|
||||
ReplayKart &kart = m_Karts[ m_Karts.size() - 1 ];
|
||||
if( !kart.init( buff ) ) return false;
|
||||
|
||||
scene->add ( kart.getModel() );
|
||||
}
|
||||
|
||||
if( !m_ReplayBuffers.loadReplayHumanReadable( fd, number_karts ) ) return false;
|
||||
|
||||
m_current_frame_index = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReplayPlayer::showReplayAt( float abs_time )
|
||||
{
|
||||
assert( m_ReplayBuffers.getNumberFrames() );
|
||||
assert( m_current_frame_index > -1 );
|
||||
assert( (size_t)m_current_frame_index < m_ReplayBuffers.getNumberFrames() );
|
||||
|
||||
ReplayFrame const* frame;
|
||||
|
||||
// find the current frame, we only scroll forward ..
|
||||
while(1)
|
||||
{
|
||||
// end reached?
|
||||
if( (m_current_frame_index + 1) == m_ReplayBuffers.getNumberFrames() ) break;
|
||||
|
||||
// check time of next frame
|
||||
frame = m_ReplayBuffers.getFrameAt( m_current_frame_index+1 );
|
||||
if( frame->time > abs_time ) break;
|
||||
|
||||
++m_current_frame_index;
|
||||
}
|
||||
|
||||
frame = m_ReplayBuffers.getFrameAt( m_current_frame_index );
|
||||
|
||||
// interpolate, if we are not at the end
|
||||
if( (m_current_frame_index + 1) < (int)m_ReplayBuffers.getNumberFrames() )
|
||||
{
|
||||
ReplayFrame const* frame_next = m_ReplayBuffers.getFrameAt( m_current_frame_index+1 );
|
||||
|
||||
// calc scale factor based on time between frames
|
||||
assert( frame_next->time > frame->time );
|
||||
assert( frame_next->time != frame->time );
|
||||
float scale = (abs_time - frame->time) / (frame_next->time - frame->time);
|
||||
|
||||
sgVec3 tmp_v3;
|
||||
sgCoord pos;
|
||||
|
||||
// calc interpolations for all objects
|
||||
for( size_t k = 0; k < m_Karts.size(); ++k )
|
||||
{
|
||||
// calc distance between next and current frame-position
|
||||
sgCopyVec3( pos.xyz, frame->p_kart_states[k].position.xyz ) ;
|
||||
sgCopyVec3( tmp_v3, frame_next->p_kart_states[k].position.xyz ) ;
|
||||
sgSubVec3( tmp_v3, pos.xyz );
|
||||
|
||||
// scale it based on time between frames
|
||||
sgScaleVec3( tmp_v3, scale );
|
||||
|
||||
// add interpolated vector
|
||||
sgAddVec3( pos.xyz, tmp_v3 );
|
||||
|
||||
// no orientation-interpolation for starters
|
||||
sgCopyVec3( pos.hpr, frame->p_kart_states[k].position.hpr );
|
||||
|
||||
m_Karts[ k ].setPosition( pos );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// replay finished, leave them at last known position
|
||||
for( size_t k = 0; k < m_Karts.size(); ++k )
|
||||
{
|
||||
m_Karts[ k ].setPosition( frame->p_kart_states[ k ].position );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
@ -1,86 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_REPLAYPLAYER_HPP
|
||||
#define HEADER_REPLAYPLAYER_HPP
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
#include <vector>
|
||||
#include "replay/replay_base.hpp"
|
||||
|
||||
|
||||
class KartProperties;
|
||||
class ReplayKart
|
||||
{
|
||||
public:
|
||||
ReplayKart();
|
||||
~ReplayKart();
|
||||
|
||||
ReplayKart( ReplayKart const &kart ) { *this = kart; }
|
||||
ReplayKart& operator=( ReplayKart const &kart )
|
||||
{
|
||||
assert( this != &kart );
|
||||
m_kart_properties = kart.m_kart_properties;
|
||||
m_model = kart.m_model;
|
||||
sgCopyCoord ( &m_position, &kart.m_position );
|
||||
return *this;
|
||||
}
|
||||
bool init( const std::string &strKartIdent );
|
||||
void destroy();
|
||||
|
||||
ssgTransform* getModel() { return m_model; }
|
||||
|
||||
void setPosition( const sgCoord &pos ) { sgCopyCoord ( &m_position, &pos ); m_model->setTransform(&m_position); }
|
||||
|
||||
private:
|
||||
const KartProperties *m_kart_properties;
|
||||
sgCoord m_position;
|
||||
ssgTransform *m_model;
|
||||
};
|
||||
|
||||
// class managing:
|
||||
// - the loading of replay-file
|
||||
// - the rendering of the replay (interpolation if needed)
|
||||
class ReplayPlayer : public ReplayBase
|
||||
{
|
||||
public:
|
||||
ReplayPlayer();
|
||||
virtual ~ReplayPlayer();
|
||||
|
||||
void destroy();
|
||||
|
||||
bool loadReplayHumanReadable( FILE *fd );
|
||||
|
||||
// calc state of replay-objects at given time
|
||||
void showReplayAt( float abs_time );
|
||||
|
||||
void reset() { m_current_frame_index = 0; }
|
||||
|
||||
private:
|
||||
typedef std::vector<ReplayKart> ReplayKarts;
|
||||
|
||||
int m_current_frame_index;
|
||||
ReplayKarts m_Karts;
|
||||
};
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
||||
|
||||
#endif // HEADER_REPLAYPLAYER_HPP
|
||||
|
@ -1,85 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
#include "replay/replay_recorder.hpp"
|
||||
|
||||
#include <cassert>
|
||||
|
||||
#include "modes/world.hpp"
|
||||
|
||||
const float ReplayRecorder::REPLAY_TIME_STEP_MIN = 1.0f / (float)ReplayRecorder::REPLAY_FREQUENCY_MAX;
|
||||
|
||||
ReplayRecorder::ReplayRecorder()
|
||||
: ReplayBase()
|
||||
{
|
||||
}
|
||||
|
||||
ReplayRecorder::~ReplayRecorder()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void ReplayRecorder::destroy()
|
||||
{
|
||||
ReplayBase::destroy();
|
||||
}
|
||||
|
||||
bool ReplayRecorder::initRecorder( unsigned int number_karts, size_t number_preallocated_frames )
|
||||
{
|
||||
assert( number_karts );
|
||||
|
||||
destroy();
|
||||
|
||||
if( !m_ReplayBuffers.init( number_karts, number_preallocated_frames ) ) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ReplayRecorder::pushFrame()
|
||||
{
|
||||
// we dont record the startphase ..
|
||||
assert( RaceManager::getWorld()->getPhase() != World::START_PHASE );
|
||||
assert( RaceManager::getWorld()->getNumKarts() == m_ReplayBuffers.getNumberKarts() );
|
||||
|
||||
// make sure we're not under time-step-min
|
||||
if( m_ReplayBuffers.getNumberFrames() )
|
||||
{
|
||||
ReplayFrame const *last_Frame = m_ReplayBuffers.getFrameAt( m_ReplayBuffers.getNumberFrames() - 1 );
|
||||
if( (RaceManager::getWorld()->getTime() - last_Frame->time) < REPLAY_TIME_STEP_MIN ) return true;
|
||||
}
|
||||
|
||||
ReplayFrame *pFrame = getNewFrame();
|
||||
if( !pFrame ) return false;
|
||||
pFrame->time = RaceManager::getWorld()->getClock();
|
||||
|
||||
Kart const *kart;
|
||||
int number_karts = RaceManager::getWorld()->getNumKarts();
|
||||
for( int kart_index = 0; kart_index < number_karts; ++kart_index )
|
||||
{
|
||||
kart = RaceManager::getKart( kart_index );
|
||||
sgCopyCoord( &( pFrame->p_kart_states[ kart_index ].position ),
|
||||
kart->getCoord() );
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
@ -1,62 +0,0 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2007 Maik Semder <ikework@gmx.de>
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_REPLAYRECORDER_HPP
|
||||
#define HEADER_REPLAYRECORDER_HPP
|
||||
|
||||
#ifdef HAVE_GHOST_REPLAY
|
||||
|
||||
#include "replay/replay_base.hpp"
|
||||
|
||||
|
||||
// class managing:
|
||||
// - the recording of the replay
|
||||
// - the serializing to file
|
||||
class ReplayRecorder : public ReplayBase
|
||||
{
|
||||
private:
|
||||
// assuming 10 minutes with 50 frames per second
|
||||
enum { BUFFER_PREALLOCATE_FRAMES = 10 * 50 * 60, };
|
||||
enum { REPLAY_FREQUENCY_MAX = 30 };
|
||||
// calculated from REPLAY_FREQUENCY_MAX
|
||||
static const float REPLAY_TIME_STEP_MIN;
|
||||
|
||||
public:
|
||||
ReplayRecorder();
|
||||
virtual ~ReplayRecorder();
|
||||
|
||||
void destroy();
|
||||
bool initRecorder( unsigned int number_karts,
|
||||
size_t number_preallocated_frames = BUFFER_PREALLOCATE_FRAMES );
|
||||
|
||||
// something might go wrong, since a new buffer may be allocated, so false means
|
||||
// no memory available
|
||||
bool pushFrame();
|
||||
|
||||
private:
|
||||
// returns a new *free* frame to be used to store the current frame-data into it
|
||||
// used to *record* the replay
|
||||
ReplayFrame* getNewFrame() { return m_ReplayBuffers.getNewFrame(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif // HAVE_GHOST_REPLAY
|
||||
|
||||
#endif // HEADER_REPLAYRECORDER_HPP
|
||||
|
Loading…
Reference in New Issue
Block a user