diff --git a/direct/src/dcparser/dcAtomicField.cxx b/direct/src/dcparser/dcAtomicField.cxx index 7cefdc350d..bc3108a32d 100644 --- a/direct/src/dcparser/dcAtomicField.cxx +++ b/direct/src/dcparser/dcAtomicField.cxx @@ -240,7 +240,7 @@ end_array() { bool DCAtomicField::ElementType:: format_default_value(double num, string &formatted) const { double real_value = num * _divisor; - int int_value = (int)cfloor(real_value + 0.5); + int int_value = (int)floor(real_value + 0.5); switch (_type) { case ST_int8: @@ -564,6 +564,17 @@ is_ownsend() const { return (_flags & F_ownsend) != 0; } +//////////////////////////////////////////////////////////////////// +// Function: DCAtomicField::is_compress +// Access: Public +// Description: Returns true if the "compress" flag is set for this +// field, false otherwise. +//////////////////////////////////////////////////////////////////// +bool DCAtomicField:: +is_compress() const { + return (_flags & F_compress) != 0; +} + //////////////////////////////////////////////////////////////////// // Function: DCAtomicField::Constructor // Access: Public @@ -621,6 +632,9 @@ write(ostream &out, int indent_level) const { if ((_flags & F_ownsend) != 0) { out << " ownsend"; } + if ((_flags & F_compress) != 0) { + out << " compress"; + } out << "; // field " << _number << "\n"; } diff --git a/direct/src/dcparser/dcAtomicField.h b/direct/src/dcparser/dcAtomicField.h index 1f6397bf05..7c366e6b9b 100644 --- a/direct/src/dcparser/dcAtomicField.h +++ b/direct/src/dcparser/dcAtomicField.h @@ -19,11 +19,14 @@ #ifndef DCATOMICFIELD_H #define DCATOMICFIELD_H -#include #include "dcbase.h" #include "dcField.h" #include "dcSubatomicType.h" +// Must use math.h instead of cmath.h so this can compile outside of +// Panda. +#include + //////////////////////////////////////////////////////////////////// // Class : DCAtomicField // Description : A single atomic field of a Distributed Class, as read @@ -50,6 +53,7 @@ PUBLISHED: bool is_clsend() const; bool is_clrecv() const; bool is_ownsend() const; + bool is_compress() const; public: DCAtomicField(); @@ -94,6 +98,7 @@ public: F_clsend = 0x0020, F_clrecv = 0x0040, F_ownsend = 0x0080, + F_compress = 0x0100, }; int _flags; // A bitmask union of any of the above values. diff --git a/direct/src/dcparser/dcLexer.lxx b/direct/src/dcparser/dcLexer.lxx index 4fdab47709..adb8ccb1fb 100644 --- a/direct/src/dcparser/dcLexer.lxx +++ b/direct/src/dcparser/dcLexer.lxx @@ -471,6 +471,11 @@ mol[0-9]+ { return KW_OWNSEND; } +"compress" { + accept(); + return KW_COMPRESS; +} + {INTEGERNUM} { // An integer number. accept(); diff --git a/direct/src/dcparser/dcParser.yxx b/direct/src/dcparser/dcParser.yxx index 5dd4fb8fa7..84ddcf98ae 100644 --- a/direct/src/dcparser/dcParser.yxx +++ b/direct/src/dcparser/dcParser.yxx @@ -77,6 +77,7 @@ dc_cleanup_parser() { %token KW_CLSEND %token KW_CLRECV %token KW_OWNSEND +%token KW_COMPRESS %type dclass_name %type atomic_name @@ -414,6 +415,10 @@ atomic_flags: | atomic_flags KW_OWNSEND { current_atomic->_flags |= DCAtomicField::F_ownsend; +} + | atomic_flags KW_COMPRESS +{ + current_atomic->_flags |= DCAtomicField::F_compress; } ; diff --git a/direct/src/dcparser/dcbase.h b/direct/src/dcparser/dcbase.h index 2944fe3073..4eba1e177e 100644 --- a/direct/src/dcparser/dcbase.h +++ b/direct/src/dcparser/dcbase.h @@ -46,15 +46,9 @@ #pragma warning (disable : 4503) #endif /* WIN32_VC */ -#if defined(WIN32) #include #include #include -#else -#include -#include -#include -#endif #include #include diff --git a/direct/src/distributed/ClientDistClass.py b/direct/src/distributed/ClientDistClass.py index 7f00a58ad7..1af5c45adc 100644 --- a/direct/src/distributed/ClientDistClass.py +++ b/direct/src/distributed/ClientDistClass.py @@ -62,14 +62,14 @@ class ClientDistClass: requiredCDU.append(i) return requiredCDU - def updateField(self, do, di): + def updateField(self, do, di, allowCompress): # Get the update field id fieldId = di.getArg(STUint16) # look up the CDU assert(self.number2CDU.has_key(fieldId)) cdu = self.number2CDU[fieldId] # Let the cdu finish the job - cdu.updateField(self, do, di) + cdu.updateField(self, do, di, allowCompress) return None def sendUpdate(self, cr, do, fieldName, args, sendToId = None): diff --git a/direct/src/distributed/ClientDistUpdate.py b/direct/src/distributed/ClientDistUpdate.py index 9a82ffd4d3..0185e41853 100644 --- a/direct/src/distributed/ClientDistUpdate.py +++ b/direct/src/distributed/ClientDistUpdate.py @@ -20,6 +20,7 @@ class ClientDistUpdate: self.name = dcField.getName() self.types = [] self.divisors = [] + self.compress = 0 self.deriveTypesFromParticle(dcField) # Figure out our function pointer exec("import " + cdc.name, moduleGlobals, moduleLocals) @@ -40,19 +41,24 @@ class ClientDistUpdate: for i in range(0, dcFieldAtomic.getNumElements()): self.types.append(dcFieldAtomic.getElementType(i)) self.divisors.append(dcFieldAtomic.getElementDivisor(i)) + if dcFieldAtomic.isCompress(): + self.compress = 1 + elif dcFieldMolecular: for i in range(0, dcFieldMolecular.getNumAtomics()): componentField = dcFieldMolecular.getAtomic(i) for j in range(0, componentField.getNumElements()): self.types.append(componentField.getElementType(j)) self.divisors.append(componentField.getElementDivisor(j)) + if componentField.isCompress(): + self.compress = 1 else: ClientDistUpdate.notify.error("field is neither atom nor molecule") return None - def updateField(self, cdc, do, di): + def updateField(self, cdc, do, di, allowCompress): # Get the arguments into a list - args = self.extractArgs(di) + args = self.extractArgs(di, allowCompress) assert(self.notify.debug("Received update for %d: %s.%s(%s)" % (do.doId, cdc.name, self.name, args))) @@ -61,7 +67,13 @@ class ClientDistUpdate: apply(self.func, [do] + args) return None - def extractArgs(self, di): + def extractArgs(self, di, allowCompress): + if allowCompress and self.compress: + # Technically, the datagram pointer is const, so this is + # invalid. Ignore that for now. + argsAt = di.getCurrentIndex() + di.getDatagram().uncompress(argsAt) + args = [] assert(len(self.types) == len(self.divisors)) numTypes = len(self.types) @@ -88,7 +100,10 @@ class ClientDistUpdate: datagram.addUint32(sendToId) # Add the field id datagram.addUint16(self.number) + argsAt = datagram.getLength() # Add the arguments self.addArgs(datagram, args) + if self.compress: + datagram.compress(argsAt) # send the datagram cr.send(datagram) diff --git a/direct/src/distributed/ClientRepository.py b/direct/src/distributed/ClientRepository.py index ffa512ff30..4ac255074e 100644 --- a/direct/src/distributed/ClientRepository.py +++ b/direct/src/distributed/ClientRepository.py @@ -517,7 +517,7 @@ class ClientRepository(DirectObject.DirectObject): cdc = self.doId2cdc.get(doId) if (do != None and cdc != None): # Let the cdc finish the job - cdc.updateField(do, di) + cdc.updateField(do, di, 1) else: ClientRepository.notify.warning( "Asked to update non-existent DistObj " + str(doId)) diff --git a/direct/src/distributed/DistributedObject.py b/direct/src/distributed/DistributedObject.py index 5e4ce86761..7792999377 100644 --- a/direct/src/distributed/DistributedObject.py +++ b/direct/src/distributed/DistributedObject.py @@ -182,21 +182,21 @@ class DistributedObject(PandaObject): def updateRequiredFields(self, cdc, di): for i in cdc.broadcastRequiredCDU: - i.updateField(cdc, self, di) + i.updateField(cdc, self, di, 0) def updateAllRequiredFields(self, cdc, di): for i in cdc.allRequiredCDU: - i.updateField(cdc, self, di) + i.updateField(cdc, self, di, 0) def updateRequiredOtherFields(self, cdc, di): # First, update the required fields for i in cdc.broadcastRequiredCDU: - i.updateField(cdc, self, di) + i.updateField(cdc, self, di, 0) # Determine how many other fields there are numberOfOtherFields = di.getArg(STUint16) # Update each of the other fields for i in range(numberOfOtherFields): - cdc.updateField(self, di) + cdc.updateField(self, di, 0) return None def sendUpdate(self, fieldName, args = [], sendToId = None): diff --git a/panda/src/express/datagram.cxx b/panda/src/express/datagram.cxx index dcdef7c44b..b454546028 100644 --- a/panda/src/express/datagram.cxx +++ b/panda/src/express/datagram.cxx @@ -154,3 +154,41 @@ append_data(const void *data, size_t size) { _data.v().push_back(source[i]); } } + +//////////////////////////////////////////////////////////////////// +// Function: Datagram::compress +// Access: Public +// Description: Performs a simple bit-compression on the data stored +// within the datagram. Data before from_byte will be +// unaffected. This will be exactly reversed by a later +// call to uncompress(), but you must be careful to call +// each function exactly once. +//////////////////////////////////////////////////////////////////// +void Datagram:: +compress(size_t from_byte) { + // For now, we don't actually compress the data, but just trivially + // encode it. + + char *message = (char *)get_data(); + size_t num_bytes = get_length(); + for (size_t i = from_byte; i < num_bytes; i++) { + message[i] ^= 0x55; + } +} + +//////////////////////////////////////////////////////////////////// +// Function: Datagram::uncompress +// Access: Public +// Description: Reverses the effect of a previous call to compress(). +//////////////////////////////////////////////////////////////////// +void Datagram:: +uncompress(size_t from_byte) { + // For now, we don't actually compress the data, but just trivially + // encode it. + + char *message = (char *)get_data(); + size_t num_bytes = get_length(); + for (size_t i = from_byte; i < num_bytes; i++) { + message[i] ^= 0x55; + } +} diff --git a/panda/src/express/datagram.h b/panda/src/express/datagram.h index d5ae2b7848..d595f2986d 100644 --- a/panda/src/express/datagram.h +++ b/panda/src/express/datagram.h @@ -93,6 +93,9 @@ PUBLISHED: INLINE const void *get_data() const; INLINE size_t get_length() const; + void compress(size_t from_byte); + void uncompress(size_t from_byte); + INLINE bool operator == (const Datagram &other) const; INLINE bool operator != (const Datagram &other) const; INLINE bool operator < (const Datagram &other) const;