Merge branch 'master' into deploy-ng

This commit is contained in:
rdb 2018-12-26 23:41:50 +01:00
commit 01915a36db
112 changed files with 4161 additions and 3354 deletions

View File

@ -653,15 +653,11 @@ class Actor(DirectObject, NodePath):
"""
# make sure we don't call this twice in a row
# and pollute the the switches dictionary
## sortedKeys = list(self.switches.keys())
## sortedKeys.sort()
child = self.__LODNode.find(str(lodName))
index = self.__LODNode.node().findChild(child.node())
self.__LODNode.node().forceSwitch(index)
def printLOD(self):
## sortedKeys = list(self.switches.keys())
## sortedKeys.sort()
sortedKeys = self.__sortedLODNames
for eachLod in sortedKeys:
print("python switches for %s: in: %d, out %d" % (eachLod,
@ -679,12 +675,6 @@ class Actor(DirectObject, NodePath):
"""
Restore all switch distance info (usually after a useLOD call)"""
self.__LODNode.node().clearForceSwitch()
## sortedKeys = list(self.switches.keys())
## sortedKeys.sort()
## for eachLod in sortedKeys:
## index = sortedKeys.index(eachLod)
## self.__LODNode.node().setSwitch(index, self.switches[eachLod][0],
## self.switches[eachLod][1])
def addLOD(self, lodName, inDist=0, outDist=0, center=None):
"""addLOD(self, string)
@ -706,8 +696,6 @@ class Actor(DirectObject, NodePath):
# save the switch distance info
self.switches[lodName] = [inDist, outDist]
# add the switch distance info
## sortedKeys = list(self.switches.keys())
## sortedKeys.sort()
self.__LODNode.node().setSwitch(self.getLODIndex(lodName), inDist, outDist)
def getLODIndex(self, lodName):

View File

@ -262,6 +262,38 @@ pack_string(DCPackData &pack_data, const string &value,
}
}
/**
* Packs the indicated numeric or string value into the stream.
*/
void DCArrayParameter::
pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const {
// We can only pack a string if the array element type is char or int8.
DCSimpleParameter *simple_type = _element_type->as_simple_parameter();
if (simple_type == nullptr) {
pack_error = true;
return;
}
size_t blob_size = value.size();
switch (simple_type->get_type()) {
case ST_char:
case ST_uint8:
case ST_int8:
_array_size_range.validate(blob_size, range_error);
if (_num_length_bytes != 0) {
nassertv(_num_length_bytes == 2);
do_pack_uint16(pack_data.get_write_pointer(2), blob_size);
}
pack_data.append_data((const char *)value.data(), blob_size);
break;
default:
pack_error = true;
}
}
/**
* Packs the arrayParameter's specified default value (or a sensible default
* if no value is specified) into the stream. Returns true if the default
@ -339,6 +371,46 @@ unpack_string(const char *data, size_t length, size_t &p, string &value,
}
}
/**
* Unpacks the current numeric or string value from the stream.
*/
void DCArrayParameter::
unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value,
bool &pack_error, bool &range_error) const {
// We can only unpack a string if the array element type is char or int8.
DCSimpleParameter *simple_type = _element_type->as_simple_parameter();
if (simple_type == nullptr) {
pack_error = true;
return;
}
size_t blob_size;
switch (simple_type->get_type()) {
case ST_char:
case ST_uint8:
case ST_int8:
if (_num_length_bytes != 0) {
blob_size = do_unpack_uint16(data + p);
p += 2;
} else {
nassertv(_array_size >= 0);
blob_size = _array_size;
}
if (p + blob_size > length) {
pack_error = true;
return;
}
value = vector_uchar((const unsigned char *)data + p,
(const unsigned char *)data + p + blob_size);
p += blob_size;
break;
default:
pack_error = true;
}
}
/**
* Returns true if the other interface is bitwise the same as this one--that
* is, a uint32 only matches a uint32, etc. Names of components, and range

View File

@ -51,9 +51,13 @@ public:
virtual void generate_hash(HashGenerator &hashgen) const;
virtual void pack_string(DCPackData &pack_data, const std::string &value,
bool &pack_error, bool &range_error) const;
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const;
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
virtual void unpack_string(const char *data, size_t length, size_t &p,
std::string &value, bool &pack_error, bool &range_error) const;
virtual void unpack_blob(const char *data, size_t length, size_t &p,
vector_uchar &value, bool &pack_error, bool &range_error) const;
protected:
virtual bool do_check_match(const DCPackerInterface *other) const;

View File

@ -88,11 +88,11 @@ get_element(int n) const {
* If the element is an array-type element, the returned value will include
* the two-byte length preceding the array data.
*
* This is deprecated; use get_element() instead.
* @deprecated use get_element() instead.
*/
string DCAtomicField::
vector_uchar DCAtomicField::
get_element_default(int n) const {
nassertr(n >= 0 && n < (int)_elements.size(), string());
nassertr(n >= 0 && n < (int)_elements.size(), vector_uchar());
return _elements[n]->get_default_value();
}
@ -100,7 +100,7 @@ get_element_default(int n) const {
* Returns true if the nth element of the field has a default value specified,
* false otherwise.
*
* This is deprecated; use get_element() instead.
* @deprecated use get_element() instead.
*/
bool DCAtomicField::
has_element_default(int n) const {
@ -113,7 +113,7 @@ has_element_default(int n) const {
* for documentary purposes; it does not generally affect operation. If a
* name is not specified, this will be the empty string.
*
* This method is deprecated; use get_element()->get_name() instead.
* @deprecated use get_element()->get_name() instead.
*/
string DCAtomicField::
get_element_name(int n) const {

View File

@ -40,7 +40,7 @@ PUBLISHED:
DCParameter *get_element(int n) const;
// These five methods are deprecated and will be removed soon.
std::string get_element_default(int n) const;
vector_uchar get_element_default(int n) const;
bool has_element_default(int n) const;
std::string get_element_name(int n) const;
DCSubatomicType get_element_type(int n) const;

View File

@ -587,7 +587,7 @@ receive_update_other(PyObject *distobj, DatagramIterator &di) const {
*/
void DCClass::
direct_update(PyObject *distobj, const string &field_name,
const string &value_blob) {
const vector_uchar &value_blob) {
DCField *field = get_field_by_name(field_name);
nassertv_always(field != nullptr);
@ -606,7 +606,14 @@ direct_update(PyObject *distobj, const string &field_name,
void DCClass::
direct_update(PyObject *distobj, const string &field_name,
const Datagram &datagram) {
direct_update(distobj, field_name, datagram.get_message());
DCField *field = get_field_by_name(field_name);
nassertv_always(field != nullptr);
DCPacker packer;
packer.set_unpack_data((const char *)datagram.get_data(), datagram.get_length(), false);
packer.begin_unpack(field);
field->receive_update(packer, distobj);
packer.end_unpack();
}
#endif // HAVE_PYTHON

View File

@ -95,7 +95,7 @@ PUBLISHED:
void receive_update_other(PyObject *distobj, DatagramIterator &di) const;
void direct_update(PyObject *distobj, const std::string &field_name,
const std::string &value_blob);
const vector_uchar &value_blob);
void direct_update(PyObject *distobj, const std::string &field_name,
const Datagram &datagram);
bool pack_required_field(Datagram &datagram, PyObject *distobj,

View File

@ -42,7 +42,7 @@ has_default_value() const {
* explicitly set (e.g. has_default_value() returns true), returns that
* value; otherwise, returns an implicit default for the field.
*/
INLINE const std::string &DCField::
INLINE const vector_uchar &DCField::
get_default_value() const {
if (_default_value_stale) {
((DCField *)this)->refresh_default_value();
@ -172,8 +172,8 @@ set_class(DCClass *dclass) {
* Establishes a default value for this field.
*/
INLINE void DCField::
set_default_value(const std::string &default_value) {
_default_value = default_value;
set_default_value(vector_uchar default_value) {
_default_value = std::move(default_value);
_has_default_value = true;
_default_value_stale = false;
}

View File

@ -162,7 +162,7 @@ as_parameter() const {
* is an error.
*/
string DCField::
format_data(const string &packed_data, bool show_field_names) {
format_data(const vector_uchar &packed_data, bool show_field_names) {
DCPacker packer;
packer.set_unpack_data(packed_data);
packer.begin_unpack(this);
@ -178,20 +178,20 @@ format_data(const string &packed_data, bool show_field_names) {
* above) that represents the value of this field, parse the string and return
* the corresponding packed data. Returns empty string if there is an error.
*/
string DCField::
vector_uchar DCField::
parse_string(const string &formatted_string) {
DCPacker packer;
packer.begin_pack(this);
if (!packer.parse_and_pack(formatted_string)) {
// Parse error.
return string();
return vector_uchar();
}
if (!packer.end_pack()) {
// Data type mismatch.
return string();
return vector_uchar();
}
return packer.get_string();
return packer.get_bytes();
}
/**
@ -200,7 +200,7 @@ parse_string(const string &formatted_string) {
* record. Returns true if all fields are valid, false otherwise.
*/
bool DCField::
validate_ranges(const string &packed_data) const {
validate_ranges(const vector_uchar &packed_data) const {
DCPacker packer;
packer.set_unpack_data(packed_data);
packer.begin_unpack(this);
@ -209,7 +209,7 @@ validate_ranges(const string &packed_data) const {
return false;
}
return (packer.get_num_unpacked_bytes() == packed_data.length());
return (packer.get_num_unpacked_bytes() == packed_data.size());
}
#ifdef HAVE_PYTHON
@ -488,7 +488,7 @@ pack_default_value(DCPackData &pack_data, bool &) const {
// The default behavior is to pack the default value if we got it;
// otherwise, to return false and let the packer visit our nested elements.
if (!_default_value_stale) {
pack_data.append_data(_default_value.data(), _default_value.length());
pack_data.append_data((const char *)_default_value.data(), _default_value.size());
return true;
}
@ -566,7 +566,8 @@ refresh_default_value() {
if (!packer.end_pack()) {
std::cerr << "Error while packing default value for " << get_name() << "\n";
} else {
_default_value.assign(packer.get_data(), packer.get_length());
const unsigned char *data = (const unsigned char *)packer.get_data();
_default_value = vector_uchar(data, data + packer.get_length());
}
_default_value_stale = false;
}

View File

@ -53,13 +53,13 @@ PUBLISHED:
virtual DCParameter *as_parameter();
virtual const DCParameter *as_parameter() const;
std::string format_data(const std::string &packed_data, bool show_field_names = true);
std::string parse_string(const std::string &formatted_string);
std::string format_data(const vector_uchar &packed_data, bool show_field_names = true);
vector_uchar parse_string(const std::string &formatted_string);
bool validate_ranges(const std::string &packed_data) const;
bool validate_ranges(const vector_uchar &packed_data) const;
INLINE bool has_default_value() const;
INLINE const std::string &get_default_value() const;
INLINE const vector_uchar &get_default_value() const;
INLINE bool is_bogus_field() const;
@ -98,7 +98,7 @@ public:
INLINE void set_number(int number);
INLINE void set_class(DCClass *dclass);
INLINE void set_default_value(const std::string &default_value);
INLINE void set_default_value(vector_uchar default_value);
#ifdef HAVE_PYTHON
static std::string get_pystr(PyObject *value);
@ -115,7 +115,7 @@ protected:
bool _bogus_field;
private:
std::string _default_value;
vector_uchar _default_value;
#ifdef WITHIN_PANDA
PStatCollector _field_update_pcollector;

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
/*
// Filename: dcLexer.lxx
// Created by: drose (05Oct00)
//
//
////////////////////////////////////////////////////////////////////
*/
@ -103,12 +103,12 @@ dcyyerror(const std::string &msg) {
if (!dc_filename.empty()) {
cerr << " in " << dc_filename;
}
cerr
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
error_count++;
}
@ -120,10 +120,10 @@ dcyywarning(const std::string &msg) {
if (!dc_filename.empty()) {
cerr << " in " << dc_filename;
}
cerr
cerr
<< " at line " << line_number << ", column " << col_number << ":\n"
<< current_line << "\n";
indent(cerr, col_number-1)
indent(cerr, col_number-1)
<< "^\n" << msg << "\n\n";
warning_count++;
@ -313,9 +313,9 @@ scan_quoted_string(char quote_mark) {
// scan_hex_string reads a string of hexadecimal digits delimited by
// angle brackets and returns the representative string.
static std::string
static vector_uchar
scan_hex_string() {
std::string result;
vector_uchar result;
// We don't touch the current line number and column number during
// scanning, so that if we detect an error while scanning the string
@ -345,24 +345,24 @@ scan_hex_string() {
line_number = line;
col_number = col;
dcyyerror("Invalid hex digit.");
return std::string();
return vector_uchar();
}
odd = !odd;
if (odd) {
last = value;
} else {
result += (char)((last << 4) | value);
result.push_back((unsigned char)((last << 4) | value));
}
c = read_char(line, col);
}
if (c == EOF) {
dcyyerror("This hex string is unterminated.");
return std::string();
return vector_uchar();
} else if (odd) {
dcyyerror("Odd number of hex digits.");
return std::string();
return vector_uchar();
}
line_number = line;
@ -382,7 +382,7 @@ eat_c_comment() {
int col = col_number;
int c, last_c;
last_c = '\0';
c = read_char(line, col);
while (c != EOF && !(last_c == '*' && c == '/')) {
@ -440,12 +440,12 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
yyless(1);
}
[ \t\r] {
[ \t\r] {
// Eat whitespace.
accept();
}
"//".* {
"//".* {
// Eat C++-style comments.
accept();
}
@ -453,7 +453,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
"/*" {
// Eat C-style comments.
accept();
eat_c_comment();
eat_c_comment();
}
@ -607,7 +607,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
return KW_CHAR;
}
{UNSIGNED_INTEGERNUM} {
{UNSIGNED_INTEGERNUM} {
// An unsigned integer number.
accept();
@ -626,11 +626,11 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
dcyylval.u.uint64 = next_value + (*p - '0');
++p;
}
return UNSIGNED_INTEGER;
}
{SIGNED_INTEGERNUM} {
{SIGNED_INTEGERNUM} {
// A signed integer number.
accept();
@ -671,14 +671,14 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
dcyyerror("Number out of range.");
dcyylval.u.int64 = 1;
}
}
}
return SIGNED_INTEGER;
}
{UNSIGNED_HEXNUM} {
// A hexadecimal integer number.
accept();
accept();
// As above, we'll decode the hex string by hand.
dcyylval.str = dcyytext;
@ -700,15 +700,15 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
++p;
}
return UNSIGNED_INTEGER;
return UNSIGNED_INTEGER;
}
{REALNUM} {
{REALNUM} {
// A floating-point number.
accept();
dcyylval.u.real = patof(dcyytext);
accept();
dcyylval.u.real = patof(dcyytext);
dcyylval.str = dcyytext;
return REAL;
return REAL;
}
["] {
@ -728,11 +728,11 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
[<] {
// Long hex string.
accept();
dcyylval.str = scan_hex_string();
dcyylval.bytes = scan_hex_string();
return HEX_STRING;
}
[A-Za-z_][A-Za-z_0-9]* {
[A-Za-z_][A-Za-z_0-9]* {
// Identifier or keyword.
accept();
dcyylval.str = dcyytext;
@ -750,7 +750,7 @@ REALNUM ([+-]?(([0-9]+[.])|([0-9]*[.][0-9]+))([eE][+-]?[0-9]+)?)
. {
// Send any other printable character as itself.
accept();
accept();
return dcyytext[0];
}

View File

@ -217,16 +217,30 @@ pack_string(const std::string &value) {
}
/**
* Adds the indicated string value into the stream, representing a single pre-
* packed field element, or a whole group of field elements at once.
* Packs the indicated numeric or string value into the stream.
*/
INLINE void DCPacker::
pack_literal_value(const std::string &value) {
pack_blob(const vector_uchar &value) {
nassertv(_mode == M_pack || _mode == M_repack);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_pack_data.append_data(value.data(), value.length());
_current_field->pack_blob(_pack_data, value, _pack_error, _range_error);
advance();
}
}
/**
* Adds the indicated string value into the stream, representing a single pre-
* packed field element, or a whole group of field elements at once.
*/
INLINE void DCPacker::
pack_literal_value(const vector_uchar &value) {
nassertv(_mode == M_pack || _mode == M_repack);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_pack_data.append_data((const char *)value.data(), value.size());
advance();
}
}
@ -345,16 +359,36 @@ unpack_string() {
return value;
}
/**
* Unpacks the current binary data value from the stream.
*/
INLINE vector_uchar DCPacker::
unpack_blob() {
vector_uchar value;
nassertr(_mode == M_unpack, value);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
value, _pack_error, _range_error);
advance();
}
return value;
}
/**
* Returns the literal string that represents the packed value of the current
* field, and advances the field pointer.
*/
INLINE std::string DCPacker::
INLINE vector_uchar DCPacker::
unpack_literal_value() {
size_t start = _unpack_p;
unpack_skip();
nassertr(_unpack_p >= start, std::string());
return std::string(_unpack_data + start, _unpack_p - start);
nassertr(_unpack_p >= start, vector_uchar());
return vector_uchar((const unsigned char *)_unpack_data + start,
(const unsigned char *)_unpack_data + _unpack_p);
}
/**
@ -453,16 +487,33 @@ unpack_string(std::string &value) {
}
}
/**
* Unpacks the current numeric or string value from the stream.
*/
INLINE void DCPacker::
unpack_blob(vector_uchar &value) {
nassertv(_mode == M_unpack);
if (_current_field == nullptr) {
_pack_error = true;
} else {
_current_field->unpack_blob(_unpack_data, _unpack_length, _unpack_p,
value, _pack_error, _range_error);
advance();
}
}
/**
* Returns the literal string that represents the packed value of the current
* field, and advances the field pointer.
*/
INLINE void DCPacker::
unpack_literal_value(std::string &value) {
unpack_literal_value(vector_uchar &value) {
size_t start = _unpack_p;
unpack_skip();
nassertv(_unpack_p >= start);
value.assign(_unpack_data + start, _unpack_p - start);
value = vector_uchar((const unsigned char *)_unpack_data + start,
(const unsigned char *)_unpack_data + _unpack_p);
}
/**
@ -541,6 +592,15 @@ get_string() const {
return _pack_data.get_string();
}
/**
* Returns the packed data buffer as a bytes object. Also see get_data().
*/
INLINE vector_uchar DCPacker::
get_bytes() const {
const unsigned char *p = (const unsigned char *)_pack_data.get_data();
return vector_uchar(p, p + _pack_data.get_length());
}
/**
* Returns the total number of bytes in the unpack data buffer. This is the
* buffer used when unpacking; it is separate from the pack data returned by
@ -601,9 +661,9 @@ take_data() {
* between packing sessions.
*/
INLINE void DCPacker::
append_data(const char *buffer, size_t size) {
append_data(const unsigned char *buffer, size_t size) {
nassertv(_mode == M_idle);
_pack_data.append_data(buffer, size);
_pack_data.append_data((const char *)buffer, size);
}
/**
@ -728,6 +788,16 @@ raw_pack_string(const std::string &value) {
_pack_data.append_data(value.data(), value.length());
}
/**
* Packs the data into the buffer between packing sessions.
*/
INLINE void DCPacker::
raw_pack_blob(const vector_uchar &value) {
nassertv(_mode == M_idle);
DCPackerInterface::do_pack_uint16(_pack_data.get_write_pointer(2), value.size());
_pack_data.append_data((const char *)value.data(), value.size());
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
@ -870,6 +940,16 @@ raw_unpack_string() {
return value;
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
INLINE vector_uchar DCPacker::
raw_unpack_blob() {
vector_uchar value;
raw_unpack_blob(value);
return value;
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
@ -971,6 +1051,24 @@ raw_unpack_string(std::string &value) {
_unpack_p += string_length;
}
/**
* Unpacks the data from the buffer between unpacking sessions.
*/
INLINE void DCPacker::
raw_unpack_blob(vector_uchar &value) {
nassertv(_mode == M_idle && _unpack_data != nullptr);
unsigned int blob_size = raw_unpack_uint16();
if (_unpack_p + blob_size > _unpack_length) {
_pack_error = true;
return;
}
const unsigned char *p = (const unsigned char *)_unpack_data + _unpack_p;
value = vector_uchar(p, p + blob_size);
_unpack_p += blob_size;
}
/**
* Advances to the next field after a call to pack_value() or pop().
*/

View File

@ -114,12 +114,12 @@ end_pack() {
* version of begin_unpack() that takes only one parameter.
*/
void DCPacker::
set_unpack_data(const string &data) {
set_unpack_data(const vector_uchar &data) {
nassertv(_mode == M_idle);
char *buffer = new char[data.length()];
memcpy(buffer, data.data(), data.length());
set_unpack_data(buffer, data.length(), true);
char *buffer = new char[data.size()];
memcpy(buffer, data.data(), data.size());
set_unpack_data(buffer, data.size(), true);
}
/**
@ -721,11 +721,11 @@ pack_object(PyObject *object) {
pack_string(string(buffer, length));
}
} else if (PyBytes_Check(object)) {
char *buffer;
const unsigned char *buffer;
Py_ssize_t length;
PyBytes_AsStringAndSize(object, &buffer, &length);
PyBytes_AsStringAndSize(object, (char **)&buffer, &length);
if (buffer) {
pack_string(string(buffer, length));
pack_blob(vector_uchar(buffer, buffer + length));
}
#else
} else if (PyString_Check(object) || PyUnicode_Check(object)) {
@ -1118,9 +1118,9 @@ enquote_string(ostream &out, char quote_mark, const string &str) {
* Outputs the indicated string as a hex constant.
*/
void DCPacker::
output_hex_string(ostream &out, const string &str) {
output_hex_string(ostream &out, const vector_uchar &str) {
out << '<';
for (string::const_iterator pi = str.begin();
for (vector_uchar::const_iterator pi = str.begin();
pi != str.end();
++pi) {
char buffer[10];

View File

@ -41,7 +41,7 @@ PUBLISHED:
void begin_pack(const DCPackerInterface *root);
bool end_pack();
void set_unpack_data(const std::string &data);
void set_unpack_data(const vector_uchar &data);
public:
void set_unpack_data(const char *unpack_data, size_t unpack_length,
bool owns_unpack_data);
@ -75,7 +75,8 @@ PUBLISHED:
INLINE void pack_int64(int64_t value);
INLINE void pack_uint64(uint64_t value);
INLINE void pack_string(const std::string &value);
INLINE void pack_literal_value(const std::string &value);
INLINE void pack_blob(const vector_uchar &value);
INLINE void pack_literal_value(const vector_uchar &value);
void pack_default_value();
INLINE double unpack_double();
@ -84,7 +85,8 @@ PUBLISHED:
INLINE int64_t unpack_int64();
INLINE uint64_t unpack_uint64();
INLINE std::string unpack_string();
INLINE std::string unpack_literal_value();
INLINE vector_uchar unpack_blob();
INLINE vector_uchar unpack_literal_value();
void unpack_validate();
void unpack_skip();
@ -97,7 +99,8 @@ public:
INLINE void unpack_int64(int64_t &value);
INLINE void unpack_uint64(uint64_t &value);
INLINE void unpack_string(std::string &value);
INLINE void unpack_literal_value(std::string &value);
INLINE void unpack_blob(vector_uchar &value);
INLINE void unpack_literal_value(vector_uchar &value);
PUBLISHED:
@ -119,6 +122,7 @@ PUBLISHED:
INLINE size_t get_length() const;
INLINE std::string get_string() const;
INLINE vector_uchar get_bytes() const;
INLINE size_t get_unpack_length() const;
INLINE std::string get_unpack_string() const;
public:
@ -126,7 +130,7 @@ public:
INLINE const char *get_data() const;
INLINE char *take_data();
INLINE void append_data(const char *buffer, size_t size);
INLINE void append_data(const unsigned char *buffer, size_t size);
INLINE char *get_write_pointer(size_t size);
INLINE const char *get_unpack_data() const;
@ -148,6 +152,7 @@ PUBLISHED:
INLINE void raw_pack_uint64(uint64_t value);
INLINE void raw_pack_float64(double value);
INLINE void raw_pack_string(const std::string &value);
INLINE void raw_pack_blob(const vector_uchar &value);
// this is a hack to allw me to get in and out of 32bit Mode Faster need to
// agree with channel_type in dcbase.h
@ -165,6 +170,7 @@ PUBLISHED:
INLINE uint64_t raw_unpack_uint64();
INLINE double raw_unpack_float64();
INLINE std::string raw_unpack_string();
INLINE vector_uchar raw_unpack_blob();
public:
INLINE void raw_unpack_int8(int &value);
@ -177,10 +183,11 @@ public:
INLINE void raw_unpack_uint64(uint64_t &value);
INLINE void raw_unpack_float64(double &value);
INLINE void raw_unpack_string(std::string &value);
INLINE void raw_unpack_blob(vector_uchar &value);
public:
static void enquote_string(std::ostream &out, char quote_mark, const std::string &str);
static void output_hex_string(std::ostream &out, const std::string &str);
static void output_hex_string(std::ostream &out, const vector_uchar &str);
private:
INLINE void advance();

View File

@ -248,6 +248,14 @@ pack_string(DCPackData &, const string &, bool &pack_error, bool &) const {
pack_error = true;
}
/**
* Packs the indicated numeric or string value into the stream.
*/
void DCPackerInterface::
pack_blob(DCPackData &, const vector_uchar &, bool &pack_error, bool &) const {
pack_error = true;
}
/**
* Packs the field's specified default value (or a sensible default if no
* value is specified) into the stream. Returns true if the default value is
@ -306,6 +314,14 @@ unpack_string(const char *, size_t, size_t &, string &, bool &pack_error, bool &
pack_error = true;
}
/**
* Unpacks the current numeric or string value from the stream.
*/
void DCPackerInterface::
unpack_blob(const char *, size_t, size_t &, vector_uchar &, bool &pack_error, bool &) const {
pack_error = true;
}
/**
* Internally unpacks the current numeric or string value and validates it
* against the type range limits, but does not return the value. Returns true

View File

@ -16,6 +16,7 @@
#include "dcbase.h"
#include "dcSubatomicType.h"
#include "vector_uchar.h"
class DCFile;
class DCField;
@ -37,8 +38,8 @@ enum DCPackType {
// These PackTypes are all fundamental types, and should be packed (or
// unpacked) with the corresponding call to pack_double(), pack_int(), etc.
// PT_blob is the same as PT_string, but implies that the string contains
// binary data.
// PT_blob is similar to PT_string, except that it contains arbitrary binary
// data instead of just UTF-8 text.
PT_double,
PT_int,
PT_uint,
@ -113,6 +114,8 @@ public:
bool &pack_error, bool &range_error) const;
virtual void pack_string(DCPackData &pack_data, const std::string &value,
bool &pack_error, bool &range_error) const;
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const;
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
virtual void unpack_double(const char *data, size_t length, size_t &p,
@ -127,6 +130,8 @@ public:
uint64_t &value, bool &pack_error, bool &range_error) const;
virtual void unpack_string(const char *data, size_t length, size_t &p,
std::string &value, bool &pack_error, bool &range_error) const;
virtual void unpack_blob(const char *data, size_t length, size_t &p,
vector_uchar &value, bool &pack_error, bool &range_error) const;
virtual bool unpack_validate(const char *data, size_t length, size_t &p,
bool &pack_error, bool &range_error) const;
virtual bool unpack_skip(const char *data, size_t length, size_t &p,

File diff suppressed because it is too large Load Diff

View File

@ -1,20 +1,19 @@
/* A Bison parser, made by GNU Bison 2.4.2. */
/* A Bison parser, made by GNU Bison 3.1. */
/* Bison interface for Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2015, 2018 Free Software Foundation, Inc.
/* Skeleton interface for Bison's Yacc-like parsers in C
Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
Foundation, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
@ -27,66 +26,74 @@
special exception, which will cause the skeleton and the resulting
Bison output files to be licensed under the GNU General Public
License without this special exception.
This special exception was added by the Free Software Foundation in
version 2.2 of Bison. */
#ifndef YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED
# define YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED
/* Debug traces. */
#ifndef YYDEBUG
# define YYDEBUG 0
#endif
#if YYDEBUG
extern int dcyydebug;
#endif
/* Tokens. */
/* Token type. */
#ifndef YYTOKENTYPE
# define YYTOKENTYPE
/* Put the tokens into the symbol table, so that GDB and other debuggers
know about them. */
enum yytokentype {
UNSIGNED_INTEGER = 258,
SIGNED_INTEGER = 259,
REAL = 260,
STRING = 261,
HEX_STRING = 262,
IDENTIFIER = 263,
KEYWORD = 264,
KW_DCLASS = 265,
KW_STRUCT = 266,
KW_FROM = 267,
KW_IMPORT = 268,
KW_TYPEDEF = 269,
KW_KEYWORD = 270,
KW_SWITCH = 271,
KW_CASE = 272,
KW_DEFAULT = 273,
KW_BREAK = 274,
KW_INT8 = 275,
KW_INT16 = 276,
KW_INT32 = 277,
KW_INT64 = 278,
KW_UINT8 = 279,
KW_UINT16 = 280,
KW_UINT32 = 281,
KW_UINT64 = 282,
KW_FLOAT64 = 283,
KW_STRING = 284,
KW_BLOB = 285,
KW_BLOB32 = 286,
KW_INT8ARRAY = 287,
KW_INT16ARRAY = 288,
KW_INT32ARRAY = 289,
KW_UINT8ARRAY = 290,
KW_UINT16ARRAY = 291,
KW_UINT32ARRAY = 292,
KW_UINT32UINT8ARRAY = 293,
KW_CHAR = 294,
START_DC = 295,
START_PARAMETER_VALUE = 296,
START_PARAMETER_DESCRIPTION = 297
};
enum yytokentype
{
UNSIGNED_INTEGER = 258,
SIGNED_INTEGER = 259,
REAL = 260,
STRING = 261,
IDENTIFIER = 262,
HEX_STRING = 263,
KEYWORD = 264,
KW_DCLASS = 265,
KW_STRUCT = 266,
KW_FROM = 267,
KW_IMPORT = 268,
KW_TYPEDEF = 269,
KW_KEYWORD = 270,
KW_SWITCH = 271,
KW_CASE = 272,
KW_DEFAULT = 273,
KW_BREAK = 274,
KW_INT8 = 275,
KW_INT16 = 276,
KW_INT32 = 277,
KW_INT64 = 278,
KW_UINT8 = 279,
KW_UINT16 = 280,
KW_UINT32 = 281,
KW_UINT64 = 282,
KW_FLOAT64 = 283,
KW_STRING = 284,
KW_BLOB = 285,
KW_BLOB32 = 286,
KW_INT8ARRAY = 287,
KW_INT16ARRAY = 288,
KW_INT32ARRAY = 289,
KW_UINT8ARRAY = 290,
KW_UINT16ARRAY = 291,
KW_UINT32ARRAY = 292,
KW_UINT32UINT8ARRAY = 293,
KW_CHAR = 294,
START_DC = 295,
START_PARAMETER_VALUE = 296,
START_PARAMETER_DESCRIPTION = 297
};
#endif
/* Tokens. */
#define UNSIGNED_INTEGER 258
#define SIGNED_INTEGER 259
#define REAL 260
#define STRING 261
#define HEX_STRING 262
#define IDENTIFIER 263
#define IDENTIFIER 262
#define HEX_STRING 263
#define KEYWORD 264
#define KW_DCLASS 265
#define KW_STRUCT 266
@ -122,15 +129,11 @@
#define START_PARAMETER_VALUE 296
#define START_PARAMETER_DESCRIPTION 297
/* Value type. */
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
# define YYSTYPE_IS_DECLARED 1
#endif
extern YYSTYPE dcyylval;
int dcyyparse (void);
#endif /* !YY_DCYY_BUILT_TMP_DCPARSER_YXX_H_INCLUDED */

View File

@ -57,7 +57,7 @@ dc_init_parser(istream &in, const string &filename, DCFile &file) {
}
void
dc_init_parser_parameter_value(istream &in, const string &filename,
dc_init_parser_parameter_value(istream &in, const string &filename,
DCPacker &packer) {
dc_file = nullptr;
current_packer = &packer;
@ -89,15 +89,16 @@ dc_cleanup_parser() {
%token <u.uint64> UNSIGNED_INTEGER
%token <u.int64> SIGNED_INTEGER
%token <u.real> REAL
%token <str> STRING HEX_STRING IDENTIFIER
%token <str> STRING IDENTIFIER
%token <bytes> HEX_STRING
%token <u.keyword> KEYWORD
%token KW_DCLASS
%token KW_STRUCT
%token KW_FROM
%token KW_IMPORT
%token KW_TYPEDEF
%token KW_KEYWORD
%token KW_DCLASS
%token KW_STRUCT
%token KW_FROM
%token KW_IMPORT
%token KW_TYPEDEF
%token KW_KEYWORD
%token KW_SWITCH
%token KW_CASE
%token KW_DEFAULT
@ -224,7 +225,7 @@ import:
{
dc_file->add_import_module($2);
}
| KW_FROM import_identifier KW_IMPORT
| KW_FROM import_identifier KW_IMPORT
{
dc_file->add_import_module($2);
}
@ -255,7 +256,7 @@ typedef_decl:
{
if ($2 != nullptr) {
DCTypedef *dtypedef = new DCTypedef($2);
if (!dc_file->add_typedef(dtypedef)) {
DCTypedef *old_typedef = dc_file->get_typedef_by_name(dtypedef->get_name());
if (old_typedef->is_bogus_typedef()) {
@ -294,7 +295,7 @@ dclass_or_struct:
;
dclass:
KW_DCLASS optional_name
KW_DCLASS optional_name
{
current_class = new DCClass(dc_file, $2, false, false);
}
@ -322,7 +323,7 @@ dclass_name:
if (dclass->is_struct()) {
yyerror("struct name not allowed");
}
$$ = dclass;
}
}
@ -398,7 +399,7 @@ dclass_field:
;
struct:
KW_STRUCT optional_name
KW_STRUCT optional_name
{
current_class = new DCClass(dc_file, $2, true, false);
}
@ -426,7 +427,7 @@ struct_name:
if (!dstruct->is_struct()) {
yyerror("struct name required");
}
$$ = dstruct;
}
}
@ -538,7 +539,7 @@ unnamed_parameter:
named_parameter_with_default:
named_parameter
| named_parameter '='
| named_parameter '='
{
current_packer = &default_packer;
current_packer->clear_data();
@ -553,7 +554,7 @@ named_parameter_with_default:
is_valid = $1->is_valid();
}
if (current_packer->end_pack()) {
$1->set_default_value(current_packer->get_string());
$1->set_default_value(current_packer->get_bytes());
} else {
if (is_valid) {
@ -568,7 +569,7 @@ named_parameter_with_default:
unnamed_parameter_with_default:
unnamed_parameter
| unnamed_parameter '='
| unnamed_parameter '='
{
current_packer = &default_packer;
current_packer->clear_data();
@ -583,7 +584,7 @@ unnamed_parameter_with_default:
is_valid = $1->is_valid();
}
if (current_packer->end_pack()) {
$1->set_default_value(current_packer->get_string());
$1->set_default_value(current_packer->get_bytes());
} else {
if (is_valid) {
@ -663,7 +664,7 @@ simple_type_name:
$$ = simple_param;
}
| simple_type_name '%' number
{
{
DCSimpleParameter *simple_param = $1->as_simple_parameter();
nassertr(simple_param != nullptr, 0);
if (!simple_param->is_numeric_type()) {
@ -703,10 +704,10 @@ type_name:
dtypedef = new DCTypedef($1);
}
}
dc_file->add_typedef(dtypedef);
}
$$ = dtypedef->make_new_parameter();
}
}
@ -974,7 +975,7 @@ parameter_value:
{
if ($1 != current_packer->get_current_field_name()) {
ostringstream strm;
strm << "Got '" << $1 << "', expected '"
strm << "Got '" << $1 << "', expected '"
<< current_packer->get_current_field_name() << "'";
yyerror(strm.str());
}
@ -1005,7 +1006,7 @@ parameter_actual_value:
{
current_packer->pack_literal_value($1);
}
| '{'
| '{'
{
current_packer->push();
}
@ -1013,7 +1014,7 @@ parameter_actual_value:
{
current_packer->pop();
}
| '['
| '['
{
current_packer->push();
}
@ -1021,7 +1022,7 @@ parameter_actual_value:
{
current_packer->pop();
}
| '('
| '('
{
current_packer->push();
}
@ -1223,7 +1224,7 @@ molecular_atom_list:
if ($3 != nullptr) {
current_molecular->add_atomic($3);
if (!$3->is_bogus_field() && !current_molecular->compare_keywords(*$3)) {
yyerror("Mismatched keywords in molecule between " +
yyerror("Mismatched keywords in molecule between " +
current_molecular->get_atomic(0)->get_name() + " and " +
$3->get_name());
}
@ -1283,7 +1284,7 @@ switch_case:
yyerror("Invalid value for switch parameter");
current_switch->add_invalid_case();
} else {
int case_index = current_switch->add_case(current_packer->get_string());
int case_index = current_switch->add_case(current_packer->get_bytes());
if (case_index == -1) {
yyerror("Duplicate case value");
}

View File

@ -16,6 +16,7 @@
#include "dcbase.h"
#include "dcSubatomicType.h"
#include "vector_uchar.h"
class DCFile;
class DCClass;
@ -61,6 +62,7 @@ public:
const DCKeyword *keyword;
} u;
std::string str;
vector_uchar bytes;
};
// The yacc-generated code expects to use the symbol 'YYSTYPE' to refer to the

View File

@ -1069,6 +1069,52 @@ pack_string(DCPackData &pack_data, const string &value,
}
}
/**
* Packs the indicated numeric or string value into the stream.
*/
void DCSimpleParameter::
pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const {
size_t blob_size = value.size();
switch (_type) {
case ST_char:
case ST_uint8:
case ST_int8:
if (blob_size == 0) {
pack_error = true;
} else {
if (blob_size != 1) {
range_error = true;
}
_uint_range.validate((unsigned int)value[0], range_error);
do_pack_uint8(pack_data.get_write_pointer(1), (unsigned int)value[0]);
}
break;
case ST_string:
case ST_blob:
_uint_range.validate(blob_size, range_error);
validate_uint_limits(blob_size, 16, range_error);
if (_num_length_bytes != 0) {
do_pack_uint16(pack_data.get_write_pointer(2), blob_size);
}
pack_data.append_data((const char *)value.data(), blob_size);
break;
case ST_blob32:
_uint_range.validate(blob_size, range_error);
if (_num_length_bytes != 0) {
do_pack_uint32(pack_data.get_write_pointer(4), blob_size);
}
pack_data.append_data((const char *)value.data(), blob_size);
break;
default:
pack_error = true;
}
}
/**
* Packs the simpleParameter's specified default value (or a sensible default
* if no value is specified) into the stream. Returns true if the default
@ -1937,6 +1983,79 @@ unpack_string(const char *data, size_t length, size_t &p, string &value,
return;
}
/**
* Unpacks the current numeric or string value from the stream.
*/
void DCSimpleParameter::
unpack_blob(const char *data, size_t length, size_t &p, vector_uchar &value,
bool &pack_error, bool &range_error) const {
// If the type is a single byte, unpack it into a string of length 1.
switch (_type) {
case ST_char:
case ST_int8:
case ST_uint8:
{
if (p + 1 > length) {
pack_error = true;
return;
}
unsigned int int_value = do_unpack_uint8(data + p);
_uint_range.validate(int_value, range_error);
value.resize(1);
value[0] = int_value;
p++;
}
return;
default:
break;
}
size_t blob_size;
if (_num_length_bytes == 0) {
blob_size = _fixed_byte_size;
} else {
switch (_type) {
case ST_string:
case ST_blob:
if (p + 2 > length) {
pack_error = true;
return;
}
blob_size = do_unpack_uint16(data + p);
p += 2;
break;
case ST_blob32:
if (p + 4 > length) {
pack_error = true;
return;
}
blob_size = do_unpack_uint32(data + p);
p += 4;
break;
default:
pack_error = true;
return;
}
}
_uint_range.validate(blob_size, range_error);
if (p + blob_size > length) {
pack_error = true;
return;
}
value = vector_uchar((const unsigned char *)data + p,
(const unsigned char *)data + p + blob_size);
p += blob_size;
return;
}
/**
* Internally unpacks the current numeric or string value and validates it
* against the type range limits, but does not return the value. Returns true

View File

@ -62,6 +62,8 @@ public:
bool &pack_error, bool &range_error) const;
virtual void pack_string(DCPackData &pack_data, const std::string &value,
bool &pack_error, bool &range_error) const;
virtual void pack_blob(DCPackData &pack_data, const vector_uchar &value,
bool &pack_error, bool &range_error) const;
virtual bool pack_default_value(DCPackData &pack_data, bool &pack_error) const;
virtual void unpack_double(const char *data, size_t length, size_t &p,
@ -76,6 +78,8 @@ public:
uint64_t &value, bool &pack_error, bool &range_error) const;
virtual void unpack_string(const char *data, size_t length, size_t &p,
std::string &value, bool &pack_error, bool &range_error) const;
virtual void unpack_blob(const char *data, size_t length, size_t &p,
vector_uchar &value, bool &pack_error, bool &range_error) const;
virtual bool unpack_validate(const char *data, size_t length, size_t &p,
bool &pack_error, bool &range_error) const;
virtual bool unpack_skip(const char *data, size_t length, size_t &p,

View File

@ -109,7 +109,7 @@ get_num_cases() const {
* if no case has this value.
*/
int DCSwitch::
get_case_by_value(const string &case_value) const {
get_case_by_value(const vector_uchar &case_value) const {
CasesByValue::const_iterator vi;
vi = _cases_by_value.find(case_value);
if (vi != _cases_by_value.end()) {
@ -140,9 +140,9 @@ get_default_case() const {
/**
* Returns the packed value associated with the indicated case.
*/
string DCSwitch::
vector_uchar DCSwitch::
get_value(int case_index) const {
nassertr(case_index >= 0 && case_index < (int)_cases.size(), string());
nassertr(case_index >= 0 && case_index < (int)_cases.size(), vector_uchar());
return _cases[case_index]->_value;
}
@ -198,7 +198,7 @@ is_field_valid() const {
* -1. This is normally called only by the parser.
*/
int DCSwitch::
add_case(const string &value) {
add_case(const vector_uchar &value) {
int case_index = (int)_cases.size();
if (!_cases_by_value.insert(CasesByValue::value_type(value, case_index)).second) {
add_invalid_case();
@ -283,7 +283,8 @@ add_break() {
const DCPackerInterface *DCSwitch::
apply_switch(const char *value_data, size_t length) const {
CasesByValue::const_iterator vi;
vi = _cases_by_value.find(string(value_data, length));
vi = _cases_by_value.find(vector_uchar((const unsigned char *)value_data,
(const unsigned char *)value_data + length));
if (vi != _cases_by_value.end()) {
return _cases[(*vi).second]->_fields;
}
@ -421,7 +422,7 @@ generate_hash(HashGenerator &hashgen) const {
Cases::const_iterator ci;
for (ci = _cases.begin(); ci != _cases.end(); ++ci) {
const SwitchCase *dcase = (*ci);
hashgen.add_string(dcase->_value);
hashgen.add_blob(dcase->_value);
const SwitchFields *fields = dcase->_fields;
hashgen.add_int(fields->_fields.size());
@ -702,7 +703,7 @@ do_check_match(const DCPackerInterface *) const {
*
*/
DCSwitch::SwitchCase::
SwitchCase(const string &value, DCSwitch::SwitchFields *fields) :
SwitchCase(const vector_uchar &value, DCSwitch::SwitchFields *fields) :
_value(value),
_fields(fields)
{

View File

@ -40,18 +40,18 @@ PUBLISHED:
DCField *get_key_parameter() const;
int get_num_cases() const;
int get_case_by_value(const std::string &case_value) const;
int get_case_by_value(const vector_uchar &case_value) const;
DCPackerInterface *get_case(int n) const;
DCPackerInterface *get_default_case() const;
std::string get_value(int case_index) const;
vector_uchar get_value(int case_index) const;
int get_num_fields(int case_index) const;
DCField *get_field(int case_index, int n) const;
DCField *get_field_by_name(int case_index, const std::string &name) const;
public:
bool is_field_valid() const;
int add_case(const std::string &value);
int add_case(const vector_uchar &value);
void add_invalid_case();
bool add_default();
bool add_field(DCField *field);
@ -98,13 +98,13 @@ public:
class SwitchCase {
public:
SwitchCase(const std::string &value, SwitchFields *fields);
SwitchCase(const vector_uchar &value, SwitchFields *fields);
~SwitchCase();
bool do_check_match_switch_case(const SwitchCase *other) const;
public:
std::string _value;
vector_uchar _value;
SwitchFields *_fields;
};
@ -137,7 +137,7 @@ private:
bool _fields_added;
// This map indexes into the _cases vector, above.
typedef pmap<std::string, int> CasesByValue;
typedef pmap<vector_uchar, int> CasesByValue;
CasesByValue _cases_by_value;
};

View File

@ -56,6 +56,18 @@ add_string(const std::string &str) {
}
}
/**
* Adds a blob to the hash, by breaking it down into a sequence of integers.
*/
void HashGenerator::
add_blob(const vector_uchar &bytes) {
add_int(bytes.size());
vector_uchar::const_iterator bi;
for (bi = bytes.begin(); bi != bytes.end(); ++bi) {
add_int(*bi);
}
}
/**
* Returns the hash number generated.
*/

View File

@ -16,6 +16,7 @@
#include "dcbase.h"
#include "primeNumberGenerator.h"
#include "vector_uchar.h"
/**
* This class generates an arbitrary hash number from a sequence of ints.
@ -26,6 +27,7 @@ public:
void add_int(int num);
void add_string(const std::string &str);
void add_blob(const vector_uchar &bytes);
unsigned long get_hash() const;

View File

@ -797,7 +797,15 @@ EXCLUDE = dtool/src/parser-inc \
panda/src/linmath/fltnames.h \
panda/src/linmath/dblnames.h \
panda/src/linmath/dbl2fltnames.h \
panda/src/linmath/flt2dblnames.h
panda/src/linmath/flt2dblnames.h \
panda/src/android \
panda/src/iphone \
panda/src/tinydisplay \
panda/src/movies/dr_flac.h \
dtool/src/dtoolbase/pdtoa.cxx \
dtool/src/dtoolutil/panda_getopt_long.h \
dtool/src/dtoolutil/panda_getopt_impl.h \
dtool/src/dtoolutil/panda_getopt_impl.cxx
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
@ -1972,7 +1980,13 @@ PREDEFINED = TVOLATILE= \
EXTEND= \
ALLOC_DELETED_CHAIN(x)= \
BLOCKING= \
TYPENAME=typename
TYPENAME=typename \
MAKE_PROPERTY(x)= \
MAKE_PROPERTY2(x)= \
MAKE_SEQ(x)= \
MAKE_SEQ_PROPERTY(x)= \
MAKE_MAP_PROPERTY(x)= \
MAKE_MAP_KEYS_SEQ(x)=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The

View File

@ -665,7 +665,9 @@ EXCLUDE_SYMLINKS = NO
# for example use the pattern */test/*
EXCLUDE_PATTERNS = */Opt*-*/* \
*/CVS/*
*/CVS/* \
*/.git/* \
*/__pycache__/*
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the

View File

@ -9,9 +9,20 @@ from __future__ import print_function
__all__ = []
import os
import os, sys
from distutils import sysconfig
import panda3d, pandac
from panda3d.dtoolconfig import *
from panda3d.interrogatedb import *
if 'interrogate_element_is_sequence' not in globals():
def interrogate_element_is_sequence(element):
return False
if 'interrogate_element_is_mapping' not in globals():
def interrogate_element_is_mapping(element):
return False
LICENSE = """PANDA 3D SOFTWARE
Copyright (c) Carnegie Mellon University. All rights reserved.
@ -19,6 +30,16 @@ All use of this software is subject to the terms of the revised BSD
license. You should have received a copy of this license along
with this source code in a file named \"LICENSE.\"""".split("\n")
MAINPAGE = """@mainpage Panda3D Python API Reference
Welcome to the Panda3D API reference.
Use the links at the top of this page to browse through the list of modules or
the list of classes.
This reference is automatically generated from comments in the source code.
"""
def comment(code):
if not code:
return ""
@ -45,49 +66,16 @@ def comment(code):
return ''
def block_comment(code):
if not code:
code = code.strip()
if not code.startswith('///<') and '@verbatim' not in code:
code = code.replace('<', '\\<').replace('>', '\\>')
if not code or code[0] != '/':
# Not really a comment; get rid of it.
return ""
lines = code.split("\n")
newlines = []
indent = 0
reading_desc = False
for line in lines:
if line.startswith("////"):
continue
line = line.rstrip()
strline = line.lstrip('/ \t')
if ':' in strline:
pre, post = strline.split(':', 1)
pre = pre.rstrip()
if pre == "Description":
strline = post.lstrip()
elif pre in ("Class", "Access", "Function", "Created by", "Enum"):
continue
if strline or len(newlines) > 0:
newlines.append('/// ' + strline)
#if reading_desc:
# newlines.append('/// ' + line[min(indent, len(line) - len(strline)):])
#else:
# # A "Description:" text starts the description.
# if strline.startswith("Description"):
# strline = strline[11:].lstrip(': \t')
# indent = len(line) - len(strline)
# reading_desc = True
# newlines.append('/// ' + strline)
# else:
# print line
newcode = '\n'.join(newlines)
if len(newcode) > 0:
return newcode
else:
return ""
return code
def translateFunctionName(name):
if name.startswith("__"):
@ -139,11 +127,17 @@ def translated_type_name(type, scoped=True):
return "object"
elif typename == "PN_stdfloat":
return "float"
elif typename == "size_t":
return "int"
if interrogate_type_is_atomic(type):
token = interrogate_type_atomic_token(type)
if token == 7:
return 'str'
elif token == 8:
return 'long'
elif token == 9:
return 'NoneType'
else:
return typename
@ -156,12 +150,25 @@ def translated_type_name(type, scoped=True):
else:
return typename
def processElement(handle, element):
if interrogate_element_has_comment(element):
print(comment(interrogate_element_comment(element)), file=handle)
elif interrogate_element_has_getter(element):
# If the property has no comment, use the comment of the getter.
getter = interrogate_element_getter(element)
if interrogate_function_has_comment(getter):
print(block_comment(interrogate_function_comment(getter)), file=handle)
if interrogate_element_is_mapping(element) or \
interrogate_element_is_sequence(element):
suffix = "[]"
else:
suffix = ""
print(translated_type_name(interrogate_element_type(element)), end=' ', file=handle)
print(interrogate_element_name(element) + ';', file=handle)
print(interrogate_element_name(element) + suffix + ';', file=handle)
def processFunction(handle, function, isConstructor = False):
for i_wrapper in range(interrogate_function_number_of_python_wrappers(function)):
@ -195,6 +202,7 @@ def processFunction(handle, function, isConstructor = False):
print(");", file=handle)
def processType(handle, type):
typename = translated_type_name(type, scoped=False)
derivations = [ translated_type_name(interrogate_type_get_derivation(type, n)) for n in range(interrogate_type_number_of_derivations(type)) ]
@ -211,8 +219,10 @@ def processType(handle, type):
print(interrogate_type_enum_value_name(type, i_value), "=", interrogate_type_enum_value(type, i_value), ",", file=handle)
elif interrogate_type_is_typedef(type):
wrapped_type = translated_type_name(interrogate_type_wrapped_type(type))
print("typedef %s %s;" % (wrapped_type, typename), file=handle)
wrapped_type = interrogate_type_wrapped_type(type)
if interrogate_type_is_global(wrapped_type):
wrapped_type_name = translated_type_name(wrapped_type)
print("typedef %s %s;" % (wrapped_type_name, typename), file=handle)
return
else:
if interrogate_type_is_struct(type):
@ -249,6 +259,7 @@ def processType(handle, type):
print("};", file=handle)
def processModule(handle, package):
print("Processing module %s" % (package))
print("namespace %s {" % package, file=handle)
if package != "core":
@ -280,22 +291,39 @@ def processModule(handle, package):
if __name__ == "__main__":
handle = open("pandadoc.hpp", "w")
mainpage = MAINPAGE.strip()
if mainpage:
print("/**\n * " + mainpage.replace('\n', '\n * ') + '\n */', file=handle)
print(comment("Panda3D modules that are implemented in C++."), file=handle)
print("namespace panda3d {", file=handle)
# Determine the path to the interrogatedb files
interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "..", "..", "etc"))
interrogate_add_search_directory(os.path.join(os.path.dirname(pandac.__file__), "input"))
pandac = os.path.dirname(pandac.__file__)
interrogate_add_search_directory(os.path.join(pandac, "..", "..", "etc"))
interrogate_add_search_directory(os.path.join(pandac, "input"))
import panda3d.core
processModule(handle, "core")
# Determine the suffix for the extension modules.
if sys.version_info >= (3, 0):
import _imp
ext_suffix = _imp.extension_suffixes()[0]
elif sys.platform == "win32":
ext_suffix = ".pyd"
else:
ext_suffix = ".so"
for lib in os.listdir(os.path.dirname(panda3d.__file__)):
if lib.endswith(('.pyd', '.so')) and not lib.startswith('core.'):
module_name = os.path.splitext(lib)[0]
if lib.endswith(ext_suffix) and not lib.startswith('core.'):
module_name = lib[:-len(ext_suffix)]
__import__("panda3d." + module_name)
processModule(handle, module_name)
print("}", file=handle)
handle.close()
print("Wrote output to pandadoc.hpp. You can now run:")
print()
print(" doxygen built/direct/directscripts/Doxyfile.python")

View File

@ -891,7 +891,7 @@ describe_message(std::ostream &out, const string &prefix,
const Datagram &dg) const {
DCPacker packer;
packer.set_unpack_data(dg.get_message());
packer.set_unpack_data((const char *)dg.get_data(), dg.get_length(), false);
CHANNEL_TYPE do_id;
int msg_type;
bool is_update = false;

View File

@ -277,13 +277,6 @@ class _local(object):
d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
d[key] = value
## def __getattr__(self, key):
## d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
## try:
## return d[key]
## except KeyError:
## raise AttributeError
def __getattribute__(self, key):
d = _get_thread_locals(core.Thread.getCurrentThread(), id(self))
if key == '__dict__':
@ -292,6 +285,3 @@ class _local(object):
return d[key]
except KeyError:
return object.__getattribute__(self, key)

File diff suppressed because it is too large Load Diff

View File

@ -25,6 +25,7 @@
#include "cppFunctionGroup.h"
#include "cppFunctionType.h"
#include "cppClosureType.h"
#include "cppReferenceType.h"
#include "cppStructType.h"
#include "cppBison.h"
#include "pdtoa.h"
@ -260,12 +261,12 @@ CPPExpression(CPPIdentifier *ident, CPPScope *current_scope,
_u._variable = inst;
return;
}
CPPFunctionGroup *fgroup = decl->as_function_group();
/*CPPFunctionGroup *fgroup = decl->as_function_group();
if (fgroup != nullptr) {
_type = T_function;
_u._fgroup = fgroup;
return;
}
}*/
}
_type = T_unknown_ident;
@ -1232,6 +1233,61 @@ determine_type() const {
return nullptr; // Compiler kludge; can't get here.
}
/**
* Returns true if this is an lvalue expression.
*/
bool CPPExpression::
is_lvalue() const {
switch (_type) {
case T_variable:
case T_function:
case T_unknown_ident:
return true;
case T_typecast:
case T_static_cast:
case T_dynamic_cast:
case T_const_cast:
case T_reinterpret_cast:
{
CPPReferenceType *ref_type = _u._typecast._to->as_reference_type();
return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue;
}
case T_unary_operation:
if (_u._op._operator == 'f') {
// A function returning an lvalue reference.
CPPType *return_type = determine_type();
if (return_type != nullptr) {
CPPReferenceType *ref_type = return_type->as_reference_type();
return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue;
}
}
return _u._op._operator == PLUSPLUS
|| _u._op._operator == MINUSMINUS
|| _u._op._operator == '*';
case T_binary_operation:
if (_u._op._operator == ',') {
CPPReferenceType *ref_type = _u._op._op2->as_reference_type();
return ref_type != nullptr && ref_type->_value_category == CPPReferenceType::VC_lvalue;
}
return (_u._op._operator == POINTSAT || _u._op._operator == ',');
case T_trinary_operation:
return _u._op._op2->is_lvalue() && _u._op._op3->is_lvalue();
case T_literal:
case T_raw_literal:
return true;
default:
break;
}
return false;
}
/**
* Returns true if this declaration is an actual, factual declaration, or
* false if some part of the declaration depends on a template parameter which

View File

@ -133,6 +133,7 @@ public:
Result evaluate() const;
CPPType *determine_type() const;
bool is_lvalue() const;
bool is_tbd() const;
virtual bool is_fully_specified() const;

View File

@ -4078,13 +4078,9 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) {
/**
* Special case optimization: if the last map is a subset of the map before
* it, and the last parameter is only a simple parameter type (that we have
* special default argument handling for), we can merge the cases. When this
* happens, we can make use of a special feature of PyArg_ParseTuple for
* handling of these last few default arguments. This doesn't work well for
* all types of default expressions, though, hence the need for this elaborate
* checking mechanism down here, which goes in parallel with the actual
* optional arg handling logic in write_function_instance.
* it, we can merge the cases. When this happens, we can make use of a
* special feature of PyArg_ParseTuple for handling of these last few default
* arguments.
*
* This isn't just to help reduce the amount of generated code; it also
* enables arbitrary selection of keyword arguments for many functions, ie.
@ -4095,14 +4091,6 @@ write_coerce_constructor(ostream &out, Object *obj, bool is_const) {
* Thanks to this mechanism, we can call it like so:
*
* func(c=True, d=".")
*
* The return value is the minimum of the number of maximum arguments.
*
* Sorry, let me try that again: it returns the largest number of arguments
* for which the overloads will be separated out rather than handled via the
* special default handling mechanism. Or something.
*
* Please don't hate me.
*/
int InterfaceMakerPythonNative::
collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
@ -4118,70 +4106,8 @@ collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
if (std::includes(rmi_next->second.begin(), rmi_next->second.end(),
rmi->second.begin(), rmi->second.end())) {
// Check if the nth argument is something we can easily create a default
// for.
std::set<FunctionRemap *>::iterator sii;
for (sii = rmi->second.begin(); sii != rmi->second.end(); ++sii) {
FunctionRemap *remap = (*sii);
size_t pn = (size_t)rmi->first;
if (!remap->_has_this || remap->_type == FunctionRemap::T_constructor) {
--pn;
}
nassertd(pn < remap->_parameters.size()) goto abort_iteration;
ParameterRemap *param = remap->_parameters[pn]._remap;
CPPType *type = param->get_new_type();
if (param->new_type_is_atomic_string()) {
CPPType *orig_type = param->get_orig_type();
if (TypeManager::is_char_pointer(orig_type)) {
} else if (TypeManager::is_wchar_pointer(orig_type)) {
goto abort_iteration;
} else if (TypeManager::is_wstring(orig_type)) {
goto abort_iteration;
} else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
goto abort_iteration;
} else {
// Regular strings are OK if the default argument is a string
// literal or the default string constructor, since those are
// trivial to handle. This actually covers almost all of the
// cases of default string args.
CPPExpression::Type expr_type = param->get_default_value()->_type;
if (expr_type != CPPExpression::T_default_construct &&
expr_type != CPPExpression::T_string) {
goto abort_iteration;
}
}
} else if (TypeManager::is_integer(type)) {
} else if (TypeManager::is_float(type)) {
} else if (TypeManager::is_const_char_pointer(type)) {
} else if (TypeManager::is_pointer_to_PyTypeObject(type)) {
} else if (TypeManager::is_pointer_to_PyStringObject(type)) {
} else if (TypeManager::is_pointer_to_PyUnicodeObject(type)) {
} else if (TypeManager::is_pointer_to_PyObject(type)) {
} else if (TypeManager::is_pointer_to_Py_buffer(type)) {
goto abort_iteration;
} else if (TypeManager::is_pointer_to_simple(type)) {
goto abort_iteration;
} else if (TypeManager::is_pointer(type)) {
// I'm allowing other pointer types, but only if the expression
// happens to evaluate to a numeric constant (which will likely only
// be NULL). There are too many issues to resolve right now with
// allowing more complex default expressions, including issues in
// the C++ parser (but the reader is welcome to give it a try!)
CPPExpression::Result res = param->get_default_value()->evaluate();
if (res._type != CPPExpression::RT_integer &&
res._type != CPPExpression::RT_pointer) {
goto abort_iteration;
}
} else {
goto abort_iteration;
}
}
// rmi_next has a superset of the remaps in rmi, and we are going to
// erase rmi_next, so put all the remaps in rmi. rmi->second =
// rmi_next->second;
// erase rmi_next, so put all the remaps in rmi.
max_required_args = rmi_next->first;
rmi = rmi_next;
@ -4191,7 +4117,6 @@ collapse_default_remaps(std::map<int, std::set<FunctionRemap *> > &map_sets,
}
}
abort_iteration:
// Now erase the other remap sets. Reverse iterators are weird, we first
// need to get forward iterators and decrement them by one.
std::map<int, std::set<FunctionRemap *> >::iterator erase_begin, erase_end;
@ -4738,6 +4663,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
"(" + orig_type->get_local_name(&parser) + ")" + param_name;
string default_expr;
const char *null_assign = "";
if (is_optional) {
// If this is an optional argument, PyArg_ParseTuple will leave the
@ -4747,6 +4673,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
default_expr_str << " = ";
default_value->output(default_expr_str, 0, &parser, false);
default_expr = default_expr_str.str();
null_assign = " = nullptr";
// We should only ever have to consider optional arguments for functions
// taking a variable number of arguments.
@ -4776,23 +4703,40 @@ write_function_instance(ostream &out, FunctionRemap *remap,
expected_params += "str";
} else if (TypeManager::is_wchar_pointer(orig_type)) {
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
indent(out, indent_level) << "#else\n";
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
indent(out, indent_level) << "#endif\n";
out << "#if PY_VERSION_HEX >= 0x03020000\n";
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
out << "#else\n";
indent(out, indent_level) << "PyUnicodeObject *" << param_name << null_assign << ";\n";
out << "#endif\n";
format_specifiers += "U";
parameter_list += ", &" + param_name;
extra_convert
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n"
<< "#else"
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
<< param_name << "_str[" << param_name << "_len] = 0;\n"
<< "#endif\n";
if (is_optional) {
extra_convert
<< "wchar_t *" << param_name << "_str;\n"
<< "if (" << param_name << " != nullptr) {\n"
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< " " << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n"
<< "#else"
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
<< " " << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
<< param_name << "_str[" << param_name << "_len] = 0;\n"
<< "#endif\n"
<< "} else {\n"
<< " " << param_name << "_str" << default_expr << ";\n"
<< "}\n";
} else {
extra_convert
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString(" << param_name << ", nullptr);\n"
<< "#else"
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
<< param_name << "_str[" << param_name << "_len] = 0;\n"
<< "#endif\n";
}
pexpr_string = param_name + "_str";
@ -4803,56 +4747,48 @@ write_function_instance(ostream &out, FunctionRemap *remap,
expected_params += "unicode";
} else if (TypeManager::is_wstring(orig_type)) {
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
indent(out, indent_level) << "#else\n";
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
indent(out, indent_level) << "#endif\n";
} else if (TypeManager::is_wstring(orig_type) ||
TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
out << "#if PY_VERSION_HEX >= 0x03020000\n";
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
out << "#else\n";
indent(out, indent_level) << "PyUnicodeObject *" << param_name << null_assign << ";\n";
out << "#endif\n";
format_specifiers += "U";
parameter_list += ", &" + param_name;
extra_convert
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< "Py_ssize_t " << param_name << "_len;\n"
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString("
<< param_name << ", &" << param_name << "_len);\n"
<< "#else\n"
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
<< "#endif\n";
pexpr_string = param_name + "_str, " + param_name + "_len";
extra_cleanup
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< "PyMem_Free(" << param_name << "_str);\n"
<< "#endif\n";
expected_params += "unicode";
} else if (TypeManager::is_const_ptr_to_basic_string_wchar(orig_type)) {
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
indent(out, indent_level) << "#else\n";
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
indent(out, indent_level) << "#endif\n";
format_specifiers += "U";
parameter_list += ", &" + param_name;
extra_convert
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< "Py_ssize_t " << param_name << "_len;\n"
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString("
<< param_name << ", &" << param_name << "_len);\n"
<< "#else\n"
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
<< "#endif\n";
pexpr_string = param_name + "_str, " + param_name + "_len";
if (is_optional) {
extra_convert
<< "Py_ssize_t " << param_name << "_len;\n"
<< "wchar_t *" << param_name << "_str;\n"
<< "std::wstring " << param_name << "_wstr;\n"
<< "if (" << param_name << " != nullptr) {\n"
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< " " << param_name << "_str = PyUnicode_AsWideCharString("
<< param_name << ", &" << param_name << "_len);\n"
<< "#else\n"
<< " " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
<< " " << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
<< "#endif\n"
<< " " << param_name << "_wstr.assign(" << param_name << "_str, " << param_name << "_len);\n"
<< "} else {\n"
<< " " << param_name << "_wstr" << default_expr << ";\n"
<< "}\n";
pexpr_string = "std::move(" + param_name + "_wstr)";
} else {
extra_convert
<< "#if PY_VERSION_HEX >= 0x03030000\n"
<< "Py_ssize_t " << param_name << "_len;\n"
<< "wchar_t *" << param_name << "_str = PyUnicode_AsWideCharString("
<< param_name << ", &" << param_name << "_len);\n"
<< "#else\n"
<< "Py_ssize_t " << param_name << "_len = PyUnicode_GET_SIZE(" << param_name << ");\n"
<< "wchar_t *" << param_name << "_str = (wchar_t *)alloca(sizeof(wchar_t) * (" + param_name + "_len + 1));\n"
<< "PyUnicode_AsWideChar(" << param_name << ", " << param_name << "_str, " << param_name << "_len);\n"
<< "#endif\n";
pexpr_string = param_name + "_str, " + param_name + "_len";
}
extra_cleanup
<< "#if PY_VERSION_HEX >= 0x03030000\n"
@ -5019,11 +4955,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
only_pyobjects = false;
} else if (TypeManager::is_wchar(type)) {
indent(out, indent_level) << "#if PY_VERSION_HEX >= 0x03020000\n";
out << "#if PY_VERSION_HEX >= 0x03020000\n";
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
indent(out, indent_level) << "#else\n";
out << "#else\n";
indent(out, indent_level) << "PyUnicodeObject *" << param_name << ";\n";
indent(out, indent_level) << "#endif\n";
out << "#endif\n";
format_specifiers += "U";
parameter_list += ", &" + param_name;
@ -5348,17 +5284,36 @@ write_function_instance(ostream &out, FunctionRemap *remap,
if (args_type == AT_single_arg) {
param_name = "arg";
} else {
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
format_specifiers += "O";
parameter_list += ", &" + param_name;
}
indent(out, indent_level) << "Py_buffer " << param_name << "_view;\n";
extra_param_check << " && PyObject_GetBuffer("
<< param_name << ", &"
<< param_name << "_view, PyBUF_FULL) == 0";
pexpr_string = "&" + param_name + "_view";
extra_cleanup << "PyBuffer_Release(&" << param_name << "_view);\n";
if (is_optional) {
indent(out, indent_level) << "Py_buffer *" << param_name << "_viewp;\n";
extra_convert
<< "bool " << param_name << "_success;\n"
<< "if (" << param_name << " != nullptr) {\n"
<< " " << param_name << "_success = (PyObject_GetBuffer("
<< param_name << ", &" << param_name << "_view, PyBUF_FULL) == 0);\n"
<< " " << param_name << "_viewp = &" << param_name << "_view;\n"
<< "} else {\n"
<< " " << param_name << "_viewp" << default_expr << ";\n"
<< " " << param_name << "_success = true;\n"
<< "}\n";
extra_param_check << " && " << param_name << "_success";
pexpr_string = param_name + "_viewp";
extra_cleanup << "if (" << param_name << " != nullptr) PyBuffer_Release(&" << param_name << "_view);\n";
} else {
extra_param_check << " && PyObject_GetBuffer("
<< param_name << ", &"
<< param_name << "_view, PyBUF_FULL) == 0";
pexpr_string = "&" + param_name + "_view";
extra_cleanup << "PyBuffer_Release(&" << param_name << "_view);\n";
}
expected_params += "buffer";
may_raise_typeerror = true;
clear_error = true;
@ -5367,7 +5322,7 @@ write_function_instance(ostream &out, FunctionRemap *remap,
if (args_type == AT_single_arg) {
param_name = "arg";
} else {
indent(out, indent_level) << "PyObject *" << param_name << ";\n";
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
format_specifiers += "O";
parameter_list += ", &" + param_name;
}
@ -5496,18 +5451,15 @@ write_function_instance(ostream &out, FunctionRemap *remap,
if (args_type == AT_single_arg) {
param_name = "arg";
} else {
indent(out, indent_level) << "PyObject *" << param_name;
if (is_optional) {
out << " = nullptr";
}
out << ";\n";
indent(out, indent_level) << "PyObject *" << param_name << null_assign << ";\n";
format_specifiers += "O";
parameter_list += ", &" + param_name;
}
// If the default value is NULL, we also accept a None value.
bool maybe_none = false;
if (default_value != nullptr && (return_flags & RF_coerced) == 0) {
if (default_value != nullptr && (return_flags & RF_coerced) == 0 &&
TypeManager::is_pointer(orig_type)) {
CPPExpression::Result res = param->get_default_value()->evaluate();
if (res._type == CPPExpression::RT_integer ||
res._type == CPPExpression::RT_pointer) {
@ -5576,8 +5528,11 @@ write_function_instance(ostream &out, FunctionRemap *remap,
<< "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n"
<< " " << param_name << "_this";
} else if (is_optional) {
if (TypeManager::is_pointer(orig_type)) {
extra_convert << default_expr;
}
extra_convert
<< default_expr << ";\n"
<< ";\n"
<< "if (" << param_name << " != nullptr) {\n"
<< " " << param_name << "_this";
} else if (maybe_none) {
@ -5590,7 +5545,13 @@ write_function_instance(ostream &out, FunctionRemap *remap,
extra_convert << " = Dtool_Coerce_" + make_safe_name(class_name) +
"(" + param_name + ", " + param_name + "_local);\n";
if (is_optional || maybe_none) {
if (is_optional && !TypeManager::is_pointer(orig_type)) {
extra_convert
<< "} else {\n"
<< " " << param_name << "_local" << default_expr << ";\n"
<< " " << param_name << "_this = &" << param_name << "_local;\n"
<< "}\n";
} else if (is_optional || maybe_none) {
extra_convert << "}\n";
}
@ -5645,21 +5606,60 @@ write_function_instance(ostream &out, FunctionRemap *remap,
} else { // The regular, non-coercion case.
type->output_instance(extra_convert, param_name + "_this", &parser);
if (is_optional && maybe_none) {
// This parameter has a default value of nullptr, so we need to also
// allow passing in None.
extra_convert
<< default_expr << ";\n"
<< "if (" << param_name << " != nullptr && " << param_name << " != Py_None) {\n"
<< " " << param_name << "_this";
} else if (is_optional) {
}
else if (is_optional && !TypeManager::is_pointer(orig_type) && !default_value->is_lvalue()) {
// Most annoying case, where we have to use an rvalue reference to
// extend the lifetime of the default argument. In this case, the
// default expression is invoked even if not used.
extra_convert << ";\n";
if (TypeManager::is_const_pointer_to_anything(type)) {
extra_convert << "const ";
obj_type->output_instance(extra_convert, "&" + param_name + "_ref", &parser);
} else {
obj_type->output_instance(extra_convert, "&&" + param_name + "_ref", &parser);
}
extra_convert
<< default_expr << ";\n"
<< "if (" << param_name << " != nullptr) {\n"
<< "if (" << param_name << " == nullptr) {\n"
<< " " << param_name << "_this = &" << param_name << "_ref;\n"
<< "} else {\n"
<< " " << param_name << "_this";
} else if (maybe_none) {
}
else if (is_optional) {
// General case where the default argument is either an lvalue or a
// pointer.
extra_convert
<< ";\n"
<< "if (" << param_name << " == nullptr) {\n"
<< " " << param_name << "_this = ";
if (TypeManager::is_pointer(orig_type)) {
default_value->output(extra_convert, 0, &parser, false);
extra_convert << ";\n";
} else {
// The rvalue case was handled above, so this is an lvalue, which
// means we can safely take a reference to it.
extra_convert << "&(";
default_value->output(extra_convert, 0, &parser, false);
extra_convert << ");\n";
}
extra_convert
<< "} else {\n"
<< " " << param_name << "_this";
}
else if (maybe_none) {
// No default argument, but we still need to check for None.
extra_convert
<< " = nullptr;\n"
<< "if (" << param_name << " != Py_None) {\n"
<< " " << param_name << "_this";
}
if (const_ok && !report_errors) {
// This function does the same thing in this case and is slightly
// simpler. But maybe we should just reorganize these functions

View File

@ -312,7 +312,10 @@ main(int argc, char **argv) {
string command_line;
int i;
for (i = 0; i < argc; i++) {
command_line += string(argv[i]) + " ";
if (i > 0) {
command_line += ' ';
}
command_line += string(argv[i]);
}
Filename fn;

View File

@ -2024,6 +2024,7 @@ get_make_property(CPPMakeProperty *make_property, CPPStructType *struct_type, CP
if (iproperty._type != 0 && iproperty._type != return_index) {
cerr << "Property " << property_name << " has inconsistent element type!\n";
}
iproperty._type = return_index;
} else {
iproperty._type = 0;
}

View File

@ -176,6 +176,18 @@ interrogate_element_setter(ElementIndex element) {
return InterrogateDatabase::get_ptr()->get_element(element).get_setter();
}
bool
interrogate_element_is_sequence(ElementIndex element) {
// cerr << "interrogate_element_is_sequence(" << element << ")\n";
return InterrogateDatabase::get_ptr()->get_element(element).is_sequence();
}
bool
interrogate_element_is_mapping(ElementIndex element) {
// cerr << "interrogate_element_is_mapping(" << element << ")\n";
return InterrogateDatabase::get_ptr()->get_element(element).is_mapping();
}
int
interrogate_number_of_globals() {
// cerr << "interrogate_number_of_globals()\n";

View File

@ -153,6 +153,9 @@ EXPCL_INTERROGATEDB FunctionIndex interrogate_element_getter(ElementIndex elemen
EXPCL_INTERROGATEDB bool interrogate_element_has_setter(ElementIndex element);
EXPCL_INTERROGATEDB FunctionIndex interrogate_element_setter(ElementIndex element);
EXPCL_INTERROGATEDB bool interrogate_element_is_sequence(ElementIndex element);
EXPCL_INTERROGATEDB bool interrogate_element_is_mapping(ElementIndex element);
// Global Data
// This is the list of global data elements.

View File

@ -14,7 +14,7 @@
;
; BUILT - location of panda install tree.
; SOURCE - location of the panda source-tree if available, OR location of panda install tree.
; PYVER - version of Python that Panda was built with (ie, "2.7")
; INCLUDE_PYVER - version of Python that Panda was built with (eg. "2.7", "3.5-32")
; REGVIEW - either 32 or 64, depending on the build architecture.
;
@ -46,7 +46,9 @@ SetCompressor ${COMPRESSOR}
!insertmacro MUI_PAGE_LICENSE "${SOURCE}/doc/LICENSE"
!insertmacro MUI_PAGE_DIRECTORY
!ifdef INCLUDE_PYVER
!define MUI_PAGE_CUSTOMFUNCTION_LEAVE ConfirmPythonSelection
!endif
!insertmacro MUI_PAGE_COMPONENTS
!insertmacro MUI_PAGE_INSTFILES
@ -64,8 +66,9 @@ ShowUninstDetails hide
LicenseData "${SOURCE}/doc/LICENSE"
InstType "Full (Recommended)"
InstType "Minimal"
InstType "Auto (Recommended)"
InstType "Full"
InstType "Light"
LangString DESC_SecCore ${LANG_ENGLISH} "The Panda3D core libraries, configuration files and models/textures that are needed to use Panda3D."
LangString DESC_SecOpenGL ${LANG_ENGLISH} "The OpenGL graphics back-end is the most well-supported renderer."
@ -78,8 +81,9 @@ LangString DESC_SecODE ${LANG_ENGLISH} "Support for the Open Dynamics Engine to
LangString DESC_SecPhysX ${LANG_ENGLISH} "Support for NVIDIA PhysX to implement physics."
LangString DESC_SecRocket ${LANG_ENGLISH} "Support for the libRocket GUI library. This is an optional library that offers an HTML/CSS-like approach to creating user interfaces."
LangString DESC_SecTools ${LANG_ENGLISH} "Useful tools and model converters to help with Panda3D development. Recommended."
LangString DESC_SecPyBindings ${LANG_ENGLISH} "Contains the Python modules that allow use of Panda3D using Python. These will only work with a ${REGVIEW}-bit version of Python ${PYVER}."
LangString DESC_SecPython ${LANG_ENGLISH} "Contains a ${REGVIEW}-bit copy of Python ${PYVER} preconfigured to make use of Panda3D."
LangString DESC_SecGroupPython ${LANG_ENGLISH} "Contains modules that provide Python support for Panda3D."
LangString DESC_SecPyShared ${LANG_ENGLISH} "Contains the common Python code used by the Panda3D Python bindings."
LangString DESC_SecPython ${LANG_ENGLISH} "Contains a ${REGVIEW}-bit copy of Python ${INCLUDE_PYVER} preconfigured to make use of Panda3D."
LangString DESC_SecHeadersLibs ${LANG_ENGLISH} "Headers and libraries needed for C++ development with Panda3D."
LangString DESC_SecSamples ${LANG_ENGLISH} "The sample programs demonstrate how to make Python applications with Panda3D."
LangString DESC_SecMaxPlugins ${LANG_ENGLISH} "Plug-ins for Autodesk 3ds Max (${REGVIEW}-bit) that can be used to export models to Panda3D."
@ -112,222 +116,38 @@ var MANPAGE
!insertmacro !defineifexist HAVE_ODE "${BUILT}\bin\libpandaode.dll"
!insertmacro !defineifexist HAVE_PHYSX "${BUILT}\bin\libpandaphysx.dll"
!insertmacro !defineifexist HAVE_ROCKET "${BUILT}\bin\libp3rocket.dll"
!insertmacro !defineifexist HAVE_PYTHON "${BUILT}\python"
!insertmacro !defineifexist HAVE_SAMPLES "${SOURCE}\samples"
!insertmacro !defineifexist HAVE_MAX_PLUGINS "${BUILT}\plugins\*.dlo"
!insertmacro !defineifexist HAVE_MAYA_PLUGINS "${BUILT}\plugins\*.mll"
Function runFunction
ExecShell "open" "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk"
FunctionEnd
!macro RemovePythonPath PYVER
ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D" ""
StrCmp $0 "$INSTDIR" 0 +2
DeleteRegKey HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D"
!macroend
Function .onInit
${If} ${REGVIEW} = 64
${AndIfNot} ${RunningX64}
MessageBox MB_OK|MB_ICONEXCLAMATION "You are attempting to install the 64-bit version of Panda3D on a 32-bit version of Windows. Please download and install the 32-bit version of Panda3D instead."
Abort
${EndIf}
FunctionEnd
!macro PyBindingSection PYVER EXT_SUFFIX
LangString DESC_SecPyBindings${PYVER} ${LANG_ENGLISH} "Contains the Python modules that allow use of Panda3D using a ${REGVIEW}-bit version of Python ${PYVER}."
SectionGroup "Panda3D Libraries"
Section "Core Libraries" SecCore
SectionIn 1 2 RO
SetShellVarContext current
SetOverwrite try
!insertmacro !defineifexist _present "${BUILT}\panda3d\core${EXT_SUFFIX}"
!ifdef _present
Section "${PYVER} bindings" SecPyBindings${PYVER}
!if "${PYVER}" == "${INCLUDE_PYVER}"
SectionIn 1 2 3
!else
!if "${PYVER}" == "2.7"
SectionIn 1 2
!else
; See .onInit function where this is dynamically enabled.
SectionIn 2
!endif
!endif
SetDetailsPrint both
DetailPrint "Installing Panda3D libraries..."
DetailPrint "Installing Panda3D bindings for Python ${PYVER}..."
SetDetailsPrint listonly
SetOutPath "$INSTDIR"
File /nonfatal "${BUILT}\LICENSE"
File /nonfatal "${BUILT}\ReleaseNotes"
File /nonfatal "${BUILT}\pandaIcon.ico"
SetOutPath $INSTDIR\etc
File /r "${BUILT}\etc\*"
SetOutPath $INSTDIR\bin
File /r /x api-ms-win-*.dll /x ucrtbase.dll /x libpandagl.dll /x libpandadx9.dll /x cgD3D*.dll /x python*.dll /x libpandaode.dll /x libp3fmod_audio.dll /x fmodex*.dll /x libp3ffmpeg.dll /x av*.dll /x postproc*.dll /x swscale*.dll /x swresample*.dll /x NxCharacter*.dll /x cudart*.dll /x PhysX*.dll /x libpandaphysx.dll /x libp3rocket.dll /x boost_python*.dll /x Rocket*.dll /x _rocket*.pyd /x libpandabullet.dll /x OpenAL32.dll /x *_oal.dll /x libp3openal_audio.dll "${BUILT}\bin\*.dll"
File /nonfatal /r "${BUILT}\bin\Microsoft.*.manifest"
; Before Windows 10, we need these stubs for the UCRT as well.
ReadRegDWORD $0 HKLM "Software\Microsoft\Windows NT\CurrentVersion" "CurrentMajorVersionNumber"
${If} $0 < 10
ClearErrors
File /nonfatal /r "${BUILT}\bin\api-ms-win-*.dll"
File /nonfatal "${BUILT}\bin\ucrtbase.dll"
${Endif}
SetDetailsPrint both
DetailPrint "Installing models..."
SetDetailsPrint listonly
SetOutPath $INSTDIR\models
File /r /x CVS "${BUILT}\models\*"
SetDetailsPrint both
DetailPrint "Installing optional components..."
SetDetailsPrint listonly
RMDir /r "$SMPROGRAMS\${TITLE}"
CreateDirectory "$SMPROGRAMS\${TITLE}"
SectionEnd
!ifdef HAVE_GL
Section "OpenGL" SecOpenGL
SectionIn 1 2 RO
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandagl.dll"
SectionEnd
!endif
!ifdef HAVE_DX9
Section "Direct3D 9" SecDirect3D9
SectionIn 1
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandadx9.dll"
File /nonfatal /r "${BUILT}\bin\cgD3D9.dll"
SectionEnd
!endif
!ifdef HAVE_OPENAL
Section "OpenAL Audio" SecOpenAL
SectionIn 1 2
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3openal_audio.dll"
File /nonfatal /r "${BUILT}\bin\OpenAL32.dll"
File /nonfatal /r "${BUILT}\bin\*_oal.dll"
SectionEnd
!endif
!ifdef HAVE_FMOD
Section "FMOD Audio" SecFMOD
SectionIn 1
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3fmod_audio.dll"
File /r "${BUILT}\bin\fmodex*.dll"
SectionEnd
!endif
!ifdef HAVE_FFMPEG
Section "FFMpeg" SecFFMpeg
SectionIn 1
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3ffmpeg.dll"
File /nonfatal /r "${BUILT}\bin\av*.dll"
File /nonfatal /r "${BUILT}\bin\swscale*.dll"
File /nonfatal /r "${BUILT}\bin\swresample*.dll"
File /nonfatal /r "${BUILT}\bin\postproc*.dll"
SectionEnd
!endif
!ifdef HAVE_BULLET
Section "Bullet Physics" SecBullet
SectionIn 1
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandabullet.dll"
SectionEnd
!endif
!ifdef HAVE_ODE
Section "ODE Physics" SecODE
SectionIn 1
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandaode.dll"
SectionEnd
!endif
!ifdef HAVE_PHYSX
Section "NVIDIA PhysX" SecPhysX
SectionIn 1
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandaphysx.dll"
File /nonfatal /r "${BUILT}\bin\PhysX*.dll"
File /nonfatal /r "${BUILT}\bin\NxCharacter*.dll"
File /nonfatal /r "${BUILT}\bin\cudart*.dll"
SectionEnd
!endif
!ifdef HAVE_ROCKET
Section "libRocket GUI" SecRocket
SectionIn 1
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3rocket.dll"
File /nonfatal /r "${BUILT}\bin\Rocket*.dll"
File /nonfatal /r "${BUILT}\bin\_rocket*.pyd"
File /nonfatal /r "${BUILT}\bin\boost_python*.dll"
SectionEnd
!endif
SectionGroupEnd
Section "Tools and utilities" SecTools
SectionIn 1 2
SetDetailsPrint both
DetailPrint "Installing utilities..."
SetDetailsPrint listonly
SetOutPath "$INSTDIR\bin"
File /r "${BUILT}\bin\*.exe"
File /nonfatal /r "${BUILT}\bin\*.p3d"
SetOutPath "$INSTDIR\NSIS"
File /r /x CVS "${NSISDIR}\*"
WriteRegStr HKCU "Software\Classes\Panda3D.Model" "" "Panda3D model/animation"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\DefaultIcon" "" "$INSTDIR\bin\pview.exe"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell" "" "open"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell\open\command" "" '"$INSTDIR\bin\pview.exe" -l "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell\compress" "" "Compress to .pz"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell\compress\command" "" '"$INSTDIR\bin\pzip.exe" "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed" "" "Compressed file"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\DefaultIcon" "" "$INSTDIR\bin\pzip.exe"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell" "" "open"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell\open\command" "" '"$INSTDIR\bin\pview.exe" -l "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell\decompress" "" "Decompress"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell\decompress\command" "" '"$INSTDIR\bin\punzip.exe" "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile" "" "Panda3D Multifile"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\DefaultIcon" "" "$INSTDIR\bin\multify.exe"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\shell" "" "open"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\shell\extract" "" "Extract here"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\shell\extract\command" "" '"$INSTDIR\bin\multify.exe" -xf "%1"'
SectionEnd
SectionGroup "Python support"
Section "Python bindings" SecPyBindings
SectionIn 1 2
SetDetailsPrint both
DetailPrint "Installing Panda3D Python modules..."
SetDetailsPrint listonly
SetOutPath "$INSTDIR\bin"
File /nonfatal /r "${BUILT}\bin\*.pyd"
SetOutPath $INSTDIR\direct\directscripts
File /r /x CVS /x Opt?-Win32 "${BUILT}\direct\directscripts\*"
SetOutPath $INSTDIR\direct
File /r /x CVS /x Opt?-Win32 "${BUILT}\direct\*.py"
Delete "$INSTDIR\panda3d.py"
Delete "$INSTDIR\panda3d.pyc"
Delete "$INSTDIR\panda3d.pyo"
SetOutPath $INSTDIR\pandac
File /r "${BUILT}\pandac\*.py"
SetOutPath $INSTDIR\panda3d
File /r "${BUILT}\panda3d\*.py"
File /nonfatal /r "${BUILT}\panda3d\core${EXT_SUFFIX}"
File /nonfatal /r "${BUILT}\panda3d\ai${EXT_SUFFIX}"
@ -384,87 +204,342 @@ SectionGroup "Python support"
SetRegView ${REGVIEW}
!endif
; Check for a non-Panda3D system-wide Python installation.
ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" UserExternalPthCheck 0
StrCmp $0 "" UserExternalPthCheck 0
IfFileExists "$0\ppython.exe" UserExternalPthCheck 0
IfFileExists "$0\python.exe" AskExternalPth UserExternalPthCheck
; Check for a non-Panda3D user installation of Python.
UserExternalPthCheck:
ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" SkipExternalPth 0
StrCmp $0 "" SkipExternalPth 0
IfFileExists "$0\ppython.exe" SkipExternalPth 0
IfFileExists "$0\python.exe" AskExternalPth SkipExternalPth
; We're pretty sure this Python build is of the right architecture.
AskExternalPth:
MessageBox MB_YESNO|MB_ICONQUESTION \
"Your system already has a copy of Python ${PYVER} installed in:$\r$\n$0$\r$\nWould you like to configure it to be able to use the Panda3D libraries?$\r$\nIf you choose no, you will only be able to use Panda3D's own copy of Python." \
IDYES WriteExternalPth IDNO SkipExternalPth
WriteExternalPth:
;FileOpen $1 "$0\Lib\site-packages\panda.pth" w
;FileWrite $1 "$INSTDIR$\r$\n"
;FileWrite $1 "$INSTDIR\bin$\r$\n"
;FileClose $1
; Actually, it looks like we can just do this instead:
; Install a Panda3D path into the global PythonPath for this version
; of Python.
WriteRegStr HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D" "" "$INSTDIR"
SectionEnd
!undef _present
!endif
!macroend
SkipExternalPth:
Function runFunction
ExecShell "open" "$SMPROGRAMS\${TITLE}\Panda3D Manual.lnk"
FunctionEnd
SectionGroup "Panda3D Libraries"
Section "Core Libraries" SecCore
SectionIn 1 2 3 RO
SetShellVarContext current
SetOverwrite try
SetDetailsPrint both
DetailPrint "Installing Panda3D libraries..."
SetDetailsPrint listonly
SetOutPath "$INSTDIR"
File /nonfatal "${BUILT}\LICENSE"
File /nonfatal "${BUILT}\ReleaseNotes"
File /nonfatal "${BUILT}\pandaIcon.ico"
SetOutPath $INSTDIR\etc
File /r "${BUILT}\etc\*"
SetOutPath $INSTDIR\bin
File /r /x api-ms-win-*.dll /x ucrtbase.dll /x libpandagl.dll /x libpandadx9.dll /x cgD3D*.dll /x python*.dll /x libpandaode.dll /x libp3fmod_audio.dll /x fmodex*.dll /x libp3ffmpeg.dll /x av*.dll /x postproc*.dll /x swscale*.dll /x swresample*.dll /x NxCharacter*.dll /x cudart*.dll /x PhysX*.dll /x libpandaphysx.dll /x libp3rocket.dll /x boost_python*.dll /x Rocket*.dll /x _rocket*.pyd /x libpandabullet.dll /x OpenAL32.dll /x *_oal.dll /x libp3openal_audio.dll "${BUILT}\bin\*.dll"
File /nonfatal /r "${BUILT}\bin\Microsoft.*.manifest"
; Before Windows 10, we need these stubs for the UCRT as well.
ReadRegDWORD $0 HKLM "Software\Microsoft\Windows NT\CurrentVersion" "CurrentMajorVersionNumber"
${If} $0 < 10
ClearErrors
File /nonfatal /r "${BUILT}\bin\api-ms-win-*.dll"
File /nonfatal "${BUILT}\bin\ucrtbase.dll"
${Endif}
SetDetailsPrint both
DetailPrint "Installing models..."
SetDetailsPrint listonly
SetOutPath $INSTDIR\models
File /r /x CVS "${BUILT}\models\*"
SetDetailsPrint both
DetailPrint "Installing optional components..."
SetDetailsPrint listonly
RMDir /r "$SMPROGRAMS\${TITLE}"
CreateDirectory "$SMPROGRAMS\${TITLE}"
SectionEnd
!ifdef HAVE_PYTHON
Section "Python ${PYVER}" SecPython
SectionIn 1 2
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
SetDetailsPrint both
DetailPrint "Installing Python ${PYVER} (${REGVIEW}-bit)..."
SetDetailsPrint listonly
!ifdef HAVE_GL
Section "OpenGL" SecOpenGL
SectionIn 1 2 3 RO
SetOutPath "$INSTDIR\bin"
File /nonfatal "${BUILT}\bin\python*.dll"
File "${BUILT}\bin\libpandagl.dll"
SectionEnd
!endif
SetOutPath "$INSTDIR\python"
File /r /x *.pdb "${BUILT}\python\*"
!ifdef HAVE_DX9
Section "Direct3D 9" SecDirect3D9
SectionIn 1 2
SetDetailsPrint both
DetailPrint "Adding registry keys for Python..."
SetDetailsPrint listonly
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandadx9.dll"
File /nonfatal /r "${BUILT}\bin\cgD3D9.dll"
SectionEnd
!endif
; Check if a copy of Python is installed for this user.
ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp "$0" "$INSTDIR\python" RegPath 0
StrCmp "$0" "" SkipFileCheck 0
IfFileExists "$0\python.exe" AskRegPath 0
SkipFileCheck:
!ifdef HAVE_OPENAL
Section "OpenAL Audio" SecOpenAL
SectionIn 1 2 3
; Check if a system-wide copy of Python is installed.
ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp "$0" "$INSTDIR\python" RegPath 0
StrCmp "$0" "" RegPath 0
IfFileExists "$0\python.exe" AskRegPath RegPath
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3openal_audio.dll"
File /nonfatal /r "${BUILT}\bin\OpenAL32.dll"
File /nonfatal /r "${BUILT}\bin\*_oal.dll"
SectionEnd
!endif
AskRegPath:
MessageBox MB_YESNO|MB_ICONQUESTION \
"You already have a copy of Python ${PYVER} installed in:$\r$\n$0$\r$\n$\r$\nPanda3D installs its own copy of Python ${PYVER}, which will install alongside your existing copy. Would you like to make Panda's copy the default Python for your user account?" \
IDNO SkipRegPath
!ifdef HAVE_FMOD
Section "FMOD Audio" SecFMOD
SectionIn 1 2
RegPath:
WriteRegStr HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" "" "$INSTDIR\python"
SkipRegPath:
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3fmod_audio.dll"
File /r "${BUILT}\bin\fmodex*.dll"
SectionEnd
!endif
!ifdef HAVE_FFMPEG
Section "FFMpeg" SecFFMpeg
SectionIn 1 2
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3ffmpeg.dll"
File /nonfatal /r "${BUILT}\bin\av*.dll"
File /nonfatal /r "${BUILT}\bin\swscale*.dll"
File /nonfatal /r "${BUILT}\bin\swresample*.dll"
File /nonfatal /r "${BUILT}\bin\postproc*.dll"
SectionEnd
!endif
!ifdef HAVE_BULLET
Section "Bullet Physics" SecBullet
SectionIn 1 2
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandabullet.dll"
SectionEnd
!endif
!ifdef HAVE_ODE
Section "ODE Physics" SecODE
SectionIn 1 2
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandaode.dll"
SectionEnd
!endif
!ifdef HAVE_PHYSX
Section "NVIDIA PhysX" SecPhysX
; Only enable in "Full"
SectionIn 2
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libpandaphysx.dll"
File /nonfatal /r "${BUILT}\bin\PhysX*.dll"
File /nonfatal /r "${BUILT}\bin\NxCharacter*.dll"
File /nonfatal /r "${BUILT}\bin\cudart*.dll"
SectionEnd
!endif
!ifdef HAVE_ROCKET
Section "libRocket GUI" SecRocket
SectionIn 1 2
SetOutPath "$INSTDIR\bin"
File "${BUILT}\bin\libp3rocket.dll"
File /nonfatal /r "${BUILT}\bin\Rocket*.dll"
File /nonfatal /r "${BUILT}\bin\_rocket*.pyd"
File /nonfatal /r "${BUILT}\bin\boost_python*.dll"
SectionEnd
!endif
SectionGroupEnd
Section "Tools and utilities" SecTools
SectionIn 1 2 3
SetDetailsPrint both
DetailPrint "Installing utilities..."
SetDetailsPrint listonly
SetOutPath "$INSTDIR\bin"
File /r "${BUILT}\bin\*.exe"
File /nonfatal /r "${BUILT}\bin\*.p3d"
SetOutPath "$INSTDIR\NSIS"
File /r /x CVS "${NSISDIR}\*"
WriteRegStr HKCU "Software\Classes\Panda3D.Model" "" "Panda3D model/animation"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\DefaultIcon" "" "$INSTDIR\bin\pview.exe"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell" "" "open"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell\open\command" "" '"$INSTDIR\bin\pview.exe" -l "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell\compress" "" "Compress to .pz"
WriteRegStr HKCU "Software\Classes\Panda3D.Model\shell\compress\command" "" '"$INSTDIR\bin\pzip.exe" "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed" "" "Compressed file"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\DefaultIcon" "" "$INSTDIR\bin\pzip.exe"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell" "" "open"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell\open\command" "" '"$INSTDIR\bin\pview.exe" -l "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell\decompress" "" "Decompress"
WriteRegStr HKCU "Software\Classes\Panda3D.Compressed\shell\decompress\command" "" '"$INSTDIR\bin\punzip.exe" "%1"'
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile" "" "Panda3D Multifile"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\DefaultIcon" "" "$INSTDIR\bin\multify.exe"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\shell" "" "open"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\shell\extract" "" "Extract here"
WriteRegStr HKCU "Software\Classes\Panda3D.Multifile\shell\extract\command" "" '"$INSTDIR\bin\multify.exe" -xf "%1"'
SectionEnd
SectionGroup "Python modules" SecGroupPython
Section "Shared code" SecPyShared
SectionIn 1 2 3
SetDetailsPrint both
DetailPrint "Installing Panda3D shared Python modules..."
SetDetailsPrint listonly
SetOutPath $INSTDIR\direct\directscripts
File /r /x CVS /x Opt?-Win32 "${BUILT}\direct\directscripts\*"
SetOutPath $INSTDIR\direct
File /r /x CVS /x Opt?-Win32 "${BUILT}\direct\*.py"
Delete "$INSTDIR\panda3d.py"
Delete "$INSTDIR\panda3d.pyc"
Delete "$INSTDIR\panda3d.pyo"
SetOutPath $INSTDIR\pandac
File /r "${BUILT}\pandac\*.py"
SetOutPath $INSTDIR\panda3d
File /r "${BUILT}\panda3d\*.py"
SectionEnd
!insertmacro PyBindingSection 2.7 .pyd
!if "${REGVIEW}" == "32"
!insertmacro PyBindingSection 3.5-32 .cp35-win32.pyd
!insertmacro PyBindingSection 3.6-32 .cp36-win32.pyd
!insertmacro PyBindingSection 3.7-32 .cp37-win32.pyd
!insertmacro PyBindingSection 3.8-32 .cp38-win32.pyd
!insertmacro PyBindingSection 3.9-32 .cp39-win32.pyd
!else
!insertmacro PyBindingSection 3.5 .cp35-win_amd64.pyd
!insertmacro PyBindingSection 3.6 .cp36-win_amd64.pyd
!insertmacro PyBindingSection 3.7 .cp37-win_amd64.pyd
!insertmacro PyBindingSection 3.8 .cp38-win_amd64.pyd
!insertmacro PyBindingSection 3.9 .cp39-win_amd64.pyd
!endif
SectionGroupEnd
!ifdef INCLUDE_PYVER
Section "Python ${INCLUDE_PYVER}" SecPython
SectionIn 1 2 3
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
SetDetailsPrint both
DetailPrint "Installing Python ${INCLUDE_PYVER} interpreter (${REGVIEW}-bit)..."
SetDetailsPrint listonly
SetOutPath "$INSTDIR\bin"
File /nonfatal "${BUILT}\bin\python*.dll"
SetOutPath "$INSTDIR\python"
File /r /x *.pdb "${BUILT}\python\*"
SetDetailsPrint both
DetailPrint "Adding registry keys for Python..."
SetDetailsPrint listonly
; Check if a copy of Python is installed for this user.
ReadRegStr $0 HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
StrCmp "$0" "$INSTDIR\python" RegPath 0
StrCmp "$0" "" SkipFileCheck 0
IfFileExists "$0\python.exe" AskRegPath 0
SkipFileCheck:
; Check if a system-wide copy of Python is installed.
ReadRegStr $0 HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
StrCmp "$0" "$INSTDIR\python" RegPath 0
StrCmp "$0" "" RegPath 0
IfFileExists "$0\python.exe" AskRegPath RegPath
AskRegPath:
MessageBox MB_YESNO|MB_ICONQUESTION \
"You already have a copy of Python ${INCLUDE_PYVER} installed in:$\r$\n$0$\r$\n$\r$\nPanda3D installs its own copy of Python ${INCLUDE_PYVER}, which will install alongside your existing copy. Would you like to make Panda's copy the default Python for your user account?" \
IDNO SkipRegPath
RegPath:
WriteRegStr HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" "" "$INSTDIR\python"
WriteRegStr HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" "ExecutablePath" "$INSTDIR\python\python.exe"
SkipRegPath:
SectionEnd
!endif
!macro MaybeEnablePyBindingSection PYVER
!if "${INCLUDE_PYVER}" != "${PYVER}"
!ifdef SecPyBindings${PYVER}
; Check if a copy of Python is installed for this user.
Push $0
ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp "$0" "" +2 0
IfFileExists "$0\python.exe" Py${PYVER}Exists 0
; Check if a system-wide copy of Python is installed.
ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp "$0" "" Py${PYVER}ExistsNot 0
IfFileExists "$0\python.exe" Py${PYVER}Exists Py${PYVER}ExistsNot
Py${PYVER}Exists:
SectionSetFlags ${SecPyBindings${PYVER}} ${SF_SELECTED}
SectionSetInstTypes ${SecPyBindings${PYVER}} 3
Py${PYVER}ExistsNot:
Pop $0
!endif
!endif
!macroend
Function .onInit
${If} ${REGVIEW} = 64
${AndIfNot} ${RunningX64}
MessageBox MB_OK|MB_ICONEXCLAMATION "You are attempting to install the 64-bit version of Panda3D on a 32-bit version of Windows. Please download and install the 32-bit version of Panda3D instead."
Abort
${EndIf}
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
; We never check for 2.7; it is always enabled in Auto mode
!if "${REGVIEW}" == "32"
!insertmacro MaybeEnablePyBindingSection 3.5-32
!insertmacro MaybeEnablePyBindingSection 3.6-32
!insertmacro MaybeEnablePyBindingSection 3.7-32
!insertmacro MaybeEnablePyBindingSection 3.8-32
!insertmacro MaybeEnablePyBindingSection 3.9-32
!else
!insertmacro MaybeEnablePyBindingSection 3.5
!insertmacro MaybeEnablePyBindingSection 3.6
!insertmacro MaybeEnablePyBindingSection 3.7
!insertmacro MaybeEnablePyBindingSection 3.8
!insertmacro MaybeEnablePyBindingSection 3.9
!endif
FunctionEnd
Function .onSelChange
; If someone selects any Python version, the "shared modules" must be on.
${If} ${SectionIsPartiallySelected} ${SecGroupPython}
SectionGetFlags ${SecPyShared} $R0
IntOp $R0 $R0 | ${SF_SELECTED}
SectionSetFlags ${SecPyShared} $R0
${EndIf}
FunctionEnd
!ifdef INCLUDE_PYVER
Function ConfirmPythonSelection
; Check the current state of the "Python" section selection.
SectionGetFlags ${SecPython} $R0
@ -474,16 +549,14 @@ Function ConfirmPythonSelection
StrCmp $R1 ${SF_SELECTED} SkipCheck 0
; Maybe the user just doesn't want Python support at all?
SectionGetFlags ${SecPyBindings} $R1
IntOp $R1 $R1 & ${SF_SELECTED}
StrCmp $R1 ${SF_SELECTED} 0 SkipCheck
!insertmacro SectionFlagIsSet ${SecGroupPython} ${SF_PSELECTED} 0 SkipCheck
!ifdef REGVIEW
SetRegView ${REGVIEW}
!endif
; Check for a user installation of Python.
ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
ReadRegStr $0 HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" CheckSystemWidePython 0
StrCmp $0 "" CheckSystemWidePython 0
IfFileExists "$0\ppython.exe" CheckSystemWidePython 0
@ -491,7 +564,7 @@ Function ConfirmPythonSelection
; Check for a system-wide Python installation.
CheckSystemWidePython:
ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
ReadRegStr $0 HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" AskConfirmation 0
StrCmp $0 "" AskConfirmation 0
IfFileExists "$0\ppython.exe" AskConfirmation 0
@ -501,7 +574,7 @@ Function ConfirmPythonSelection
; of a different Panda3D build.) Ask the user if he's sure about this.
AskConfirmation:
MessageBox MB_YESNO|MB_ICONQUESTION \
"You do not appear to have a ${REGVIEW}-bit version of Python ${PYVER} installed. Are you sure you don't want Panda to install a compatible copy of Python?$\r$\n$\r$\nIf you choose Yes, you will not be able to do Python development with Panda3D until you install a ${REGVIEW}-bit version of Python ${PYVER} and manually configure it to be able to use Panda3D." \
"You do not appear to have a ${REGVIEW}-bit version of Python ${INCLUDE_PYVER} installed. Are you sure you don't want Panda to install a compatible copy of Python?$\r$\n$\r$\nIf you choose Yes, you will not be able to do Python development with Panda3D until you install a ${REGVIEW}-bit version of Python and install the bindings for this version." \
IDYES SkipCheck
; User clicked no, so re-enable the select box and abort.
@ -511,9 +584,10 @@ Function ConfirmPythonSelection
SkipCheck:
FunctionEnd
!endif
Section "C++ support" SecHeadersLibs
SectionIn 1
SectionIn 1 2
SetDetailsPrint both
DetailPrint "Installing header files..."
@ -532,7 +606,7 @@ SectionEnd
!ifdef HAVE_SAMPLES
Section "Sample programs" SecSamples
SectionIn 1
SectionIn 1 2
; Necessary for proper start menu shortcut installation
SetShellVarContext current
@ -599,7 +673,7 @@ SectionEnd
!ifdef HAVE_MAX_PLUGINS
Section "3ds Max plug-ins" SecMaxPlugins
SectionIn 1 3
SectionIn 1 2
SetDetailsPrint both
DetailPrint "Installing Autodesk 3ds Max plug-ins..."
@ -614,7 +688,7 @@ SectionEnd
!ifdef HAVE_MAYA_PLUGINS
Section "Maya plug-ins" SecMayaPlugins
SectionIn 1 3
SectionIn 1 2
SetDetailsPrint both
DetailPrint "Installing Autodesk Maya plug-ins..."
@ -737,17 +811,30 @@ Section Uninstall
DeleteRegKey HKCU "Software\Classes\Panda3D.Multifile\DefaultIcon"
DeleteRegKey HKCU "Software\Classes\Panda3D.Multifile\shell"
ReadRegStr $0 HKLM "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" 0 +2
DeleteRegKey HKLM "Software\Python\PythonCore\${PYVER}"
!ifdef INCLUDE_PYVER
ReadRegStr $0 HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" 0 +2
DeleteRegKey HKLM "Software\Python\PythonCore\${INCLUDE_PYVER}"
ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" 0 +2
DeleteRegKey HKCU "Software\Python\PythonCore\${PYVER}"
ReadRegStr $0 HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}\InstallPath" ""
StrCmp $0 "$INSTDIR\python" 0 +2
DeleteRegKey HKCU "Software\Python\PythonCore\${INCLUDE_PYVER}"
!endif
ReadRegStr $0 HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D" ""
StrCmp $0 "$INSTDIR" 0 +2
DeleteRegKey HKCU "Software\Python\PythonCore\${PYVER}\PythonPath\Panda3D"
!insertmacro RemovePythonPath 2.7
!if "${REGVIEW}" == "32"
!insertmacro RemovePythonPath 3.5-32
!insertmacro RemovePythonPath 3.6-32
!insertmacro RemovePythonPath 3.7-32
!insertmacro RemovePythonPath 3.8-32
!insertmacro RemovePythonPath 3.9-32
!else
!insertmacro RemovePythonPath 3.5
!insertmacro RemovePythonPath 3.6
!insertmacro RemovePythonPath 3.7
!insertmacro RemovePythonPath 3.8
!insertmacro RemovePythonPath 3.9
!endif
SetDetailsPrint both
DetailPrint "Deleting files..."
@ -812,8 +899,23 @@ SectionEnd
!insertmacro MUI_DESCRIPTION_TEXT ${SecRocket} $(DESC_SecRocket)
!endif
!insertmacro MUI_DESCRIPTION_TEXT ${SecTools} $(DESC_SecTools)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings} $(DESC_SecPyBindings)
!ifdef HAVE_PYTHON
!insertmacro MUI_DESCRIPTION_TEXT ${SecGroupPython} $(DESC_SecGroupPython)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyShared} $(DESC_SecPyShared)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings2.7} $(DESC_SecPyBindings2.7)
!if "${REGVIEW}" == "32"
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.5-32} $(DESC_SecPyBindings3.5-32)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.6-32} $(DESC_SecPyBindings3.6-32)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.7-32} $(DESC_SecPyBindings3.7-32)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.8-32} $(DESC_SecPyBindings3.8-32)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.9-32} $(DESC_SecPyBindings3.9-32)
!else
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.5} $(DESC_SecPyBindings3.5)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.6} $(DESC_SecPyBindings3.6)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.7} $(DESC_SecPyBindings3.7)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.8} $(DESC_SecPyBindings3.8)
!insertmacro MUI_DESCRIPTION_TEXT ${SecPyBindings3.9} $(DESC_SecPyBindings3.9)
!endif
!ifdef INCLUDE_PYVER
!insertmacro MUI_DESCRIPTION_TEXT ${SecPython} $(DESC_SecPython)
!endif
!insertmacro MUI_DESCRIPTION_TEXT ${SecHeadersLibs} $(DESC_SecHeadersLibs)

View File

@ -13,10 +13,6 @@ from distutils.sysconfig import get_python_lib
from optparse import OptionParser
from makepandacore import *
def python_sitepackages_path():
from distutils.sysconfig import get_python_lib
return get_python_lib(1)
PYTHON_SITEPACKAGES=python_sitepackages_path()
MIME_INFO = (
("egg", "model/x-egg", "EGG model file", "pview"),
@ -153,18 +149,11 @@ def GetLibDir():
return "lib"
def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir()):
def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir(), python_versions=[]):
if (not prefix.startswith("/")):
prefix = "/" + prefix
libdir = prefix + "/" + libdir
# Determine the location of the Python executable and site-packages dir.
PPATH = get_python_lib(1)
if os.path.islink(sys.executable):
PEXEC = os.path.join(os.path.dirname(sys.executable), os.readlink(sys.executable))
else:
PEXEC = sys.executable
# Create the directory structure that we will be putting our files in.
oscmd("mkdir -m 0755 -p "+destdir+prefix+"/bin")
oscmd("mkdir -m 0755 -p "+destdir+prefix+"/include")
@ -174,8 +163,10 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir(
oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/application-registry")
oscmd("mkdir -m 0755 -p "+destdir+prefix+"/share/applications")
oscmd("mkdir -m 0755 -p "+destdir+libdir+"/panda3d")
oscmd("mkdir -m 0755 -p "+destdir+PPATH)
oscmd("mkdir -m 0755 -p "+destdir+PPATH+"/panda3d")
for python_version in python_versions:
oscmd("mkdir -m 0755 -p "+destdir+python_version["purelib"])
oscmd("mkdir -m 0755 -p "+destdir+python_version["platlib"]+"/panda3d")
if (sys.platform.startswith("freebsd")):
oscmd("mkdir -m 0755 -p "+destdir+prefix+"/etc")
@ -201,10 +192,12 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir(
if os.path.isdir(outputdir+"/Pmw"): oscmd("cp -R "+outputdir+"/Pmw "+destdir+prefix+"/share/panda3d/")
if os.path.isdir(outputdir+"/plugins"): oscmd("cp -R "+outputdir+"/plugins "+destdir+prefix+"/share/panda3d/")
suffix = GetExtensionSuffix()
for base in os.listdir(outputdir + "/panda3d"):
if base.endswith(".py") or (base.endswith(suffix) and '.' not in base[:-len(suffix)]):
oscmd("cp "+outputdir+"/panda3d/"+base+" "+destdir+PPATH+"/panda3d/"+base)
for python_version in python_versions:
for base in os.listdir(outputdir + "/panda3d"):
suffix = python_version["ext_suffix"]
platlib = python_version["platlib"]
if base.endswith(".py") or (base.endswith(suffix) and '.' not in base[:-len(suffix)]):
oscmd("cp "+outputdir+"/panda3d/"+base+" "+destdir+platlib+"/panda3d/"+base)
WriteMimeFile(destdir+prefix+"/share/mime-info/panda3d.mime", MIME_INFO)
WriteKeysFile(destdir+prefix+"/share/mime-info/panda3d.keys", MIME_INFO)
@ -214,10 +207,14 @@ def InstallPanda(destdir="", prefix="/usr", outputdir="built", libdir=GetLibDir(
oscmd("cp makepanda/pview.desktop "+destdir+prefix+"/share/applications/pview.desktop")
oscmd("cp doc/ReleaseNotes "+destdir+prefix+"/share/panda3d/ReleaseNotes")
oscmd("echo '"+prefix+"/share/panda3d' > "+destdir+PPATH+"/panda3d.pth")
oscmd("echo '"+libdir+"/panda3d'>> "+destdir+PPATH+"/panda3d.pth")
if os.path.isdir(outputdir+"/panda3d.dist-info"):
oscmd("cp -R "+outputdir+"/panda3d.dist-info "+destdir+PPATH)
for python_version in python_versions:
pth_file = python_version["purelib"] + "/panda3d.pth"
oscmd("echo '"+prefix+"/share/panda3d' > "+destdir+pth_file)
if os.path.isdir(outputdir+"/panda3d.dist-info"):
oscmd("cp -R "+outputdir+"/panda3d.dist-info "+destdir+python_version["platlib"])
if (sys.platform.startswith("freebsd")):
oscmd("echo '"+libdir+"/panda3d'> "+destdir+"/usr/local/libdata/ldconfig/panda3d")
else:
@ -302,6 +299,8 @@ if (__name__ == "__main__"):
if (destdir != "" and not os.path.isdir(destdir)):
exit("Directory '%s' does not exist!" % destdir)
SetOutputDir(options.outputdir)
if options.verbose:
SetVerbose(True)
@ -310,6 +309,8 @@ if (__name__ == "__main__"):
InstallRuntime(destdir = destdir, prefix = options.prefix, outputdir = options.outputdir)
else:
print("Installing Panda3D SDK into " + destdir + options.prefix)
InstallPanda(destdir = destdir, prefix = options.prefix, outputdir = options.outputdir)
InstallPanda(destdir=destdir,
prefix=options.prefix,
outputdir=options.outputdir,
python_versions=ReadPythonVersionInfoFile())
print("Installation finished!")

View File

@ -16,9 +16,9 @@ Architecture: ARCH
Essential: no
Depends: DEPENDS
Recommends: RECOMMENDS
Provides: panda3d, pythonPV-panda3d
Conflicts: panda3d, pythonPV-panda3d
Replaces: panda3d, pythonPV-panda3d
Provides: PROVIDES
Conflicts: PROVIDES
Replaces: PROVIDES
Maintainer: rdb <me@rdb.name>
Installed-Size: INSTSIZE
Description: Panda3D free 3D engine SDK
@ -73,7 +73,6 @@ This package contains the SDK for development with Panda3D, install panda3d-runt
/usr/share/panda3d
/etc/ld.so.conf.d/panda3d.conf
/usr/%_lib/panda3d
""" + PYTHON_SITEPACKAGES + """
/usr/include/panda3d
"""
INSTALLER_SPEC_FILE_PVIEW = \
@ -169,17 +168,10 @@ def MakeInstallerNSIS(version, file, title, installdir, runtime=False, compresso
elif os.path.isdir(file):
shutil.rmtree(file)
if "PYTHONVERSION" in SDK:
pyver = SDK["PYTHONVERSION"][6:9]
else:
pyver = "%d.%d" % (sys.version_info[:2])
if GetTargetArch() == 'x64':
regview = '64'
else:
regview = '32'
if int(pyver[0]) == 3 and int(pyver[2]) >= 5:
pyver += '-32'
if runtime:
# Invoke the make_installer script.
@ -212,11 +204,22 @@ def MakeInstallerNSIS(version, file, title, installdir, runtime=False, compresso
'OUTFILE' : '..\\' + file,
'BUILT' : '..\\' + outputdir,
'SOURCE' : '..',
'PYVER' : pyver,
'REGVIEW' : regview,
'EXT_SUFFIX': GetExtensionSuffix(),
}
# Are we shipping a version of Python?
if os.path.isfile(os.path.join(outputdir, "python", "python.exe")):
py_dlls = glob.glob(os.path.join(outputdir, "python", "python[0-9][0-9].dll")) \
+ glob.glob(os.path.join(outputdir, "python", "python[0-9][0-9]_d.dll"))
assert py_dlls
py_dll = os.path.basename(py_dlls[0])
pyver = py_dll[6] + "." + py_dll[7]
if GetTargetArch() != 'x64':
pyver += '-32'
nsis_defs['INCLUDE_PYVER'] = pyver
if GetHost() == 'windows':
cmd = os.path.join(GetThirdpartyBase(), 'win-nsis', 'makensis') + ' /V2'
for item in nsis_defs.items():
@ -254,17 +257,28 @@ def MakeDebugSymbolArchive(zipname, dirname):
zip.close()
def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
def MakeInstallerLinux(version, debversion=None, rpmrelease=1, runtime=False,
python_versions=[], **kwargs):
outputdir = GetOutputDir()
if not runtime and not PkgSkip("PYTHON"):
if "PYTHONVERSION" in SDK:
PYTHONV = SDK["PYTHONVERSION"].rstrip('dmu')
else:
PYTHONV = "python%d.%d" % (sys.version_info[:2])
else:
PYTHONV = "python"
PV = PYTHONV.replace("python", "")
# We pack Python 2 and Python 3, if we built with support for it.
python2_ver = None
python3_ver = None
install_python_versions = []
if not runtime:
# What's the system version of Python 3?
oscmd('python3 -V > "%s/tmp/python3_version.txt"' % (outputdir))
sys_python3_ver = '.'.join(ReadFile(outputdir + "/tmp/python3_version.txt").strip().split(' ')[1].split('.')[:2])
# Check that we built with support for these.
for version_info in python_versions:
if version_info["version"] == "2.7":
python2_ver = "2.7"
install_python_versions.append(version_info)
elif version_info["version"] == sys_python3_ver:
python3_ver = sys_python3_ver
install_python_versions.append(version_info)
major_version = '.'.join(version.split('.')[:2])
if not debversion:
@ -272,7 +286,7 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
# Clean and set up a directory to install Panda3D into
oscmd("rm -rf targetroot data.tar.gz control.tar.gz panda3d.spec")
oscmd("mkdir --mode=0755 targetroot")
oscmd("mkdir -m 0755 targetroot")
dpkg_present = False
if os.path.exists("/usr/bin/dpkg-architecture") and os.path.exists("/usr/bin/dpkg-deb"):
@ -288,9 +302,12 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
# Invoke installpanda.py to install it into a temporary dir
lib_dir = GetDebLibDir()
if runtime:
InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=lib_dir)
InstallRuntime(destdir="targetroot", prefix="/usr",
outputdir=outputdir, libdir=lib_dir)
else:
InstallPanda(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=lib_dir)
InstallPanda(destdir="targetroot", prefix="/usr",
outputdir=outputdir, libdir=lib_dir,
python_versions=install_python_versions)
oscmd("chmod -R 755 targetroot/usr/share/panda3d")
oscmd("mkdir -m 0755 -p targetroot/usr/share/man/man1")
oscmd("install -m 0644 doc/man/*.1 targetroot/usr/share/man/man1/")
@ -301,9 +318,10 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
txt = RUNTIME_INSTALLER_DEB_FILE[1:]
else:
txt = INSTALLER_DEB_FILE[1:]
txt = txt.replace("VERSION", debversion).replace("ARCH", pkg_arch).replace("PV", PV).replace("MAJOR", major_version)
txt = txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") / 1024))
oscmd("mkdir --mode=0755 -p targetroot/DEBIAN")
txt = txt.replace("VERSION", debversion).replace("ARCH", pkg_arch).replace("MAJOR", major_version)
txt = txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") // 1024))
oscmd("mkdir -m 0755 -p targetroot/DEBIAN")
oscmd("cd targetroot && (find usr -type f -exec md5sum {} ;) > DEBIAN/md5sums")
if not runtime:
oscmd("cd targetroot && (find etc -type f -exec md5sum {} ;) >> DEBIAN/md5sums")
@ -337,6 +355,7 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
oscmd("cd targetroot && %(dpkg_shlibdeps)s -x%(pkg_name)s %(lib_pattern)s %(bin_pattern)s*" % locals())
depends = ReadFile("targetroot/debian/substvars").replace("shlibs:Depends=", "").strip()
recommends = ""
provides = "panda3d-runtime"
else:
pkg_name = "panda3d" + major_version
pkg_dir = "debian/panda3d" + major_version
@ -352,15 +371,29 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
# Parse the substvars files generated by dpkg-shlibdeps.
depends = ReadFile("targetroot/debian/substvars_dep").replace("shlibs:Depends=", "").strip()
recommends = ReadFile("targetroot/debian/substvars_rec").replace("shlibs:Depends=", "").strip()
if PkgSkip("PYTHON")==0:
depends += ", " + PYTHONV
recommends += ", python-wxversion, python-profiler (>= " + PV + "), python-pmw, python-tk (>= " + PV + ")"
if PkgSkip("NVIDIACG")==0:
provides = "panda3d"
if python2_ver or python3_ver:
recommends += ", python-pmw"
if python2_ver:
depends += ", python%s" % (python2_ver)
recommends += ", python-wxversion"
recommends += ", python-tk (>= %s)" % (python2_ver)
provides += ", python2-panda3d"
if python3_ver:
depends += ", python%s" % (python3_ver)
recommends += ", python3-tk (>= %s)" % (python3_ver)
provides += ", python3-panda3d"
if not PkgSkip("NVIDIACG"):
depends += ", nvidia-cg-toolkit"
# Write back the dependencies, and delete the dummy set-up.
txt = txt.replace("DEPENDS", depends.strip(', '))
txt = txt.replace("RECOMMENDS", recommends.strip(', '))
txt = txt.replace("PROVIDES", provides.strip(', '))
WriteFile("targetroot/DEBIAN/control", txt)
oscmd("rm -rf targetroot/debian")
@ -376,7 +409,9 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
if runtime:
InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=GetRPMLibDir())
else:
InstallPanda(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=GetRPMLibDir())
InstallPanda(destdir="targetroot", prefix="/usr",
outputdir=outputdir, libdir=GetRPMLibDir(),
python_versions=install_python_versions)
oscmd("chmod -R 755 targetroot/usr/share/panda3d")
oscmd("rpm -E '%_target_cpu' > "+outputdir+"/tmp/architecture.txt")
@ -392,15 +427,23 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
if not PkgSkip("PVIEW"):
txt += INSTALLER_SPEC_FILE_PVIEW
# Add the platform-specific Python directories.
dirs = set()
for version_info in install_python_versions:
dirs.add(version_info["platlib"])
dirs.add(version_info["purelib"])
for dir in dirs:
txt += dir + "\n"
# Add the binaries in /usr/bin explicitly to the spec file
for base in os.listdir(outputdir + "/bin"):
txt += "/usr/bin/%s\n" % (base)
# Write out the spec file.
txt = txt.replace("VERSION", version)
txt = txt.replace("RPMRELEASE", rpmrelease)
txt = txt.replace("RPMRELEASE", str(rpmrelease))
txt = txt.replace("PANDASOURCE", pandasource)
txt = txt.replace("PV", PV)
WriteFile("panda3d.spec", txt)
oscmd("fakeroot rpmbuild --define '_rpmdir "+pandasource+"' --buildroot '"+os.path.abspath("targetroot")+"' -bb panda3d.spec")
@ -414,7 +457,7 @@ def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs):
exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!")
def MakeInstallerOSX(version, runtime=False, **kwargs):
def MakeInstallerOSX(version, runtime=False, python_versions=[], **kwargs):
outputdir = GetOutputDir()
if runtime:
@ -428,17 +471,11 @@ def MakeInstallerOSX(version, runtime=False, **kwargs):
oscmd(cmdstr)
return
if "PYTHONVERSION" in SDK:
pyver = SDK["PYTHONVERSION"][6:9]
else:
pyver = "%d.%d" % (sys.version_info[:2])
dmg_name = "Panda3D-" + version
if not pyver.startswith("2."):
if len(python_versions) == 1 and not python_versions[0]["version"].startswith("2."):
dmg_name += "-py" + pyver
dmg_name += ".dmg"
import compileall
if (os.path.isfile(dmg_name)): oscmd("rm -f %s" % dmg_name)
if (os.path.exists("dstroot")): oscmd("rm -rf dstroot")
if (os.path.exists("Panda3D-rw.dmg")): oscmd('rm -f Panda3D-rw.dmg')
@ -479,33 +516,43 @@ def MakeInstallerOSX(version, runtime=False, **kwargs):
# OSX needs the -R argument to copy symbolic links correctly, it doesn't have -d. How weird.
oscmd("cp -R " + outputdir + "/bin/" + base + " " + binname)
if not PkgSkip("PYTHON"):
pyexec = SDK.get("PYTHONEXEC", sys.executable)
oscmd("mkdir -p dstroot/pythoncode/usr/local/bin")
if python_versions:
# Let's only write a ppython link if there is only one Python version.
if len(python_versions) == 1:
oscmd("mkdir -p dstroot/pythoncode/usr/local/bin")
oscmd("ln -s %s dstroot/pythoncode/usr/local/bin/ppython" % (python_versions[0]["executable"]))
oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/panda3d")
oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % pyver)
WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % pyver, "/Developer/Panda3D")
oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % outputdir)
oscmd("cp -R %s/direct dstroot/pythoncode/Developer/Panda3D/direct" % outputdir)
oscmd("ln -s %s dstroot/pythoncode/usr/local/bin/ppython" % pyexec)
oscmd("cp -R %s/*.so dstroot/pythoncode/Developer/Panda3D/" % outputdir, True)
oscmd("cp -R %s/*.py dstroot/pythoncode/Developer/Panda3D/" % outputdir, True)
if os.path.isdir(outputdir+"/Pmw"):
oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % outputdir)
compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/Pmw")
WriteFile("dstroot/pythoncode/Developer/Panda3D/direct/__init__.py", "")
for base in os.listdir("dstroot/pythoncode/Developer/Panda3D/direct"):
if ((base != "extensions") and (base != "extensions_native")):
compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/direct/"+base)
suffix = GetExtensionSuffix()
for base in os.listdir(outputdir+"/panda3d"):
if base.endswith('.py') or (base.endswith(suffix) and '.' not in base[:-len(suffix)]):
if base.endswith('.py'):
libname = "dstroot/pythoncode/Developer/Panda3D/panda3d/" + base
oscmd("cp -R " + outputdir + "/panda3d/" + base + " " + libname)
for version_info in python_versions:
pyver = version_info["version"]
oscmd("mkdir -p dstroot/pybindings%s/Library/Python/%s/site-packages" % (pyver, pyver))
oscmd("mkdir -p dstroot/pybindings%s/Developer/Panda3D/panda3d" % (pyver))
# Copy over extension modules.
suffix = version_info["ext_suffix"]
for base in os.listdir(outputdir+"/panda3d"):
if base.endswith(suffix) and '.' not in base[:-len(suffix)]:
libname = "dstroot/pybindings%s/Developer/Panda3D/panda3d/%s" % (pyver, base)
# We really need to specify -R in order not to follow symlinks
# On OSX, just specifying -P is not enough to do that.
oscmd("cp -R -P " + outputdir + "/panda3d/" + base + " " + libname)
# Write a .pth file.
oscmd("mkdir -p dstroot/pybindings%s/Library/Python/%s/site-packages" % (pyver, pyver))
WriteFile("dstroot/pybindings%s/Library/Python/%s/site-packages/Panda3D.pth" % (pyver, pyver), "/Developer/Panda3D")
if not PkgSkip("FFMPEG"):
oscmd("mkdir -p dstroot/ffmpeg/Developer/Panda3D/lib")
oscmd("cp -R %s/lib/libp3ffmpeg.* dstroot/ffmpeg/Developer/Panda3D/lib/" % outputdir)
@ -528,9 +575,19 @@ def MakeInstallerOSX(version, runtime=False, **kwargs):
oscmd("mkdir -p dstroot/samples/Developer/Examples/Panda3D")
oscmd("cp -R samples/* dstroot/samples/Developer/Examples/Panda3D/")
oscmd("chmod -R 0775 dstroot/*")
DeleteVCS("dstroot")
DeleteBuildFiles("dstroot")
# Compile Python files. Do this *after* the DeleteVCS step, above, which
# deletes __pycache__ directories.
for version_info in python_versions:
if os.path.isdir("dstroot/pythoncode/Developer/Panda3D/Pmw"):
oscmd("%s -m compileall -q -f -d /Developer/Panda3D/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % (version_info["executable"]), True)
oscmd("%s -m compileall -q -f -d /Developer/Panda3D/direct dstroot/pythoncode/Developer/Panda3D/direct" % (version_info["executable"]))
oscmd("%s -m compileall -q -f -d /Developer/Panda3D/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % (version_info["executable"]))
oscmd("%s -m compileall -q -f -d /Developer/Panda3D/panda3d dstroot/pythoncode/Developer/Panda3D/panda3d" % (version_info["executable"]))
oscmd("chmod -R 0775 dstroot/*")
# We need to be root to perform a chown. Bleh.
# Fortunately PackageMaker does it for us, on 10.5 and above.
#oscmd("chown -R root:admin dstroot/*", True)
@ -539,7 +596,10 @@ def MakeInstallerOSX(version, runtime=False, **kwargs):
oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Resources/en.lproj/")
pkgs = ["base", "tools", "headers"]
if not PkgSkip("PYTHON"): pkgs.append("pythoncode")
if python_versions:
pkgs.append("pythoncode")
for version_info in python_versions:
pkgs.append("pybindings" + version_info["version"])
if not PkgSkip("FFMPEG"): pkgs.append("ffmpeg")
#if not PkgSkip("OPENAL"): pkgs.append("openal")
if not PkgSkip("FMODEX"): pkgs.append("fmodex")
@ -581,22 +641,55 @@ def MakeInstallerOSX(version, runtime=False, **kwargs):
dist.write(' <title>Panda3D SDK %s</title>\n' % (version))
dist.write(' <options customize="always" allow-external-scripts="no" rootVolumeOnly="false"/>\n')
dist.write(' <license language="en" mime-type="text/plain">%s</license>\n' % ReadFile("doc/LICENSE"))
dist.write(' <script>\n')
dist.write(' function isPythonVersionInstalled(version) {\n')
dist.write(' return system.files.fileExistsAtPath("/usr/bin/python" + version)\n')
dist.write(' || system.files.fileExistsAtPath("/usr/local/bin/python" + version)\n')
dist.write(' || system.files.fileExistsAtPath("/opt/local/bin/python" + version)\n')
dist.write(' || system.files.fileExistsAtPath("/sw/bin/python" + version)\n')
dist.write(' || system.files.fileExistsAtPath("/System/Library/Frameworks/Python.framework/Versions/" + version + "/bin/python")\n')
dist.write(' || system.files.fileExistsAtPath("/Library/Frameworks/Python.framework/Versions/" + version + "/bin/python");\n')
dist.write(' }\n')
dist.write(' </script>\n')
dist.write(' <choices-outline>\n')
for pkg in pkgs:
dist.write(' <line choice="%s"/>\n' % (pkg))
dist.write(' <line choice="base"/>\n')
if python_versions:
dist.write(' <line choice="pythoncode">\n')
for version_info in sorted(python_versions, key=lambda info:info["version"], reverse=True):
dist.write(' <line choice="pybindings%s"/>\n' % (version_info["version"]))
dist.write(' </line>\n')
dist.write(' <line choice="tools"/>\n')
if os.path.isdir("samples"):
dist.write(' <line choice="samples"/>\n')
if not PkgSkip("FFMPEG"):
dist.write(' <line choice="ffmpeg"/>\n')
if not PkgSkip("FMODEX"):
dist.write(' <line choice="fmodex"/>\n')
dist.write(' <line choice="headers"/>\n')
dist.write(' </choices-outline>\n')
dist.write(' <choice id="base" title="Panda3D Base Installation" description="This package contains the Panda3D libraries, configuration files and models/textures that are needed to use Panda3D. Location: /Developer/Panda3D/" start_enabled="false">\n')
dist.write(' <choice id="base" title="Panda3D Base Installation" description="This package contains the Panda3D libraries, configuration files and models/textures that are needed to use Panda3D.&#10;&#10;Location: /Developer/Panda3D/" start_enabled="false">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.base.pkg"/>\n')
dist.write(' </choice>\n')
dist.write(' <choice id="tools" title="Tools" tooltip="Useful tools and model converters to help with Panda3D development" description="This package contains the various utilities that ship with Panda3D, including packaging tools, model converters, and many more. Location: /Developer/Panda3D/bin/">\n')
dist.write(' <choice id="tools" title="Tools" tooltip="Useful tools and model converters to help with Panda3D development" description="This package contains the various utilities that ship with Panda3D, including packaging tools, model converters, and many more.&#10;&#10;Location: /Developer/Panda3D/bin/">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.tools.pkg"/>\n')
dist.write(' </choice>\n')
if not PkgSkip("PYTHON"):
dist.write(' <choice id="pythoncode" title="Python Support" tooltip="Python bindings for the Panda3D libraries" description="This package contains the \'direct\', \'pandac\' and \'panda3d\' python packages that are needed to do Python development with Panda3D. Location: /Developer/Panda3D/">\n')
if python_versions:
dist.write(' <choice id="pythoncode" title="Python Support" tooltip="Python bindings for the Panda3D libraries" description="This package contains the \'direct\', \'pandac\' and \'panda3d\' python packages that are needed to do Python development with Panda3D.&#10;&#10;Location: /Developer/Panda3D/">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg"/>\n')
dist.write(' </choice>\n')
for version_info in python_versions:
pyver = version_info["version"]
if pyver == "2.7":
# Always install Python 2.7 by default; it's included on macOS.
cond = "true"
else:
cond = "isPythonVersionInstalled('%s')" % (pyver)
dist.write(' <choice id="pybindings%s" start_selected="%s" title="Python %s Bindings" tooltip="Python bindings for the Panda3D libraries" description="Support for Python %s.">\n' % (pyver, cond, pyver, pyver))
dist.write(' <pkg-ref id="org.panda3d.panda3d.pybindings%s.pkg"/>\n' % (pyver))
dist.write(' </choice>\n')
if not PkgSkip("FFMPEG"):
dist.write(' <choice id="ffmpeg" title="FFMpeg Plug-In" tooltip="FFMpeg video and audio decoding plug-in" description="This package contains the FFMpeg plug-in, which is used for decoding video and audio files with OpenAL.')
if PkgSkip("VORBIS") and PkgSkip("OPUS"):
@ -621,11 +714,11 @@ def MakeInstallerOSX(version, runtime=False, **kwargs):
dist.write(' </choice>\n')
if os.path.isdir("samples"):
dist.write(' <choice id="samples" title="Sample Programs" tooltip="Python sample programs that use Panda3D" description="This package contains the Python sample programs that can help you with learning how to use Panda3D. Location: /Developer/Examples/Panda3D/">\n')
dist.write(' <choice id="samples" title="Sample Programs" tooltip="Python sample programs that use Panda3D" description="This package contains the Python sample programs that can help you with learning how to use Panda3D.&#10;&#10;Location: /Developer/Examples/Panda3D/">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.samples.pkg"/>\n')
dist.write(' </choice>\n')
dist.write(' <choice id="headers" title="C++ Header Files" tooltip="Header files for C++ development with Panda3D" description="This package contains the C++ header files that are needed in order to do C++ development with Panda3D. You don\'t need this if you want to develop in Python. Location: /Developer/Panda3D/include/" start_selected="false">\n')
dist.write(' <choice id="headers" title="C++ Header Files" tooltip="Header files for C++ development with Panda3D" description="This package contains the C++ header files that are needed in order to do C++ development with Panda3D. You don\'t need this if you want to develop in Python.&#10;&#10;Location: /Developer/Panda3D/include/" start_selected="false">\n')
dist.write(' <pkg-ref id="org.panda3d.panda3d.headers.pkg"/>\n')
dist.write(' </choice>\n')
for pkg in pkgs:
@ -693,7 +786,7 @@ def MakeInstallerFreeBSD(version, runtime=False, **kwargs):
manifest_txt = manifest_txt.replace("ARCH", pkg_arch)
manifest_txt = manifest_txt.replace("ORIGIN", 'devel/panda3d' if not runtime else 'graphics/panda3d-runtime')
manifest_txt = manifest_txt.replace("DEPENDS", dependencies)
manifest_txt = manifest_txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") / 1024 / 1024))
manifest_txt = manifest_txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") // 1024 // 1024))
WriteFile("pkg-plist", plist_txt)
WriteFile("+DESC", INSTALLER_PKG_DESCR_FILE[1:] if not runtime else RUNTIME_INSTALLER_PKG_DESCR_FILE[1:])
@ -889,13 +982,9 @@ def MakeInstaller(version, **kwargs):
fn += version
if "PYTHONVERSION" in SDK:
pyver = SDK["PYTHONVERSION"][6:9]
else:
pyver = "%d.%d" % (sys.version_info[:2])
if not runtime and pyver != "2.7":
fn += '-py' + pyver
python_versions = kwargs.get('python_versions', [])
if not runtime and len(python_versions) == 1 and python_versions[0]["version"] != "2.7":
fn += '-py' + python_versions[0]["version"]
if GetOptimize() <= 2:
fn += "-dbg"
@ -961,4 +1050,5 @@ if __name__ == "__main__":
compressor=options.compressor,
debversion=options.debversion,
rpmrelease=options.rpmrelease,
runtime=options.runtime)
runtime=options.runtime,
python_versions=ReadPythonVersionInfoFile())

View File

@ -72,6 +72,7 @@ MSVC_VERSION = None
BOOUSEINTELCOMPILER = False
OPENCV_VER_23 = False
PLATFORM = None
COPY_PYTHON = True
if "MACOSX_DEPLOYMENT_TARGET" in os.environ:
OSXTARGET=os.environ["MACOSX_DEPLOYMENT_TARGET"]
@ -172,6 +173,7 @@ def parseopts(args):
global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL
global DEBVERSION,WHLVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION
global STRDXSDKVERSION, WINDOWS_SDK, MSVC_VERSION, BOOUSEINTELCOMPILER
global COPY_PYTHON
# Options for which to display a deprecation warning.
removedopts = [
@ -185,7 +187,7 @@ def parseopts(args):
"version=","lzma","no-python","threads=","outputdir=","override=",
"static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=",
"directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl",
"universal", "target=", "arch=", "git-commit=",
"universal", "target=", "arch=", "git-commit=", "no-copy-python",
] + removedopts
anything = 0
@ -251,6 +253,7 @@ def parseopts(args):
MSVC_VERSION = value.strip().lower()
elif (option=="--use-icl"): BOOUSEINTELCOMPILER = True
elif (option=="--clean"): clean_build = True
elif (option=="--no-copy-python"): COPY_PYTHON = False
elif (option[2:] in removedopts):
Warn("Ignoring removed option %s" % (option))
else:
@ -3031,7 +3034,7 @@ else:
configprc = configprc.replace("aux-display pandadx9", "")
if (GetTarget() == 'darwin'):
configprc = configprc.replace("$XDG_CACHE_HOME/panda3d", "Library/Caches/Panda3D-%s" % MAJOR_VERSION)
configprc = configprc.replace("$XDG_CACHE_HOME/panda3d", "$HOME/Library/Caches/Panda3D-%s" % MAJOR_VERSION)
# OpenAL is not yet working well on OSX for us, so let's do this for now.
configprc = configprc.replace("p3openal_audio", "p3fmod_audio")
@ -3155,7 +3158,8 @@ if tp_dir is not None:
CopyFile(GetOutputDir() + "/bin/", fn)
# Copy the whole Python directory.
CopyTree(GetOutputDir() + "/python", SDK["PYTHON"])
if COPY_PYTHON:
CopyTree(GetOutputDir() + "/python", SDK["PYTHON"])
# NB: Python does not always ship with the correct manifest/dll.
# Figure out the correct one to ship, and grab it from WinSxS dir.
@ -3164,7 +3168,7 @@ if tp_dir is not None:
os.unlink(manifest)
oscmd('mt -inputresource:"%s\\python.exe";#1 -out:"%s" -nologo' % (SDK["PYTHON"], manifest), True)
if os.path.isfile(manifest):
if COPY_PYTHON and os.path.isfile(manifest):
import xml.etree.ElementTree as ET
tree = ET.parse(manifest)
idents = tree.findall('./{urn:schemas-microsoft-com:asm.v1}dependency/{urn:schemas-microsoft-com:asm.v1}dependentAssembly/{urn:schemas-microsoft-com:asm.v1}assemblyIdentity')
@ -3194,11 +3198,12 @@ if tp_dir is not None:
CopyFile(GetOutputDir() + "/python/", file)
# Copy python.exe to ppython.exe.
if not os.path.isfile(SDK["PYTHON"] + "/ppython.exe") and os.path.isfile(SDK["PYTHON"] + "/python.exe"):
CopyFile(GetOutputDir() + "/python/ppython.exe", SDK["PYTHON"] + "/python.exe")
if not os.path.isfile(SDK["PYTHON"] + "/ppythonw.exe") and os.path.isfile(SDK["PYTHON"] + "/pythonw.exe"):
CopyFile(GetOutputDir() + "/python/ppythonw.exe", SDK["PYTHON"] + "/pythonw.exe")
ConditionalWriteFile(GetOutputDir() + "/python/panda.pth", "..\n../bin\n")
if COPY_PYTHON:
if not os.path.isfile(SDK["PYTHON"] + "/ppython.exe") and os.path.isfile(SDK["PYTHON"] + "/python.exe"):
CopyFile(GetOutputDir() + "/python/ppython.exe", SDK["PYTHON"] + "/python.exe")
if not os.path.isfile(SDK["PYTHON"] + "/ppythonw.exe") and os.path.isfile(SDK["PYTHON"] + "/pythonw.exe"):
CopyFile(GetOutputDir() + "/python/ppythonw.exe", SDK["PYTHON"] + "/pythonw.exe")
ConditionalWriteFile(GetOutputDir() + "/python/panda.pth", "..\n../bin\n")
# Copy over the MSVC runtime.
if GetTarget() == 'windows' and "VISUALSTUDIO" in SDK:
@ -6869,6 +6874,10 @@ if RUNTESTS:
cmdstr += " --verbose"
oscmd(cmdstr)
# Write out information about the Python versions in the built dir.
python_version_info = GetCurrentPythonVersionInfo()
UpdatePythonVersionInfoFile(python_version_info)
##########################################################################################
#
# The Installers
@ -6882,10 +6891,16 @@ if RUNTESTS:
if INSTALLER:
ProgressOutput(100.0, "Building installer")
from makepackage import MakeInstaller
# When using the --installer flag, only install for the current version.
python_versions = []
if python_version_info:
python_versions.append(python_version_info)
MakeInstaller(version=VERSION, outputdir=GetOutputDir(),
optimize=GetOptimize(), compressor=COMPRESSOR,
debversion=DEBVERSION, rpmrelease=RPMRELEASE,
runtime=RUNTIME)
runtime=RUNTIME, python_versions=python_versions)
if WHEEL:
ProgressOutput(100.0, "Building wheel")

View File

@ -1043,7 +1043,7 @@
<File RelativePath="..\panda\src\collide\collisionLine.I"></File>
<File RelativePath="..\panda\src\collide\collisionHandlerFluidPusher.h"></File>
<File RelativePath="..\panda\src\collide\config_collide.h"></File>
<File RelativePath="..\panda\src\collide\collisionTube.h"></File>
<File RelativePath="..\panda\src\collide\collisionCapsule.h"></File>
<File RelativePath="..\panda\src\collide\collisionSegment.cxx"></File>
<File RelativePath="..\panda\src\collide\collisionBox.h"></File>
<File RelativePath="..\panda\src\collide\collide_composite1.cxx"></File>
@ -1054,7 +1054,7 @@
<File RelativePath="..\panda\src\collide\collisionNode.h"></File>
<File RelativePath="..\panda\src\collide\collisionGeom.I"></File>
<File RelativePath="..\panda\src\collide\collisionSegment.I"></File>
<File RelativePath="..\panda\src\collide\collisionTube.cxx"></File>
<File RelativePath="..\panda\src\collide\collisionCapsule.cxx"></File>
<File RelativePath="..\panda\src\collide\collisionHandlerQueue.h"></File>
<File RelativePath="..\panda\src\collide\collisionParabola.I"></File>
<File RelativePath="..\panda\src\collide\collisionPlane.cxx"></File>
@ -1089,7 +1089,7 @@
<File RelativePath="..\panda\src\collide\collisionInvSphere.cxx"></File>
<File RelativePath="..\panda\src\collide\collisionLine.cxx"></File>
<File RelativePath="..\panda\src\collide\collisionEntry.I"></File>
<File RelativePath="..\panda\src\collide\collisionTube.I"></File>
<File RelativePath="..\panda\src\collide\collisionCapsule.I"></File>
<File RelativePath="..\panda\src\collide\collisionSolid.h"></File>
<File RelativePath="..\panda\src\collide\collisionPlane.I"></File>
<File RelativePath="..\panda\src\collide\collisionHandlerGravity.cxx"></File>

View File

@ -3383,6 +3383,71 @@ def FindLocation(fn, ipath, pyabi=None):
ORIG_EXT[loc] = ext
return loc
########################################################################
##
## These files maintain a python_versions.json file in the built/tmp
## directory that can be used by the other scripts in this directory.
##
########################################################################
def GetCurrentPythonVersionInfo():
if PkgSkip("PYTHON"):
return
from distutils.sysconfig import get_python_lib
return {
"version": SDK["PYTHONVERSION"][6:9],
"soabi": GetPythonABI(),
"ext_suffix": GetExtensionSuffix(),
"executable": sys.executable,
"purelib": get_python_lib(False),
"platlib": get_python_lib(True),
}
def UpdatePythonVersionInfoFile(new_info):
import json
json_file = os.path.join(GetOutputDir(), "tmp", "python_versions.json")
json_data = []
if os.path.isfile(json_file) and not PkgSkip("PYTHON"):
try:
json_data = json.load(open(json_file, 'r'))
except:
json_data = []
# Prune the list by removing the entries that conflict with our build,
# plus the entries that no longer exist
for version_info in json_data[:]:
core_pyd = os.path.join(GetOutputDir(), "panda3d", "core" + version_info["ext_suffix"])
if version_info["ext_suffix"] == new_info["ext_suffix"] or \
version_info["soabi"] == new_info["soabi"] or \
not os.path.isfile(core_pyd):
json_data.remove(version_info)
if not PkgSkip("PYTHON"):
json_data.append(new_info)
if VERBOSE:
print("Writing %s" % (json_file))
json.dump(json_data, open(json_file, 'w'), indent=4)
def ReadPythonVersionInfoFile():
import json
json_file = os.path.join(GetOutputDir(), "tmp", "python_versions.json")
if os.path.isfile(json_file):
try:
return json.load(open(json_file, 'r'))
except:
pass
return []
########################################################################
##
## TargetAdd

View File

@ -28,7 +28,7 @@
#include "collisionPlane.h"
#include "collisionSphere.h"
#include "collisionPolygon.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
TypeHandle BulletBodyNode::_type_handle;
@ -813,12 +813,12 @@ add_shapes_from_collision_solids(CollisionNode *cnode) {
do_add_shape(BulletBoxShape::make_from_solid(box), ts);
}
// CollisionTube
else if (CollisionTube::get_class_type() == type) {
CPT(CollisionTube) tube = DCAST(CollisionTube, solid);
CPT(TransformState) ts = TransformState::make_pos((tube->get_point_b() + tube->get_point_a()) / 2.0);
// CollisionCapsule
else if (CollisionCapsule::get_class_type() == type) {
CPT(CollisionCapsule) capsule = DCAST(CollisionCapsule, solid);
CPT(TransformState) ts = TransformState::make_pos((capsule->get_point_b() + capsule->get_point_a()) / 2.0);
do_add_shape(BulletCapsuleShape::make_from_solid(tube), ts);
do_add_shape(BulletCapsuleShape::make_from_solid(capsule), ts);
}
// CollisionPlane

View File

@ -87,16 +87,16 @@ ptr() const {
/**
* Constructs a new BulletCapsuleShape using the information from a
* CollisionTube from the builtin collision system.
* CollisionCapsule from the builtin collision system.
*/
BulletCapsuleShape *BulletCapsuleShape::
make_from_solid(const CollisionTube *solid) {
make_from_solid(const CollisionCapsule *solid) {
PN_stdfloat radius = solid->get_radius();
// Get tube's cylinder height: length from point A to point B
// Get capsule's cylinder height: length from point A to point B
PN_stdfloat height = (solid->get_point_b() - solid->get_point_a()).length();
// CollisionTubes are always Z-Up.
// CollisionCapsules are always Z-Up.
return new BulletCapsuleShape(radius, height, Z_up);
}

View File

@ -20,7 +20,7 @@
#include "bullet_utils.h"
#include "bulletShape.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
/**
*
@ -35,7 +35,7 @@ PUBLISHED:
BulletCapsuleShape(const BulletCapsuleShape &copy);
INLINE ~BulletCapsuleShape();
static BulletCapsuleShape *make_from_solid(const CollisionTube *solid);
static BulletCapsuleShape *make_from_solid(const CollisionCapsule *solid);
INLINE PN_stdfloat get_radius() const;
INLINE PN_stdfloat get_half_height() const;

View File

@ -20,6 +20,7 @@
#import <AppKit/NSOpenGL.h>
#import <OpenGL/OpenGL.h>
#import <CoreVideo/CoreVideo.h>
/**
* A tiny specialization on GLGraphicsStateGuardian to add some Cocoa-specific
@ -38,14 +39,21 @@ public:
CocoaGraphicsStateGuardian *share_with);
virtual ~CocoaGraphicsStateGuardian();
bool setup_vsync();
INLINE void lock_context();
INLINE void unlock_context();
NSOpenGLContext *_share_context;
NSOpenGLContext *_context;
NSOpenGLPixelFormat *_format = nullptr;
FrameBufferProperties _fbprops;
CVDisplayLinkRef _display_link = nullptr;
TrueMutexImpl _swap_lock;
TrueConditionVarImpl _swap_condition;
AtomicAdjust::Integer _last_wait_frame = 0;
protected:
virtual void query_gl_version();
virtual void *do_get_extension_func(const char *name);

View File

@ -28,6 +28,21 @@
#define NSAppKitVersionNumber10_7 1138
#endif
/**
* Called whenever a display wants a frame. The context argument contains the
* applicable CocoaGraphicsStateGuardian.
*/
static CVReturn
display_link_cb(CVDisplayLinkRef link, const CVTimeStamp *now,
const CVTimeStamp* output_time, CVOptionFlags flags_in,
CVOptionFlags *flags_out, void *context) {
CocoaGraphicsStateGuardian *gsg = (CocoaGraphicsStateGuardian *)context;
gsg->_swap_lock.lock();
gsg->_swap_condition.notify();
gsg->_swap_lock.unlock();
return kCVReturnSuccess;
}
TypeHandle CocoaGraphicsStateGuardian::_type_handle;
/**
@ -36,7 +51,8 @@ TypeHandle CocoaGraphicsStateGuardian::_type_handle;
CocoaGraphicsStateGuardian::
CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
CocoaGraphicsStateGuardian *share_with) :
GLGraphicsStateGuardian(engine, pipe)
GLGraphicsStateGuardian(engine, pipe),
_swap_condition(_swap_lock)
{
_share_context = nil;
_context = nil;
@ -52,12 +68,60 @@ CocoaGraphicsStateGuardian(GraphicsEngine *engine, GraphicsPipe *pipe,
*/
CocoaGraphicsStateGuardian::
~CocoaGraphicsStateGuardian() {
if (_format != nil) {
[_format release];
}
if (_display_link != nil) {
CVDisplayLinkRelease(_display_link);
_display_link = nil;
_swap_lock.lock();
_swap_condition.notify();
_swap_lock.unlock();
}
if (_context != nil) {
[_context clearDrawable];
[_context release];
}
}
/**
* Creates a CVDisplayLink, which tells us when the display the window is on
* will want a frame.
*/
bool CocoaGraphicsStateGuardian::
setup_vsync() {
if (_display_link != nil) {
// Already set up.
return true;
}
CVReturn result = CVDisplayLinkCreateWithActiveCGDisplays(&_display_link);
if (result != kCVReturnSuccess) {
cocoadisplay_cat.error() << "Failed to create CVDisplayLink.\n";
return false;
}
result = CVDisplayLinkSetCurrentCGDisplayFromOpenGLContext(_display_link, (CGLContextObj)[_context CGLContextObj], (CGLPixelFormatObj)[_format CGLPixelFormatObj]);
if (result != kCVReturnSuccess) {
cocoadisplay_cat.error() << "Failed to set CVDisplayLink's current display.\n";
return false;
}
result = CVDisplayLinkSetOutputCallback(_display_link, &display_link_cb, this);
if (result != kCVReturnSuccess) {
cocoadisplay_cat.error() << "Failed to set CVDisplayLink output callback.\n";
return false;
}
result = CVDisplayLinkStart(_display_link);
if (result != kCVReturnSuccess) {
cocoadisplay_cat.error() << "Failed to start the CVDisplayLink.\n";
return false;
}
return true;
}
/**
* Gets the FrameBufferProperties to match the indicated config.
*/
@ -262,15 +326,15 @@ choose_pixel_format(const FrameBufferProperties &properties,
// TODO: print out renderer
_context = [[NSOpenGLContext alloc] initWithFormat:format shareContext:_share_context];
[format release];
_format = format;
if (_context == nil) {
cocoadisplay_cat.error() <<
"Failed to create OpenGL context!\n";
return;
}
// Set vsync setting on the context
GLint swap = sync_video ? 1 : 0;
// Disable vsync via the built-in mechanism, which doesn't work on Mojave
GLint swap = 0;
[_context setValues:&swap forParameter:NSOpenGLCPSwapInterval];
cocoadisplay_cat.debug()

View File

@ -23,6 +23,8 @@
#import <AppKit/NSView.h>
#import <AppKit/NSWindow.h>
#import <CoreVideo/CoreVideo.h>
/**
* An interface to the Cocoa system for managing OpenGL windows under Mac OS
* X.
@ -92,6 +94,7 @@ private:
PT(GraphicsWindowInputDevice) _input;
bool _mouse_hidden;
bool _context_needs_update;
bool _vsync_enabled = false;
#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1060
CGDisplayModeRef _fullscreen_mode;

View File

@ -274,6 +274,15 @@ end_flip() {
CocoaGraphicsStateGuardian *cocoagsg;
DCAST_INTO_V(cocoagsg, _gsg);
if (_vsync_enabled) {
AtomicAdjust::Integer cur_frame = ClockObject::get_global_clock()->get_frame_count();
if (AtomicAdjust::set(cocoagsg->_last_wait_frame, cur_frame) != cur_frame) {
cocoagsg->_swap_lock.lock();
cocoagsg->_swap_condition.wait();
cocoagsg->_swap_lock.unlock();
}
}
cocoagsg->lock_context();
// Swap the front and back buffer.
@ -669,6 +678,8 @@ open_window() {
mouse_mode_relative();
}
_vsync_enabled = sync_video && cocoagsg->setup_vsync();
return true;
}
@ -710,6 +721,8 @@ close_window() {
_view = nil;
}
_vsync_enabled = false;
GraphicsWindow::close_window();
}
@ -1491,6 +1504,7 @@ handle_close_event() {
cocoagsg->unlock_context();
}
_gsg.clear();
_vsync_enabled = false;
}
// Dump the view, too

View File

@ -16,7 +16,7 @@
#include "collisionRay.h"
#include "collisionSphere.h"
#include "collisionSegment.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "collisionHandler.h"
#include "collisionEntry.h"
#include "config_collide.h"
@ -547,19 +547,19 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
}
/**
* Double dispatch point for tube as a FROM object
* Double dispatch point for capsule as a FROM object
*/
PT(CollisionEntry) CollisionBox::
test_intersection_from_tube(const CollisionEntry &entry) const {
const CollisionTube *tube;
DCAST_INTO_R(tube, entry.get_from(), nullptr);
test_intersection_from_capsule(const CollisionEntry &entry) const {
const CollisionCapsule *capsule;
DCAST_INTO_R(capsule, entry.get_from(), nullptr);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
LPoint3 from_a = tube->get_point_a() * wrt_mat;
LPoint3 from_b = tube->get_point_b() * wrt_mat;
LPoint3 from_a = capsule->get_point_a() * wrt_mat;
LPoint3 from_b = capsule->get_point_b() * wrt_mat;
LVector3 from_direction = from_b - from_a;
PN_stdfloat radius_sq = wrt_mat.xform_vec(LVector3(0, 0, tube->get_radius())).length_squared();
PN_stdfloat radius_sq = wrt_mat.xform_vec(LVector3(0, 0, capsule->get_radius())).length_squared();
PN_stdfloat radius = csqrt(radius_sq);
LPoint3 box_min = get_min();
@ -620,7 +620,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
LVector3 delta(0);
delta[edges[i].axis] = dimensions[edges[i].axis];
double u1, u2;
CollisionTube::calc_closest_segment_points(u1, u2, from_a, from_direction, vertex, delta);
CollisionCapsule::calc_closest_segment_points(u1, u2, from_a, from_direction, vertex, delta);
PN_stdfloat dist_sq = ((from_a + from_direction * u1) - (vertex + delta * u2)).length_squared();
if (dist_sq < best_dist_sq) {
best_dist_sq = dist_sq;
@ -682,7 +682,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
new_entry->set_interior_point(point - interior_vec * radius);
new_entry->set_surface_point(surface_point);
if (has_effective_normal() && tube->get_respect_effective_normal()) {
if (has_effective_normal() && capsule->get_respect_effective_normal()) {
new_entry->set_surface_normal(get_effective_normal());
} else {
new_entry->set_surface_normal(normal);

View File

@ -82,7 +82,7 @@ protected:
virtual PT(CollisionEntry)
test_intersection_from_segment(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_tube(const CollisionEntry &entry) const;
test_intersection_from_capsule(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_box(const CollisionEntry &entry) const;

View File

@ -6,7 +6,7 @@
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file collisionTube.I
* @file collisionCapsule.I
* @author drose
* @date 2003-09-25
*/
@ -14,8 +14,8 @@
/**
*
*/
INLINE CollisionTube::
CollisionTube(const LPoint3 &a, const LPoint3 &b, PN_stdfloat radius) :
INLINE CollisionCapsule::
CollisionCapsule(const LPoint3 &a, const LPoint3 &b, PN_stdfloat radius) :
_a(a), _b(b), _radius(radius)
{
recalc_internals();
@ -25,8 +25,8 @@ CollisionTube(const LPoint3 &a, const LPoint3 &b, PN_stdfloat radius) :
/**
*
*/
INLINE CollisionTube::
CollisionTube(PN_stdfloat ax, PN_stdfloat ay, PN_stdfloat az,
INLINE CollisionCapsule::
CollisionCapsule(PN_stdfloat ax, PN_stdfloat ay, PN_stdfloat az,
PN_stdfloat bx, PN_stdfloat by, PN_stdfloat bz,
PN_stdfloat radius) :
_a(ax, ay, az), _b(bx, by, bz), _radius(radius)
@ -36,17 +36,17 @@ CollisionTube(PN_stdfloat ax, PN_stdfloat ay, PN_stdfloat az,
}
/**
* Creates an invalid tube. Only used when reading from a bam file.
* Creates an invalid capsule. Only used when reading from a bam file.
*/
INLINE CollisionTube::
CollisionTube() {
INLINE CollisionCapsule::
CollisionCapsule() {
}
/**
*
*/
INLINE CollisionTube::
CollisionTube(const CollisionTube &copy) :
INLINE CollisionCapsule::
CollisionCapsule(const CollisionCapsule &copy) :
CollisionSolid(copy),
_a(copy._a),
_b(copy._b),
@ -58,7 +58,7 @@ CollisionTube(const CollisionTube &copy) :
/**
* Flushes the PStatCollectors used during traversal.
*/
INLINE void CollisionTube::
INLINE void CollisionCapsule::
flush_level() {
_volume_pcollector.flush_level();
_test_pcollector.flush_level();
@ -67,7 +67,7 @@ flush_level() {
/**
*
*/
INLINE void CollisionTube::
INLINE void CollisionCapsule::
set_point_a(const LPoint3 &a) {
_a = a;
recalc_internals();
@ -76,7 +76,7 @@ set_point_a(const LPoint3 &a) {
/**
*
*/
INLINE void CollisionTube::
INLINE void CollisionCapsule::
set_point_a(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
set_point_a(LPoint3(x, y, z));
}
@ -84,7 +84,7 @@ set_point_a(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
/**
*
*/
INLINE const LPoint3 &CollisionTube::
INLINE const LPoint3 &CollisionCapsule::
get_point_a() const {
return _a;
}
@ -92,7 +92,7 @@ get_point_a() const {
/**
*
*/
INLINE void CollisionTube::
INLINE void CollisionCapsule::
set_point_b(const LPoint3 &b) {
_b = b;
recalc_internals();
@ -101,7 +101,7 @@ set_point_b(const LPoint3 &b) {
/**
*
*/
INLINE void CollisionTube::
INLINE void CollisionCapsule::
set_point_b(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
set_point_b(LPoint3(x, y, z));
}
@ -109,7 +109,7 @@ set_point_b(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z) {
/**
*
*/
INLINE const LPoint3 &CollisionTube::
INLINE const LPoint3 &CollisionCapsule::
get_point_b() const {
return _b;
}
@ -117,7 +117,7 @@ get_point_b() const {
/**
*
*/
INLINE void CollisionTube::
INLINE void CollisionCapsule::
set_radius(PN_stdfloat radius) {
nassertv(radius >= 0.0f);
_radius = radius;
@ -131,7 +131,7 @@ set_radius(PN_stdfloat radius) {
/**
*
*/
INLINE PN_stdfloat CollisionTube::
INLINE PN_stdfloat CollisionCapsule::
get_radius() const {
return _radius;
}

View File

@ -6,12 +6,12 @@
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file collisionTube.cxx
* @file collisionCapsule.cxx
* @author drose
* @date 2003-09-25
*/
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "collisionSphere.h"
#include "collisionLine.h"
#include "collisionRay.h"
@ -35,30 +35,30 @@
#include "geomVertexWriter.h"
#include "boundingSphere.h"
PStatCollector CollisionTube::_volume_pcollector("Collision Volumes:CollisionTube");
PStatCollector CollisionTube::_test_pcollector("Collision Tests:CollisionTube");
TypeHandle CollisionTube::_type_handle;
PStatCollector CollisionCapsule::_volume_pcollector("Collision Volumes:CollisionCapsule");
PStatCollector CollisionCapsule::_test_pcollector("Collision Tests:CollisionCapsule");
TypeHandle CollisionCapsule::_type_handle;
/**
*
*/
CollisionSolid *CollisionTube::
CollisionSolid *CollisionCapsule::
make_copy() {
return new CollisionTube(*this);
return new CollisionCapsule(*this);
}
/**
*
*/
PT(CollisionEntry) CollisionTube::
PT(CollisionEntry) CollisionCapsule::
test_intersection(const CollisionEntry &entry) const {
return entry.get_into()->test_intersection_from_tube(entry);
return entry.get_into()->test_intersection_from_capsule(entry);
}
/**
* Transforms the solid by the indicated matrix.
*/
void CollisionTube::
void CollisionCapsule::
xform(const LMatrix4 &mat) {
_a = _a * mat;
_b = _b * mat;
@ -77,7 +77,7 @@ xform(const LMatrix4 &mat) {
* collision purposes. The closest intersection point to this origin point is
* considered to be the most significant.
*/
LPoint3 CollisionTube::
LPoint3 CollisionCapsule::
get_collision_origin() const {
return get_point_a();
}
@ -86,7 +86,7 @@ get_collision_origin() const {
* Returns a PStatCollector that is used to count the number of bounding
* volume tests made against a solid of this type in a given frame.
*/
PStatCollector &CollisionTube::
PStatCollector &CollisionCapsule::
get_volume_pcollector() {
return _volume_pcollector;
}
@ -95,7 +95,7 @@ get_volume_pcollector() {
* Returns a PStatCollector that is used to count the number of intersection
* tests made against a solid of this type in a given frame.
*/
PStatCollector &CollisionTube::
PStatCollector &CollisionCapsule::
get_test_pcollector() {
return _test_pcollector;
}
@ -103,15 +103,15 @@ get_test_pcollector() {
/**
*
*/
void CollisionTube::
void CollisionCapsule::
output(std::ostream &out) const {
out << "tube, a (" << _a << "), b (" << _b << "), r " << _radius;
out << "capsule, a (" << _a << "), b (" << _b << "), r " << _radius;
}
/**
*
*/
PT(BoundingVolume) CollisionTube::
PT(BoundingVolume) CollisionCapsule::
compute_internal_bounds() const {
PT(BoundingVolume) bound = CollisionSolid::compute_internal_bounds();
@ -143,7 +143,7 @@ compute_internal_bounds() const {
/**
*
*/
PT(CollisionEntry) CollisionTube::
PT(CollisionEntry) CollisionCapsule::
test_intersection_from_sphere(const CollisionEntry &entry) const {
const CollisionSphere *sphere;
DCAST_INTO_R(sphere, entry.get_from(), nullptr);
@ -160,7 +160,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
PN_stdfloat actual_t = 0.0f;
if (wrt_prev_space != wrt_space) {
// If the sphere is moving relative to the tube, it becomes a tube itself.
// If the sphere is moving relative to the capsule, it becomes a capsule itself.
from_a = sphere->get_center() * wrt_prev_space->get_mat();
}
@ -195,11 +195,11 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
LPoint3 into_intersection_point;
if (t2 > 1.0) {
// Point b is within the tube. The first intersection point is point b
// Point b is within the capsule. The first intersection point is point b
// itself.
into_intersection_point = from_b;
} else {
// Point b is outside the tube, and point a is either inside the tube or
// Point b is outside the capsule, and point a is either inside the capsule or
// beyond it. The first intersection point is at t2.
into_intersection_point = from_a + t2 * from_direction;
}
@ -221,7 +221,7 @@ test_intersection_from_sphere(const CollisionEntry &entry) const {
/**
*
*/
PT(CollisionEntry) CollisionTube::
PT(CollisionEntry) CollisionCapsule::
test_intersection_from_line(const CollisionEntry &entry) const {
const CollisionLine *line;
DCAST_INTO_R(line, entry.get_from(), nullptr);
@ -269,7 +269,7 @@ test_intersection_from_line(const CollisionEntry &entry) const {
/**
*
*/
PT(CollisionEntry) CollisionTube::
PT(CollisionEntry) CollisionCapsule::
test_intersection_from_ray(const CollisionEntry &entry) const {
const CollisionRay *ray;
DCAST_INTO_R(ray, entry.get_from(), nullptr);
@ -299,11 +299,11 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
LPoint3 into_intersection_point;
if (t1 < 0.0) {
// Point a is within the tube. The first intersection point is point a
// Point a is within the capsule. The first intersection point is point a
// itself.
into_intersection_point = from_origin;
} else {
// Point a is outside the tube. The first intersection point is at t1.
// Point a is outside the capsule. The first intersection point is at t1.
into_intersection_point = from_origin + t1 * from_direction;
}
set_intersection_point(new_entry, into_intersection_point, 0.0);
@ -330,7 +330,7 @@ test_intersection_from_ray(const CollisionEntry &entry) const {
/**
*
*/
PT(CollisionEntry) CollisionTube::
PT(CollisionEntry) CollisionCapsule::
test_intersection_from_segment(const CollisionEntry &entry) const {
const CollisionSegment *segment;
DCAST_INTO_R(segment, entry.get_from(), nullptr);
@ -362,11 +362,11 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
LPoint3 into_intersection_point;
if (t1 < 0.0) {
// Point a is within the tube. The first intersection point is point a
// Point a is within the capsule. The first intersection point is point a
// itself.
into_intersection_point = from_a;
} else {
// Point a is outside the tube, and point b is either inside the tube or
// Point a is outside the capsule, and point b is either inside the capsule or
// beyond it. The first intersection point is at t1.
into_intersection_point = from_a + t1 * from_direction;
}
@ -394,22 +394,22 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
/**
*
*/
PT(CollisionEntry) CollisionTube::
test_intersection_from_tube(const CollisionEntry &entry) const {
const CollisionTube *tube;
DCAST_INTO_R(tube, entry.get_from(), nullptr);
PT(CollisionEntry) CollisionCapsule::
test_intersection_from_capsule(const CollisionEntry &entry) const {
const CollisionCapsule *capsule;
DCAST_INTO_R(capsule, entry.get_from(), nullptr);
LPoint3 into_a = _a;
LVector3 into_direction = _b - into_a;
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
LPoint3 from_a = tube->get_point_a() * wrt_mat;
LPoint3 from_b = tube->get_point_b() * wrt_mat;
LPoint3 from_a = capsule->get_point_a() * wrt_mat;
LPoint3 from_b = capsule->get_point_b() * wrt_mat;
LVector3 from_direction = from_b - from_a;
LVector3 from_radius_v =
LVector3(tube->get_radius(), 0.0f, 0.0f) * wrt_mat;
LVector3(capsule->get_radius(), 0.0f, 0.0f) * wrt_mat;
PN_stdfloat from_radius = length(from_radius_v);
// Determine the points on each segment with the smallest distance between.
@ -420,7 +420,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
LPoint3 into_closest = into_a + into_direction * into_t;
LPoint3 from_closest = from_a + from_direction * from_t;
// If the distance is greater than the sum of tube radii, the test fails.
// If the distance is greater than the sum of capsule radii, the test fails.
LVector3 closest_vec = from_closest - into_closest;
PN_stdfloat distance = closest_vec.length();
if (distance > _radius + from_radius) {
@ -442,7 +442,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
new_entry->set_surface_point(into_closest + surface_normal * _radius);
new_entry->set_interior_point(from_closest - surface_normal * from_radius);
if (has_effective_normal() && tube->get_respect_effective_normal()) {
if (has_effective_normal() && capsule->get_respect_effective_normal()) {
new_entry->set_surface_normal(get_effective_normal());
} else if (distance != 0) {
new_entry->set_surface_normal(surface_normal);
@ -458,7 +458,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
/**
*
*/
PT(CollisionEntry) CollisionTube::
PT(CollisionEntry) CollisionCapsule::
test_intersection_from_parabola(const CollisionEntry &entry) const {
const CollisionParabola *parabola;
DCAST_INTO_R(parabola, entry.get_from(), nullptr);
@ -510,14 +510,14 @@ test_intersection_from_parabola(const CollisionEntry &entry) const {
* Fills the _viz_geom GeomNode up with Geoms suitable for rendering this
* solid.
*/
void CollisionTube::
void CollisionCapsule::
fill_viz_geom() {
if (collide_cat.is_debug()) {
collide_cat.debug()
<< "Recomputing viz for " << *this << "\n";
}
// Generate the vertices such that we draw a tube with one endpoint at (0,
// Generate the vertices such that we draw a capsule with one endpoint at (0,
// 0, 0), and another at (0, length, 0). Then we'll rotate and translate it
// into place with the appropriate look_at matrix.
LVector3 direction = (_b - _a);
@ -576,9 +576,9 @@ fill_viz_geom() {
/**
* Should be called internally to recompute the matrix and length when the
* properties of the tube have changed.
* properties of the capsule have changed.
*/
void CollisionTube::
void CollisionCapsule::
recalc_internals() {
LVector3 direction = (_b - _a);
_length = direction.length();
@ -595,7 +595,7 @@ recalc_internals() {
* Calculates a particular vertex on the surface of the first endcap
* hemisphere, for use in generating the viz geometry.
*/
LVertex CollisionTube::
LVertex CollisionCapsule::
calc_sphere1_vertex(int ri, int si, int num_rings, int num_slices) {
PN_stdfloat r = (PN_stdfloat)ri / (PN_stdfloat)num_rings;
PN_stdfloat s = (PN_stdfloat)si / (PN_stdfloat)num_slices;
@ -620,7 +620,7 @@ calc_sphere1_vertex(int ri, int si, int num_rings, int num_slices) {
* Calculates a particular vertex on the surface of the second endcap
* hemisphere, for use in generating the viz geometry.
*/
LVertex CollisionTube::
LVertex CollisionCapsule::
calc_sphere2_vertex(int ri, int si, int num_rings, int num_slices,
PN_stdfloat length) {
PN_stdfloat r = (PN_stdfloat)ri / (PN_stdfloat)num_rings;
@ -646,7 +646,7 @@ calc_sphere2_vertex(int ri, int si, int num_rings, int num_slices,
* Given line segments s1 and s2 defined by two points each, computes the
* point on each segment with the closest distance between them.
*/
void CollisionTube::
void CollisionCapsule::
calc_closest_segment_points(double &t1, double &t2,
const LPoint3 &from1, const LVector3 &delta1,
const LPoint3 &from2, const LVector3 &delta2) {
@ -717,18 +717,18 @@ calc_closest_segment_points(double &t1, double &t2,
}
/**
* Determine the point(s) of intersection of a parametric line with the tube.
* Determine the point(s) of intersection of a parametric line with the capsule.
* The line is infinite in both directions, and passes through "from" and
* from+delta. If the line does not intersect the tube, the function returns
* false, and t1 and t2 are undefined. If it does intersect the tube, it
* from+delta. If the line does not intersect the capsule, the function returns
* false, and t1 and t2 are undefined. If it does intersect the capsule, it
* returns true, and t1 and t2 are set to the points along the equation
* from+t*delta that correspond to the two points of intersection.
*/
bool CollisionTube::
bool CollisionCapsule::
intersects_line(double &t1, double &t2,
const LPoint3 &from0, const LVector3 &delta0,
PN_stdfloat inflate_radius) const {
// Convert the line into our canonical coordinate space: the tube is aligned
// Convert the line into our canonical coordinate space: the capsule is aligned
// with the y axis.
LPoint3 from = from0 * _inv_mat;
LVector3 delta = delta0 * _inv_mat;
@ -776,7 +776,7 @@ intersects_line(double &t1, double &t2,
}
}
// The point is within the tube!
// The point is within the capsule!
t1 = t2 = 0.0;
return true;
}
@ -819,15 +819,15 @@ intersects_line(double &t1, double &t2,
PN_stdfloat t2_y = from[1] + t2 * delta[1];
if (t1_y < -radius && t2_y < -radius) {
// Both points are way off the bottom of the tube; no intersection.
// Both points are way off the bottom of the capsule; no intersection.
return false;
} else if (t1_y > _length + radius && t2_y > _length + radius) {
// Both points are way off the top of the tube; no intersection.
// Both points are way off the top of the capsule; no intersection.
return false;
}
if (t1_y < 0.0f) {
// The starting point is off the bottom of the tube. Test the line
// The starting point is off the bottom of the capsule. Test the line
// against the first endcap.
double t1a, t2a;
if (!sphere_intersects_line(t1a, t2a, 0.0f, from, delta, radius)) {
@ -838,7 +838,7 @@ intersects_line(double &t1, double &t2,
t1 = t1a;
} else if (t1_y > _length) {
// The starting point is off the top of the tube. Test the line against
// The starting point is off the top of the capsule. Test the line against
// the second endcap.
double t1b, t2b;
if (!sphere_intersects_line(t1b, t2b, _length, from, delta, radius)) {
@ -850,7 +850,7 @@ intersects_line(double &t1, double &t2,
}
if (t2_y < 0.0f) {
// The ending point is off the bottom of the tube. Test the line against
// The ending point is off the bottom of the capsule. Test the line against
// the first endcap.
double t1a, t2a;
if (!sphere_intersects_line(t1a, t2a, 0.0f, from, delta, radius)) {
@ -861,7 +861,7 @@ intersects_line(double &t1, double &t2,
t2 = t2a;
} else if (t2_y > _length) {
// The ending point is off the top of the tube. Test the line against the
// The ending point is off the top of the capsule. Test the line against the
// second endcap.
double t1b, t2b;
if (!sphere_intersects_line(t1b, t2b, _length, from, delta, radius)) {
@ -880,7 +880,7 @@ intersects_line(double &t1, double &t2,
* whether it intersects one or the other endcaps. The y parameter specifies
* the center of the sphere (and hence the particular endcap).
*/
bool CollisionTube::
bool CollisionCapsule::
sphere_intersects_line(double &t1, double &t2, PN_stdfloat center_y,
const LPoint3 &from, const LVector3 &delta,
PN_stdfloat radius) {
@ -917,14 +917,14 @@ sphere_intersects_line(double &t1, double &t2, PN_stdfloat center_y,
}
/**
* Determine a point of intersection of a parametric parabola with the tube.
* Determine a point of intersection of a parametric parabola with the capsule.
*
* We only consider the segment of the parabola between t1 and t2, which has
* already been computed as corresponding to points p1 and p2. If there is an
* intersection, t is set to the parametric point of intersection, and true is
* returned; otherwise, false is returned.
*/
bool CollisionTube::
bool CollisionCapsule::
intersects_parabola(double &t, const LParabola &parabola,
double t1, double t2,
const LPoint3 &p1, const LPoint3 &p2) const {
@ -965,11 +965,11 @@ intersects_parabola(double &t, const LParabola &parabola,
}
/**
* Calculates a point that is exactly on the surface of the tube and its
* Calculates a point that is exactly on the surface of the capsule and its
* corresponding normal, given a point that is supposedly on the surface of
* the tube.
* the capsule.
*/
void CollisionTube::
void CollisionCapsule::
calculate_surface_point_and_normal(const LPoint3 &surface_point,
double extra_radius,
LPoint3 &result_point,
@ -1015,7 +1015,7 @@ calculate_surface_point_and_normal(const LPoint3 &surface_point,
* point in the CollisionEntry, and also compute the relevant normal based on
* that point.
*/
void CollisionTube::
void CollisionCapsule::
set_intersection_point(CollisionEntry *new_entry,
const LPoint3 &into_intersection_point,
double extra_radius) const {
@ -1033,16 +1033,16 @@ set_intersection_point(CollisionEntry *new_entry,
new_entry->set_surface_normal(normal);
new_entry->set_surface_point(point);
// Also adjust the original point into the tube by the amount of
// extra_radius, which should put it on the surface of the tube if our
// Also adjust the original point into the capsule by the amount of
// extra_radius, which should put it on the surface of the capsule if our
// collision was tangential.
new_entry->set_interior_point(into_intersection_point - normal * extra_radius);
}
/**
* Tells the BamReader how to create objects of type CollisionTube.
* Tells the BamReader how to create objects of type CollisionCapsule.
*/
void CollisionTube::
void CollisionCapsule::
register_with_read_factory() {
BamReader::get_factory()->register_factory(get_class_type(), make_from_bam);
}
@ -1051,7 +1051,7 @@ register_with_read_factory() {
* Writes the contents of this object to the datagram for shipping out to a
* Bam file.
*/
void CollisionTube::
void CollisionCapsule::
write_datagram(BamWriter *manager, Datagram &dg) {
CollisionSolid::write_datagram(manager, dg);
_a.write_datagram(dg);
@ -1061,12 +1061,12 @@ write_datagram(BamWriter *manager, Datagram &dg) {
/**
* This function is called by the BamReader's factory when a new object of
* type CollisionTube is encountered in the Bam file. It should create the
* CollisionTube and extract its information from the file.
* type CollisionCapsule is encountered in the Bam file. It should create the
* CollisionCapsule and extract its information from the file.
*/
TypedWritable *CollisionTube::
TypedWritable *CollisionCapsule::
make_from_bam(const FactoryParams &params) {
CollisionTube *node = new CollisionTube();
CollisionCapsule *node = new CollisionCapsule();
DatagramIterator scan;
BamReader *manager;
@ -1078,9 +1078,9 @@ make_from_bam(const FactoryParams &params) {
/**
* This internal function is called by make_from_bam to read in all of the
* relevant data from the BamFile for the new CollisionTube.
* relevant data from the BamFile for the new CollisionCapsule.
*/
void CollisionTube::
void CollisionCapsule::
fillin(DatagramIterator &scan, BamReader *manager) {
CollisionSolid::fillin(scan, manager);
_a.read_datagram(scan);

View File

@ -0,0 +1,161 @@
/**
* PANDA 3D SOFTWARE
* Copyright (c) Carnegie Mellon University. All rights reserved.
*
* All use of this software is subject to the terms of the revised BSD
* license. You should have received a copy of this license along
* with this source code in a file named "LICENSE."
*
* @file collisionCapsule.h
* @author drose
* @date 2003-09-25
*/
#ifndef COLLISIONCAPSULE_H
#define COLLISIONCAPSULE_H
#include "pandabase.h"
#include "collisionSolid.h"
#include "parabola.h"
/**
* This implements a solid consisting of a cylinder with hemispherical endcaps,
* also known as a capsule or a spherocylinder.
*
* This shape was previously erroneously called CollisionTube.
*/
class EXPCL_PANDA_COLLIDE CollisionCapsule : public CollisionSolid {
PUBLISHED:
INLINE explicit CollisionCapsule(const LPoint3 &a, const LPoint3 &db,
PN_stdfloat radius);
INLINE explicit CollisionCapsule(PN_stdfloat ax, PN_stdfloat ay, PN_stdfloat az,
PN_stdfloat bx, PN_stdfloat by, PN_stdfloat bz,
PN_stdfloat radius);
virtual LPoint3 get_collision_origin() const;
private:
INLINE CollisionCapsule();
public:
INLINE CollisionCapsule(const CollisionCapsule &copy);
virtual CollisionSolid *make_copy();
virtual PT(CollisionEntry)
test_intersection(const CollisionEntry &entry) const;
virtual void xform(const LMatrix4 &mat);
virtual PStatCollector &get_volume_pcollector();
virtual PStatCollector &get_test_pcollector();
virtual void output(std::ostream &out) const;
INLINE static void flush_level();
PUBLISHED:
INLINE void set_point_a(const LPoint3 &a);
INLINE void set_point_a(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z);
INLINE const LPoint3 &get_point_a() const;
INLINE void set_point_b(const LPoint3 &b);
INLINE void set_point_b(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z);
INLINE const LPoint3 &get_point_b() const;
INLINE void set_radius(PN_stdfloat radius);
INLINE PN_stdfloat get_radius() const;
PUBLISHED:
MAKE_PROPERTY(point_a, get_point_a, set_point_a);
MAKE_PROPERTY(point_b, get_point_b, set_point_b);
MAKE_PROPERTY(radius, get_radius, set_radius);
protected:
virtual PT(BoundingVolume) compute_internal_bounds() const;
protected:
virtual PT(CollisionEntry)
test_intersection_from_sphere(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_line(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_ray(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_segment(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_capsule(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_parabola(const CollisionEntry &entry) const;
virtual void fill_viz_geom();
private:
void recalc_internals();
LVertex calc_sphere1_vertex(int ri, int si, int num_rings, int num_slices);
LVertex calc_sphere2_vertex(int ri, int si, int num_rings, int num_slices,
PN_stdfloat length);
static void calc_closest_segment_points(double &t1, double &t2,
const LPoint3 &from1, const LVector3 &delta1,
const LPoint3 &from2, const LVector3 &delta2);
bool intersects_line(double &t1, double &t2,
const LPoint3 &from, const LVector3 &delta,
PN_stdfloat inflate_radius) const;
static bool sphere_intersects_line(double &t1, double &t2, PN_stdfloat center_y,
const LPoint3 &from, const LVector3 &delta,
PN_stdfloat radius);
bool intersects_parabola(double &t, const LParabola &parabola,
double t1, double t2,
const LPoint3 &p1, const LPoint3 &p2) const;
void calculate_surface_point_and_normal(const LPoint3 &surface_point,
double extra_radius,
LPoint3 &result_point,
LVector3 &result_normal) const;
void set_intersection_point(CollisionEntry *new_entry,
const LPoint3 &into_intersection_point,
double extra_radius) const;
private:
LPoint3 _a, _b;
PN_stdfloat _radius;
// These are derived from the above.
LMatrix4 _mat;
LMatrix4 _inv_mat;
PN_stdfloat _length;
static PStatCollector _volume_pcollector;
static PStatCollector _test_pcollector;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
CollisionSolid::init_type();
register_type(_type_handle, "CollisionCapsule",
CollisionSolid::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;
friend class CollisionBox;
};
#include "collisionCapsule.I"
#endif

View File

@ -72,7 +72,7 @@ handle_entries() {
PosB = collider's current position
M = movement vector (PosB - PosA)
BV = bounding sphere that includes collider at PosA and PosB
CS = 'collision set', all 'collidables' within BV (collision polys, tubes, etc)
CS = 'collision set', all 'collidables' within BV (collision polys, capsules, etc)
VARIABLES
N = movement vector since most recent collision (or start of frame)

View File

@ -18,7 +18,7 @@
#include "collisionLine.h"
#include "collisionRay.h"
#include "collisionSegment.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "collisionParabola.h"
#include "config_collide.h"
#include "pointerToArray.h"
@ -298,16 +298,16 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
*
*/
PT(CollisionEntry) CollisionPlane::
test_intersection_from_tube(const CollisionEntry &entry) const {
const CollisionTube *tube;
DCAST_INTO_R(tube, entry.get_from(), nullptr);
test_intersection_from_capsule(const CollisionEntry &entry) const {
const CollisionCapsule *capsule;
DCAST_INTO_R(capsule, entry.get_from(), nullptr);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
LPoint3 from_a = tube->get_point_a() * wrt_mat;
LPoint3 from_b = tube->get_point_b() * wrt_mat;
LPoint3 from_a = capsule->get_point_a() * wrt_mat;
LPoint3 from_b = capsule->get_point_b() * wrt_mat;
LVector3 from_radius_v =
LVector3(tube->get_radius(), 0.0f, 0.0f) * wrt_mat;
LVector3(capsule->get_radius(), 0.0f, 0.0f) * wrt_mat;
PN_stdfloat from_radius = length(from_radius_v);
PN_stdfloat dist_a = _plane.dist_to_plane(from_a);
@ -325,7 +325,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
}
PT(CollisionEntry) new_entry = new CollisionEntry(entry);
LVector3 normal = (has_effective_normal() && tube->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
LVector3 normal = (has_effective_normal() && capsule->get_respect_effective_normal()) ? get_effective_normal() : get_normal();
new_entry->set_surface_normal(normal);
PN_stdfloat t;
@ -339,17 +339,17 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
new_entry->set_surface_point(from_a - get_normal() * dist_a);
} else {
// Within the tube! Yay, that means we have a surface point.
// Within the capsule! Yay, that means we have a surface point.
new_entry->set_surface_point(from_a + t * from_direction);
}
} else {
// If it's completely parallel, pretend it's colliding in the center of
// the tube.
// the capsule.
new_entry->set_surface_point(from_a + 0.5f * from_direction - get_normal() * dist_a);
}
if (IS_NEARLY_EQUAL(dist_a, dist_b)) {
// Let's be fair and choose the center of the tube.
// Let's be fair and choose the center of the capsule.
new_entry->set_interior_point(from_a + 0.5f * from_direction - get_normal() * from_radius);
} else if (dist_a < dist_b) {

View File

@ -72,7 +72,7 @@ protected:
virtual PT(CollisionEntry)
test_intersection_from_segment(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_tube(const CollisionEntry &entry) const;
test_intersection_from_capsule(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_parabola(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)

View File

@ -17,7 +17,7 @@
#include "collisionLine.h"
#include "collisionRay.h"
#include "collisionSegment.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "collisionParabola.h"
#include "collisionBox.h"
#include "collisionEntry.h"
@ -240,11 +240,11 @@ test_intersection_from_segment(const CollisionEntry &) const {
/**
* This is part of the double-dispatch implementation of test_intersection().
* It is called when the "from" object is a tube.
* It is called when the "from" object is a capsule.
*/
PT(CollisionEntry) CollisionSolid::
test_intersection_from_tube(const CollisionEntry &) const {
report_undefined_intersection_test(CollisionTube::get_class_type(),
test_intersection_from_capsule(const CollisionEntry &) const {
report_undefined_intersection_test(CollisionCapsule::get_class_type(),
get_type());
return nullptr;
}

View File

@ -108,7 +108,7 @@ protected:
virtual PT(CollisionEntry)
test_intersection_from_segment(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_tube(const CollisionEntry &entry) const;
test_intersection_from_capsule(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_parabola(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
@ -177,7 +177,7 @@ private:
friend class CollisionLine;
friend class CollisionRay;
friend class CollisionSegment;
friend class CollisionTube;
friend class CollisionCapsule;
friend class CollisionParabola;
friend class CollisionHandlerFluidPusher;
friend class CollisionBox;

View File

@ -17,7 +17,7 @@
#include "collisionHandler.h"
#include "collisionEntry.h"
#include "collisionSegment.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "collisionParabola.h"
#include "collisionBox.h"
#include "config_collide.h"
@ -444,18 +444,18 @@ test_intersection_from_segment(const CollisionEntry &entry) const {
*
*/
PT(CollisionEntry) CollisionSphere::
test_intersection_from_tube(const CollisionEntry &entry) const {
const CollisionTube *tube;
DCAST_INTO_R(tube, entry.get_from(), nullptr);
test_intersection_from_capsule(const CollisionEntry &entry) const {
const CollisionCapsule *capsule;
DCAST_INTO_R(capsule, entry.get_from(), nullptr);
const LMatrix4 &wrt_mat = entry.get_wrt_mat();
LPoint3 from_a = tube->get_point_a() * wrt_mat;
LPoint3 from_b = tube->get_point_b() * wrt_mat;
LPoint3 from_a = capsule->get_point_a() * wrt_mat;
LPoint3 from_b = capsule->get_point_b() * wrt_mat;
LVector3 from_direction = from_b - from_a;
LVector3 from_radius_v =
LVector3(tube->get_radius(), 0.0f, 0.0f) * wrt_mat;
LVector3(capsule->get_radius(), 0.0f, 0.0f) * wrt_mat;
PN_stdfloat from_radius = length(from_radius_v);
double t1, t2;
@ -465,8 +465,8 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
}
if (t2 < 0.0 || t1 > 1.0) {
// Both intersection points are before the start of the tube or after
// the end of the tube.
// Both intersection points are before the start of the capsule or after
// the end of the capsule.
return nullptr;
}
@ -487,7 +487,7 @@ test_intersection_from_tube(const CollisionEntry &entry) const {
new_entry->set_surface_point(get_center() + normal * get_radius());
new_entry->set_interior_point(inner_point - normal * from_radius);
if (has_effective_normal() && tube->get_respect_effective_normal()) {
if (has_effective_normal() && capsule->get_respect_effective_normal()) {
new_entry->set_surface_normal(get_effective_normal());
} else {
new_entry->set_surface_normal(normal);

View File

@ -72,7 +72,7 @@ protected:
virtual PT(CollisionEntry)
test_intersection_from_segment(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_tube(const CollisionEntry &entry) const;
test_intersection_from_capsule(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_parabola(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)

View File

@ -20,7 +20,7 @@
#include "collisionVisualizer.h"
#include "collisionSphere.h"
#include "collisionBox.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "collisionPolygon.h"
#include "collisionPlane.h"
#include "config_collide.h"
@ -345,7 +345,7 @@ traverse(const NodePath &root) {
_geom_volume_pcollector.flush_level();
CollisionSphere::flush_level();
CollisionTube::flush_level();
CollisionCapsule::flush_level();
CollisionPolygon::flush_level();
CollisionPlane::flush_level();
CollisionBox::flush_level();

View File

@ -7,154 +7,21 @@
* with this source code in a file named "LICENSE."
*
* @file collisionTube.h
* @author drose
* @date 2003-09-25
* @author rdb
* @date 2018-12-23
*/
#ifndef COLLISIONTUBE_H
#define COLLISIONTUBE_H
#include "pandabase.h"
#include "collisionSolid.h"
#include "parabola.h"
#include "collisionCapsule.h"
BEGIN_PUBLISH
/**
* This implements a solid roughly in cylindrical shape. It's not called a
* CollisionCylinder because it's not a true cylinder; specifically, it has
* rounded ends instead of flat ends. It looks more like a Contac pill.
* Alias for backward compatibility.
* @deprecated use CollisionCapsule instead.
*/
class EXPCL_PANDA_COLLIDE CollisionTube : public CollisionSolid {
PUBLISHED:
INLINE explicit CollisionTube(const LPoint3 &a, const LPoint3 &db,
PN_stdfloat radius);
INLINE explicit CollisionTube(PN_stdfloat ax, PN_stdfloat ay, PN_stdfloat az,
PN_stdfloat bx, PN_stdfloat by, PN_stdfloat bz,
PN_stdfloat radius);
virtual LPoint3 get_collision_origin() const;
private:
INLINE CollisionTube();
public:
INLINE CollisionTube(const CollisionTube &copy);
virtual CollisionSolid *make_copy();
virtual PT(CollisionEntry)
test_intersection(const CollisionEntry &entry) const;
virtual void xform(const LMatrix4 &mat);
virtual PStatCollector &get_volume_pcollector();
virtual PStatCollector &get_test_pcollector();
virtual void output(std::ostream &out) const;
INLINE static void flush_level();
PUBLISHED:
INLINE void set_point_a(const LPoint3 &a);
INLINE void set_point_a(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z);
INLINE const LPoint3 &get_point_a() const;
INLINE void set_point_b(const LPoint3 &b);
INLINE void set_point_b(PN_stdfloat x, PN_stdfloat y, PN_stdfloat z);
INLINE const LPoint3 &get_point_b() const;
INLINE void set_radius(PN_stdfloat radius);
INLINE PN_stdfloat get_radius() const;
PUBLISHED:
MAKE_PROPERTY(point_a, get_point_a, set_point_a);
MAKE_PROPERTY(point_b, get_point_b, set_point_b);
MAKE_PROPERTY(radius, get_radius, set_radius);
protected:
virtual PT(BoundingVolume) compute_internal_bounds() const;
protected:
virtual PT(CollisionEntry)
test_intersection_from_sphere(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_line(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_ray(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_segment(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_tube(const CollisionEntry &entry) const;
virtual PT(CollisionEntry)
test_intersection_from_parabola(const CollisionEntry &entry) const;
virtual void fill_viz_geom();
private:
void recalc_internals();
LVertex calc_sphere1_vertex(int ri, int si, int num_rings, int num_slices);
LVertex calc_sphere2_vertex(int ri, int si, int num_rings, int num_slices,
PN_stdfloat length);
static void calc_closest_segment_points(double &t1, double &t2,
const LPoint3 &from1, const LVector3 &delta1,
const LPoint3 &from2, const LVector3 &delta2);
bool intersects_line(double &t1, double &t2,
const LPoint3 &from, const LVector3 &delta,
PN_stdfloat inflate_radius) const;
static bool sphere_intersects_line(double &t1, double &t2, PN_stdfloat center_y,
const LPoint3 &from, const LVector3 &delta,
PN_stdfloat radius);
bool intersects_parabola(double &t, const LParabola &parabola,
double t1, double t2,
const LPoint3 &p1, const LPoint3 &p2) const;
void calculate_surface_point_and_normal(const LPoint3 &surface_point,
double extra_radius,
LPoint3 &result_point,
LVector3 &result_normal) const;
void set_intersection_point(CollisionEntry *new_entry,
const LPoint3 &into_intersection_point,
double extra_radius) const;
private:
LPoint3 _a, _b;
PN_stdfloat _radius;
// These are derived from the above.
LMatrix4 _mat;
LMatrix4 _inv_mat;
PN_stdfloat _length;
static PStatCollector _volume_pcollector;
static PStatCollector _test_pcollector;
public:
static void register_with_read_factory();
virtual void write_datagram(BamWriter *manager, Datagram &dg);
protected:
static TypedWritable *make_from_bam(const FactoryParams &params);
void fillin(DatagramIterator &scan, BamReader *manager);
public:
static TypeHandle get_class_type() {
return _type_handle;
}
static void init_type() {
CollisionSolid::init_type();
register_type(_type_handle, "CollisionTube",
CollisionSolid::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;
friend class CollisionBox;
};
#include "collisionTube.I"
typedef CollisionCapsule CollisionTube;
END_PUBLISH
#endif

View File

@ -13,6 +13,7 @@
#include "config_collide.h"
#include "collisionBox.h"
#include "collisionCapsule.h"
#include "collisionEntry.h"
#include "collisionHandler.h"
#include "collisionHandlerEvent.h"
@ -38,7 +39,6 @@
#include "collisionSolid.h"
#include "collisionSphere.h"
#include "collisionTraverser.h"
#include "collisionTube.h"
#include "collisionVisualizer.h"
#include "dconfig.h"
@ -126,6 +126,7 @@ init_libcollide() {
initialized = true;
CollisionBox::init_type();
CollisionCapsule::init_type();
CollisionEntry::init_type();
CollisionHandler::init_type();
CollisionHandlerEvent::init_type();
@ -150,14 +151,18 @@ init_libcollide() {
CollisionSolid::init_type();
CollisionSphere::init_type();
CollisionTraverser::init_type();
CollisionTube::init_type();
#ifdef DO_COLLISION_RECORDING
CollisionRecorder::init_type();
CollisionVisualizer::init_type();
#endif
// Record the old name for CollisionCapsule for backwards compatibility.
BamWriter::record_obsolete_type_name(CollisionCapsule::get_class_type(),
"CollisionTube", 6, 44);
CollisionBox::register_with_read_factory();
CollisionCapsule::register_with_read_factory();
CollisionInvSphere::register_with_read_factory();
CollisionLine::register_with_read_factory();
CollisionNode::register_with_read_factory();
@ -168,5 +173,4 @@ init_libcollide() {
CollisionRay::register_with_read_factory();
CollisionSegment::register_with_read_factory();
CollisionSphere::register_with_read_factory();
CollisionTube::register_with_read_factory();
}

View File

@ -1,5 +1,6 @@
#include "config_collide.cxx"
#include "collisionBox.cxx"
#include "collisionCapsule.cxx"
#include "collisionEntry.cxx"
#include "collisionGeom.cxx"
#include "collisionHandler.cxx"
@ -12,5 +13,3 @@
#include "collisionHandlerFluidPusher.cxx"
#include "collisionHandlerQueue.cxx"
#include "collisionInvSphere.cxx"
#include "collisionLevelStateBase.cxx"
#include "collisionLevelState.cxx"

View File

@ -1,3 +1,5 @@
#include "collisionLevelStateBase.cxx"
#include "collisionLevelState.cxx"
#include "collisionLine.cxx"
#include "collisionNode.cxx"
#include "collisionParabola.cxx"
@ -10,5 +12,4 @@
#include "collisionSolid.cxx"
#include "collisionSphere.cxx"
#include "collisionTraverser.cxx"
#include "collisionTube.cxx"
#include "collisionVisualizer.cxx"

View File

@ -110,8 +110,8 @@ PStatCollector GraphicsEngine::_volume_sphere_pcollector("Collision Volumes:Coll
PStatCollector GraphicsEngine::_test_sphere_pcollector("Collision Tests:CollisionSphere");
PStatCollector GraphicsEngine::_volume_box_pcollector("Collision Volumes:CollisionBox");
PStatCollector GraphicsEngine::_test_box_pcollector("Collision Tests:CollisionBox");
PStatCollector GraphicsEngine::_volume_tube_pcollector("Collision Volumes:CollisionTube");
PStatCollector GraphicsEngine::_test_tube_pcollector("Collision Tests:CollisionTube");
PStatCollector GraphicsEngine::_volume_capsule_pcollector("Collision Volumes:CollisionCapsule");
PStatCollector GraphicsEngine::_test_capsule_pcollector("Collision Tests:CollisionCapsule");
PStatCollector GraphicsEngine::_volume_inv_sphere_pcollector("Collision Volumes:CollisionInvSphere");
PStatCollector GraphicsEngine::_test_inv_sphere_pcollector("Collision Tests:CollisionInvSphere");
PStatCollector GraphicsEngine::_volume_geom_pcollector("Collision Volumes:CollisionGeom");
@ -875,8 +875,8 @@ render_frame() {
_test_sphere_pcollector.clear_level();
_volume_box_pcollector.clear_level();
_test_box_pcollector.clear_level();
_volume_tube_pcollector.clear_level();
_test_tube_pcollector.clear_level();
_volume_capsule_pcollector.clear_level();
_test_capsule_pcollector.clear_level();
_volume_inv_sphere_pcollector.clear_level();
_test_inv_sphere_pcollector.clear_level();
_volume_geom_pcollector.clear_level();

View File

@ -401,8 +401,8 @@ private:
static PStatCollector _test_sphere_pcollector;
static PStatCollector _volume_box_pcollector;
static PStatCollector _test_box_pcollector;
static PStatCollector _volume_tube_pcollector;
static PStatCollector _test_tube_pcollector;
static PStatCollector _volume_capsule_pcollector;
static PStatCollector _test_capsule_pcollector;
static PStatCollector _volume_inv_sphere_pcollector;
static PStatCollector _test_inv_sphere_pcollector;
static PStatCollector _volume_geom_pcollector;

View File

@ -6,7 +6,7 @@ camera-collide: for things that the camera should avoid
trigger: for things (usually not barriers or floors) that should trigger an
event when avatars intersect with them
sphere: for things that should have a collision sphere around them
tube: for things that should have a collision tube (cylinder) around them
tube: for things that should have a collision capsule around them
NOTES

View File

@ -30,14 +30,12 @@ ConfigureFn(config_dxml) {
init_libdxml();
}
////////////////////////////////////////////////////////////////////
// Function: init_libdxml
// Description: Initializes the library. This must be called at
// least once before any of the functions or classes in
// this library can be used. Normally it will be
// called by the static initializers and need not be
// called explicitly, but special cases exist.
////////////////////////////////////////////////////////////////////
/**
* Initializes the library. This must be called at least once before any of
* the functions or classes in this library can be used. Normally it will be
* called by the static initializers and need not be called explicitly, but
* special cases exist.
*/
void
init_libdxml() {
static bool initialized = false;
@ -48,11 +46,10 @@ init_libdxml() {
}
BEGIN_PUBLISH
////////////////////////////////////////////////////////////////////
// Function: read_xml_stream
// Description: Reads an XML document from the indicated stream.
// Returns the document, or NULL on error.
////////////////////////////////////////////////////////////////////
/**
* Reads an XML document from the indicated stream.
* @returns the document, or NULL on error.
*/
TiXmlDocument *
read_xml_stream(std::istream &in) {
TiXmlDocument *doc = new TiXmlDocument;
@ -67,10 +64,9 @@ read_xml_stream(std::istream &in) {
END_PUBLISH
BEGIN_PUBLISH
////////////////////////////////////////////////////////////////////
// Function: write_xml_stream
// Description: Writes an XML document to the indicated stream.
////////////////////////////////////////////////////////////////////
/**
* Writes an XML document to the indicated stream.
*/
void
write_xml_stream(std::ostream &out, TiXmlDocument *doc) {
out << *doc;
@ -78,10 +74,9 @@ write_xml_stream(std::ostream &out, TiXmlDocument *doc) {
END_PUBLISH
BEGIN_PUBLISH
////////////////////////////////////////////////////////////////////
// Function: print_xml
// Description: Writes an XML object to stdout, with formatting.
////////////////////////////////////////////////////////////////////
/**
* Writes an XML object to stdout, with formatting.
*/
void
print_xml(TiXmlNode *xnode) {
xnode->Print(stdout, 0);
@ -89,12 +84,10 @@ print_xml(TiXmlNode *xnode) {
END_PUBLISH
BEGIN_PUBLISH
////////////////////////////////////////////////////////////////////
// Function: print_xml_to_file
// Description: Writes an XML object to the indicated file, with
// formatting. Unfortunately the VFS cannot be
// supported; the file must be a real filename on disk.
////////////////////////////////////////////////////////////////////
/**
* Writes an XML object to the indicated file, with formatting. Unfortunately
* the VFS cannot be supported; the file must be a real filename on disk.
*/
void
print_xml_to_file(const Filename &filename, TiXmlNode *xnode) {
std::string os_name = filename.to_os_specific();

View File

@ -897,7 +897,8 @@ string_cs_type(const string &strval) {
} else if (cmp_nocase_uh(strval, "inv-sphere") == 0 ||
cmp_nocase_uh(strval, "invsphere") == 0) {
return CST_inv_sphere;
} else if (cmp_nocase_uh(strval, "tube") == 0) {
} else if (cmp_nocase_uh(strval, "tube") == 0 ||
cmp_nocase_uh(strval, "capsule") == 0) {
return CST_tube;
} else if (cmp_nocase_uh(strval, "floor-mesh") == 0 ||
cmp_nocase_uh(strval, "floormesh") == 0) {

View File

@ -74,7 +74,7 @@
#include "collisionNode.h"
#include "collisionSphere.h"
#include "collisionInvSphere.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "collisionPlane.h"
#include "collisionPolygon.h"
#include "collisionFloorMesh.h"
@ -2865,7 +2865,7 @@ make_collision_solids(EggGroup *start_group, EggGroup *egg_group,
break;
case EggGroup::CST_tube:
make_collision_tube(egg_group, cnode, start_group->get_collide_flags());
make_collision_capsule(egg_group, cnode, start_group->get_collide_flags());
break;
case EggGroup::CST_floor_mesh:
@ -3045,12 +3045,12 @@ make_collision_inv_sphere(EggGroup *egg_group, CollisionNode *cnode,
}
/**
* Creates a single CollisionTube corresponding to the polygons associated
* Creates a single CollisionCapsule corresponding to the polygons associated
* with this group.
*/
void EggLoader::
make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::CollideFlags flags) {
make_collision_capsule(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::CollideFlags flags) {
EggGroup *geom_group = find_collision_geometry(egg_group, flags);
if (geom_group != nullptr) {
// Collect all of the vertices.
@ -3175,7 +3175,7 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
// Transform all of the points so that the major axis is along the Y
// axis, and the origin is the center. This is very similar to the
// CollisionTube's idea of its canonical orientation (although not
// CollisionCapsule's idea of its canonical orientation (although not
// exactly the same, since it is centered on the origin instead of
// having point_a on the origin). It makes it easier to determine the
// length and radius of the cylinder.
@ -3230,11 +3230,11 @@ make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
LPoint3d point_a = center - half;
LPoint3d point_b = center + half;
CollisionTube *cstube =
new CollisionTube(LCAST(PN_stdfloat, point_a), LCAST(PN_stdfloat, point_b),
CollisionCapsule *cscapsule =
new CollisionCapsule(LCAST(PN_stdfloat, point_a), LCAST(PN_stdfloat, point_b),
radius);
apply_collision_flags(cstube, flags);
cnode->add_solid(cstube);
apply_collision_flags(cscapsule, flags);
cnode->add_solid(cscapsule);
}
}
}

View File

@ -180,8 +180,8 @@ private:
EggGroup::CollideFlags flags);
void make_collision_inv_sphere(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::CollideFlags flags);
void make_collision_tube(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::CollideFlags flags);
void make_collision_capsule(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::CollideFlags flags);
void make_collision_floor_mesh(EggGroup *egg_group, CollisionNode *cnode,
EggGroup::CollideFlags flags);
void apply_collision_flags(CollisionSolid *solid,

View File

@ -39,7 +39,7 @@
#include "collisionSphere.h"
#include "collisionBox.h"
#include "collisionInvSphere.h"
#include "collisionTube.h"
#include "collisionCapsule.h"
#include "textureStage.h"
#include "geomNode.h"
#include "geom.h"
@ -620,13 +620,13 @@ convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
egg_poly->add_vertex(cvpool->create_unique_vertex(ev0));
egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));
} else if (child->is_of_type(CollisionTube::get_class_type())) {
CPT(CollisionTube) tube = DCAST(CollisionTube, child);
LPoint3 point_a = tube->get_point_a();
LPoint3 point_b = tube->get_point_b();
} else if (child->is_of_type(CollisionCapsule::get_class_type())) {
CPT(CollisionCapsule) capsule = DCAST(CollisionCapsule, child);
LPoint3 point_a = capsule->get_point_a();
LPoint3 point_b = capsule->get_point_b();
LPoint3 centroid = (point_a + point_b) * 0.5f;
// Also get an arbitrary vector perpendicular to the tube.
// Also get an arbitrary vector perpendicular to the capsule.
LVector3 axis = point_b - point_a;
LVector3 sideways;
if (std::fabs(axis[2]) > std::fabs(axis[1])) {
@ -635,18 +635,18 @@ convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
sideways = axis.cross(LVector3(0, 0, 1));
}
sideways.normalize();
sideways *= tube->get_radius();
LVector3 extend = axis.normalized() * tube->get_radius();
sideways *= capsule->get_radius();
LVector3 extend = axis.normalized() * capsule->get_radius();
EggGroup *egg_tube;
EggGroup *egg_capsule;
if (num_solids == 1) {
egg_tube = egg_group;
egg_capsule = egg_group;
} else {
egg_tube = new EggGroup;
egg_group->add_child(egg_tube);
egg_capsule = new EggGroup;
egg_group->add_child(egg_capsule);
}
egg_tube->set_cs_type(EggGroup::CST_tube);
egg_tube->set_collide_flags(flags);
egg_capsule->set_cs_type(EggGroup::CST_tube);
egg_capsule->set_collide_flags(flags);
// Add two points for the endcaps, and then two points around the
// centroid to indicate the radius.
@ -657,7 +657,7 @@ convert_collision_node(CollisionNode *node, const WorkingNodePath &node_path,
ev3.set_pos(LCAST(double, (centroid - sideways) * net_mat));
EggPolygon *egg_poly = new EggPolygon;
egg_tube->add_child(egg_poly);
egg_capsule->add_child(egg_poly);
egg_poly->add_vertex(cvpool->create_unique_vertex(ev0));
egg_poly->add_vertex(cvpool->create_unique_vertex(ev1));

View File

@ -79,8 +79,6 @@ init_from(FfmpegVideo *source) {
return;
}
ReMutexHolder av_holder(_av_lock);
#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(55, 45, 101)
_frame = av_frame_alloc();
_frame_out = av_frame_alloc();
@ -109,6 +107,8 @@ init_from(FfmpegVideo *source) {
_eof_known = false;
_eof_frame = 0;
ReMutexHolder av_holder(_av_lock);
// Check if we got an alpha format. Please note that some video codecs
// (eg. libvpx) change the pix_fmt after decoding the first frame, which is
// why we didn't do this earlier.

View File

@ -16,8 +16,9 @@
*/
INLINE CLP(BufferContext)::
CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg,
PreparedGraphicsObjects *pgo) :
BufferContext(&pgo->_sbuffer_residency),
PreparedGraphicsObjects *pgo,
TypedWritableReferenceCount *object) :
BufferContext(&pgo->_sbuffer_residency, object),
AdaptiveLruPage(0),
_glgsg(glgsg)
{

View File

@ -21,7 +21,8 @@
class EXPCL_GL CLP(BufferContext) : public BufferContext, public AdaptiveLruPage {
public:
INLINE CLP(BufferContext)(CLP(GraphicsStateGuardian) *glgsg,
PreparedGraphicsObjects *pgo);
PreparedGraphicsObjects *pgo,
TypedWritableReferenceCount *object);
ALLOC_DELETED_CHAIN(CLP(BufferContext));
virtual void evict_lru();

View File

@ -1413,7 +1413,7 @@ open_buffer() {
}
if (_rb_context == nullptr) {
_rb_context = new BufferContext(&(glgsg->_renderbuffer_residency));
_rb_context = new BufferContext(&(glgsg->_renderbuffer_residency), nullptr);
}
/*

View File

@ -6519,7 +6519,7 @@ prepare_shader_buffer(ShaderBuffer *data) {
if (_supports_shader_buffers) {
PStatGPUTimer timer(this, _prepare_shader_buffer_pcollector);
CLP(BufferContext) *gbc = new CLP(BufferContext)(this, _prepared_objects);
CLP(BufferContext) *gbc = new CLP(BufferContext)(this, _prepared_objects, data);
_glGenBuffers(1, &gbc->_index);
if (GLCAT.is_debug() && gl_debug_buffers) {
@ -7049,6 +7049,16 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
} else {
format = Texture::F_srgb;
}
} else if (_current_properties->get_float_color()) {
if (_current_properties->get_alpha_bits()) {
format = Texture::F_rgba32;
} else if (_current_properties->get_blue_bits()) {
format = Texture::F_rgb32;
} else if (_current_properties->get_green_bits()) {
format = Texture::F_rg32;
} else {
format = Texture::F_r32;
}
} else {
if (_current_properties->get_alpha_bits()) {
format = Texture::F_rgba;
@ -7058,7 +7068,11 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
}
if (_current_properties->get_float_color()) {
component_type = Texture::T_float;
} else if (_current_properties->get_color_bits() <= 24) {
} else if (_current_properties->get_color_bits() <= 24
&& _current_properties->get_red_bits() <= 8
&& _current_properties->get_green_bits() <= 8
&& _current_properties->get_blue_bits() <= 8
&& _current_properties->get_alpha_bits() <= 8) {
component_type = Texture::T_unsigned_byte;
} else {
component_type = Texture::T_unsigned_short;

View File

@ -2797,14 +2797,24 @@ update_shader_texture_bindings(ShaderContext *prev) {
}
if (tex->get_texture_type() != spec._desired_type) {
if (id != nullptr) {
switch (spec._part) {
case Shader::STO_named_input:
GLCAT.error()
<< "Sampler type of GLSL shader input '" << *id << "' does not "
"match type of texture " << *tex << ".\n";
} else {
break;
case Shader::STO_stage_i:
GLCAT.error()
<< "Sampler type of GLSL shader input p3d_Texture" << spec._stage
<< " does not match type of texture " << *tex << ".\n";
break;
case Shader::STO_light_i_shadow_map:
GLCAT.error()
<< "Sampler type of GLSL shader input p3d_LightSource[" << spec._stage
<< "].shadowMap does not match type of texture " << *tex << ".\n";
break;
}
// TODO: also check whether shadow sampler textures have shadow filter
// enabled.

View File

@ -11,6 +11,14 @@
* @date 2006-03-16
*/
/**
* Returns the associated object.
*/
INLINE TypedWritableReferenceCount *BufferContext::
get_object() const {
return _object;
}
/**
* Returns the number of bytes previously reported for the data object. This
* is used to track changes in the data object's allocated size; if it changes

View File

@ -19,7 +19,8 @@ TypeHandle BufferContext::_type_handle;
*
*/
BufferContext::
BufferContext(BufferResidencyTracker *residency) :
BufferContext(BufferResidencyTracker *residency, TypedWritableReferenceCount *object) :
_object(object),
_residency(residency),
_residency_state(0),
_data_size_bytes(0),

View File

@ -23,6 +23,7 @@
#include "bufferResidencyTracker.h"
class PreparedGraphicsObjects;
class TypedWritableReferenceCount;
/**
* This is a base class for those kinds of SavedContexts that occupy an
@ -36,15 +37,19 @@ class PreparedGraphicsObjects;
*/
class EXPCL_PANDA_GOBJ BufferContext : public SavedContext, private LinkedListNode {
public:
BufferContext(BufferResidencyTracker *residency);
BufferContext(BufferResidencyTracker *residency, TypedWritableReferenceCount *object);
virtual ~BufferContext();
INLINE TypedWritableReferenceCount *get_object() const;
PUBLISHED:
INLINE size_t get_data_size_bytes() const;
INLINE UpdateSeq get_modified() const;
INLINE bool get_active() const;
INLINE bool get_resident() const;
MAKE_PROPERTY(object, get_object);
MAKE_PROPERTY(data_size_bytes, get_data_size_bytes);
MAKE_PROPERTY(modified, get_modified);
MAKE_PROPERTY(active, get_active);
@ -62,6 +67,11 @@ public:
private:
void set_owning_chain(BufferContextChain *chain);
protected:
// This cannot be a PT(), because the object and the GSG both own their
// BufferContexts! That would create a circular reference count.
TypedWritableReferenceCount *_object;
private:
BufferResidencyTracker *_residency;
int _residency_state;

View File

@ -16,9 +16,8 @@
*/
INLINE IndexBufferContext::
IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
BufferContext(&pgo->_ibuffer_residency),
AdaptiveLruPage(0),
_data(data)
BufferContext(&pgo->_ibuffer_residency, data),
AdaptiveLruPage(0)
{
}
@ -27,7 +26,7 @@ IndexBufferContext(PreparedGraphicsObjects *pgo, GeomPrimitive *data) :
*/
INLINE GeomPrimitive *IndexBufferContext::
get_data() const {
return _data;
return (GeomPrimitive *)_object;
}
/**
@ -36,7 +35,7 @@ get_data() const {
*/
INLINE bool IndexBufferContext::
changed_size(const GeomPrimitivePipelineReader *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_data_size_bytes() != (size_t)reader->get_data_size_bytes();
}
@ -46,7 +45,7 @@ changed_size(const GeomPrimitivePipelineReader *reader) const {
*/
INLINE bool IndexBufferContext::
changed_usage_hint(const GeomPrimitivePipelineReader *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return _usage_hint != reader->get_usage_hint();
}
@ -56,7 +55,7 @@ changed_usage_hint(const GeomPrimitivePipelineReader *reader) const {
*/
INLINE bool IndexBufferContext::
was_modified(const GeomPrimitivePipelineReader *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_modified() != reader->get_modified();
}
@ -76,7 +75,7 @@ update_data_size_bytes(size_t new_data_size_bytes) {
*/
INLINE void IndexBufferContext::
mark_loaded(const GeomPrimitivePipelineReader *reader) {
nassertv(reader->get_object() == _data);
nassertv(reader->get_object() == get_data());
update_data_size_bytes(reader->get_data_size_bytes());
update_modified(reader->get_modified());
_usage_hint = reader->get_usage_hint();

View File

@ -50,9 +50,6 @@ public:
virtual void write(std::ostream &out, int indent_level) const;
private:
// This cannot be a PT(GeomPrimitive), because the data and the GSG both own
// their IndexBufferContexts! That would create a circular reference count.
GeomPrimitive *_data;
GeomEnums::UsageHint _usage_hint;
public:

View File

@ -270,11 +270,11 @@ void PreparedGraphicsObjects::
release_texture(TextureContext *tc) {
ReMutexHolder holder(_lock);
tc->_texture->clear_prepared(tc->get_view(), this);
tc->get_texture()->clear_prepared(tc->get_view(), this);
// We have to set the Texture pointer to NULL at this point, since the
// Texture itself might destruct at any time after it has been released.
tc->_texture = nullptr;
tc->_object = nullptr;
bool removed = (_prepared_textures.erase(tc) != 0);
nassertv(removed);
@ -307,8 +307,8 @@ release_all_textures() {
tci != _prepared_textures.end();
++tci) {
TextureContext *tc = (*tci);
tc->_texture->clear_prepared(tc->get_view(), this);
tc->_texture = nullptr;
tc->get_texture()->clear_prepared(tc->get_view(), this);
tc->_object = nullptr;
_released_textures.insert(tc);
}
@ -946,14 +946,14 @@ void PreparedGraphicsObjects::
release_vertex_buffer(VertexBufferContext *vbc) {
ReMutexHolder holder(_lock);
vbc->_data->clear_prepared(this);
vbc->get_data()->clear_prepared(this);
size_t data_size_bytes = vbc->_data->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = vbc->_data->get_usage_hint();
size_t data_size_bytes = vbc->get_data()->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = vbc->get_data()->get_usage_hint();
// We have to set the Data pointer to NULL at this point, since the Data
// itself might destruct at any time after it has been released.
vbc->_data = nullptr;
vbc->_object = nullptr;
bool removed = (_prepared_vertex_buffers.erase(vbc) != 0);
nassertv(removed);
@ -985,8 +985,8 @@ release_all_vertex_buffers() {
vbci != _prepared_vertex_buffers.end();
++vbci) {
VertexBufferContext *vbc = (VertexBufferContext *)(*vbci);
vbc->_data->clear_prepared(this);
vbc->_data = nullptr;
vbc->get_data()->clear_prepared(this);
vbc->_object = nullptr;
_released_vertex_buffers.insert(vbc);
}
@ -1061,7 +1061,7 @@ prepare_vertex_buffer_now(GeomVertexArrayData *data, GraphicsStateGuardianBase *
_vertex_buffer_cache, _vertex_buffer_cache_lru,
_vertex_buffer_cache_size);
if (vbc != nullptr) {
vbc->_data = data;
vbc->_object = data;
} else {
// Ask the GSG to create a brand new VertexBufferContext. There might be
@ -1144,14 +1144,14 @@ void PreparedGraphicsObjects::
release_index_buffer(IndexBufferContext *ibc) {
ReMutexHolder holder(_lock);
ibc->_data->clear_prepared(this);
ibc->get_data()->clear_prepared(this);
size_t data_size_bytes = ibc->_data->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = ibc->_data->get_usage_hint();
size_t data_size_bytes = ibc->get_data()->get_data_size_bytes();
GeomEnums::UsageHint usage_hint = ibc->get_data()->get_usage_hint();
// We have to set the Data pointer to NULL at this point, since the Data
// itself might destruct at any time after it has been released.
ibc->_data = nullptr;
ibc->_object = nullptr;
bool removed = (_prepared_index_buffers.erase(ibc) != 0);
nassertv(removed);
@ -1183,8 +1183,8 @@ release_all_index_buffers() {
ibci != _prepared_index_buffers.end();
++ibci) {
IndexBufferContext *ibc = (IndexBufferContext *)(*ibci);
ibc->_data->clear_prepared(this);
ibc->_data = nullptr;
ibc->get_data()->clear_prepared(this);
ibc->_object = nullptr;
_released_index_buffers.insert(ibc);
}
@ -1258,7 +1258,7 @@ prepare_index_buffer_now(GeomPrimitive *data, GraphicsStateGuardianBase *gsg) {
_index_buffer_cache, _index_buffer_cache_lru,
_index_buffer_cache_size);
if (ibc != nullptr) {
ibc->_data = data;
ibc->_object = data;
} else {
// Ask the GSG to create a brand new IndexBufferContext. There might be
@ -1341,6 +1341,13 @@ void PreparedGraphicsObjects::
release_shader_buffer(BufferContext *bc) {
ReMutexHolder holder(_lock);
ShaderBuffer *buffer = (ShaderBuffer *)bc->_object;
buffer->clear_prepared(this);
// We have to set the ShaderBuffer pointer to NULL at this point, since the
// buffer itself might destruct at any time after it has been released.
bc->_object = nullptr;
bool removed = (_prepared_shader_buffers.erase(bc) != 0);
nassertv(removed);

View File

@ -143,6 +143,31 @@ release_all() {
return num_freed;
}
/**
* Removes the indicated PreparedGraphicsObjects table from the buffer's
* table, without actually releasing the texture. This is intended to be
* called only from PreparedGraphicsObjects::release_shader_buffer(); it
* should never be called by user code.
*/
void ShaderBuffer::
clear_prepared(PreparedGraphicsObjects *prepared_objects) {
nassertv(_contexts != nullptr);
Contexts::iterator ci;
ci = _contexts->find(prepared_objects);
if (ci != _contexts->end()) {
_contexts->erase(ci);
if (_contexts->empty()) {
delete _contexts;
_contexts = nullptr;
}
} else {
// If this assertion fails, clear_prepared() was given a prepared_objects
// which the data array didn't know about.
nassert_raise("unknown PreparedGraphicsObjects");
}
}
/**
* Tells the BamReader how to create objects of type ParamValue.
*/

View File

@ -57,6 +57,9 @@ PUBLISHED:
bool release(PreparedGraphicsObjects *prepared_objects);
int release_all();
private:
void clear_prepared(PreparedGraphicsObjects *prepared_objects);
private:
uint64_t _data_size_bytes;
UsageHint _usage_hint;
@ -91,6 +94,8 @@ public:
private:
static TypeHandle _type_handle;
friend class PreparedGraphicsObjects;
};
INLINE std::ostream &operator << (std::ostream &out, const ShaderBuffer &m) {

View File

@ -16,9 +16,8 @@
*/
INLINE TextureContext::
TextureContext(PreparedGraphicsObjects *pgo, Texture *tex, int view) :
BufferContext(&pgo->_texture_residency),
BufferContext(&pgo->_texture_residency, tex),
AdaptiveLruPage(0),
_texture(tex),
_view(view)
{
}
@ -28,7 +27,7 @@ TextureContext(PreparedGraphicsObjects *pgo, Texture *tex, int view) :
*/
INLINE Texture *TextureContext::
get_texture() const {
return _texture;
return (Texture *)_object;
}
/**
@ -56,7 +55,7 @@ was_modified() const {
*/
INLINE bool TextureContext::
was_properties_modified() const {
return _properties_modified != _texture->get_properties_modified();
return _properties_modified != get_texture()->get_properties_modified();
}
/**
@ -65,7 +64,7 @@ was_properties_modified() const {
*/
INLINE bool TextureContext::
was_image_modified() const {
return _image_modified != _texture->get_image_modified();
return _image_modified != get_texture()->get_image_modified();
}
/**
@ -74,7 +73,7 @@ was_image_modified() const {
*/
INLINE bool TextureContext::
was_simple_image_modified() const {
return _simple_image_modified != _texture->get_simple_image_modified();
return _simple_image_modified != get_texture()->get_simple_image_modified();
}
/**
@ -121,8 +120,8 @@ update_data_size_bytes(size_t new_data_size_bytes) {
INLINE void TextureContext::
mark_loaded() {
// _data_size_bytes = _data->get_texture_size_bytes();
_properties_modified = _texture->get_properties_modified();
_image_modified = _texture->get_image_modified();
_properties_modified = get_texture()->get_properties_modified();
_image_modified = get_texture()->get_image_modified();
update_modified(std::max(_properties_modified, _image_modified));
// Assume the texture is now resident.
@ -135,8 +134,8 @@ mark_loaded() {
*/
INLINE void TextureContext::
mark_simple_loaded() {
_properties_modified = _texture->get_properties_modified();
_simple_image_modified = _texture->get_simple_image_modified();
_properties_modified = get_texture()->get_properties_modified();
_simple_image_modified = get_texture()->get_simple_image_modified();
update_modified(std::max(_properties_modified, _simple_image_modified));
// The texture's not exactly resident now, but some part of it is.

View File

@ -60,9 +60,6 @@ public:
virtual void write(std::ostream &out, int indent_level) const;
private:
// This cannot be a PT(Texture), because the texture and the GSG both own
// their TextureContexts! That would create a circular reference count.
Texture *_texture;
int _view;
UpdateSeq _properties_modified;
UpdateSeq _image_modified;

View File

@ -140,6 +140,12 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) {
_get_texel = get_texel_la;
break;
case Texture::F_rg16:
case Texture::F_rg32:
case Texture::F_rg:
_get_texel = get_texel_rg;
break;
case Texture::F_rgb:
case Texture::F_rgb5:
case Texture::F_rgb8:
@ -148,6 +154,7 @@ TexturePeeker(Texture *tex, Texture::CData *cdata) {
case Texture::F_rgb332:
case Texture::F_r11_g11_b10:
case Texture::F_rgb9_e5:
case Texture::F_rgb32:
_get_texel = get_texel_rgb;
break;
@ -582,6 +589,18 @@ get_texel_la(LColor &color, const unsigned char *&p, GetComponentFunc *get_compo
color[3] = (*get_component)(p);
}
/**
* Gets the color of the texel at byte p, given that the texture is in format
* F_rg or similar.
*/
void TexturePeeker::
get_texel_rg(LColor &color, const unsigned char *&p, GetComponentFunc *get_component) {
color[0] = (*get_component)(p);
color[1] = (*get_component)(p);
color[2] = 0.0f;
color[3] = 1.0f;
}
/**
* Gets the color of the texel at byte p, given that the texture is in format
* F_rgb or similar.

View File

@ -77,6 +77,7 @@ private:
static void get_texel_a(LColor &color, const unsigned char *&p, GetComponentFunc *get_component);
static void get_texel_l(LColor &color, const unsigned char *&p, GetComponentFunc *get_component);
static void get_texel_la(LColor &color, const unsigned char *&p, GetComponentFunc *get_component);
static void get_texel_rg(LColor &color, const unsigned char *&p, GetComponentFunc *get_component);
static void get_texel_rgb(LColor &color, const unsigned char *&p, GetComponentFunc *get_component);
static void get_texel_rgba(LColor &color, const unsigned char *&p, GetComponentFunc *get_component);
static void get_texel_srgb(LColor &color, const unsigned char *&p, GetComponentFunc *get_component);

View File

@ -16,9 +16,8 @@
*/
INLINE VertexBufferContext::
VertexBufferContext(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
BufferContext(&pgo->_vbuffer_residency),
AdaptiveLruPage(0),
_data(data)
BufferContext(&pgo->_vbuffer_residency, data),
AdaptiveLruPage(0)
{
}
@ -27,7 +26,7 @@ VertexBufferContext(PreparedGraphicsObjects *pgo, GeomVertexArrayData *data) :
*/
INLINE GeomVertexArrayData *VertexBufferContext::
get_data() const {
return _data;
return (GeomVertexArrayData *)_object;
}
/**
@ -36,7 +35,7 @@ get_data() const {
*/
INLINE bool VertexBufferContext::
changed_size(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_data_size_bytes() != (size_t)reader->get_data_size_bytes();
}
@ -46,7 +45,7 @@ changed_size(const GeomVertexArrayDataHandle *reader) const {
*/
INLINE bool VertexBufferContext::
changed_usage_hint(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return _usage_hint != reader->get_usage_hint();
}
@ -56,7 +55,7 @@ changed_usage_hint(const GeomVertexArrayDataHandle *reader) const {
*/
INLINE bool VertexBufferContext::
was_modified(const GeomVertexArrayDataHandle *reader) const {
nassertr(reader->get_object() == _data, false);
nassertr(reader->get_object() == get_data(), false);
return get_modified() != reader->get_modified();
}
@ -77,7 +76,7 @@ update_data_size_bytes(size_t new_data_size_bytes) {
*/
INLINE void VertexBufferContext::
mark_loaded(const GeomVertexArrayDataHandle *reader) {
nassertv(reader->get_object() == _data);
nassertv(reader->get_object() == get_data());
update_data_size_bytes(reader->get_data_size_bytes());
update_modified(reader->get_modified());
_usage_hint = reader->get_usage_hint();

View File

@ -51,10 +51,6 @@ public:
virtual void write(std::ostream &out, int indent_level) const;
private:
// This cannot be a PT(GeomVertexArrayData), because the data and the GSG
// both own their VertexBufferContexts! That would create a circular
// reference count.
GeomVertexArrayData *_data;
GeomEnums::UsageHint _usage_hint;
public:

View File

@ -280,13 +280,10 @@ write_datagram(BamWriter *manager, Datagram &dg) {
}
}
////////////////////////////////////////////////////////////////////
// Function: Camera::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.
////////////////////////////////////////////////////////////////////
/**
* Receives an array of pointers, one for each time manager->read_pointer()
* was called in fillin(). Returns the number of pointers processed.
*/
int Camera::
complete_pointers(TypedWritable **p_list, BamReader *manager) {
int pi = LensNode::complete_pointers(p_list, manager);

View File

@ -1084,6 +1084,8 @@ set_effects(const RenderEffects *effects, Thread *current_thread) {
*/
void PandaNode::
set_transform(const TransformState *transform, Thread *current_thread) {
nassertv(!transform->is_invalid());
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
@ -1120,6 +1122,8 @@ set_transform(const TransformState *transform, Thread *current_thread) {
*/
void PandaNode::
set_prev_transform(const TransformState *transform, Thread *current_thread) {
nassertv(!transform->is_invalid());
// Need to have this held before we grab any other locks.
LightMutexHolder holder(_dirty_prev_transforms._lock);
@ -3510,12 +3514,12 @@ update_cached(bool update_bounds, int pipeline_stage, PandaNode::CDLockedStageRe
const BoundingVolume **child_begin = &child_volumes[0];
const BoundingVolume **child_end = child_begin + child_volumes_i;
((BoundingVolume *)gbv)->around(child_begin, child_end);
}
// If we have a transform, apply it to the bounding volume we just
// computed.
if (!transform->is_identity()) {
gbv->xform(transform->get_mat());
// If we have a transform, apply it to the bounding volume we just
// computed.
if (!transform->is_identity()) {
gbv->xform(transform->get_mat());
}
}
cdataw->_external_bounds = gbv;
@ -3849,6 +3853,9 @@ complete_pointers(TypedWritable **p_list, BamReader *manager) {
// Mark the bounds stale.
++_next_update;
nassertr(!_transform->is_invalid(), pi);
nassertr(!_prev_transform->is_invalid(), pi);
return pi;
}

Some files were not shown because too many files have changed in this diff Show More