add session recording and playback
This commit is contained in:
parent
f8ce9193c2
commit
889be29b47
|
|
@ -17,6 +17,8 @@ class ClientRepository(ConnectionRepository.ConnectionRepository):
|
|||
|
||||
def __init__(self, dcFileName):
|
||||
ConnectionRepository.ConnectionRepository.__init__(self, base.config)
|
||||
|
||||
self.recorder = base.recorder
|
||||
|
||||
self.number2cdc={}
|
||||
self.name2cdc={}
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ class ConnectionRepository(DirectObject.DirectObject):
|
|||
self.cw = None
|
||||
|
||||
self.tcpConn = None
|
||||
self.recorder = None
|
||||
|
||||
# Reader statistics
|
||||
self.rsDatagramCount = 0
|
||||
|
|
@ -65,6 +66,22 @@ class ConnectionRepository(DirectObject.DirectObject):
|
|||
known.
|
||||
"""
|
||||
|
||||
if self.recorder and self.recorder.isPlaying():
|
||||
|
||||
# If we have a recorder and it's already in playback mode,
|
||||
# don't actually attempt to connect to a gameserver since
|
||||
# we don't need to. Just let it play back the data.
|
||||
self.notify.info("Not connecting to gameserver; using playback data instead.")
|
||||
|
||||
self.connectHttp = 1
|
||||
self.tcpConn = SocketStreamRecorder()
|
||||
self.recorder.addRecorder('gameserver', self.tcpConn)
|
||||
|
||||
self.startReaderPollTask()
|
||||
if successCallback:
|
||||
successCallback(*successArgs)
|
||||
return
|
||||
|
||||
hasProxy = 0
|
||||
if self.checkHttp():
|
||||
proxies = self.http.getProxiesForUrl(serverList[0])
|
||||
|
|
@ -151,6 +168,24 @@ class ConnectionRepository(DirectObject.DirectObject):
|
|||
if ch.isConnectionReady():
|
||||
self.tcpConn = ch.getConnection()
|
||||
self.tcpConn.userManagesMemory = 1
|
||||
|
||||
if self.recorder:
|
||||
# If we have a recorder, we wrap the connect inside a
|
||||
# SocketStreamRecorder, which will trap incoming data
|
||||
# when the recorder is set to record mode. (It will
|
||||
# also play back data when the recorder is in playback
|
||||
# mode, but in that case we never get this far in the
|
||||
# code, since we just create an empty
|
||||
# SocketStreamRecorder without actually connecting to
|
||||
# the gameserver.)
|
||||
stream = SocketStreamRecorder(self.tcpConn, 1)
|
||||
self.recorder.addRecorder('gameserver', stream)
|
||||
|
||||
# In this case, we pass ownership of the original
|
||||
# connection to the SocketStreamRecorder object.
|
||||
self.tcpConn.userManagesMemory = 0
|
||||
self.tcpConn = stream
|
||||
|
||||
self.startReaderPollTask()
|
||||
if successCallback:
|
||||
successCallback(*successArgs)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
|
||||
from libpandaexpressModules import *
|
||||
from MessengerGlobal import *
|
||||
from TaskManagerGlobal import *
|
||||
from DirectNotifyGlobal import *
|
||||
|
|
@ -16,15 +15,8 @@ class EventManager:
|
|||
if (EventManager.notify == None):
|
||||
EventManager.notify = directNotify.newCategory("EventManager")
|
||||
|
||||
if eventQueue != None:
|
||||
self.eventQueue = eventQueue
|
||||
else:
|
||||
self.eventQueue = EventQueue.getGlobalEventQueue()
|
||||
|
||||
try:
|
||||
self.eventHandler = EventHandler.getGlobalEventHandler(self.eventQueue)
|
||||
except:
|
||||
self.eventHandler = EventHandler(self.eventQueue)
|
||||
self.eventQueue = eventQueue
|
||||
self.eventHandler = None
|
||||
|
||||
def doEvents(self):
|
||||
"""
|
||||
|
|
@ -78,13 +70,29 @@ class EventManager:
|
|||
else:
|
||||
messenger.send(eventName)
|
||||
# Also send the event down into C++ land
|
||||
self.eventHandler.dispatchEvent(event)
|
||||
if self.eventHandler:
|
||||
self.eventHandler.dispatchEvent(event)
|
||||
|
||||
else:
|
||||
# An unnamed event from C++ is probably a bad thing
|
||||
EventManager.notify.warning('unnamed event in processEvent')
|
||||
|
||||
|
||||
def restart(self):
|
||||
from PandaModules import EventQueue, EventHandler
|
||||
|
||||
if self.eventQueue == None:
|
||||
self.eventQueue = EventQueue.getGlobalEventQueue()
|
||||
|
||||
if self.eventHandler == None:
|
||||
if self.eventQueue == EventQueue.getGlobalEventQueue():
|
||||
# If we are using the global event queue, then we also
|
||||
# want to use the global event handler.
|
||||
self.eventHandler = EventHandler.getGlobalEventHandler(self.eventQueue)
|
||||
else:
|
||||
# Otherwise, we need our own event handler.
|
||||
self.eventHandler = EventHandler(self.eventQueue)
|
||||
|
||||
taskMgr.add(self.eventLoopTask, 'eventManager')
|
||||
|
||||
def shutdown(self):
|
||||
|
|
|
|||
|
|
@ -132,6 +132,28 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.cameraList = []
|
||||
self.camera2d = self.render2d.attachNewNode('camera2d')
|
||||
|
||||
# Maybe create a RecorderController to record and/or play back
|
||||
# the user session.
|
||||
self.recorder = None
|
||||
playbackSession = self.config.GetString('playback-session', '')
|
||||
recordSession = self.config.GetString('record-session', '')
|
||||
if playbackSession:
|
||||
self.recorder = RecorderController()
|
||||
self.recorder.beginPlayback(Filename.fromOsSpecific(playbackSession))
|
||||
elif recordSession:
|
||||
self.recorder = RecorderController()
|
||||
self.recorder.beginRecord(Filename.fromOsSpecific(recordSession))
|
||||
|
||||
if self.recorder:
|
||||
# If we're either playing back or recording, pass the
|
||||
# random seed into the system so each session will have
|
||||
# the same random seed.
|
||||
import random, whrandom
|
||||
|
||||
seed = self.recorder.getRandomSeed()
|
||||
random.seed(seed)
|
||||
whrandom.seed(seed & 0xff, (seed >> 8) & 0xff, (seed >> 16) & 0xff)
|
||||
|
||||
# Now that we've set up the window structures, assign an exitfunc.
|
||||
self.oldexitfunc = getattr(sys, 'exitfunc', None)
|
||||
sys.exitfunc = self.exitfunc
|
||||
|
|
@ -563,6 +585,16 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.mak = self.dataRoot.attachNewNode(MouseAndKeyboard(win, 0, 'mak'))
|
||||
self.mouseWatcherNode = MouseWatcher('mouseWatcher')
|
||||
self.mouseWatcher = self.mak.attachNewNode(self.mouseWatcherNode)
|
||||
|
||||
if self.recorder:
|
||||
# If we have a recorder, the mouseWatcher belongs under a
|
||||
# special MouseRecorder node, which may intercept the
|
||||
# mouse activity.
|
||||
mouseRecorder = MouseRecorder('mouse')
|
||||
self.recorder.addRecorder('mouse', mouseRecorder.upcastToRecorderBase())
|
||||
np = self.mak.attachNewNode(mouseRecorder)
|
||||
self.mouseWatcher.reparentTo(np)
|
||||
|
||||
mb = self.mouseWatcherNode.getModifierButtons()
|
||||
mb.addButton(KeyboardButton.shift())
|
||||
mb.addButton(KeyboardButton.control())
|
||||
|
|
@ -867,6 +899,9 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# as we reasonably can before the renderFrame().
|
||||
onScreenDebug.render()
|
||||
|
||||
if self.recorder:
|
||||
self.recorder.recordFrame()
|
||||
|
||||
# Finally, render the frame.
|
||||
self.graphicsEngine.renderFrame()
|
||||
if self.clusterSyncFlag:
|
||||
|
|
@ -876,6 +911,9 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# We clear the text buffer for the onScreenDebug as soon
|
||||
# as we reasonably can after the renderFrame().
|
||||
onScreenDebug.clear()
|
||||
|
||||
if self.recorder:
|
||||
self.recorder.playFrame()
|
||||
|
||||
if self.mainWinMinimized:
|
||||
# If the main window is minimized, slow down the app a bit
|
||||
|
|
|
|||
|
|
@ -10,15 +10,15 @@
|
|||
#define WIN_SYS_LIBS $[WIN_SYS_LIBS] Ws2_32.lib
|
||||
|
||||
#define COMPONENT_LIBS \
|
||||
pgraph \
|
||||
recorder pgraph \
|
||||
pvrpn grutil chan chancfg pstatclient \
|
||||
char chat collide cull device \
|
||||
dgraph display gobj graph gsgbase \
|
||||
dgraph display event gobj graph gsgbase \
|
||||
gsgmisc light linmath mathutil net \
|
||||
parametrics pnm \
|
||||
pnmimagetypes pnmimage sgattrib sgmanip sgraph sgraphutil \
|
||||
switchnode pnmtext text tform tiff lerp loader putil \
|
||||
audio pgui pandabase
|
||||
audio pgui pandabase
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@
|
|||
#define BUILDING_DLL BUILDING_PANDAEXPRESS
|
||||
#define USE_PACKAGES net
|
||||
|
||||
#define COMPONENT_LIBS downloader event ipc express pandabase
|
||||
#define COMPONENT_LIBS downloader ipc express pandabase
|
||||
#define OTHER_LIBS dtoolconfig dtool
|
||||
|
||||
#begin metalib_target
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
#include "collisionRecorder.h"
|
||||
|
||||
#include "transformState.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "luse.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pandaNode.h"
|
||||
|
|
@ -47,7 +47,7 @@
|
|||
// is up to the handler to determine what information is
|
||||
// known and to do the right thing with it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA CollisionEntry : public TypedReferenceCount {
|
||||
class EXPCL_PANDA CollisionEntry : public TypedWritableReferenceCount {
|
||||
public:
|
||||
INLINE CollisionEntry();
|
||||
CollisionEntry(const CollisionEntry ©);
|
||||
|
|
@ -150,9 +150,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
TypedWritableReferenceCount::init_type();
|
||||
register_type(_type_handle, "CollisionEntry",
|
||||
TypedReferenceCount::get_class_type());
|
||||
TypedWritableReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -30,9 +30,9 @@ TrackerNode::
|
|||
TrackerNode(ClientBase *client, const string &device_name) :
|
||||
DataNode(device_name)
|
||||
{
|
||||
_transform_output = define_output("transform", EventStoreTransform::get_class_type());
|
||||
_transform_output = define_output("transform", TransformState::get_class_type());
|
||||
|
||||
_transform = new EventStoreTransform(TransformState::make_identity());
|
||||
_transform = TransformState::make_identity();
|
||||
|
||||
nassertv(client != (ClientBase *)NULL);
|
||||
set_tracker_coordinate_system(client->get_coordinate_system());
|
||||
|
|
@ -99,7 +99,7 @@ do_transmit_data(const DataNodeTransmit &, DataNodeTransmit &output) {
|
|||
|
||||
// Now send our matrix down the pipe. TODO: store this
|
||||
// componentwise instead of just as a matrix-based transform.
|
||||
_transform->set_value(TransformState::make_mat(_mat));
|
||||
_transform = TransformState::make_mat(_mat);
|
||||
output.set_data(_transform_output, EventParameter(_transform));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ private:
|
|||
// outputs
|
||||
int _transform_output;
|
||||
|
||||
PT(EventStoreTransform) _transform;
|
||||
CPT(TransformState) _transform;
|
||||
|
||||
private:
|
||||
PT(ClientTrackerDevice) _tracker;
|
||||
|
|
|
|||
|
|
@ -18,12 +18,16 @@
|
|||
|
||||
#include "config_dgraph.h"
|
||||
#include "dataNode.h"
|
||||
#include "dataNodeTransmit.h"
|
||||
|
||||
#include <dconfig.h>
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_dgraph);
|
||||
NotifyCategoryDef(dgraph, "");
|
||||
|
||||
ConfigureFn(config_dgraph) {
|
||||
DataNode::init_type();
|
||||
DataNodeTransmit::init_type();
|
||||
|
||||
DataNodeTransmit::register_with_read_factory();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -333,3 +333,26 @@ reconnect() {
|
|||
<< "No data connected to " << *this << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNode::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DataNode::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
PandaNode::write_datagram(manager, dg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNode::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DataNode::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
PandaNode::fillin(scan, manager);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,12 @@ private:
|
|||
typedef pvector<DataConnection> DataConnections;
|
||||
DataConnections _data_connections;
|
||||
|
||||
public:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
|
|||
|
|
@ -47,15 +47,6 @@ operator = (const DataNodeTransmit ©) {
|
|||
_data = copy._data;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::Destructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE DataNodeTransmit::
|
||||
~DataNodeTransmit() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::reserve
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -17,6 +17,19 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "dataNodeTransmit.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
|
||||
TypeHandle DataNodeTransmit::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::Destructor
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
DataNodeTransmit::
|
||||
~DataNodeTransmit() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::slot_data
|
||||
|
|
@ -31,3 +44,91 @@ slot_data(int index) {
|
|||
_data.push_back(EventParameter());
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DataNodeTransmit::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DataNodeTransmit::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
TypedWritable::write_datagram(manager, dg);
|
||||
|
||||
dg.add_uint16(_data.size());
|
||||
Data::const_iterator di;
|
||||
for (di = _data.begin(); di != _data.end(); ++di) {
|
||||
const EventParameter ¶m = (*di);
|
||||
TypedWritableReferenceCount *ptr = param.get_ptr();
|
||||
manager->write_pointer(dg, ptr);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::complete_pointers
|
||||
// Access: Public, Virtual
|
||||
// Description: Receives an array of pointers, one for each time
|
||||
// manager->read_pointer() was called in fillin().
|
||||
// Returns the number of pointers processed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int DataNodeTransmit::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = TypedWritable::complete_pointers(p_list, manager);
|
||||
|
||||
Data::iterator di;
|
||||
for (di = _data.begin(); di != _data.end(); ++di) {
|
||||
(*di) = EventParameter(DCAST(TypedWritableReferenceCount, p_list[pi++]));
|
||||
}
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type Lens is encountered
|
||||
// in the Bam file. It should create the Lens
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *DataNodeTransmit::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
DataNodeTransmit *xmit = new DataNodeTransmit;
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
xmit->fillin(scan, manager);
|
||||
|
||||
return xmit;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DataNodeTransmit::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void DataNodeTransmit::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
TypedWritable::fillin(scan, manager);
|
||||
|
||||
int num_params = scan.get_uint16();
|
||||
_data.reserve(num_params);
|
||||
for (int i = 0; i < num_params; i++) {
|
||||
manager->read_pointer(scan);
|
||||
_data.push_back(EventParameter());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
#include "eventParameter.h"
|
||||
#include "typedWritable.h"
|
||||
|
||||
class Datagram;
|
||||
class DatagramIterator;
|
||||
class BamReader;
|
||||
class BamWriter;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : DataNodeTransmit
|
||||
|
|
@ -29,12 +35,12 @@
|
|||
// array of EventParameters, one for each registered
|
||||
// input or output wire.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA DataNodeTransmit {
|
||||
class EXPCL_PANDA DataNodeTransmit : public TypedWritable {
|
||||
public:
|
||||
INLINE DataNodeTransmit();
|
||||
INLINE DataNodeTransmit(const DataNodeTransmit ©);
|
||||
INLINE void operator = (const DataNodeTransmit ©);
|
||||
INLINE ~DataNodeTransmit();
|
||||
virtual ~DataNodeTransmit();
|
||||
|
||||
INLINE void reserve(int num_wires);
|
||||
|
||||
|
|
@ -47,6 +53,33 @@ private:
|
|||
|
||||
typedef pvector<EventParameter> Data;
|
||||
Data _data;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
virtual int complete_pointers(TypedWritable **plist,
|
||||
BamReader *manager);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedWritable::init_type();
|
||||
register_type(_type_handle, "DataNodeTransmit",
|
||||
TypedWritable::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "dataNodeTransmit.I"
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "graphicsStateGuardian.h"
|
||||
#include "clearableRegion.h"
|
||||
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "mouseData.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "buttonEvent.h"
|
||||
|
|
@ -55,8 +55,14 @@
|
|||
// input. The actual rendering, and anything associated
|
||||
// with the graphics context itself, is managed by the
|
||||
// window's GraphicsStateGuardian.
|
||||
//
|
||||
// GraphicsWindows are not actually writable to bam
|
||||
// files, of course, but they may be passed as event
|
||||
// parameters, so they inherit from
|
||||
// TypedWritableReferenceCount instead of
|
||||
// TypedReferenceCount for that convenience.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA GraphicsWindow : public TypedReferenceCount, public ClearableRegion {
|
||||
class EXPCL_PANDA GraphicsWindow : public TypedWritableReferenceCount, public ClearableRegion {
|
||||
protected:
|
||||
GraphicsWindow(GraphicsPipe *pipe, GraphicsStateGuardian *gsg);
|
||||
|
||||
|
|
@ -183,9 +189,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
TypedWritableReferenceCount::init_type();
|
||||
register_type(_type_handle, "GraphicsWindow",
|
||||
TypedReferenceCount::get_class_type());
|
||||
TypedWritableReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#define LOCAL_LIBS event express pandabase
|
||||
#define LOCAL_LIBS express pandabase
|
||||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m
|
||||
#define USE_PACKAGES zlib net ssl
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#define LOCAL_LIBS express pandabase
|
||||
#define LOCAL_LIBS putil express pandabase
|
||||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m
|
||||
|
||||
|
|
@ -8,20 +8,28 @@
|
|||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx
|
||||
|
||||
#define SOURCES \
|
||||
config_event.h event.I event.h eventHandler.h eventHandler.I eventParameter.I \
|
||||
eventParameter.h eventQueue.I eventQueue.h eventReceiver.h \
|
||||
pt_Event.h throw_event.I throw_event.h
|
||||
config_event.h \
|
||||
buttonEvent.I buttonEvent.h \
|
||||
buttonEventList.I buttonEventList.h \
|
||||
event.I event.h eventHandler.h eventHandler.I \
|
||||
eventParameter.I eventParameter.h \
|
||||
eventQueue.I eventQueue.h eventReceiver.h \
|
||||
pt_Event.h throw_event.I throw_event.h
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
config_event.cxx event.cxx eventHandler.cxx \
|
||||
eventParameter.cxx eventQueue.cxx eventReceiver.cxx \
|
||||
pt_Event.cxx
|
||||
buttonEvent.cxx \
|
||||
buttonEventList.cxx \
|
||||
config_event.cxx event.cxx eventHandler.cxx \
|
||||
eventParameter.cxx eventQueue.cxx eventReceiver.cxx \
|
||||
pt_Event.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
event.I event.h eventHandler.h eventHandler.I eventParameter.I eventParameter.h \
|
||||
eventQueue.h eventQueue.I throw_event.h throw_event.I \
|
||||
eventReceiver.h \
|
||||
pt_Event.h
|
||||
#define INSTALL_HEADERS \
|
||||
buttonEvent.I buttonEvent.h \
|
||||
buttonEventList.I buttonEventList.h \
|
||||
event.I event.h eventHandler.h eventHandler.I \
|
||||
eventParameter.I eventParameter.h \
|
||||
eventQueue.I eventQueue.h eventReceiver.h \
|
||||
pt_Event.h throw_event.I throw_event.h
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
|
|
|
|||
|
|
@ -125,3 +125,23 @@ operator < (const ButtonEvent &other) const {
|
|||
|
||||
return _type < other._type;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEvent::update_mods
|
||||
// Access: Published
|
||||
// Description: Calls button_down() or button_up(), as appropriate,
|
||||
// according to the ButtonEvent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ButtonEvent::
|
||||
update_mods(ModifierButtons &mods) const {
|
||||
switch (_type) {
|
||||
case T_down:
|
||||
return mods.button_down(_button);
|
||||
|
||||
case T_up:
|
||||
return mods.button_up(_button);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,94 @@
|
|||
// Filename: buttonEvent.cxx
|
||||
// Created by: drose (01Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "buttonEvent.h"
|
||||
#include "datagram.h"
|
||||
#include "datagramIterator.h"
|
||||
#include "buttonRegistry.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEvent::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEvent::
|
||||
output(ostream &out) const {
|
||||
switch (_type) {
|
||||
case T_down:
|
||||
out << "button " << _button << " down";
|
||||
break;
|
||||
|
||||
case T_resume_down:
|
||||
out << "button " << _button << " resume down";
|
||||
break;
|
||||
|
||||
case T_up:
|
||||
out << "button " << _button << " up";
|
||||
break;
|
||||
|
||||
case T_keystroke:
|
||||
out << "keystroke " << _keycode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEvent::write_datagram
|
||||
// Access: Public
|
||||
// Description: Writes the event into a datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEvent::
|
||||
write_datagram(Datagram &dg) const {
|
||||
dg.add_uint8(_type);
|
||||
switch (_type) {
|
||||
case T_down:
|
||||
case T_resume_down:
|
||||
case T_up:
|
||||
// We write the button name. This is not particularly compact, but
|
||||
// presumably we don't get thousands of button events per frame, and
|
||||
// it is robust as the button index may change between sessions but
|
||||
// the button name will not.
|
||||
dg.add_string(_button.get_name());
|
||||
break;
|
||||
|
||||
case T_keystroke:
|
||||
dg.add_int16(_keycode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEvent::read_datagram
|
||||
// Access: Public
|
||||
// Description: Restores the event from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEvent::
|
||||
read_datagram(DatagramIterator &scan) {
|
||||
_type = (Type)scan.get_uint8();
|
||||
switch (_type) {
|
||||
case T_down:
|
||||
case T_resume_down:
|
||||
case T_up:
|
||||
_button = ButtonRegistry::ptr()->get_button(scan.get_string());
|
||||
break;
|
||||
|
||||
case T_keystroke:
|
||||
_keycode = scan.get_int16();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -23,6 +23,10 @@
|
|||
|
||||
#include "buttonHandle.h"
|
||||
#include "clockObject.h"
|
||||
#include "modifierButtons.h"
|
||||
|
||||
class Datagram;
|
||||
class DatagramIterator;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ButtonEvent
|
||||
|
|
@ -81,8 +85,14 @@ public:
|
|||
INLINE bool operator != (const ButtonEvent &other) const;
|
||||
INLINE bool operator < (const ButtonEvent &other) const;
|
||||
|
||||
INLINE bool update_mods(ModifierButtons &mods) const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
void write_datagram(Datagram &dg) const;
|
||||
void read_datagram(DatagramIterator &scan);
|
||||
|
||||
public:
|
||||
// _button will be filled in if type is T_down, T_resume_down, or
|
||||
// T_up.
|
||||
ButtonHandle _button;
|
||||
|
|
@ -0,0 +1,163 @@
|
|||
// Filename: buttonEventList.cxx
|
||||
// Created by: drose (12Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "buttonEventList.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "indent.h"
|
||||
|
||||
TypeHandle ButtonEventList::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::add_events
|
||||
// Access: Public
|
||||
// Description: Appends the events from the other list onto the end
|
||||
// of this one.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
add_events(const ButtonEventList &other) {
|
||||
_events.reserve(_events.size() + other._events.size());
|
||||
Events::const_iterator ei;
|
||||
for (ei = other._events.begin(); ei != other._events.end(); ++ei) {
|
||||
_events.push_back(*ei);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::update_mods
|
||||
// Access: Public
|
||||
// Description: Updates the indicated ModifierButtons object with all
|
||||
// of the button up/down transitions indicated in the
|
||||
// list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
update_mods(ModifierButtons &mods) const {
|
||||
Events::const_iterator ei;
|
||||
for (ei = _events.begin(); ei != _events.end(); ++ei) {
|
||||
(*ei).update_mods(mods);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
output(ostream &out) const {
|
||||
if (_events.empty()) {
|
||||
out << "(no buttons)";
|
||||
} else {
|
||||
Events::const_iterator ei;
|
||||
ei = _events.begin();
|
||||
out << "(" << (*ei);
|
||||
++ei;
|
||||
while (ei != _events.end()) {
|
||||
out << " " << (*ei);
|
||||
++ei;
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level) << _events.size() << " events:\n";
|
||||
Events::const_iterator ei;
|
||||
for (ei = _events.begin(); ei != _events.end(); ++ei) {
|
||||
indent(out, indent_level + 2) << (*ei) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
TypedWritable::write_datagram(manager, dg);
|
||||
|
||||
dg.add_uint16(_events.size());
|
||||
Events::const_iterator ei;
|
||||
for (ei = _events.begin(); ei != _events.end(); ++ei) {
|
||||
(*ei).write_datagram(dg);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type Lens is encountered
|
||||
// in the Bam file. It should create the Lens
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *ButtonEventList::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
ButtonEventList *list = new ButtonEventList;
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
list->fillin(scan, manager);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::fillin
|
||||
// Access: Public
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new ButtonEventList.
|
||||
//
|
||||
// This function is normally protected, but it is
|
||||
// declared public in this case so that MouseRecorder
|
||||
// may call it to read a ButtonEventList from the middle
|
||||
// of a datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
TypedWritable::fillin(scan, manager);
|
||||
|
||||
int num_events = scan.get_uint16();
|
||||
_events.clear();
|
||||
_events.reserve(num_events);
|
||||
for (int i = 0; i < num_events; i++) {
|
||||
ButtonEvent event;
|
||||
event.read_datagram(scan);
|
||||
_events.push_back(event);
|
||||
}
|
||||
}
|
||||
|
|
@ -27,6 +27,8 @@
|
|||
#include "pvector.h"
|
||||
|
||||
class ModifierButtons;
|
||||
class Datagram;
|
||||
class DatagramIterator;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ButtonEventList
|
||||
|
|
@ -45,6 +47,7 @@ public:
|
|||
INLINE const ButtonEvent &get_event(int n) const;
|
||||
INLINE void clear();
|
||||
|
||||
void add_events(const ButtonEventList &other);
|
||||
void update_mods(ModifierButtons &mods) const;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
|
@ -53,6 +56,16 @@ public:
|
|||
private:
|
||||
typedef pvector<ButtonEvent> Events;
|
||||
Events _events;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -17,21 +17,28 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_event.h"
|
||||
#include "buttonEventList.h"
|
||||
#include "event.h"
|
||||
#include "eventHandler.h"
|
||||
#include "eventParameter.h"
|
||||
|
||||
#include <dconfig.h>
|
||||
#include "dconfig.h"
|
||||
|
||||
Configure(config_event);
|
||||
NotifyCategoryDef(event, "");
|
||||
|
||||
ConfigureFn(config_event) {
|
||||
ButtonEventList::init_type();
|
||||
Event::init_type();
|
||||
EventHandler::init_type();
|
||||
EventStoreValueBase::init_type();
|
||||
EventStoreInt::init_type("EventStoreInt");
|
||||
EventStoreDouble::init_type("EventStoreDouble");
|
||||
EventStoreString::init_type("EventStoreString");
|
||||
|
||||
ButtonEventList::register_with_read_factory();
|
||||
EventStoreInt::register_with_read_factory();
|
||||
EventStoreDouble::register_with_read_factory();
|
||||
EventStoreString::register_with_read_factory();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include <notifyCategoryProxy.h>
|
||||
#include "notifyCategoryProxy.h"
|
||||
|
||||
NotifyCategoryDecl(event, EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS);
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ class EventReceiver;
|
|||
// makes it too expensive to get its name the Python
|
||||
// code. Now it just copies the Namable interface in.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS Event : public TypedReferenceCount {
|
||||
class EXPCL_PANDA Event : public TypedReferenceCount {
|
||||
PUBLISHED:
|
||||
Event(const string &event_name, EventReceiver *receiver = NULL);
|
||||
Event(const Event ©);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
// Filename: eventHandler.h
|
||||
// Created by: drose (08Feb99)
|
||||
// Filename: eventHandler.I
|
||||
// Created by: skyler (27Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
|
|
|
|||
|
|
@ -35,8 +35,8 @@ EventParameter() {
|
|||
// Function: EventParameter::Pointer constructor
|
||||
// Access: Public
|
||||
// Description: Defines an EventParameter that stores a pointer to
|
||||
// any kind of TypedReferenceCount object. This is the
|
||||
// most general constructor.
|
||||
// any kind of TypedWritableReferenceCount object. This
|
||||
// is the most general constructor.
|
||||
//
|
||||
// This accepts a const pointer, even though it stores
|
||||
// (and eventually returns) a non-const pointer. This
|
||||
|
|
@ -45,7 +45,7 @@ EventParameter() {
|
|||
// constness. Be careful.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE EventParameter::
|
||||
EventParameter(const TypedReferenceCount *ptr) : _ptr((TypedReferenceCount *)ptr) { }
|
||||
EventParameter(const TypedWritableReferenceCount *ptr) : _ptr((TypedWritableReferenceCount *)ptr) { }
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -105,7 +105,7 @@ operator = (const EventParameter &other) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool EventParameter::
|
||||
is_empty() const {
|
||||
return (_ptr == (TypedReferenceCount *)NULL);
|
||||
return (_ptr == (TypedWritableReferenceCount *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -201,7 +201,7 @@ get_string_value() const {
|
|||
// contains. This is the only way to retrieve the value
|
||||
// when it is not one of the above predefined types.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE TypedReferenceCount *EventParameter::
|
||||
INLINE TypedWritableReferenceCount *EventParameter::
|
||||
get_ptr() const {
|
||||
return _ptr;
|
||||
}
|
||||
|
|
@ -248,3 +248,63 @@ void EventStoreValue<Type>::
|
|||
output(ostream &out) const {
|
||||
out << _value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreValue::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
void EventStoreValue<Type>::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreValue::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
void EventStoreValue<Type>::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
TypedWritable::write_datagram(manager, dg);
|
||||
generic_write_datagram(dg, _value);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreValue::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type Lens is encountered
|
||||
// in the Bam file. It should create the Lens
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
TypedWritable *EventStoreValue<Type>::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
EventStoreValue<Type> *esv = new EventStoreValue<Type>;
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
esv->fillin(scan, manager);
|
||||
|
||||
return esv;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreValue::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
void EventStoreValue<Type>::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
TypedWritable::fillin(scan, manager);
|
||||
generic_read_datagram(_value, scan);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ TypeHandle EventStoreValueBase::_type_handle;
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void EventParameter::
|
||||
output(ostream &out) const {
|
||||
if (_ptr == (TypedReferenceCount *)NULL) {
|
||||
if (_ptr == (TypedWritableReferenceCount *)NULL) {
|
||||
out << "(empty)";
|
||||
|
||||
} else if (_ptr->is_of_type(EventStoreValueBase::get_class_type())) {
|
||||
|
|
|
|||
|
|
@ -23,23 +23,26 @@
|
|||
|
||||
#include "typedef.h"
|
||||
#include "typedObject.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "pointerTo.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EventParameter
|
||||
// Description : An optional parameter associated with an event. Each
|
||||
// event may have zero or more of these. Each parameter
|
||||
// stores a pointer to a TypedReferenceCount object,
|
||||
// which of course could be pretty much anything. To
|
||||
// store a simple value like a double or a string, the
|
||||
// EventParameter constructors transparently use the
|
||||
// EventStoreValue template class, defined below.
|
||||
// stores a pointer to a TypedWritableReferenceCount
|
||||
// object, which of course could be pretty much
|
||||
// anything. To store a simple value like a double or a
|
||||
// string, the EventParameter constructors transparently
|
||||
// use the EventStoreValue template class, defined
|
||||
// below.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS EventParameter {
|
||||
class EXPCL_PANDA EventParameter {
|
||||
PUBLISHED:
|
||||
INLINE EventParameter();
|
||||
INLINE EventParameter(const TypedReferenceCount *ptr);
|
||||
INLINE EventParameter(const TypedWritableReferenceCount *ptr);
|
||||
INLINE EventParameter(int value);
|
||||
INLINE EventParameter(double value);
|
||||
INLINE EventParameter(const string &value);
|
||||
|
|
@ -60,12 +63,12 @@ PUBLISHED:
|
|||
INLINE bool is_string() const;
|
||||
INLINE string get_string_value() const;
|
||||
|
||||
INLINE TypedReferenceCount *get_ptr() const;
|
||||
INLINE TypedWritableReferenceCount *get_ptr() const;
|
||||
|
||||
void output(ostream &out) const;
|
||||
|
||||
private:
|
||||
PT(TypedReferenceCount) _ptr;
|
||||
PT(TypedWritableReferenceCount) _ptr;
|
||||
};
|
||||
|
||||
INLINE ostream &operator << (ostream &out, const EventParameter ¶m);
|
||||
|
|
@ -76,7 +79,7 @@ INLINE ostream &operator << (ostream &out, const EventParameter ¶m);
|
|||
// which serves mainly to define the placeholder for the
|
||||
// virtual output function.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS EventStoreValueBase : public TypedReferenceCount {
|
||||
class EXPCL_PANDAEXPRESS EventStoreValueBase : public TypedWritableReferenceCount {
|
||||
public:
|
||||
virtual void output(ostream &out) const=0;
|
||||
|
||||
|
|
@ -89,9 +92,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
TypedWritableReferenceCount::init_type();
|
||||
register_type(_type_handle, "EventStoreValueBase",
|
||||
TypedReferenceCount::get_class_type());
|
||||
TypedWritableReferenceCount::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -103,12 +106,15 @@ private:
|
|||
// Description : A handy class object for storing simple values (like
|
||||
// integers or strings) passed along with an Event.
|
||||
// This is essentially just a wrapper around whatever
|
||||
// data type you like, to make it a TypedReferenceCount
|
||||
// object which can be passed along inside an
|
||||
// EventParameter.
|
||||
// data type you like, to make it a
|
||||
// TypedWritableReferenceCount object which can be
|
||||
// passed along inside an EventParameter.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
template<class Type>
|
||||
class EventStoreValue : public EventStoreValueBase {
|
||||
private:
|
||||
// This constructor is only for make_from_bam().
|
||||
EventStoreValue() { }
|
||||
public:
|
||||
EventStoreValue(const Type &value) : _value(value) { }
|
||||
|
||||
|
|
@ -119,6 +125,14 @@ public:
|
|||
|
||||
Type _value;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
@ -141,9 +155,9 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS, EventStoreValue<int>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS, EventStoreValue<double>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDAEXPRESS, EXPTP_PANDAEXPRESS, EventStoreValue<std::string>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, EventStoreValue<int>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, EventStoreValue<double>);
|
||||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA, EXPTP_PANDA, EventStoreValue<std::string>);
|
||||
|
||||
typedef EventStoreValue<int> EventStoreInt;
|
||||
typedef EventStoreValue<double> EventStoreDouble;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
|
||||
#include "buttonEvent.cxx"
|
||||
#include "buttonEventList.cxx"
|
||||
#include "config_event.cxx"
|
||||
#include "event.cxx"
|
||||
#include "eventHandler.cxx"
|
||||
|
|
|
|||
|
|
@ -456,3 +456,28 @@ operator < (const Datagram &other) const {
|
|||
// One of the pointers is NULL, but not the other one.
|
||||
return _data.size() < other._data.size();
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, bool value) {
|
||||
dest.add_bool(value);
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, int value) {
|
||||
dest.add_int32(value);
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, float value) {
|
||||
dest.add_float32(value);
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, double value) {
|
||||
dest.add_float64(value);
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, const string &value) {
|
||||
dest.add_string(value);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -120,6 +120,23 @@ private:
|
|||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
// These generic functions are primarily for writing a value to a
|
||||
// datagram from within a template in which the actual type of the
|
||||
// value is not known. If you do know the type, it's preferable to
|
||||
// use the explicit add_*() method from above instead.
|
||||
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, bool value);
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, int value);
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, float value);
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, double value);
|
||||
INLINE void
|
||||
generic_write_datagram(Datagram &dest, const string &value);
|
||||
|
||||
|
||||
#include "datagram.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -482,3 +482,30 @@ INLINE size_t DatagramIterator::
|
|||
get_current_index() const {
|
||||
return _current_index;
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_read_datagram(bool &result, DatagramIterator &source) {
|
||||
result = source.get_bool();
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_read_datagram(int &result, DatagramIterator &source) {
|
||||
result = source.get_int32();
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_read_datagram(float &result, DatagramIterator &source) {
|
||||
result = source.get_float32();
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_read_datagram(double &result, DatagramIterator &source) {
|
||||
result = source.get_float64();
|
||||
}
|
||||
|
||||
INLINE void
|
||||
generic_read_datagram(string &result, DatagramIterator &source) {
|
||||
result = source.get_string();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -80,6 +80,22 @@ private:
|
|||
size_t _current_index;
|
||||
};
|
||||
|
||||
// These generic functions are primarily for reading a value from a
|
||||
// datagram from within a template in which the actual type of the
|
||||
// value is not known. If you do know the type, it's preferable to
|
||||
// use the explicit get_*() method from above instead.
|
||||
|
||||
INLINE void
|
||||
generic_read_datagram(bool &result, DatagramIterator &source);
|
||||
INLINE void
|
||||
generic_read_datagram(int &result, DatagramIterator &source);
|
||||
INLINE void
|
||||
generic_read_datagram(float &result, DatagramIterator &source);
|
||||
INLINE void
|
||||
generic_read_datagram(double &result, DatagramIterator &source);
|
||||
INLINE void
|
||||
generic_read_datagram(string &result, DatagramIterator &source);
|
||||
|
||||
#include "datagramIterator.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -35,16 +35,24 @@ bool
|
|||
_dcast_verify(TypeHandle want_handle, size_t want_size,
|
||||
const TypedObject *ptr) {
|
||||
if (get_verify_dcast()) {
|
||||
if ((ptr == (const TypedObject *)NULL)
|
||||
if (ptr == (const TypedObject *)NULL) {
|
||||
// This is allowed these days. It used to be an error, but
|
||||
// what the heck.
|
||||
if (express_cat->is_debug()) {
|
||||
express_cat->debug()
|
||||
<< "Attempt to cast NULL pointer to "
|
||||
<< want_handle << "\n";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#if defined(_DEBUG) && defined(_WIN32)
|
||||
|| IsBadWritePtr((TypedObject *)ptr, want_size)
|
||||
#endif
|
||||
) {
|
||||
if (IsBadWritePtr((TypedObject *)ptr, want_size)) {
|
||||
express_cat->warning()
|
||||
<< "Attempt to cast NULL or invalid pointer to "
|
||||
<< "Attempt to cast invalid pointer to "
|
||||
<< want_handle << "\n";
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
if (!ptr->is_of_type(want_handle)) {
|
||||
express_cat->error()
|
||||
<< "Attempt to cast pointer from " << ptr->get_type()
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
// pass around pointers to things which are both
|
||||
// TypedObjects and ReferenceCounters.
|
||||
//
|
||||
// See Also TypeObject for detailed instructions.
|
||||
// See also TypedObject for detailed instructions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDAEXPRESS TypedReferenceCount : public TypedObject, public ReferenceCount {
|
||||
public:
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@
|
|||
#define TARGET framework
|
||||
#define BUILDING_DLL BUILDING_FRAMEWORK
|
||||
#define LOCAL_LIBS \
|
||||
pgui pgraph putil collide chan text chancfg \
|
||||
recorder pgui pgraph putil collide chan text chancfg \
|
||||
pnmimage pnmimagetypes event
|
||||
|
||||
#define SOURCES \
|
||||
|
|
|
|||
|
|
@ -41,3 +41,7 @@ const bool show_frame_rate_meter = config_framework.GetBool("show-frame-rate-met
|
|||
const float win_background_r = config_framework.GetFloat("win-background-r", 0.41);
|
||||
const float win_background_g = config_framework.GetFloat("win-background-g", 0.41);
|
||||
const float win_background_b = config_framework.GetFloat("win-background-b", 0.41);
|
||||
|
||||
const string record_session = config_framework.GetString("record-session", "");
|
||||
const string playback_session = config_framework.GetString("playback-session", "");
|
||||
|
||||
|
|
|
|||
|
|
@ -38,4 +38,7 @@ extern const float win_background_r;
|
|||
extern const float win_background_g;
|
||||
extern const float win_background_b;
|
||||
|
||||
extern const string record_session;
|
||||
extern const string playback_session;
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -172,6 +172,41 @@ get_highlight() const {
|
|||
return _highlight;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::get_recorder
|
||||
// Access: Public
|
||||
// Description: Returns the RecorderController that has been
|
||||
// associated with the PandaFramework, if any, or NULL
|
||||
// if none has (the normal case).
|
||||
//
|
||||
// If a RecorderController is associated, it will
|
||||
// presumably be used for recording user input to a
|
||||
// session file, or for playing back the user input from
|
||||
// a previously-recorded session.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE RecorderController *PandaFramework::
|
||||
get_recorder() const {
|
||||
return _recorder;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_recorder
|
||||
// Access: Public
|
||||
// Description: Assigns a RecorderController with the PandaFramework.
|
||||
// This should be called before any windows are opened.
|
||||
// The subsequently opened windows will register their
|
||||
// user inputs with the recorder.
|
||||
//
|
||||
// If a RecorderController is associated, it will
|
||||
// presumably be used for recording user input to a
|
||||
// session file, or for playing back the user input from
|
||||
// a previously-recorded session.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void PandaFramework::
|
||||
set_recorder(RecorderController *recorder) {
|
||||
_recorder = recorder;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaFramework::set_exit_flag
|
||||
// Access: Public
|
||||
|
|
|
|||
|
|
@ -52,6 +52,19 @@ PandaFramework() :
|
|||
_highlight_wireframe.set_color(1.0f, 0.0f, 0.0f, 1.0f, 1);
|
||||
_default_keys_enabled = false;
|
||||
_exit_flag = false;
|
||||
|
||||
if (!playback_session.empty()) {
|
||||
// If the config file so indicates, create a recorder and start it
|
||||
// playing.
|
||||
_recorder = new RecorderController;
|
||||
_recorder->begin_playback(Filename::from_os_specific(playback_session));
|
||||
|
||||
} else if (!record_session.empty()) {
|
||||
// If the config file so indicates, create a recorder and start it
|
||||
// recording.
|
||||
_recorder = new RecorderController;
|
||||
_recorder->begin_record(Filename::from_os_specific(record_session));
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -115,6 +128,8 @@ close_framework() {
|
|||
_lighting_enabled = false;
|
||||
_default_keys_enabled = false;
|
||||
_exit_flag = false;
|
||||
|
||||
_recorder = NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -603,8 +618,16 @@ do_frame() {
|
|||
DataGraphTraverser dg_trav;
|
||||
dg_trav.traverse(_data_root.node());
|
||||
_event_handler.process_events();
|
||||
if (_recorder != (RecorderController *)NULL) {
|
||||
_recorder->record_frame();
|
||||
}
|
||||
|
||||
_engine.render_frame();
|
||||
|
||||
if (_recorder != (RecorderController *)NULL) {
|
||||
_recorder->play_frame();
|
||||
}
|
||||
|
||||
return !_exit_flag;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@
|
|||
#include "graphicsPipe.h"
|
||||
#include "graphicsEngine.h"
|
||||
#include "graphicsWindow.h"
|
||||
#include "recorderController.h"
|
||||
#include "pointerTo.h"
|
||||
|
||||
#include "pvector.h"
|
||||
|
|
@ -99,6 +100,9 @@ public:
|
|||
INLINE bool has_highlight() const;
|
||||
INLINE const NodePath &get_highlight() const;
|
||||
|
||||
INLINE RecorderController *get_recorder() const;
|
||||
INLINE void set_recorder(RecorderController *recorder);
|
||||
|
||||
void enable_default_keys();
|
||||
|
||||
virtual bool do_frame();
|
||||
|
|
@ -177,6 +181,8 @@ private:
|
|||
KeyDefinitions _key_definitions;
|
||||
|
||||
NodePath _help_text;
|
||||
|
||||
PT(RecorderController) _recorder;
|
||||
};
|
||||
|
||||
#include "pandaFramework.I"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
#include "windowFramework.h"
|
||||
#include "pandaFramework.h"
|
||||
#include "mouseAndKeyboard.h"
|
||||
#include "mouseRecorder.h"
|
||||
#include "buttonThrower.h"
|
||||
#include "transform2sg.h"
|
||||
#include "dSearchPath.h"
|
||||
|
|
@ -292,6 +293,14 @@ get_mouse() {
|
|||
MouseAndKeyboard *mouse_node =
|
||||
new MouseAndKeyboard(_window, 0, "mouse");
|
||||
_mouse = data_root.attach_new_node(mouse_node);
|
||||
|
||||
RecorderController *recorder = _panda_framework->get_recorder();
|
||||
if (recorder != (RecorderController *)NULL) {
|
||||
// If we're in recording or playback mode, associate a recorder.
|
||||
MouseRecorder *mouse_recorder = new MouseRecorder("mouse");
|
||||
_mouse = _mouse.attach_new_node(mouse_recorder);
|
||||
recorder->add_recorder("mouse", mouse_recorder);
|
||||
}
|
||||
}
|
||||
return _mouse;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#include "frameRateMeter.h"
|
||||
#include "pointerTo.h"
|
||||
#include "pvector.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
|
||||
class PandaFramework;
|
||||
class AmbientLight;
|
||||
|
|
@ -42,7 +42,7 @@ class GraphicsPipe;
|
|||
// Description : This encapsulates the data that is normally
|
||||
// associated with a single window that we've opened.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_FRAMEWORK WindowFramework : public TypedReferenceCount {
|
||||
class EXPCL_FRAMEWORK WindowFramework : public TypedWritableReferenceCount {
|
||||
protected:
|
||||
WindowFramework(PandaFramework *panda_framework);
|
||||
public:
|
||||
|
|
@ -146,9 +146,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
TypedWritableReferenceCount::init_type();
|
||||
register_type(_type_handle, "WindowFramework",
|
||||
TypedReferenceCount::get_class_type());
|
||||
TypedWritableReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -208,5 +208,8 @@ ConfigureFn(config_gobj) {
|
|||
GeomTrifan::register_with_read_factory();
|
||||
GeomSphere::register_with_read_factory();
|
||||
Material::register_with_read_factory();
|
||||
OrthographicLens::register_with_read_factory();
|
||||
MatrixLens::register_with_read_factory();
|
||||
PerspectiveLens::register_with_read_factory();
|
||||
Texture::register_with_read_factory();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1734,3 +1734,50 @@ sqr_dist_to_line(const LPoint3f &point, const LPoint3f &origin,
|
|||
float leg = d.dot(norm);
|
||||
return hyp_2 - leg * leg;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Lens::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Lens::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
TypedWritable::write_datagram(manager, dg);
|
||||
|
||||
dg.add_string(_change_event);
|
||||
dg.add_uint8((int)_cs);
|
||||
_film_size.write_datagram(dg);
|
||||
_film_offset.write_datagram(dg);
|
||||
dg.add_float32(_focal_length);
|
||||
_fov.write_datagram(dg);
|
||||
dg.add_float32(_aspect_ratio);
|
||||
dg.add_float32(_near_distance);
|
||||
dg.add_float32(_far_distance);
|
||||
dg.add_uint16(_user_flags);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: Lens::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void Lens::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
TypedWritable::fillin(scan, manager);
|
||||
|
||||
_change_event = scan.get_string();
|
||||
_cs = (CoordinateSystem)scan.get_uint8();
|
||||
_film_size.read_datagram(scan);
|
||||
_film_offset.read_datagram(scan);
|
||||
_focal_length = scan.get_float32();
|
||||
_fov.read_datagram(scan);
|
||||
_aspect_ratio = scan.get_float32();
|
||||
_near_distance = scan.get_float32();
|
||||
_far_distance = scan.get_float32();
|
||||
_user_flags = scan.get_uint16();
|
||||
|
||||
_comp_flags = 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
#include "luse.h"
|
||||
#include "geom.h"
|
||||
#include "updateSeq.h"
|
||||
|
|
@ -40,7 +40,7 @@ class BoundingVolume;
|
|||
// also used in other contexts, however; for instance, a
|
||||
// Spotlight is also defined using a lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA Lens : public TypedReferenceCount {
|
||||
class EXPCL_PANDA Lens : public TypedWritableReferenceCount {
|
||||
public:
|
||||
Lens();
|
||||
Lens(const Lens ©);
|
||||
|
|
@ -244,6 +244,12 @@ protected:
|
|||
|
||||
static const float _default_fov;
|
||||
|
||||
public:
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
@ -253,9 +259,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
TypedWritableReferenceCount::init_type();
|
||||
register_type(_type_handle, "Lens",
|
||||
TypedReferenceCount::get_class_type());
|
||||
TypedWritableReferenceCount::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -68,3 +68,34 @@ compute_projection_mat() {
|
|||
adjust_comp_flags(CF_projection_mat_inv,
|
||||
CF_projection_mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MatrixLens::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MatrixLens::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MatrixLens::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type Lens is encountered
|
||||
// in the Bam file. It should create the Lens
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *MatrixLens::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
MatrixLens *lens = new MatrixLens;
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
lens->fillin(scan, manager);
|
||||
|
||||
return lens;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MatrixLens
|
||||
// Description : A completely generic linear lens. This is provided
|
||||
// for the benefit low-level code that wants to specify
|
||||
// a perspective or orthographic frustum via an explicit
|
||||
// projection matrix, but not mess around with fov's or
|
||||
// focal lengths or any of that nonsense.
|
||||
// for the benefit of low-level code that wants to
|
||||
// specify a perspective or orthographic frustum via an
|
||||
// explicit projection matrix, but not mess around with
|
||||
// fov's or focal lengths or any of that nonsense.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA MatrixLens : public Lens {
|
||||
PUBLISHED:
|
||||
|
|
@ -56,6 +56,12 @@ protected:
|
|||
private:
|
||||
LMatrix4f _user_mat;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -112,3 +112,34 @@ compute_projection_mat() {
|
|||
adjust_comp_flags(CF_projection_mat_inv,
|
||||
CF_projection_mat);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OrthographicLens::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void OrthographicLens::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: OrthographicLens::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type Lens is encountered
|
||||
// in the Bam file. It should create the Lens
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *OrthographicLens::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
OrthographicLens *lens = new OrthographicLens;
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
lens->fillin(scan, manager);
|
||||
|
||||
return lens;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,6 +52,12 @@ public:
|
|||
protected:
|
||||
virtual void compute_projection_mat();
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -150,3 +150,34 @@ float PerspectiveLens::
|
|||
film_to_fov(float film_size, float focal_length, bool) const {
|
||||
return rad_2_deg(catan(film_size * 0.5f / focal_length)) * 2.0f;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PerspectiveLens::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PerspectiveLens::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PerspectiveLens::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type Lens is encountered
|
||||
// in the Bam file. It should create the Lens
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *PerspectiveLens::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
PerspectiveLens *lens = new PerspectiveLens;
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
lens->fillin(scan, manager);
|
||||
|
||||
return lens;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,6 +47,12 @@ protected:
|
|||
virtual float fov_to_focal_length(float fov, float film_size, bool horiz) const;
|
||||
virtual float film_to_fov(float film_size, float focal_length, bool horiz) const;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -99,3 +99,39 @@ operator * (const FLOATNAME(LPoint3) &v, const FLOATNAME(LMatrix4) &m) {
|
|||
return m.xform_point(v);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_write_datagram
|
||||
// Description: Writes the value to the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LMatrix3) &value) {
|
||||
value.write_datagram(dest);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_read_datagram
|
||||
// Description: Reads the value from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LMatrix3) &result, DatagramIterator &source) {
|
||||
result.read_datagram(source);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_write_datagram
|
||||
// Description: Writes the value to the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LMatrix4) &value) {
|
||||
value.write_datagram(dest);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_read_datagram
|
||||
// Description: Reads the value from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LMatrix4) &result, DatagramIterator &source) {
|
||||
result.read_datagram(source);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,15 @@ operator * (const FLOATNAME(LVector3) &v, const FLOATNAME(LMatrix4) &m);
|
|||
INLINE_LINMATH FLOATNAME(LPoint3)
|
||||
operator * (const FLOATNAME(LPoint3) &v, const FLOATNAME(LMatrix4) &m);
|
||||
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LMatrix3) &value);
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LMatrix3) &result, DatagramIterator &source);
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LMatrix4) &value);
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LMatrix4) &result, DatagramIterator &source);
|
||||
|
||||
END_PUBLISH
|
||||
|
||||
#include "lmat_ops_src.I"
|
||||
|
|
|
|||
|
|
@ -71,3 +71,22 @@ normalize(const FLOATNAME(LVector2) &v) {
|
|||
v1.normalize();
|
||||
return v1;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_write_datagram
|
||||
// Description: Writes the value to the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase2) &value) {
|
||||
value.write_datagram(dest);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_read_datagram
|
||||
// Description: Reads the value from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LVecBase2) &result, DatagramIterator &source) {
|
||||
result.read_datagram(source);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,11 @@ length(const FLOATNAME(LVector2) &a);
|
|||
INLINE_LINMATH FLOATNAME(LVector2)
|
||||
normalize(const FLOATNAME(LVector2) &v);
|
||||
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase2) &value);
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LVecBase2) &result, DatagramIterator &source);
|
||||
|
||||
|
||||
#include "lvec2_ops_src.I"
|
||||
|
||||
|
|
|
|||
|
|
@ -97,3 +97,21 @@ normalize(const FLOATNAME(LVector3) &v) {
|
|||
v1.normalize();
|
||||
return v1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_write_datagram
|
||||
// Description: Writes the value to the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase3) &value) {
|
||||
value.write_datagram(dest);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_read_datagram
|
||||
// Description: Reads the value from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LVecBase3) &result, DatagramIterator &source) {
|
||||
result.read_datagram(source);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -54,4 +54,9 @@ length(const FLOATNAME(LVector3) &a);
|
|||
INLINE_LINMATH FLOATNAME(LVector3)
|
||||
normalize(const FLOATNAME(LVector3) &v);
|
||||
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase3) &value);
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LVecBase3) &result, DatagramIterator &source);
|
||||
|
||||
#include "lvec3_ops_src.I"
|
||||
|
|
|
|||
|
|
@ -75,3 +75,21 @@ normalize(const FLOATNAME(LVector4) &v) {
|
|||
v1.normalize();
|
||||
return v1;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_write_datagram
|
||||
// Description: Writes the value to the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase4) &value) {
|
||||
value.write_datagram(dest);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: generic_read_datagram
|
||||
// Description: Reads the value from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LVecBase4) &result, DatagramIterator &source) {
|
||||
result.read_datagram(source);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -47,5 +47,10 @@ length(const FLOATNAME(LVector4) &a);
|
|||
INLINE_LINMATH FLOATNAME(LVector4)
|
||||
normalize(const FLOATNAME(LVector4) &v);
|
||||
|
||||
INLINE_LINMATH void
|
||||
generic_write_datagram(Datagram &dest, const FLOATNAME(LVecBase4) &value);
|
||||
INLINE_LINMATH void
|
||||
generic_read_datagram(FLOATNAME(LVecBase4) &result, DatagramIterator &source);
|
||||
|
||||
|
||||
#include "lvec4_ops_src.I"
|
||||
|
|
|
|||
|
|
@ -46,5 +46,9 @@ ConfigureFn(config_mathutil) {
|
|||
EventStoreVec2::init_type("EventStoreVec2");
|
||||
EventStoreVec3::init_type("EventStoreVec3");
|
||||
EventStoreMat4::init_type("EventStoreMat4");
|
||||
|
||||
EventStoreVec2::register_with_read_factory();
|
||||
EventStoreVec3::register_with_read_factory();
|
||||
EventStoreMat4::register_with_read_factory();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,9 @@ PUBLISHED:
|
|||
bool open_read(const Filename &bam_filename, bool report_errors = true);
|
||||
bool open_read(istream &in, const string &bam_filename = "stream",
|
||||
bool report_errors = true);
|
||||
|
||||
TypedWritable *read_object();
|
||||
|
||||
bool is_eof() const;
|
||||
bool resolve();
|
||||
|
||||
|
|
|
|||
|
|
@ -226,7 +226,6 @@ init_libpgraph() {
|
|||
PosHprScaleLerpFunctor::init_type();
|
||||
ColorLerpFunctor::init_type();
|
||||
ColorScaleLerpFunctor::init_type();
|
||||
EventStoreTransform::init_type();
|
||||
|
||||
AlphaTestAttrib::register_with_read_factory();
|
||||
AmbientLight::register_with_read_factory();
|
||||
|
|
|
|||
|
|
@ -141,8 +141,7 @@ void LensNode::
|
|||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
PandaNode::write_datagram(manager, dg);
|
||||
|
||||
// We should actually write out the lens. Easy to do, but not
|
||||
// immediately pressing; I hope no one gets burned by the omission.
|
||||
manager->write_pointer(dg, _lens);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -155,7 +154,7 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
|||
int LensNode::
|
||||
complete_pointers(TypedWritable **p_list, BamReader *manager) {
|
||||
int pi = PandaNode::complete_pointers(p_list, manager);
|
||||
|
||||
_lens = DCAST(Lens, p_list[pi++]);
|
||||
return pi;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2046,6 +2046,27 @@ write_datagram(BamWriter *manager, Datagram &dg) {
|
|||
manager->write_cdata(dg, _cycler);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::write_recorder
|
||||
// Access: Public
|
||||
// Description: This method is provided for the benefit of classes
|
||||
// (like MouseRecorder) that inherit from PandaMode and
|
||||
// also RecorderBase. It's not virtual at this level
|
||||
// since it doesn't need to be (it's called up from the
|
||||
// derived class).
|
||||
//
|
||||
// This method acts very like write_datagram, but it
|
||||
// writes the node as appropriate for writing a
|
||||
// RecorderBase object as described in the beginning of
|
||||
// a session file, meaning it doesn't need to write
|
||||
// things such as children. It balances with
|
||||
// fillin_recorder().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaNode::
|
||||
write_recorder(BamWriter *, Datagram &dg) {
|
||||
dg.add_string(get_name());
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::make_from_bam
|
||||
// Access: Protected, Static
|
||||
|
|
@ -2082,3 +2103,18 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
|
||||
manager->read_cdata(scan, _cycler);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: PandaNode::fillin_recorder
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_recorder (in
|
||||
// classes derived from RecorderBase, such as
|
||||
// MouseRecorder) to read in all of the relevant data
|
||||
// from the session file. It balances with
|
||||
// write_recorder().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void PandaNode::
|
||||
fillin_recorder(DatagramIterator &scan, BamReader *) {
|
||||
string name = scan.get_string();
|
||||
set_name(name);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -376,10 +376,12 @@ public:
|
|||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
void write_recorder(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
void fillin_recorder(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
|
|
@ -582,34 +582,3 @@ is_destructing() const {
|
|||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreTransform::Constructor
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE EventStoreTransform::
|
||||
EventStoreTransform(const TransformState *value) :
|
||||
_value(value)
|
||||
{
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreTransform::set_value
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void EventStoreTransform::
|
||||
set_value(const TransformState *value) {
|
||||
_value = value;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreTransform::get_value
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const TransformState *EventStoreTransform::
|
||||
get_value() const {
|
||||
return _value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,7 +27,6 @@
|
|||
TransformState::States *TransformState::_states = NULL;
|
||||
CPT(TransformState) TransformState::_identity_state;
|
||||
TypeHandle TransformState::_type_handle;
|
||||
TypeHandle EventStoreTransform::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: TransformState::Constructor
|
||||
|
|
@ -1326,13 +1325,3 @@ fillin(DatagramIterator &scan, BamReader *manager) {
|
|||
_mat.read_datagram(scan);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: EventStoreTransform::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void EventStoreTransform::
|
||||
output(ostream &out) const {
|
||||
out << *_value;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -244,40 +244,6 @@ INLINE ostream &operator << (ostream &out, const TransformState &state) {
|
|||
return out;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : EventStoreTransform
|
||||
// Description : This class is used to pass TransformState pointers as
|
||||
// parameters to events, or as elements on a data graph.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA EventStoreTransform : public EventStoreValueBase {
|
||||
public:
|
||||
INLINE EventStoreTransform(const TransformState *value);
|
||||
INLINE void set_value(const TransformState *value);
|
||||
INLINE const TransformState *get_value() const;
|
||||
|
||||
virtual void output(ostream &out) const;
|
||||
|
||||
CPT(TransformState) _value;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
EventStoreValueBase::init_type();
|
||||
register_type(_type_handle, "EventStoreTransform",
|
||||
EventStoreValueBase::get_class_type());
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "transformState.I"
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -22,20 +22,20 @@
|
|||
#include "pandabase.h"
|
||||
|
||||
#include "mouseWatcherParameter.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "typedWritableReferenceCount.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : PGMouseWatcherParameter
|
||||
// Description : This specialization on MouseWatcherParameter allows
|
||||
// us to tag on additional elements to events for the
|
||||
// gui system, and also inherits from
|
||||
// TypedReferenceCount so we can attach this thing to an
|
||||
// TypedWritableReferenceCount so we can attach this thing to an
|
||||
// event.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA PGMouseWatcherParameter : public TypedReferenceCount, public MouseWatcherParameter {
|
||||
// For now, this must inherit from TypedReferenceCount on the left,
|
||||
// because MSVC++ wants to make that base class be the one at the
|
||||
// front of the structure, not MouseWatcherParameter for some
|
||||
class EXPCL_PANDA PGMouseWatcherParameter : public TypedWritableReferenceCount, public MouseWatcherParameter {
|
||||
// For now, this must inherit from TypedWritableReferenceCount on
|
||||
// the left, because MSVC++ wants to make that base class be the one
|
||||
// at the front of the structure, not MouseWatcherParameter for some
|
||||
// reason, and interrogate assumes that whichever base class is on
|
||||
// the left will be at the front of the structure.
|
||||
public:
|
||||
|
|
@ -52,9 +52,9 @@ public:
|
|||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
TypedWritableReferenceCount::init_type();
|
||||
register_type(_type_handle, "PGMouseWatcherParameter",
|
||||
TypedReferenceCount::get_class_type());
|
||||
TypedWritableReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m
|
||||
#define LOCAL_LIBS express event pandabase
|
||||
#define LOCAL_LIBS express pandabase
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET putil
|
||||
|
|
@ -10,8 +10,7 @@
|
|||
#define SOURCES \
|
||||
bam.h bamReader.I bamReader.N bamReader.h bamReaderParam.I \
|
||||
bamReaderParam.h bamWriter.I bamWriter.h bitMask.I \
|
||||
bitMask.h buttonEvent.I buttonEvent.h \
|
||||
buttonEventList.I buttonEventList.h \
|
||||
bitMask.h \
|
||||
buttonHandle.I \
|
||||
buttonHandle.h buttonRegistry.I buttonRegistry.h \
|
||||
collideMask.h \
|
||||
|
|
@ -53,8 +52,6 @@
|
|||
|
||||
#define INCLUDED_SOURCES \
|
||||
bamReader.cxx bamReaderParam.cxx bamWriter.cxx bitMask.cxx \
|
||||
buttonEvent.cxx \
|
||||
buttonEventList.cxx \
|
||||
buttonHandle.cxx buttonRegistry.cxx \
|
||||
config_util.cxx configurable.cxx \
|
||||
cycleData.cxx \
|
||||
|
|
@ -83,9 +80,7 @@
|
|||
|
||||
#define INSTALL_HEADERS \
|
||||
bam.h bamReader.I bamReader.h bamReaderParam.I bamReaderParam.h \
|
||||
bamWriter.I bamWriter.h bitMask.I bitMask.h buttonEvent.I \
|
||||
buttonEvent.h \
|
||||
buttonEventList.I buttonEventList.h \
|
||||
bamWriter.I bamWriter.h bitMask.I bitMask.h \
|
||||
buttonHandle.I buttonHandle.h buttonRegistry.I \
|
||||
buttonRegistry.h collideMask.h \
|
||||
compareTo.I compareTo.h \
|
||||
|
|
@ -112,7 +107,8 @@
|
|||
pipelineCycler.h pipelineCycler.I \
|
||||
pipelineCyclerBase.h pipelineCyclerBase.I \
|
||||
pta_double.h \
|
||||
pta_float.h pta_int.h pta_ushort.h string_utils.I \
|
||||
pta_float.h pta_int.h pta_ushort.h \
|
||||
string_utils.I \
|
||||
string_utils.h timedCycle.I timedCycle.h typedWritable.I \
|
||||
typedWritable.h typedWritableReferenceCount.I \
|
||||
typedWritableReferenceCount.h updateSeq.I updateSeq.h \
|
||||
|
|
|
|||
|
|
@ -83,10 +83,11 @@ get_current_minor_ver() const {
|
|||
// Description: Returns the global WritableFactory for generating
|
||||
// TypedWritable objects
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE WritableFactory* BamReader::
|
||||
INLINE WritableFactory *BamReader::
|
||||
get_factory() {
|
||||
if (_factory == NullFactory)
|
||||
if (_factory == (WritableFactory *)NULL) {
|
||||
create_factory();
|
||||
}
|
||||
return _factory;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include "config_util.h"
|
||||
#include "pipelineCyclerBase.h"
|
||||
|
||||
TypeHandle BamReader::_remove_flag;
|
||||
|
||||
WritableFactory *BamReader::_factory = (WritableFactory*)0L;
|
||||
BamReader *const BamReader::Null = (BamReader*)0L;
|
||||
WritableFactory *const BamReader::NullFactory = (WritableFactory*)0L;
|
||||
|
|
@ -48,6 +50,8 @@ BamReader(DatagramGenerator *generator)
|
|||
_now_creating = _created_objs.end();
|
||||
_reading_cycler = (PipelineCyclerBase *)NULL;
|
||||
_pta_id = -1;
|
||||
_long_object_id = false;
|
||||
_long_pta_id = false;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -78,7 +82,7 @@ init() {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!_source->get_datagram(header)) {
|
||||
if (!get_datagram(header)) {
|
||||
bam_cat.error()
|
||||
<< "Unable to read Bam header.\n";
|
||||
return false;
|
||||
|
|
@ -124,6 +128,43 @@ init() {
|
|||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::set_aux_data
|
||||
// Access: Public
|
||||
// Description: Associates an arbitrary pointer to the bam reader
|
||||
// with the indicated name. The name is an arbitrary
|
||||
// user-defined key to access the data later. This data
|
||||
// is typically queried by objects reading themselves
|
||||
// from the bam file; this is intended to provide some
|
||||
// context information to objects in the bam file. Set
|
||||
// the aux data to NULL to remove it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BamReader::
|
||||
set_aux_data(const string &name, void *data) {
|
||||
if (data == (void *)NULL) {
|
||||
_aux_data.erase(name);
|
||||
} else {
|
||||
_aux_data[name] = data;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::get_aux_data
|
||||
// Access: Public
|
||||
// Description: Returns the pointer previously associated with the
|
||||
// bam reader by a previous call to set_aux_data(), or
|
||||
// NULL if the data with the indicated key has not been
|
||||
// set.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void *BamReader::
|
||||
get_aux_data(const string &name) const {
|
||||
AuxData::const_iterator di = _aux_data.find(name);
|
||||
if (di != _aux_data.end()) {
|
||||
return (*di).second;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::read_object
|
||||
// Access: Public
|
||||
|
|
@ -237,6 +278,7 @@ resolve() {
|
|||
|
||||
CreatedObjs::iterator ci = _created_objs.find(object_id);
|
||||
nassertr(ci != _created_objs.end(), false);
|
||||
|
||||
CreatedObj &created_obj = (*ci).second;
|
||||
|
||||
TypedWritable *object_ptr = created_obj._ptr;
|
||||
|
|
@ -425,7 +467,7 @@ read_pointer(DatagramIterator &scan) {
|
|||
int requestor_id = (*_now_creating).first;
|
||||
|
||||
// Read the object ID, and associate it with the requesting object.
|
||||
int object_id = scan.get_uint16();
|
||||
int object_id = read_object_id(scan);
|
||||
|
||||
if (_reading_cycler == (PipelineCyclerBase *)NULL) {
|
||||
// This is not being read within a read_cdata() call.
|
||||
|
|
@ -471,7 +513,7 @@ read_pointers(DatagramIterator &scan, int count) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
void BamReader::
|
||||
skip_pointer(DatagramIterator &scan) {
|
||||
scan.get_uint16();
|
||||
read_object_id(scan);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -597,7 +639,7 @@ finalize_now(TypedWritable *whom) {
|
|||
void *BamReader::
|
||||
get_pta(DatagramIterator &scan) {
|
||||
nassertr(_pta_id == -1, (void *)NULL);
|
||||
int id = scan.get_uint16();
|
||||
int id = read_pta_id(scan);
|
||||
|
||||
if (id == 0) {
|
||||
// As always, a 0 ID indicates a NULL pointer. The caller will
|
||||
|
|
@ -641,12 +683,92 @@ register_pta(void *ptr) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::free_object_ids
|
||||
// Access: Private
|
||||
// Description: Handles a record that begins with the _remove_flag
|
||||
// TypeHandle; this contains a list of object ID's that
|
||||
// will no longer be used in this file and can safely be
|
||||
// removed.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BamReader::
|
||||
free_object_ids(DatagramIterator &scan) {
|
||||
// We have to fully complete any objects before we remove them.
|
||||
// Might as well try to complete everything before we get started.
|
||||
resolve();
|
||||
|
||||
while (scan.get_remaining_size() > 0) {
|
||||
int object_id = read_object_id(scan);
|
||||
|
||||
CreatedObjs::iterator ci = _created_objs.find(object_id);
|
||||
if (ci == _created_objs.end()) {
|
||||
util_cat.warning()
|
||||
<< "Bam file suggests eliminating object_id " << object_id
|
||||
<< ", already gone.\n";
|
||||
} else {
|
||||
|
||||
// Make sure the object was successfully completed.
|
||||
ObjectPointers::iterator oi = _object_pointers.find(object_id);
|
||||
if (oi != _object_pointers.end()) {
|
||||
util_cat.warning()
|
||||
<< "Unable to resolve object " << object_id
|
||||
<< " before removing from table.\n";
|
||||
}
|
||||
|
||||
_created_objs.erase(ci);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::read_object_id
|
||||
// Access: Private
|
||||
// Description: Reads an object id from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BamReader::
|
||||
read_object_id(DatagramIterator &scan) {
|
||||
int object_id;
|
||||
|
||||
if (_long_object_id) {
|
||||
object_id = scan.get_uint32();
|
||||
|
||||
} else {
|
||||
object_id = scan.get_uint16();
|
||||
if (object_id == 0xffff) {
|
||||
_long_object_id = true;
|
||||
}
|
||||
}
|
||||
|
||||
return object_id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::read_pta_id
|
||||
// Access: Private
|
||||
// Description: Reads an pta id from the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
int BamReader::
|
||||
read_pta_id(DatagramIterator &scan) {
|
||||
int pta_id;
|
||||
|
||||
if (_long_pta_id) {
|
||||
pta_id = scan.get_uint32();
|
||||
|
||||
} else {
|
||||
pta_id = scan.get_uint16();
|
||||
if (pta_id == 0xffff) {
|
||||
_long_pta_id = true;
|
||||
}
|
||||
}
|
||||
|
||||
return pta_id;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::p_read_object
|
||||
// Access: Private
|
||||
// Description: The private implementation of read_object(), this
|
||||
// Description: The private implementation of read_object(); this
|
||||
// reads an object from the file and returns its object
|
||||
// ID.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -654,14 +776,9 @@ int BamReader::
|
|||
p_read_object() {
|
||||
Datagram packet;
|
||||
|
||||
if (_source->is_error()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// First, read a datagram for the object.
|
||||
if (!_source->get_datagram(packet)) {
|
||||
if (!get_datagram(packet)) {
|
||||
// When we run out of datagrams, we're at the end of the file.
|
||||
|
||||
if (bam_cat.is_debug()) {
|
||||
bam_cat.debug()
|
||||
<< "Reached end of bam source.\n";
|
||||
|
|
@ -678,10 +795,24 @@ p_read_object() {
|
|||
// object.
|
||||
|
||||
TypeHandle type = read_handle(scan);
|
||||
int object_id = scan.get_uint16();
|
||||
|
||||
// There are two cases. Either this is a new object definition, or
|
||||
// this is a reference to an object that was previously defined.
|
||||
if (type == _remove_flag) {
|
||||
// The _remove_flag TypeHandle is a special case; it begins a
|
||||
// record that simply lists all of the object ID's that are no
|
||||
// longer important to the file and may be released.
|
||||
free_object_ids(scan);
|
||||
|
||||
// Now that we've freed all of the object id's indicate, read the
|
||||
// next object id in the stream. It's easiest to do this by
|
||||
// calling recursively.
|
||||
return p_read_object();
|
||||
}
|
||||
|
||||
int object_id = read_object_id(scan);
|
||||
|
||||
// There are two cases (not counting the special _remove_flag case,
|
||||
// above). Either this is a new object definition, or this is a
|
||||
// reference to an object that was previously defined.
|
||||
|
||||
// We use the TypeHandle to differentiate these two cases. By
|
||||
// convention, we write a TypeHandle::none() to the Bam file when we
|
||||
|
|
@ -697,7 +828,7 @@ p_read_object() {
|
|||
if (type != TypeHandle::none()) {
|
||||
// Now we are going to read and create a new object.
|
||||
|
||||
// Defined the parameters for passing to the object factory.
|
||||
// Define the parameters for passing to the object factory.
|
||||
FactoryParams fparams;
|
||||
fparams.add_param(new BamReaderParam(scan, this));
|
||||
|
||||
|
|
@ -796,7 +927,6 @@ resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids) {
|
|||
// in, we can't resolve this object--we can't do anything for a
|
||||
// given object until we have *all* outstanding pointers for
|
||||
// that object.
|
||||
|
||||
bool is_complete = true;
|
||||
vector_typedWritable references;
|
||||
|
||||
|
|
@ -932,3 +1062,18 @@ finalize() {
|
|||
fi = _finalize_list.begin();
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamReader::get_datagram
|
||||
// Access: Private
|
||||
// Description: Reads a single datagram from the stream. Returns
|
||||
// true on success, false on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool BamReader::
|
||||
get_datagram(Datagram &datagram) {
|
||||
if (_source->is_error()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _source->get_datagram(datagram);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "factory.h"
|
||||
#include "vector_int.h"
|
||||
#include "pset.h"
|
||||
#include "pmap.h"
|
||||
#include "dcast.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
|
@ -92,11 +93,14 @@ public:
|
|||
static WritableFactory *const NullFactory;
|
||||
|
||||
// The primary interface for a caller.
|
||||
|
||||
BamReader(DatagramGenerator *generator);
|
||||
~BamReader();
|
||||
|
||||
bool init();
|
||||
|
||||
void set_aux_data(const string &name, void *data);
|
||||
void *get_aux_data(const string &name) const;
|
||||
|
||||
TypedWritable *read_object();
|
||||
INLINE bool is_eof() const;
|
||||
bool resolve();
|
||||
|
|
@ -107,6 +111,10 @@ public:
|
|||
INLINE int get_current_major_ver() const;
|
||||
INLINE int get_current_minor_ver() const;
|
||||
|
||||
// This special TypeHandle is written to the bam file to indicate an
|
||||
// object id is no longer needed.
|
||||
static TypeHandle _remove_flag;
|
||||
|
||||
public:
|
||||
// Functions to support classes that read themselves from the Bam.
|
||||
|
||||
|
|
@ -135,15 +143,23 @@ private:
|
|||
INLINE static void create_factory();
|
||||
|
||||
private:
|
||||
void free_object_ids(DatagramIterator &scan);
|
||||
int read_object_id(DatagramIterator &scan);
|
||||
int read_pta_id(DatagramIterator &scan);
|
||||
int p_read_object();
|
||||
bool resolve_object_pointers(TypedWritable *object, const vector_int &pointer_ids);
|
||||
bool resolve_cycler_pointers(PipelineCyclerBase *cycler, const vector_int &pointer_ids);
|
||||
void finalize();
|
||||
|
||||
bool get_datagram(Datagram &datagram);
|
||||
|
||||
private:
|
||||
static WritableFactory *_factory;
|
||||
|
||||
DatagramGenerator *_source;
|
||||
|
||||
bool _long_object_id;
|
||||
bool _long_pta_id;
|
||||
|
||||
// This maps the type index numbers encountered within the Bam file
|
||||
// to actual TypeHandles.
|
||||
|
|
@ -202,6 +218,10 @@ private:
|
|||
typedef pset<TypeHandle> NewTypes;
|
||||
static NewTypes _new_types;
|
||||
|
||||
// This is used in support of set_aux_data() and get_aux_data().
|
||||
typedef pmap<string, void *> AuxData;
|
||||
AuxData _aux_data;
|
||||
|
||||
int _file_major, _file_minor;
|
||||
static const int _cur_major;
|
||||
static const int _cur_minor;
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@
|
|||
#include "bamWriter.h"
|
||||
#include "bamReader.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamWriter::Constructor
|
||||
// Access: Public
|
||||
|
|
@ -43,6 +45,16 @@ BamWriter(DatagramSink *sink) :
|
|||
////////////////////////////////////////////////////////////////////
|
||||
BamWriter::
|
||||
~BamWriter() {
|
||||
// Tell all the TypedWritables whose pointer we are still keeping to
|
||||
// forget about us.
|
||||
StateMap::iterator si;
|
||||
for (si = _state_map.begin(); si != _state_map.end(); ++si) {
|
||||
TypedWritable *object = (TypedWritable *)(*si).first;
|
||||
TypedWritable::BamWriters::iterator wi =
|
||||
find(object->_bam_writers.begin(), object->_bam_writers.end(), this);
|
||||
nassertv(wi != object->_bam_writers.end());
|
||||
object->_bam_writers.erase(wi);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
@ -60,7 +72,9 @@ init() {
|
|||
// Initialize the next object and PTA ID's. These start counting at
|
||||
// 1, since 0 is reserved for NULL.
|
||||
_next_object_id = 1;
|
||||
_long_object_id = false;
|
||||
_next_pta_id = 1;
|
||||
_long_pta_id = false;
|
||||
|
||||
// Write out the current major and minor BAM file version numbers.
|
||||
Datagram header;
|
||||
|
|
@ -105,6 +119,24 @@ write_object(const TypedWritable *object) {
|
|||
int object_id = enqueue_object(object);
|
||||
nassertr(object_id != 0, false);
|
||||
|
||||
// If there are any freed objects to indicate, write them out now.
|
||||
if (!_freed_object_ids.empty()) {
|
||||
Datagram dg;
|
||||
write_handle(dg, BamReader::_remove_flag);
|
||||
|
||||
FreedObjectIds::iterator fi;
|
||||
for (fi = _freed_object_ids.begin(); fi != _freed_object_ids.end(); ++fi) {
|
||||
write_object_id(dg, (*fi));
|
||||
}
|
||||
_freed_object_ids.clear();
|
||||
|
||||
if (!_target->put_datagram(dg)) {
|
||||
util_cat.error()
|
||||
<< "Unable to write data to output.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Now we write out all the objects in the queue, in order. The
|
||||
// first one on the queue will, of course, be this object we just
|
||||
// queued up, but each object we write may append more to the queue.
|
||||
|
|
@ -151,7 +183,7 @@ write_object(const TypedWritable *object) {
|
|||
}
|
||||
|
||||
write_handle(dg, type);
|
||||
dg.add_uint16(object_id);
|
||||
write_object_id(dg, object_id);
|
||||
|
||||
// We cast the const pointer to non-const so that we may call
|
||||
// write_datagram() on it. Really, write_datagram() should be a
|
||||
|
|
@ -170,12 +202,12 @@ write_object(const TypedWritable *object) {
|
|||
// BamReader that this is a previously-written object.
|
||||
|
||||
write_handle(dg, TypeHandle::none());
|
||||
dg.add_uint16(object_id);
|
||||
write_object_id(dg, object_id);
|
||||
}
|
||||
|
||||
if (!_target->put_datagram(dg)) {
|
||||
util_cat.error()
|
||||
<< "Unable to write datagram to file.\n";
|
||||
<< "Unable to write data to output.\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -215,7 +247,7 @@ write_pointer(Datagram &packet, const TypedWritable *object) {
|
|||
// If the pointer is NULL, we always simply write a zero for an
|
||||
// object ID and leave it at that.
|
||||
if (object == (const TypedWritable *)NULL) {
|
||||
packet.add_uint16(0);
|
||||
write_object_id(packet, 0);
|
||||
|
||||
} else {
|
||||
StateMap::iterator si = _state_map.find(object);
|
||||
|
|
@ -223,12 +255,12 @@ write_pointer(Datagram &packet, const TypedWritable *object) {
|
|||
// We have not written this pointer out yet. This means we must
|
||||
// queue the object definition up for later.
|
||||
int object_id = enqueue_object(object);
|
||||
packet.add_uint16(object_id);
|
||||
write_object_id(packet, object_id);
|
||||
|
||||
} else {
|
||||
// We have already assigned this pointer an ID; thus, we can
|
||||
// simply write out the ID.
|
||||
packet.add_uint16((*si).second._object_id);
|
||||
write_object_id(packet, (*si).second._object_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -273,7 +305,7 @@ register_pta(Datagram &packet, const void *ptr) {
|
|||
if (ptr == (const void *)NULL) {
|
||||
// A zero for the PTA ID indicates a NULL pointer. This is a
|
||||
// special case.
|
||||
packet.add_uint16(0);
|
||||
write_pta_id(packet, 0);
|
||||
|
||||
// We return false to indicate the user must now write out the
|
||||
// "definition" of the NULL pointer. This is necessary because of
|
||||
|
|
@ -292,14 +324,10 @@ register_pta(Datagram &packet, const void *ptr) {
|
|||
int pta_id = _next_pta_id;
|
||||
_next_pta_id++;
|
||||
|
||||
// Make sure our PTA ID will fit within the PN_uint16 we have
|
||||
// allocated for it.
|
||||
nassertr(pta_id <= 65535, 0);
|
||||
|
||||
bool inserted = _pta_map.insert(PTAMap::value_type(ptr, pta_id)).second;
|
||||
nassertr(inserted, false);
|
||||
|
||||
packet.add_uint16(pta_id);
|
||||
write_pta_id(packet, pta_id);
|
||||
|
||||
// Return false to indicate the caller must now write out the
|
||||
// array definition.
|
||||
|
|
@ -308,7 +336,7 @@ register_pta(Datagram &packet, const void *ptr) {
|
|||
} else {
|
||||
// We have encountered this pointer before.
|
||||
int pta_id = (*pi).second;
|
||||
packet.add_uint16(pta_id);
|
||||
write_pta_id(packet, pta_id);
|
||||
|
||||
// Return true to indicate the caller need do nothing further.
|
||||
return true;
|
||||
|
|
@ -336,7 +364,7 @@ write_handle(Datagram &packet, TypeHandle type) {
|
|||
int index = type.get_index();
|
||||
|
||||
// Also make sure the index number fits within a PN_uint16.
|
||||
nassertv(index <= 65535);
|
||||
nassertv(index <= 0xffff);
|
||||
|
||||
packet.add_uint16(index);
|
||||
|
||||
|
|
@ -361,6 +389,70 @@ write_handle(Datagram &packet, TypeHandle type) {
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamWriter::object_destructs
|
||||
// Access: Private
|
||||
// Description: This is called by the TypedWritable destructor. It
|
||||
// should remove the pointer from any structures that
|
||||
// keep a reference to it, and also write a flag to the
|
||||
// bam file (if it is open) so that a reader will know
|
||||
// the object id will no longer be used.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BamWriter::
|
||||
object_destructs(TypedWritable *object) {
|
||||
StateMap::iterator si = _state_map.find(object);
|
||||
if (si != _state_map.end()) {
|
||||
// We ought to have written out the object by the time it
|
||||
// destructs, or we're in trouble when we do write it out.
|
||||
nassertv((*si).second._written);
|
||||
|
||||
int object_id = (*si).second._object_id;
|
||||
_freed_object_ids.push_back(object_id);
|
||||
|
||||
_state_map.erase(si);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamWriter::write_object_id
|
||||
// Access: Private
|
||||
// Description: Writes the indicated object id to the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BamWriter::
|
||||
write_object_id(Datagram &dg, int object_id) {
|
||||
if (_long_object_id) {
|
||||
dg.add_uint32(object_id);
|
||||
|
||||
} else {
|
||||
dg.add_uint16(object_id);
|
||||
// Once we fill up our uint16, we write all object id's
|
||||
// thereafter with a uint32.
|
||||
if (object_id == 0xffff) {
|
||||
_long_object_id = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamWriter::write_pta_id
|
||||
// Access: Private
|
||||
// Description: Writes the indicated pta id to the datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void BamWriter::
|
||||
write_pta_id(Datagram &dg, int pta_id) {
|
||||
if (_long_pta_id) {
|
||||
dg.add_uint32(pta_id);
|
||||
|
||||
} else {
|
||||
dg.add_uint16(pta_id);
|
||||
// Once we fill up our uint16, we write all pta id's
|
||||
// thereafter with a uint32.
|
||||
if (pta_id == 0xffff) {
|
||||
_long_pta_id = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: BamWriter::enqueue_object
|
||||
// Access: Private
|
||||
|
|
@ -392,28 +484,22 @@ enqueue_object(const TypedWritable *object) {
|
|||
// We need to assign a unique index number to every object we write
|
||||
// out. Has this object been assigned a number yet?
|
||||
int object_id;
|
||||
// bool already_written;
|
||||
|
||||
StateMap::iterator si = _state_map.find(object);
|
||||
if (si == _state_map.end()) {
|
||||
// No, it hasn't, so assign it the next number in sequence
|
||||
// arbitrarily.
|
||||
object_id = _next_object_id;
|
||||
// already_written = false;
|
||||
|
||||
// Make sure our object ID will fit within the PN_uint16 we have
|
||||
// allocated for it.
|
||||
nassertr(object_id <= 65535, 0);
|
||||
|
||||
bool inserted =
|
||||
_state_map.insert(StateMap::value_type(object, StoreState(_next_object_id))).second;
|
||||
nassertr(inserted, false);
|
||||
((TypedWritable *)object)->_bam_writers.push_back(this);
|
||||
_next_object_id++;
|
||||
|
||||
} else {
|
||||
// Yes, it has; get the object ID.
|
||||
object_id = (*si).second._object_id;
|
||||
// already_written = (*si).second._written;
|
||||
}
|
||||
|
||||
_object_queue.push_back(object);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@
|
|||
#include "typedWritable.h"
|
||||
#include "datagramSink.h"
|
||||
#include "pdeque.h"
|
||||
#include "pset.h"
|
||||
#include "pmap.h"
|
||||
#include "vector_int.h"
|
||||
|
||||
struct PipelineCyclerBase;
|
||||
|
||||
|
|
@ -71,7 +74,7 @@ struct PipelineCyclerBase;
|
|||
// See also BamFile, which defines a higher-level
|
||||
// interface to read and write Bam files on disk.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA BamWriter{
|
||||
class EXPCL_PANDA BamWriter {
|
||||
public:
|
||||
BamWriter(DatagramSink *sink);
|
||||
~BamWriter();
|
||||
|
|
@ -90,11 +93,12 @@ public:
|
|||
bool register_pta(Datagram &packet, const void *ptr);
|
||||
void write_handle(Datagram &packet, TypeHandle type);
|
||||
|
||||
|
||||
|
||||
private:
|
||||
int enqueue_object(const TypedWritable *object);
|
||||
void object_destructs(TypedWritable *object);
|
||||
|
||||
void write_object_id(Datagram &dg, int object_id);
|
||||
void write_pta_id(Datagram &dg, int pta_id);
|
||||
int enqueue_object(const TypedWritable *object);
|
||||
|
||||
// This is the set of all TypeHandles already written.
|
||||
pset<int> _types_written;
|
||||
|
|
@ -114,20 +118,30 @@ private:
|
|||
|
||||
// This is the next object ID that will be assigned to a new object.
|
||||
int _next_object_id;
|
||||
bool _long_object_id;
|
||||
|
||||
// This is the queue of objects that need to be written when the
|
||||
// current object is finished.
|
||||
typedef pdeque<const TypedWritable *> ObjectQueue;
|
||||
ObjectQueue _object_queue;
|
||||
|
||||
// This is the set of object_id's that we won't be using any more;
|
||||
// we'll encode this set into the bam stream so the BamReader will
|
||||
// be able to clean up its internal structures.
|
||||
typedef vector_int FreedObjectIds;
|
||||
FreedObjectIds _freed_object_ids;
|
||||
|
||||
// These are used by register_pta() to unify multiple references to
|
||||
// the same PointerToArray.
|
||||
typedef pmap<const void *, int> PTAMap;
|
||||
PTAMap _pta_map;
|
||||
int _next_pta_id;
|
||||
bool _long_pta_id;
|
||||
|
||||
// The destination to write all the output to.
|
||||
DatagramSink *_target;
|
||||
|
||||
friend class TypedWritable;
|
||||
};
|
||||
|
||||
#include "bamWriter.I"
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
// Filename: buttonEvent.cxx
|
||||
// Created by: drose (01Mar00)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "buttonEvent.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEvent::output
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEvent::
|
||||
output(ostream &out) const {
|
||||
switch (_type) {
|
||||
case T_down:
|
||||
out << "button " << _button << " down";
|
||||
break;
|
||||
|
||||
case T_resume_down:
|
||||
out << "button " << _button << " resume down";
|
||||
break;
|
||||
|
||||
case T_up:
|
||||
out << "button " << _button << " up";
|
||||
break;
|
||||
|
||||
case T_keystroke:
|
||||
out << "keystroke " << _keycode;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
// Filename: buttonEventList.cxx
|
||||
// Created by: drose (12Mar02)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "buttonEventList.h"
|
||||
#include "modifierButtons.h"
|
||||
#include "indent.h"
|
||||
|
||||
TypeHandle ButtonEventList::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::update_mods
|
||||
// Access: Public
|
||||
// Description: Updates the indicated ModifierButtons object with all
|
||||
// of the button up/down transitions indicated in the
|
||||
// list.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
update_mods(ModifierButtons &mods) const {
|
||||
Events::const_iterator ei;
|
||||
for (ei = _events.begin(); ei != _events.end(); ++ei) {
|
||||
mods.add_event(*ei);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
output(ostream &out) const {
|
||||
if (_events.empty()) {
|
||||
out << "(no buttons)";
|
||||
} else {
|
||||
Events::const_iterator ei;
|
||||
ei = _events.begin();
|
||||
out << "(" << (*ei);
|
||||
++ei;
|
||||
while (ei != _events.end()) {
|
||||
out << " " << (*ei);
|
||||
++ei;
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ButtonEventList::write
|
||||
// Access: Public
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void ButtonEventList::
|
||||
write(ostream &out, int indent_level) const {
|
||||
indent(out, indent_level) << _events.size() << " events:\n";
|
||||
Events::const_iterator ei;
|
||||
for (ei = _events.begin(); ei != _events.end(); ++ei) {
|
||||
indent(out, indent_level + 2) << (*ei) << "\n";
|
||||
}
|
||||
}
|
||||
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#include "config_util.h"
|
||||
#include "bamReaderParam.h"
|
||||
#include "buttonEventList.h"
|
||||
#include "clockObject.h"
|
||||
#include "configurable.h"
|
||||
#include "datagram.h"
|
||||
|
|
@ -43,7 +42,6 @@ NotifyCategoryDef(bam, util_cat);
|
|||
|
||||
ConfigureFn(config_util) {
|
||||
BamReaderParam::init_type();
|
||||
ButtonEventList::init_type();
|
||||
Configurable::init_type();
|
||||
Datagram::init_type();
|
||||
FactoryParam::init_type();
|
||||
|
|
@ -58,6 +56,8 @@ ConfigureFn(config_util) {
|
|||
|
||||
KeyboardButton::init_keyboard_buttons();
|
||||
MouseButton::init_mouse_buttons();
|
||||
|
||||
register_type(BamReader::_remove_flag, "remove");
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -23,14 +23,9 @@
|
|||
#include "config_util.h"
|
||||
#include "config_express.h"
|
||||
#include "virtualFileSystem.h"
|
||||
|
||||
#include "streamReader.h"
|
||||
#include "datagramInputFile.h"
|
||||
|
||||
//#define SKYLER_TIMER 1
|
||||
#ifdef SKYLER_TIMER //[
|
||||
EXPCL_PANDAEXPRESS ProfileTimer Skyler_timer_file;
|
||||
#endif //]
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DatagramInputFile::open
|
||||
// Access: Public
|
||||
|
|
@ -135,26 +130,22 @@ read_header(string &header, size_t num_bytes) {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
bool DatagramInputFile::
|
||||
get_datagram(Datagram &data) {
|
||||
#ifdef SKYLER_TIMER //[
|
||||
Skyler_timer_file.on();
|
||||
#endif //]
|
||||
nassertr(_in != (istream *)NULL, false);
|
||||
_read_first_datagram = true;
|
||||
|
||||
// First, get the size of the upcoming datagram. We do this with
|
||||
// the help of a second datagram.
|
||||
char sizebuf[sizeof(PN_uint32)];
|
||||
_in->read(sizebuf, sizeof(PN_uint32));
|
||||
// First, get the size of the upcoming datagram.
|
||||
StreamReader reader(_in, false);
|
||||
PN_uint32 num_bytes = reader.get_uint32();
|
||||
if (_in->fail() || _in->eof()) {
|
||||
#ifdef SKYLER_TIMER //[
|
||||
Skyler_timer_file.off("DatagramInputFile::get_datagram");
|
||||
#endif //]
|
||||
return false;
|
||||
}
|
||||
|
||||
Datagram size(sizebuf, sizeof(PN_uint32));
|
||||
DatagramIterator di(size);
|
||||
PN_uint32 num_bytes = di.get_uint32();
|
||||
if (num_bytes == 0) {
|
||||
// A special case for a zero-length datagram: no need to try to
|
||||
// read any data.
|
||||
data.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Now, read the datagram itself.
|
||||
char *buffer = new char[num_bytes];
|
||||
|
|
@ -164,17 +155,12 @@ get_datagram(Datagram &data) {
|
|||
if (_in->fail() || _in->eof()) {
|
||||
_error = true;
|
||||
delete[] buffer;
|
||||
#ifdef SKYLER_TIMER //[
|
||||
Skyler_timer_file.off("DatagramInputFile::get_datagram");
|
||||
#endif //]
|
||||
return false;
|
||||
}
|
||||
|
||||
data = Datagram(buffer, num_bytes);
|
||||
delete[] buffer;
|
||||
#ifdef SKYLER_TIMER //[
|
||||
Skyler_timer_file.off("DatagramInputFile::get_datagram");
|
||||
#endif //]
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "datagramOutputFile.h"
|
||||
#include "streamWriter.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: DatagramOutputFile::open
|
||||
|
|
@ -103,11 +104,9 @@ put_datagram(const Datagram &data) {
|
|||
nassertr(_out != (ostream *)NULL, false);
|
||||
_wrote_first_datagram = true;
|
||||
|
||||
// First, write the size of the upcoming datagram. We do this with
|
||||
// the help of a second datagram.
|
||||
Datagram size;
|
||||
size.add_uint32(data.get_length());
|
||||
_out->write((const char *)size.get_data(), size.get_length());
|
||||
// First, write the size of the upcoming datagram.
|
||||
StreamWriter writer(_out);
|
||||
writer.add_uint32(data.get_length());
|
||||
|
||||
// Now, write the datagram itself.
|
||||
_out->write((const char *)data.get_data(), data.get_length());
|
||||
|
|
|
|||
|
|
@ -92,26 +92,6 @@ get_button(int index) const {
|
|||
return _button_list[index];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ModifierButtons::add_event
|
||||
// Access: Published
|
||||
// Description: Calls button_down() or button_up(), as appropriate,
|
||||
// according to the indicated ButtonEvent.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool ModifierButtons::
|
||||
add_event(const ButtonEvent &event) {
|
||||
switch (event._type) {
|
||||
case ButtonEvent::T_down:
|
||||
return button_down(event._button);
|
||||
|
||||
case ButtonEvent::T_up:
|
||||
return button_up(event._button);
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: ModifierButtons::all_buttons_up
|
||||
// Access: Published
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@
|
|||
|
||||
#include "buttonHandle.h"
|
||||
#include "pointerToArray.h"
|
||||
#include "buttonEvent.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : ModifierButtons
|
||||
|
|
@ -53,7 +52,6 @@ PUBLISHED:
|
|||
|
||||
bool button_down(ButtonHandle button);
|
||||
bool button_up(ButtonHandle button);
|
||||
INLINE bool add_event(const ButtonEvent &event);
|
||||
INLINE void all_buttons_up();
|
||||
|
||||
bool is_down(ButtonHandle button) const;
|
||||
|
|
|
|||
|
|
@ -2,8 +2,6 @@
|
|||
#include "bamReaderParam.cxx"
|
||||
#include "bamWriter.cxx"
|
||||
#include "bitMask.cxx"
|
||||
#include "buttonEvent.cxx"
|
||||
#include "buttonEventList.cxx"
|
||||
#include "buttonHandle.cxx"
|
||||
#include "buttonRegistry.cxx"
|
||||
#include "config_util.cxx"
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@
|
|||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "typedWritable.h"
|
||||
#include "bamWriter.h"
|
||||
|
||||
TypeHandle TypedWritable::_type_handle;
|
||||
TypedWritable* const TypedWritable::Null = (TypedWritable*)0L;
|
||||
|
|
@ -26,7 +27,14 @@ TypedWritable* const TypedWritable::Null = (TypedWritable*)0L;
|
|||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable::~TypedWritable() {
|
||||
TypedWritable::
|
||||
~TypedWritable() {
|
||||
// Remove the object pointer from the BamWriters that reference it.
|
||||
BamWriters::iterator wi;
|
||||
for (wi = _bam_writers.begin(); wi != _bam_writers.end(); ++wi) {
|
||||
BamWriter *writer = (*wi);
|
||||
writer->object_destructs(this);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
#include "typedObject.h"
|
||||
#include "vector_typedWritable.h"
|
||||
#include "pvector.h"
|
||||
|
||||
class BamReader;
|
||||
class BamWriter;
|
||||
|
|
@ -32,7 +33,7 @@ class DatagramIterator;
|
|||
// Description : Base class for objects that can be written to and
|
||||
// read from Bam files.
|
||||
//
|
||||
// See Also TypeObject for detailed instructions.
|
||||
// See also TypedObject for detailed instructions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
class EXPCL_PANDA TypedWritable : public TypedObject {
|
||||
|
|
@ -54,6 +55,13 @@ public:
|
|||
protected:
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
private:
|
||||
// We need to store a list of the BamWriter(s) that have a reference
|
||||
// to this object, so that we can remove the object from those
|
||||
// tables when it destructs.
|
||||
typedef pvector<BamWriter *> BamWriters;
|
||||
BamWriters _bam_writers;
|
||||
|
||||
PUBLISHED:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
|
|
@ -76,6 +84,8 @@ public:
|
|||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class BamWriter;
|
||||
};
|
||||
|
||||
#include "typedWritable.I"
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
// pass around pointers to things which are both
|
||||
// TypedWritables and ReferenceCounters.
|
||||
//
|
||||
// See Also TypeObject for detailed instructions.
|
||||
// See also TypedObject for detailed instructions.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA TypedWritableReferenceCount : public TypedWritable, public ReferenceCount {
|
||||
public:
|
||||
|
|
@ -42,9 +42,6 @@ public:
|
|||
INLINE TypedWritableReferenceCount(const TypedWritableReferenceCount ©);
|
||||
INLINE void operator = (const TypedWritableReferenceCount ©);
|
||||
|
||||
public:
|
||||
virtual void write_datagram(BamWriter *, Datagram &) = 0;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
#define OTHER_LIBS interrogatedb:c dconfig:c dtoolconfig:m \
|
||||
dtoolutil:c dtoolbase:c dtool:m
|
||||
#define LOCAL_LIBS dgraph putil express pandabase
|
||||
|
||||
#begin lib_target
|
||||
#define TARGET recorder
|
||||
|
||||
#define COMBINED_SOURCES $[TARGET]_composite1.cxx $[TARGET]_composite2.cxx
|
||||
|
||||
#define SOURCES \
|
||||
config_recorder.h \
|
||||
mouseRecorder.h \
|
||||
recorderBase.h recorderBase.I \
|
||||
recorderController.h recorderController.I \
|
||||
recorderFrame.h recorderFrame.I \
|
||||
recorderHeader.h recorderHeader.I \
|
||||
recorderTable.h recorderTable.I \
|
||||
socketStreamRecorder.h socketStreamRecorder.I
|
||||
|
||||
#define INCLUDED_SOURCES \
|
||||
config_recorder.cxx \
|
||||
mouseRecorder.cxx \
|
||||
recorderBase.cxx recorderController.cxx \
|
||||
recorderFrame.cxx recorderHeader.cxx recorderTable.cxx \
|
||||
socketStreamRecorder.cxx
|
||||
|
||||
#define INSTALL_HEADERS \
|
||||
mouseRecorder.h \
|
||||
recorderBase.h recorderBase.I \
|
||||
recorderController.h recorderController.I \
|
||||
recorderFrame.h recorderFrame.I \
|
||||
recorderHeader.h recorderHeader.I \
|
||||
recorderTable.h recorderTable.I \
|
||||
socketStreamRecorder.h socketStreamRecorder.I
|
||||
|
||||
#define IGATESCAN all
|
||||
|
||||
#end lib_target
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
// Filename: config_recorder.cxx
|
||||
// Created by: drose (28Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "config_recorder.h"
|
||||
|
||||
#include "mouseRecorder.h"
|
||||
#include "recorderController.h"
|
||||
#include "recorderFrame.h"
|
||||
#include "recorderHeader.h"
|
||||
#include "recorderTable.h"
|
||||
#include "socketStreamRecorder.h"
|
||||
|
||||
#include "dconfig.h"
|
||||
|
||||
ConfigureDef(config_recorder);
|
||||
NotifyCategoryDef(recorder, "");
|
||||
|
||||
ConfigureFn(config_recorder) {
|
||||
MouseRecorder::init_type();
|
||||
RecorderController::init_type();
|
||||
RecorderFrame::init_type();
|
||||
RecorderHeader::init_type();
|
||||
RecorderTable::init_type();
|
||||
ReferenceCount::init_type();
|
||||
SocketStreamRecorder::init_type();
|
||||
|
||||
MouseRecorder::register_with_read_factory();
|
||||
RecorderFrame::register_with_read_factory();
|
||||
RecorderHeader::register_with_read_factory();
|
||||
RecorderTable::register_with_read_factory();
|
||||
SocketStreamRecorder::register_with_read_factory();
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
// Filename: config_recorder.h
|
||||
// Created by: drose (28Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef CONFIG_RECORDER_H
|
||||
#define CONFIG_RECORDER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "notifyCategoryProxy.h"
|
||||
#include "dconfig.h"
|
||||
|
||||
ConfigureDecl(config_recorder, EXPCL_PANDA, EXPTP_PANDA);
|
||||
NotifyCategoryDecl(recorder, EXPCL_PANDA, EXPTP_PANDA);
|
||||
|
||||
#endif // CONFIG_RECORDER_H
|
||||
|
|
@ -0,0 +1,297 @@
|
|||
// Filename: mouseRecorder.cxx
|
||||
// Created by: drose (24Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "mouseRecorder.h"
|
||||
#include "recorderController.h"
|
||||
#include "dataNodeTransmit.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
|
||||
TypeHandle MouseRecorder::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MouseRecorder::
|
||||
MouseRecorder(const string &name) :
|
||||
DataNode(name)
|
||||
{
|
||||
_pixel_xy_input = define_input("pixel_xy", EventStoreVec2::get_class_type());
|
||||
_xy_input = define_input("xy", EventStoreVec2::get_class_type());
|
||||
_button_events_input = define_input("button_events", ButtonEventList::get_class_type());
|
||||
|
||||
_pixel_xy_output = define_output("pixel_xy", EventStoreVec2::get_class_type());
|
||||
_xy_output = define_output("xy", EventStoreVec2::get_class_type());
|
||||
_button_events_output = define_output("button_events", ButtonEventList::get_class_type());
|
||||
|
||||
_live_button_events = new ButtonEventList;
|
||||
_save_button_events = new ButtonEventList;
|
||||
|
||||
_pixel_xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
|
||||
_xy = new EventStoreVec2(LPoint2f(0.0f, 0.0f));
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::Destructor
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
MouseRecorder::
|
||||
~MouseRecorder() {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::record_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Records the most recent data collected into the
|
||||
// indicated datagram, and returns true if there is any
|
||||
// interesting data worth recording, or false if the
|
||||
// datagram is meaningless.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
record_frame(BamWriter *manager, Datagram &dg) {
|
||||
nassertv(is_recording());
|
||||
dg.add_bool(_has_mouse);
|
||||
if (_has_mouse) {
|
||||
_mouse_xy.write_datagram(dg);
|
||||
_mouse_pixel_xy.write_datagram(dg);
|
||||
}
|
||||
_save_button_events->write_datagram(manager, dg);
|
||||
_save_button_events->clear();
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::play_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Reloads the most recent data collected from the
|
||||
// indicated datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
play_frame(DatagramIterator &scan, BamReader *manager) {
|
||||
nassertv(is_playing());
|
||||
_has_mouse = scan.get_bool();
|
||||
if (_has_mouse) {
|
||||
_mouse_xy.read_datagram(scan);
|
||||
_mouse_pixel_xy.read_datagram(scan);
|
||||
}
|
||||
ButtonEventList button_events;
|
||||
button_events.fillin(scan, manager);
|
||||
_save_button_events->add_events(button_events);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::output
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
output(ostream &out) const {
|
||||
DataNode::output(out);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::write
|
||||
// Access: Public, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
write(ostream &out, int indent_level) const {
|
||||
DataNode::write(out, indent_level);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::do_transmit_data
|
||||
// Access: Protected, Virtual
|
||||
// Description: The virtual implementation of transmit_data(). This
|
||||
// function receives an array of input parameters and
|
||||
// should generate an array of output parameters. The
|
||||
// input parameters may be accessed with the index
|
||||
// numbers returned by the define_input() calls that
|
||||
// were made earlier (presumably in the constructor);
|
||||
// likewise, the output parameters should be set with
|
||||
// the index numbers returned by the define_output()
|
||||
// calls.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
do_transmit_data(const DataNodeTransmit &input, DataNodeTransmit &output) {
|
||||
bool has_mouse = false;
|
||||
LPoint2f mouse_xy;
|
||||
LPoint2f mouse_pixel_xy;
|
||||
|
||||
_live_button_events->clear();
|
||||
|
||||
if (is_playing()) {
|
||||
// If we're playing back data, copy in the data from a previous
|
||||
// call to play_frame().
|
||||
has_mouse = _has_mouse;
|
||||
mouse_xy = _mouse_xy;
|
||||
mouse_pixel_xy = _mouse_pixel_xy;
|
||||
_live_button_events->add_events(*_save_button_events);
|
||||
_save_button_events->clear();
|
||||
|
||||
} else {
|
||||
// If we're not playing back data, query the data from the data
|
||||
// graph
|
||||
|
||||
if (input.has_data(_xy_input)) {
|
||||
// The mouse is within the window. Get the current mouse position.
|
||||
const EventStoreVec2 *xy;
|
||||
DCAST_INTO_V(xy, input.get_data(_xy_input).get_ptr());
|
||||
mouse_xy = xy->get_value();
|
||||
DCAST_INTO_V(xy, input.get_data(_pixel_xy_input).get_ptr());
|
||||
mouse_pixel_xy = xy->get_value();
|
||||
has_mouse = true;
|
||||
}
|
||||
|
||||
// Look for button events.
|
||||
if (input.has_data(_button_events_input)) {
|
||||
const ButtonEventList *button_events;
|
||||
DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
|
||||
_live_button_events->add_events(*button_events);
|
||||
}
|
||||
}
|
||||
|
||||
// Now rebuild the output data for our children.
|
||||
|
||||
if (has_mouse) {
|
||||
// Transmit the mouse position.
|
||||
_pixel_xy->set_value(_mouse_pixel_xy);
|
||||
_xy->set_value(_mouse_xy);
|
||||
output.set_data(_xy_output, EventParameter(_xy));
|
||||
output.set_data(_pixel_xy_output, EventParameter(_pixel_xy));
|
||||
}
|
||||
|
||||
if (_live_button_events->get_num_events() != 0) {
|
||||
output.set_data(_button_events_output, EventParameter(_live_button_events));
|
||||
}
|
||||
|
||||
if (is_recording()) {
|
||||
// Save data for the record.
|
||||
_has_mouse = has_mouse;
|
||||
_mouse_xy = mouse_xy;
|
||||
_mouse_pixel_xy = mouse_pixel_xy;
|
||||
_save_button_events->add_events(*_live_button_events);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::register_with_read_factory
|
||||
// Access: Public, Static
|
||||
// Description: Tells the BamReader how to create objects of type
|
||||
// Lens.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
register_with_read_factory() {
|
||||
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
|
||||
RecorderController::get_factory()->register_factory(get_class_type(), make_recorder);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::write_datagram
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for shipping out to a Bam file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
write_datagram(BamWriter *manager, Datagram &dg) {
|
||||
DataNode::write_datagram(manager, dg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::write_recorder
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for encoding in the session file. This is very
|
||||
// similar to write_datagram() for TypedWritable
|
||||
// objects, but it is used specifically to write the
|
||||
// Recorder object when generating the session file. In
|
||||
// many cases, it will be the same as write_datagram().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
write_recorder(BamWriter *manager, Datagram &dg) {
|
||||
RecorderBase::write_recorder(manager, dg);
|
||||
DataNode::write_recorder(manager, dg);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::make_from_bam
|
||||
// Access: Protected, Static
|
||||
// Description: This function is called by the BamReader's factory
|
||||
// when a new object of type Lens is encountered
|
||||
// in the Bam file. It should create the Lens
|
||||
// and extract its information from the file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
TypedWritable *MouseRecorder::
|
||||
make_from_bam(const FactoryParams ¶ms) {
|
||||
MouseRecorder *node = new MouseRecorder("");
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::make_recorder
|
||||
// Access: Protected, Static
|
||||
// Description: This is similar to make_from_bam(), but it is
|
||||
// designed for loading the RecorderBase object from the
|
||||
// session log created by a RecorderController.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RecorderBase *MouseRecorder::
|
||||
make_recorder(const FactoryParams ¶ms) {
|
||||
MouseRecorder *node = new MouseRecorder("");
|
||||
DatagramIterator scan;
|
||||
BamReader *manager;
|
||||
|
||||
parse_params(params, scan, manager);
|
||||
node->fillin_recorder(scan, manager);
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::fillin
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new MouseRecorder.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
fillin(DatagramIterator &scan, BamReader *manager) {
|
||||
DataNode::fillin(scan, manager);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: MouseRecorder::fillin_recorder
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_from_bam to
|
||||
// read in all of the relevant data from the BamFile for
|
||||
// the new MouseRecorder.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void MouseRecorder::
|
||||
fillin_recorder(DatagramIterator &scan, BamReader *manager) {
|
||||
RecorderBase::fillin_recorder(scan, manager);
|
||||
DataNode::fillin_recorder(scan, manager);
|
||||
}
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
// Filename: mouseRecorder.h
|
||||
// Created by: drose (25Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef MOUSERECORDER_H
|
||||
#define MOUSERECORDER_H
|
||||
|
||||
#include "recorderBase.h"
|
||||
#include "dataNode.h"
|
||||
#include "dataNodeTransmit.h"
|
||||
#include "linmath_events.h"
|
||||
#include "buttonEventList.h"
|
||||
|
||||
class FactoryParams;
|
||||
class BamReader;
|
||||
class BamWriter;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : MouseRecorder
|
||||
// Description : This object records any data generated by a
|
||||
// particular MouseAndKeyboard node on the datagraph for
|
||||
// a session for eventual playback via a
|
||||
// DataGraphPlayback (and a PlaybackController). To use
|
||||
// it, make it a child of the node you wish to record.
|
||||
// It also serves as a pass-through, so that additional
|
||||
// child nodes may be parented directly to it.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA MouseRecorder : public DataNode, public RecorderBase {
|
||||
PUBLISHED:
|
||||
MouseRecorder(const string &name);
|
||||
virtual ~MouseRecorder();
|
||||
|
||||
public:
|
||||
virtual void record_frame(BamWriter *manager, Datagram &dg);
|
||||
virtual void play_frame(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
virtual void output(ostream &out) const;
|
||||
virtual void write(ostream &out, int indent_level = 0) const;
|
||||
|
||||
protected:
|
||||
// Inherited from DataNode
|
||||
virtual void do_transmit_data(const DataNodeTransmit &input,
|
||||
DataNodeTransmit &output);
|
||||
|
||||
private:
|
||||
// inputs
|
||||
int _pixel_xy_input;
|
||||
int _xy_input;
|
||||
int _button_events_input;
|
||||
|
||||
// outputs
|
||||
int _pixel_xy_output;
|
||||
int _xy_output;
|
||||
int _button_events_output;
|
||||
|
||||
bool _has_mouse;
|
||||
LPoint2f _mouse_xy;
|
||||
LPoint2f _mouse_pixel_xy;
|
||||
PT(ButtonEventList) _live_button_events;
|
||||
PT(ButtonEventList) _save_button_events;
|
||||
|
||||
PT(EventStoreVec2) _pixel_xy;
|
||||
PT(EventStoreVec2) _xy;
|
||||
|
||||
public:
|
||||
static void register_with_read_factory();
|
||||
virtual void write_datagram(BamWriter *manager, Datagram &dg);
|
||||
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
static TypedWritable *make_from_bam(const FactoryParams ¶ms);
|
||||
static RecorderBase *make_recorder(const FactoryParams ¶ms);
|
||||
void fillin(DatagramIterator &scan, BamReader *manager);
|
||||
void fillin_recorder(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
DataNode::init_type();
|
||||
RecorderBase::init_type();
|
||||
register_type(_type_handle, "MouseRecorder",
|
||||
DataNode::get_class_type(),
|
||||
RecorderBase::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
// Filename: recorderBase.I
|
||||
// Created by: drose (24Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::is_recording
|
||||
// Access: Published
|
||||
// Description: Returns true if this recorder is presently recording
|
||||
// data for saving to a session file, false otherwise.
|
||||
// If this is true, record_data() will be called from
|
||||
// time to time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderBase::
|
||||
is_recording() const {
|
||||
return (_flags & F_recording) != 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::is_playing
|
||||
// Access: Published
|
||||
// Description: Returns true if this recorder is presently playing back
|
||||
// data from session file, false otherwise. If this is
|
||||
// true, play_data() will be called from time to time.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderBase::
|
||||
is_playing() const {
|
||||
return (_flags & F_playing) != 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
// Filename: recorderBase.cxx
|
||||
// Created by: drose (24Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "recorderBase.h"
|
||||
|
||||
TypeHandle RecorderBase::_type_handle;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::Constructor
|
||||
// Access: Protected
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RecorderBase::
|
||||
RecorderBase() {
|
||||
_flags = 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::Destructor
|
||||
// Access: Published, Virtual
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RecorderBase::
|
||||
~RecorderBase() {
|
||||
nassertv(_flags == 0);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::record_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Records the most recent data collected into the
|
||||
// indicated datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RecorderBase::
|
||||
record_frame(BamWriter *, Datagram &) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::play_frame
|
||||
// Access: Public, Virtual
|
||||
// Description: Reloads the most recent data collected from the
|
||||
// indicated datagram.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RecorderBase::
|
||||
play_frame(DatagramIterator &scan, BamReader *manager) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::write_recorder
|
||||
// Access: Public, Virtual
|
||||
// Description: Writes the contents of this object to the datagram
|
||||
// for encoding in the session file. This is very
|
||||
// similar to write_datagram() for TypedWritable
|
||||
// objects, but it is used specifically to write the
|
||||
// Recorder object when generating the session file. In
|
||||
// many cases, it will be the same as write_datagram().
|
||||
//
|
||||
// This balances with fillin_recorder().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RecorderBase::
|
||||
write_recorder(BamWriter *, Datagram &) {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderBase::fillin_recorder
|
||||
// Access: Protected
|
||||
// Description: This internal function is called by make_recorder (in
|
||||
// derived classes) to read in all of the relevant data
|
||||
// from the session file. It balances with
|
||||
// write_recorder().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RecorderBase::
|
||||
fillin_recorder(DatagramIterator &, BamReader *) {
|
||||
}
|
||||
|
|
@ -0,0 +1,102 @@
|
|||
// Filename: recorderBase.h
|
||||
// Created by: drose (25Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef RECORDERBASE_H
|
||||
#define RECORDERBASE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "referenceCount.h"
|
||||
|
||||
class BamReader;
|
||||
class BamWriter;
|
||||
class Datagram;
|
||||
class DatagramIterator;
|
||||
class TypedWritable;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Class : RecorderBase
|
||||
// Description : This is the base class to a number of objects that
|
||||
// record particular kinds of user input (like a
|
||||
// MouseRecorder) to use in conjunction with a
|
||||
// RecorderController to record the user's inputs
|
||||
// for a session.
|
||||
//
|
||||
// Note that RecorderBase does not actually inherit from
|
||||
// TypedObject, even though it defines get_type(). The
|
||||
// assumption is that the classes that derive from
|
||||
// RecorderBase might also inherit independently from
|
||||
// TypedObject.
|
||||
//
|
||||
// It also does not inherit from TypedWritable, but it
|
||||
// defines a method called write_recorder() which is
|
||||
// very similar to a TypedWritable's write_datagram().
|
||||
// Classes that derive from RecorderBase and also
|
||||
// inherit from TypedWritable may choose to remap
|
||||
// write_recorder() to do exactly the same thing as
|
||||
// write_datagram(), or they may choose to write
|
||||
// something slightly different.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
class EXPCL_PANDA RecorderBase : virtual public ReferenceCount {
|
||||
protected:
|
||||
RecorderBase();
|
||||
|
||||
PUBLISHED:
|
||||
virtual ~RecorderBase();
|
||||
|
||||
INLINE bool is_recording() const;
|
||||
INLINE bool is_playing() const;
|
||||
|
||||
public:
|
||||
virtual void record_frame(BamWriter *manager, Datagram &dg);
|
||||
virtual void play_frame(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
virtual void write_recorder(BamWriter *manager, Datagram &dg);
|
||||
|
||||
protected:
|
||||
void fillin_recorder(DatagramIterator &scan, BamReader *manager);
|
||||
|
||||
private:
|
||||
enum Flags {
|
||||
F_recording = 0x0001,
|
||||
F_playing = 0x0002,
|
||||
};
|
||||
short _flags;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
ReferenceCount::init_type();
|
||||
register_type(_type_handle, "RecorderBase",
|
||||
ReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class RecorderController;
|
||||
};
|
||||
|
||||
#include "recorderBase.I"
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,294 @@
|
|||
// Filename: recorderController.I
|
||||
// Created by: drose (24Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_start_time
|
||||
// Access: Published
|
||||
// Description: Returns the time (and date) at which the current
|
||||
// session was originally recorded (or, in recording
|
||||
// mode, the time at which the current session began).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE time_t RecorderController::
|
||||
get_start_time() const {
|
||||
return _header._start_time;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::set_random_seed
|
||||
// Access: Published
|
||||
// Description: Indicates an arbitrary number to be recorded in the
|
||||
// session file as a random seed, should the application
|
||||
// wish to take advantage of it. This must be set
|
||||
// before begin_record() is called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void RecorderController::
|
||||
set_random_seed(int random_seed) {
|
||||
_header._random_seed = random_seed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_random_seed
|
||||
// Access: Published
|
||||
// Description: Returns the random seed that was set by a previous
|
||||
// call to set_random_seed(), or the number read from
|
||||
// the session file after begin_playback() has been
|
||||
// called.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int RecorderController::
|
||||
get_random_seed() const {
|
||||
return _header._random_seed;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::is_recording
|
||||
// Access: Published
|
||||
// Description: Returns true if the controller has been opened for
|
||||
// output, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderController::
|
||||
is_recording() const {
|
||||
return (_writer != (BamWriter *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::is_playing
|
||||
// Access: Published
|
||||
// Description: Returns true if the controller has been opened for
|
||||
// input, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderController::
|
||||
is_playing() const {
|
||||
return (_reader != (BamReader *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::is_open
|
||||
// Access: Published
|
||||
// Description: Returns true if the controller has been opened for
|
||||
// either input or output, false otherwise.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderController::
|
||||
is_open() const {
|
||||
return is_recording() || is_playing();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_filename
|
||||
// Access: Published
|
||||
// Description: Returns the filename that was passed to the most
|
||||
// recent call to begin_record() or begin_playback().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE const Filename &RecorderController::
|
||||
get_filename() const {
|
||||
return _filename;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::is_error
|
||||
// Access: Published
|
||||
// Description: Returns true if the controller has been opened for
|
||||
// input or output output and there is an error on the
|
||||
// stream, or false if the controller is closed or if
|
||||
// there is no problem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderController::
|
||||
is_error() {
|
||||
return _dout.is_error() || _din.is_error();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_clock_offset
|
||||
// Access: Published
|
||||
// Description: Returns the delta offset between the actual frame
|
||||
// time and the frame time written to the log. This is
|
||||
// essentially the time at which the recording (or
|
||||
// playback) started.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE double RecorderController::
|
||||
get_clock_offset() const {
|
||||
return _clock_offset;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_frame_offset
|
||||
// Access: Published
|
||||
// Description: Returns the delta offset between the actual frame
|
||||
// count and the frame count written to the log. This is
|
||||
// essentially the frame number at which the recording
|
||||
// (or playback) started.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE int RecorderController::
|
||||
get_frame_offset() const {
|
||||
return _frame_offset;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::add_recorder
|
||||
// Access: Published
|
||||
// Description: Adds the named recorder to the set of recorders that
|
||||
// are in use.
|
||||
//
|
||||
// If the controller is in recording mode, the named
|
||||
// recorder will begin recording its status to the
|
||||
// session file. If the controller is in playback mode
|
||||
// and the name and type matches a recorder in the
|
||||
// session file, the recorder will begin receiving data.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void RecorderController::
|
||||
add_recorder(const string &name, RecorderBase *recorder) {
|
||||
_user_table->add_recorder(name, recorder);
|
||||
_user_table_modified = true;
|
||||
|
||||
// We can only add the state flag immediately if we are in recording
|
||||
// mode. In playback mode, we're not sure yet whether the new
|
||||
// recorder state will actually be playing (we won't know until we
|
||||
// merge the tables in play_frame()).
|
||||
if (is_recording()) {
|
||||
recorder->_flags |= RecorderBase::F_recording;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::has_recorder
|
||||
// Access: Published
|
||||
// Description: Returns true if the named recorder has been added to
|
||||
// the table by a previous call to add_recorder(), false
|
||||
// otherwise.
|
||||
//
|
||||
// If the controller is in playback mode, this will also
|
||||
// return false for a recorder that was found in the
|
||||
// session file but was never explicitly added via
|
||||
// add_recorder(); see get_recorder().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderController::
|
||||
has_recorder(const string &name) const {
|
||||
return (_user_table->get_recorder(name) != (RecorderBase *)NULL);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_recorder
|
||||
// Access: Published
|
||||
// Description: Returns the recorder with the indicated name, or NULL
|
||||
// if there is no such recorder.
|
||||
//
|
||||
// If the controller is in playback mode, this may
|
||||
// return the recorder matching the indicated name as
|
||||
// read from the session file, even if it was never
|
||||
// added to the table by the user. In this case,
|
||||
// has_recorder() may return false, but get_recorder()
|
||||
// will return a non-NULL value.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE RecorderBase *RecorderController::
|
||||
get_recorder(const string &name) const {
|
||||
RecorderBase *recorder = _user_table->get_recorder(name);
|
||||
if (is_playing() && recorder == (RecorderBase *)NULL) {
|
||||
recorder = _active_table->get_recorder(name);
|
||||
}
|
||||
return recorder;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::remove_recorder
|
||||
// Access: Published
|
||||
// Description: Removes the named recorder from the table. Returns
|
||||
// true if successful, false if there was no such
|
||||
// recorder.
|
||||
//
|
||||
// If the controller is in recording mode, the named
|
||||
// recorder will stop recording. If the controller is
|
||||
// in playback mode, the named recorder will
|
||||
// disassociate itself from the session file (but if the
|
||||
// session file still has data for this name, a default
|
||||
// recorder will take its place to decode the data from
|
||||
// the session file).
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderController::
|
||||
remove_recorder(const string &name) {
|
||||
// If we are playing or recording, immediately remove the state flag
|
||||
// from the recorder. (When we are playing, the state flag will get
|
||||
// removed automatically at the next call to play_frame(), but we
|
||||
// might as well be aggressive and remove it now. When we are
|
||||
// recording, we have to remove it now.)
|
||||
if (is_recording() || is_playing()) {
|
||||
RecorderBase *recorder = _user_table->get_recorder(name);
|
||||
if (recorder != (RecorderBase *)NULL) {
|
||||
recorder->_flags &= ~(RecorderBase::F_recording | RecorderBase::F_playing);
|
||||
}
|
||||
}
|
||||
_user_table_modified = true;
|
||||
return _user_table->remove_recorder(name);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::set_frame_tie
|
||||
// Access: Published
|
||||
// Description: Sets the frame_tie flag.
|
||||
//
|
||||
// When this is true, sessions are played back
|
||||
// frame-for-frame, based on the frame count of the
|
||||
// recorded session. This gives the most accurate
|
||||
// playback, but the playback rate will vary according
|
||||
// to the frame rate of the playback machine.
|
||||
//
|
||||
// When this is false, sessions are played back at real
|
||||
// time, based on the clock of the recorded session.
|
||||
// This may introduce playback discrepencies if the
|
||||
// frames do not fall at exactly the same times as they
|
||||
// did in the original.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void RecorderController::
|
||||
set_frame_tie(bool frame_tie) {
|
||||
_frame_tie = frame_tie;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_frame_tie
|
||||
// Access: Published
|
||||
// Description: See set_frame_tie().
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE bool RecorderController::
|
||||
get_frame_tie() const {
|
||||
return _frame_tie;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::get_factory
|
||||
// Access: Public, Static
|
||||
// Description: Returns the global RecorderFactory for generating
|
||||
// TypedWritable objects
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE RecorderController::RecorderFactory *RecorderController::
|
||||
get_factory() {
|
||||
if (_factory == (RecorderFactory *)NULL) {
|
||||
create_factory();
|
||||
}
|
||||
return _factory;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::create_factory
|
||||
// Access: Private, Static
|
||||
// Description: Creates a new RecorderFactory for generating
|
||||
// TypedWritable objects
|
||||
////////////////////////////////////////////////////////////////////
|
||||
INLINE void RecorderController::
|
||||
create_factory() {
|
||||
_factory = new RecorderFactory;
|
||||
}
|
||||
|
|
@ -0,0 +1,370 @@
|
|||
// Filename: recorderController.cxx
|
||||
// Created by: drose (24Jan04)
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// PANDA 3D SOFTWARE
|
||||
// Copyright (c) 2001, Disney Enterprises, Inc. All rights reserved
|
||||
//
|
||||
// All use of this software is subject to the terms of the Panda 3d
|
||||
// Software license. You should have received a copy of this license
|
||||
// along with this source code; you will also find a current copy of
|
||||
// the license at http://www.panda3d.org/license.txt .
|
||||
//
|
||||
// To contact the maintainers of this program write to
|
||||
// panda3d@yahoogroups.com .
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "recorderController.h"
|
||||
#include "recorderFrame.h"
|
||||
#include "bamReader.h"
|
||||
#include "bamWriter.h"
|
||||
#include "config_recorder.h"
|
||||
#include "bam.h"
|
||||
|
||||
TypeHandle RecorderController::_type_handle;
|
||||
RecorderController::RecorderFactory *RecorderController::_factory = NULL;
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::Constructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RecorderController::
|
||||
RecorderController() {
|
||||
_clock_offset = 0.0;
|
||||
_frame_offset = 0;
|
||||
_writer = (BamWriter *)NULL;
|
||||
_reader = (BamReader *)NULL;
|
||||
_frame_tie = true;
|
||||
_user_table = new RecorderTable;
|
||||
_user_table_modified = false;
|
||||
_file_table = NULL;
|
||||
_active_table = NULL;
|
||||
_eof = false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::Destructor
|
||||
// Access: Published
|
||||
// Description:
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RecorderController::
|
||||
~RecorderController() {
|
||||
close();
|
||||
delete _user_table;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::begin_record
|
||||
// Access: Published
|
||||
// Description: Begins recording data to the indicated filename. All
|
||||
// of the recorders in use should already have been
|
||||
// added.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool RecorderController::
|
||||
begin_record(const Filename &filename) {
|
||||
close();
|
||||
_filename = filename;
|
||||
ClockObject *global_clock = ClockObject::get_global_clock();
|
||||
_clock_offset = global_clock->get_frame_time();
|
||||
_frame_offset = global_clock->get_frame_count();
|
||||
|
||||
time(&_header._start_time);
|
||||
|
||||
if (!_dout.open(_filename)) {
|
||||
recorder_cat.error() << "Unable to open " << _filename << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_dout.write_header(_bam_header)) {
|
||||
recorder_cat.error() << "Unable to write to " << _filename << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
_writer = new BamWriter(&_dout);
|
||||
|
||||
if (!_writer->init()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
// Write out the header information.
|
||||
_writer->write_object(&_header);
|
||||
|
||||
_user_table_modified = true;
|
||||
|
||||
// Tell all of our recorders that they're live now.
|
||||
RecorderTable::Recorders::iterator ri;
|
||||
for (ri = _user_table->_recorders.begin();
|
||||
ri != _user_table->_recorders.end();
|
||||
++ri) {
|
||||
RecorderBase *recorder = (*ri).second;
|
||||
recorder->_flags |= RecorderBase::F_recording;
|
||||
}
|
||||
|
||||
recorder_cat.info()
|
||||
<< "Recording session to " << _filename << "\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::begin_playback
|
||||
// Access: Published
|
||||
// Description: Begins playing back data from the indicated filename.
|
||||
// All of the recorders in use should already have been
|
||||
// added, although this may define additional recorders
|
||||
// if they are present in the file (these new recorders
|
||||
// will not be used). This may also undefine recorders
|
||||
// that were previously added but are not present in the
|
||||
// file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
bool RecorderController::
|
||||
begin_playback(const Filename &filename) {
|
||||
close();
|
||||
_filename = filename;
|
||||
ClockObject *global_clock = ClockObject::get_global_clock();
|
||||
_clock_offset = global_clock->get_frame_time();
|
||||
_frame_offset = global_clock->get_frame_count();
|
||||
|
||||
if (!_din.open(_filename)) {
|
||||
recorder_cat.error() << "Unable to open " << _filename << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
string head;
|
||||
if (!_din.read_header(head, _bam_header.size()) || head != _bam_header) {
|
||||
recorder_cat.error() << "Unable to read " << _filename << "\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
_reader = new BamReader(&_din);
|
||||
if (!_reader->init()) {
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
_user_table_modified = true;
|
||||
_active_table = new RecorderTable;
|
||||
_eof = false;
|
||||
|
||||
// Start out by reading the RecorderHeader.
|
||||
TypedWritable *object = _reader->read_object();
|
||||
|
||||
if (object == (TypedWritable *)NULL ||
|
||||
!object->is_of_type(RecorderHeader::get_class_type())) {
|
||||
recorder_cat.error()
|
||||
<< _filename << " does not contain a recorded session.\n";
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_reader->resolve()) {
|
||||
recorder_cat.warning()
|
||||
<< "Unable to resolve header data.\n";
|
||||
}
|
||||
|
||||
RecorderHeader *new_header = DCAST(RecorderHeader, object);
|
||||
_header = (*new_header);
|
||||
delete new_header;
|
||||
|
||||
// Now read the first frame.
|
||||
_next_frame = read_frame();
|
||||
if (_next_frame == (RecorderFrame *)NULL) {
|
||||
recorder_cat.error()
|
||||
<< _filename << " does not contain any frames.\n";
|
||||
close();
|
||||
return false;
|
||||
}
|
||||
|
||||
recorder_cat.info()
|
||||
<< "Playing back session from " << _filename << "\n";
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::close
|
||||
// Access: Published
|
||||
// Description: Finishes recording data to the indicated filename.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RecorderController::
|
||||
close() {
|
||||
if (_writer != (BamWriter *)NULL) {
|
||||
delete _writer;
|
||||
_writer = NULL;
|
||||
|
||||
// Tell all of our recorders that they're no longer recording.
|
||||
RecorderTable::Recorders::iterator ri;
|
||||
for (ri = _user_table->_recorders.begin();
|
||||
ri != _user_table->_recorders.end();
|
||||
++ri) {
|
||||
RecorderBase *recorder = (*ri).second;
|
||||
recorder->_flags &= ~RecorderBase::F_recording;
|
||||
}
|
||||
}
|
||||
if (_reader != (BamReader *)NULL) {
|
||||
delete _reader;
|
||||
_reader = NULL;
|
||||
|
||||
// Tell all of our recorders that they're no longer playing.
|
||||
RecorderTable::Recorders::iterator ri;
|
||||
for (ri = _active_table->_recorders.begin();
|
||||
ri != _active_table->_recorders.end();
|
||||
++ri) {
|
||||
RecorderBase *recorder = (*ri).second;
|
||||
recorder->_flags &= ~RecorderBase::F_playing;
|
||||
}
|
||||
}
|
||||
_dout.close();
|
||||
_din.close();
|
||||
|
||||
if (_file_table != (RecorderTable *)NULL) {
|
||||
delete _file_table;
|
||||
_file_table = (RecorderTable *)NULL;
|
||||
}
|
||||
|
||||
if (_active_table != (RecorderTable *)NULL) {
|
||||
delete _active_table;
|
||||
_active_table = (RecorderTable *)NULL;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::record_frame
|
||||
// Access: Published
|
||||
// Description: Gets the next frame of data from all of the active
|
||||
// recorders and adds it to the output file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RecorderController::
|
||||
record_frame() {
|
||||
if (is_recording()) {
|
||||
ClockObject *global_clock = ClockObject::get_global_clock();
|
||||
double now = global_clock->get_frame_time() - _clock_offset;
|
||||
int frame = global_clock->get_frame_count() - _frame_offset;
|
||||
|
||||
RecorderFrame data(now, frame, _user_table_modified, _user_table);
|
||||
_user_table_modified = false;
|
||||
|
||||
_writer->write_object(&data);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::play_frame
|
||||
// Access: Published
|
||||
// Description: Gets the next frame of data from all of the active
|
||||
// recorders and adds it to the output file.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
void RecorderController::
|
||||
play_frame() {
|
||||
if (is_playing()) {
|
||||
if (_eof) {
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
ClockObject *global_clock = ClockObject::get_global_clock();
|
||||
double now = global_clock->get_frame_time() - _clock_offset;
|
||||
int frame = global_clock->get_frame_count() - _frame_offset;
|
||||
|
||||
while (_next_frame != (RecorderFrame *)NULL) {
|
||||
if (_frame_tie) {
|
||||
if (frame < _next_frame->_frame) {
|
||||
// We haven't reached the next frame yet.
|
||||
return;
|
||||
}
|
||||
|
||||
// Insist that the clock runs at the same rate as it did in
|
||||
// the previous session.
|
||||
//global_clock->set_frame_time(_next_frame->_timestamp + _clock_offset);
|
||||
//global_clock->set_real_time(_next_frame->_timestamp + _clock_offset);
|
||||
|
||||
// Hmm, that's crummy. Just keep the clock offset up-to-date.
|
||||
_clock_offset = global_clock->get_frame_time() - _next_frame->_timestamp;
|
||||
|
||||
} else {
|
||||
if (now < _next_frame->_timestamp) {
|
||||
// We haven't reached the next frame yet.
|
||||
return;
|
||||
}
|
||||
|
||||
// Keep our frame_offset up-to-date.
|
||||
_frame_offset = global_clock->get_frame_count() - _next_frame->_frame;
|
||||
}
|
||||
|
||||
if (_next_frame->_table_changed && _file_table != _next_frame->_table) {
|
||||
delete _file_table;
|
||||
_file_table = _next_frame->_table;
|
||||
}
|
||||
|
||||
if (_next_frame->_table_changed || _user_table_modified) {
|
||||
// We're about to change the active table. Temporarily
|
||||
// disable the playing flag on the currently-active recorders.
|
||||
RecorderTable::Recorders::iterator ri;
|
||||
for (ri = _active_table->_recorders.begin();
|
||||
ri != _active_table->_recorders.end();
|
||||
++ri) {
|
||||
RecorderBase *recorder = (*ri).second;
|
||||
recorder->_flags &= ~RecorderBase::F_playing;
|
||||
}
|
||||
|
||||
delete _active_table;
|
||||
_active_table = new RecorderTable(*_file_table);
|
||||
_active_table->merge_from(*_user_table);
|
||||
_user_table_modified = false;
|
||||
|
||||
// Now reenable the playing flag on the newly-active
|
||||
// recorders.
|
||||
for (ri = _active_table->_recorders.begin();
|
||||
ri != _active_table->_recorders.end();
|
||||
++ri) {
|
||||
RecorderBase *recorder = (*ri).second;
|
||||
recorder->_flags |= RecorderBase::F_playing;
|
||||
}
|
||||
}
|
||||
|
||||
_next_frame->_table = _active_table;
|
||||
_next_frame->play_frame(_reader);
|
||||
|
||||
delete _next_frame;
|
||||
_next_frame = read_frame();
|
||||
}
|
||||
|
||||
if (_reader->is_eof()) {
|
||||
recorder_cat.info()
|
||||
<< "End of recorded session.\n";
|
||||
} else {
|
||||
recorder_cat.error()
|
||||
<< "Unable to read datagram from recorded session.\n";
|
||||
}
|
||||
_eof = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Function: RecorderController::read_frame
|
||||
// Access: Private
|
||||
// Description: Loads the next frame data from the playback session
|
||||
// file. Returns the frame data pointer on success, or
|
||||
// NULL on failure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
RecorderFrame *RecorderController::
|
||||
read_frame() {
|
||||
TypedWritable *object = _reader->read_object();
|
||||
|
||||
if (object == (TypedWritable *)NULL ||
|
||||
!object->is_of_type(RecorderFrame::get_class_type())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!_reader->resolve()) {
|
||||
recorder_cat.warning()
|
||||
<< "Unable to resolve frame data.\n";
|
||||
}
|
||||
|
||||
return DCAST(RecorderFrame, object);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue