Merge tag 'v1.10.0' into astron-master
SDK 1.10.0 release
|
|
@ -49,7 +49,7 @@ script:
|
|||
notifications:
|
||||
irc:
|
||||
channels:
|
||||
- "chat.freenode.net#panda3d"
|
||||
- secure: "jfwHT9RHAVOGRGTMY8TpYKJI6rq8nFoIj41Y0soZdJQNWtSSFEK9AyzZeMY+2dHga7cR/X+/0NWZ2ehhedTnd9FvlzOnMWWC3K0I/b3XWbEdVEqIZnggFkKGqs82Gy3omguRC63yWupeJCcSCckIhoWbLzWy6xV8lF5WC80iXi8="
|
||||
on_success: change
|
||||
on_failure: always
|
||||
use_notice: true
|
||||
|
|
|
|||
|
|
@ -55,8 +55,8 @@ depending on whether you are on a 32-bit or 64-bit system, or you can
|
|||
[click here](https://github.com/rdb/panda3d-thirdparty) for instructions on
|
||||
building them from source.
|
||||
|
||||
http://rdb.name/thirdparty-vc14-x64.7z
|
||||
http://rdb.name/thirdparty-vc14.7z
|
||||
https://www.panda3d.org/download/panda3d-1.10.0/panda3d-1.10.0-tools-win64.zip
|
||||
https://www.panda3d.org/download/panda3d-1.10.0/panda3d-1.10.0-tools-win32.zip
|
||||
|
||||
After acquiring these dependencies, you may simply build Panda3D from the
|
||||
command prompt using the following command. (Change `14.1` to `14` if you are
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 281 KiB After Width: | Height: | Size: 144 KiB |
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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().
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
print('ThreeUpStart: Starting up environment.')
|
||||
|
||||
from pandac.PandaModules import *
|
||||
from panda3d.core import *
|
||||
|
||||
from direct.showbase.PythonUtil import *
|
||||
from direct.showbase import ThreeUpShow
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -1116,7 +1124,7 @@ HTML_EXTRA_FILES =
|
|||
# Minimum value: 0, maximum value: 359, default value: 220.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COLORSTYLE_HUE = 228
|
||||
HTML_COLORSTYLE_HUE = 251
|
||||
|
||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
|
||||
# in the HTML output. For a value of 0 the output will use grayscales only. A
|
||||
|
|
@ -1124,7 +1132,7 @@ HTML_COLORSTYLE_HUE = 228
|
|||
# Minimum value: 0, maximum value: 255, default value: 100.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COLORSTYLE_SAT = 99
|
||||
HTML_COLORSTYLE_SAT = 150
|
||||
|
||||
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
|
||||
# luminance component of the colors in the HTML output. Values below 100
|
||||
|
|
@ -1135,7 +1143,7 @@ HTML_COLORSTYLE_SAT = 99
|
|||
# Minimum value: 40, maximum value: 240, default value: 80.
|
||||
# This tag requires that the tag GENERATE_HTML is set to YES.
|
||||
|
||||
HTML_COLORSTYLE_GAMMA = 56
|
||||
HTML_COLORSTYLE_GAMMA = 39
|
||||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting this
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -862,13 +864,13 @@ HTML_STYLESHEET = $(DOXYGEN_HTML_STYLESHEET)
|
|||
# 180 is cyan, 240 is blue, 300 purple, and 360 is red again.
|
||||
# The allowed range is 0 to 359.
|
||||
|
||||
HTML_COLORSTYLE_HUE = 228
|
||||
HTML_COLORSTYLE_HUE = 251
|
||||
|
||||
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of
|
||||
# the colors in the HTML output. For a value of 0 the output will use
|
||||
# grayscales only. A value of 255 will produce the most vivid colors.
|
||||
|
||||
HTML_COLORSTYLE_SAT = 99
|
||||
HTML_COLORSTYLE_SAT = 150
|
||||
|
||||
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to
|
||||
# the luminance component of the colors in the HTML output. Values below
|
||||
|
|
@ -877,7 +879,7 @@ HTML_COLORSTYLE_SAT = 99
|
|||
# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2,
|
||||
# and 100 does not change the gamma.
|
||||
|
||||
HTML_COLORSTYLE_GAMMA = 56
|
||||
HTML_COLORSTYLE_GAMMA = 39
|
||||
|
||||
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
|
||||
# page will contain the date and time when the page was generated. Setting
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -0,0 +1,908 @@
|
|||
""" Tools for manipulating Portable Executable files.
|
||||
|
||||
This can be used, for example, to extract a list of dependencies from an .exe
|
||||
or .dll file, or to add version information and an icon resource to it. """
|
||||
|
||||
__all__ = ["PEFile"]
|
||||
|
||||
from struct import Struct, unpack, pack, pack_into
|
||||
from collections import namedtuple
|
||||
from array import array
|
||||
import time
|
||||
from io import BytesIO
|
||||
import sys
|
||||
|
||||
if sys.version_info >= (3, 0):
|
||||
unicode = str
|
||||
unichr = chr
|
||||
|
||||
# Define some internally used structures.
|
||||
RVASize = namedtuple('RVASize', ('addr', 'size'))
|
||||
impdirtab = namedtuple('impdirtab', ('lookup', 'timdat', 'forward', 'name', 'impaddr'))
|
||||
expdirtab = namedtuple('expdirtab', ('flags', 'timdat', 'majver', 'minver', 'name', 'ordinal_base', 'nentries', 'nnames', 'entries', 'names', 'ordinals'))
|
||||
|
||||
|
||||
def _unpack_zstring(mem, offs=0):
|
||||
"Read a zero-terminated string from memory."
|
||||
c = mem[offs]
|
||||
str = ""
|
||||
while c:
|
||||
str += chr(c)
|
||||
offs += 1
|
||||
c = mem[offs]
|
||||
return str
|
||||
|
||||
def _unpack_wstring(mem, offs=0):
|
||||
"Read a UCS-2 string from memory."
|
||||
name_len, = unpack('<H', mem[offs:offs+2])
|
||||
name = ""
|
||||
for i in range(name_len):
|
||||
offs += 2
|
||||
name += unichr(*unpack('<H', mem[offs:offs+2]))
|
||||
return name
|
||||
|
||||
def _padded(n, boundary):
|
||||
align = n % boundary
|
||||
if align:
|
||||
n += boundary - align
|
||||
return n
|
||||
|
||||
|
||||
class Section(object):
|
||||
_header = Struct('<8sIIIIIIHHI')
|
||||
|
||||
modified = True
|
||||
|
||||
def read_header(self, fp):
|
||||
name, vsize, vaddr, size, scnptr, relptr, lnnoptr, nreloc, nlnno, flags = \
|
||||
self._header.unpack(fp.read(40))
|
||||
|
||||
self.name = name.rstrip(b'\x00')
|
||||
self.vaddr = vaddr # Base virtual address to map to.
|
||||
self.vsize = vsize
|
||||
self.offset = scnptr # Offset of the section in the file.
|
||||
self.size = size
|
||||
self.flags = flags
|
||||
|
||||
self.modified = False
|
||||
|
||||
def write_header(self, fp):
|
||||
fp.write(self._header.pack(self.name, self.vsize, self.vaddr,
|
||||
self.size, self.offset, 0, 0, 0, 0,
|
||||
self.flags))
|
||||
|
||||
def __repr__(self):
|
||||
return "<section '%s' memory %x-%x>" % (self.name, self.vaddr, self.vaddr + self.vsize)
|
||||
|
||||
def __gt__(self, other):
|
||||
return self.vaddr > other.vaddr
|
||||
|
||||
def __lt__(self, other):
|
||||
return self.vaddr < other.vaddr
|
||||
|
||||
|
||||
class DataResource(object):
|
||||
""" A resource entry in the resource table. """
|
||||
|
||||
# Resource types.
|
||||
cursor = 1
|
||||
bitmap = 2
|
||||
icon = 3
|
||||
menu = 4
|
||||
dialog = 5
|
||||
string = 6
|
||||
font_directory = 7
|
||||
font = 8
|
||||
accelerator = 9
|
||||
rcdata = 10
|
||||
message_table = 11
|
||||
cursor_group = 12
|
||||
icon_group = 14
|
||||
version = 16
|
||||
dlg_include = 17
|
||||
plug_play = 19
|
||||
vxd = 20
|
||||
animated_cursor = 21
|
||||
animated_icon = 22
|
||||
html = 23
|
||||
manifest = 24
|
||||
|
||||
def __init__(self):
|
||||
self._ident = ()
|
||||
self.data = None
|
||||
self.code_page = 0
|
||||
|
||||
@property
|
||||
def encoding(self):
|
||||
if self.code_page == 0:
|
||||
return 'ascii'
|
||||
else:
|
||||
return 'cp%d' % (self.code_page)
|
||||
|
||||
def get_data(self):
|
||||
return self.data
|
||||
|
||||
def get_text(self, errors='strict'):
|
||||
return self.data.decode(self.encoding, errors)
|
||||
|
||||
|
||||
class IconGroupResource(object):
|
||||
code_page = 0
|
||||
type = 14
|
||||
_entry = Struct('<BBBxHHIH')
|
||||
Icon = namedtuple('Icon', ('width', 'height', 'planes', 'bpp', 'size', 'id'))
|
||||
|
||||
def __init__(self):
|
||||
self.icons = []
|
||||
|
||||
def add_icon(self, *args, **kwargs):
|
||||
self.icons.append(self.Icon(*args, **kwargs))
|
||||
|
||||
def get_data(self):
|
||||
data = bytearray(pack('<HHH', 0, 1, len(self.icons)))
|
||||
|
||||
for width, height, planes, bpp, size, id in self.icons:
|
||||
colors = 1 << (planes * bpp)
|
||||
if colors >= 256:
|
||||
colors = 0
|
||||
if width >= 256:
|
||||
width = 0
|
||||
if height >= 256:
|
||||
height = 0
|
||||
data += self._entry.pack(width, height, colors, planes, bpp, size, id)
|
||||
return data
|
||||
|
||||
def unpack_from(self, data, offs=0):
|
||||
type, count = unpack('<HH', data[offs+2:offs+6])
|
||||
offs += 6
|
||||
for i in range(count):
|
||||
width, height, colors, planes, bpp, size, id = \
|
||||
self._entry.unpack(data[offs:offs+14])
|
||||
if width == 0:
|
||||
width = 256
|
||||
if height == 0:
|
||||
height = 256
|
||||
self.icons.append(self.Icon(width, height, planes, bpp, size, id))
|
||||
offs += 14
|
||||
|
||||
|
||||
class VersionInfoResource(object):
|
||||
code_page = 0
|
||||
type = 16
|
||||
|
||||
def __init__(self):
|
||||
self.string_info = {}
|
||||
self.var_info = {}
|
||||
self.signature = 0xFEEF04BD
|
||||
self.struct_version = 0x10000
|
||||
self.file_version = (0, 0, 0, 0)
|
||||
self.product_version = (0, 0, 0, 0)
|
||||
self.file_flags_mask = 0x3f
|
||||
self.file_flags = 0
|
||||
self.file_os = 0x40004 # Windows NT
|
||||
self.file_type = 1 # Application
|
||||
self.file_subtype = 0
|
||||
self.file_date = (0, 0)
|
||||
|
||||
def get_data(self):
|
||||
# The first part of the header is pretty much fixed - we'll go
|
||||
# back later to write the struct size.
|
||||
data = bytearray(b'\x00\x004\x00\x00\x00V\x00S\x00_\x00V\x00E\x00R\x00S\x00I\x00O\x00N\x00_\x00I\x00N\x00F\x00O\x00\x00\x00\x00\x00')
|
||||
data += pack('<13I', self.signature, self.struct_version,
|
||||
self.file_version[1] | (self.file_version[0] << 16),
|
||||
self.file_version[3] | (self.file_version[2] << 16),
|
||||
self.product_version[1] | (self.product_version[0] << 16),
|
||||
self.product_version[3] | (self.product_version[2] << 16),
|
||||
self.file_flags_mask, self.file_flags,
|
||||
self.file_os, self.file_type, self.file_subtype,
|
||||
self.file_date[0], self.file_date[1])
|
||||
|
||||
self._pack_info(data, 'StringFileInfo', self.string_info)
|
||||
self._pack_info(data, 'VarFileInfo', self.var_info)
|
||||
data[0:2] = pack('<H', len(data))
|
||||
return data
|
||||
|
||||
def _pack_info(self, data, key, value):
|
||||
offset = len(data)
|
||||
|
||||
if isinstance(value, dict):
|
||||
type = 1
|
||||
value_length = 0
|
||||
elif isinstance(value, bytes) or isinstance(value, unicode):
|
||||
type = 1
|
||||
value_length = len(value) * 2 + 2
|
||||
else:
|
||||
type = 0
|
||||
value_length = len(value)
|
||||
|
||||
data += pack('<HHH', 0, value_length, type)
|
||||
|
||||
for c in key:
|
||||
data += pack('<H', ord(c))
|
||||
data += b'\x00\x00'
|
||||
if len(data) & 2:
|
||||
data += b'\x00\x00'
|
||||
assert len(data) & 3 == 0
|
||||
|
||||
if isinstance(value, dict):
|
||||
for key2, value2 in sorted(value.items(), key=lambda x:x[0]):
|
||||
self._pack_info(data, key2, value2)
|
||||
elif isinstance(value, bytes) or isinstance(value, unicode):
|
||||
for c in value:
|
||||
data += pack('<H', ord(c))
|
||||
data += b'\x00\x00'
|
||||
else:
|
||||
data += value
|
||||
if len(data) & 1:
|
||||
data += b'\x00'
|
||||
|
||||
if len(data) & 2:
|
||||
data += b'\x00\x00'
|
||||
assert len(data) & 3 == 0
|
||||
|
||||
data[offset:offset+2] = pack('<H', len(data) - offset)
|
||||
|
||||
def unpack_from(self, data):
|
||||
length, value_length = unpack('<HH', data[0:4])
|
||||
offset = 40 + value_length + (value_length & 1)
|
||||
dwords = array('I')
|
||||
dwords.fromstring(bytes(data[40:offset]))
|
||||
if len(dwords) > 0:
|
||||
self.signature = dwords[0]
|
||||
if len(dwords) > 1:
|
||||
self.struct_version = dwords[1]
|
||||
if len(dwords) > 3:
|
||||
self.file_version = \
|
||||
(int(dwords[2] >> 16), int(dwords[2] & 0xffff),
|
||||
int(dwords[3] >> 16), int(dwords[3] & 0xffff))
|
||||
if len(dwords) > 5:
|
||||
self.product_version = \
|
||||
(int(dwords[4] >> 16), int(dwords[4] & 0xffff),
|
||||
int(dwords[5] >> 16), int(dwords[5] & 0xffff))
|
||||
if len(dwords) > 7:
|
||||
self.file_flags_mask = dwords[6]
|
||||
self.file_flags = dwords[7]
|
||||
if len(dwords) > 8:
|
||||
self.file_os = dwords[8]
|
||||
if len(dwords) > 9:
|
||||
self.file_type = dwords[9]
|
||||
if len(dwords) > 10:
|
||||
self.file_subtype = dwords[10]
|
||||
if len(dwords) > 12:
|
||||
self.file_date = (dwords[11], dwords[12])
|
||||
|
||||
while offset < length:
|
||||
offset += self._unpack_info(self, data, offset)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key == 'StringFileInfo':
|
||||
return self.string_info
|
||||
elif key == 'VarFileInfo':
|
||||
return self.var_info
|
||||
else:
|
||||
raise KeyError("%s does not exist" % (key))
|
||||
|
||||
def __contains__(self, key):
|
||||
return key in ('StringFileInfo', 'VarFileInfo')
|
||||
|
||||
def _unpack_info(self, dict, data, offset):
|
||||
length, value_length, type = unpack('<HHH', data[offset:offset+6])
|
||||
assert length > 0
|
||||
end = offset + length
|
||||
offset += 6
|
||||
key = ""
|
||||
c, = unpack('<H', data[offset:offset+2])
|
||||
offset += 2
|
||||
while c:
|
||||
key += unichr(c)
|
||||
c, = unpack('<H', data[offset:offset+2])
|
||||
offset += 2
|
||||
|
||||
# Padding bytes to align value to 32-bit boundary.
|
||||
offset = _padded(offset, 4)
|
||||
|
||||
if value_length > 0:
|
||||
# It contains a value.
|
||||
if type:
|
||||
# It's a wchar array value.
|
||||
value = u""
|
||||
c, = unpack('<H', data[offset:offset+2])
|
||||
offset += 2
|
||||
while c:
|
||||
value += unichr(c)
|
||||
c, = unpack('<H', data[offset:offset+2])
|
||||
offset += 2
|
||||
else:
|
||||
# A binary value.
|
||||
value = bytes(data[offset:offset+value_length])
|
||||
offset += value_length
|
||||
dict[key] = value
|
||||
else:
|
||||
# It contains sub-entries.
|
||||
if key not in dict:
|
||||
dict[key] = {}
|
||||
subdict = dict[key]
|
||||
while offset < end:
|
||||
offset += self._unpack_info(subdict, data, offset)
|
||||
|
||||
# Padding bytes to pad value to 32-bit boundary.
|
||||
return _padded(length, 4)
|
||||
|
||||
|
||||
class ResourceTable(object):
|
||||
""" A table in the resource directory. """
|
||||
|
||||
_header = Struct('<IIHHHH')
|
||||
|
||||
def __init__(self, ident=()):
|
||||
self.flags = 0
|
||||
self.timdat = 0
|
||||
self.version = (0, 0)
|
||||
self._name_leaves = []
|
||||
self._id_leaves = []
|
||||
self._ident = ident
|
||||
self._strings_size = 0 # Amount of space occupied by table keys.
|
||||
self._descs_size = 0
|
||||
|
||||
def __getitem__(self, key):
|
||||
if isinstance(key, int):
|
||||
leaves = self._id_leaves
|
||||
else:
|
||||
leaves = self._name_leaves
|
||||
|
||||
i = 0
|
||||
while i < len(leaves):
|
||||
idname, leaf = leaves[i]
|
||||
if idname >= key:
|
||||
if key == idname:
|
||||
return leaf
|
||||
break
|
||||
i += 1
|
||||
if not isinstance(key, int):
|
||||
self._strings_size += _padded(len(key) * 2 + 2, 4)
|
||||
leaf = ResourceTable(ident=self._ident + (key,))
|
||||
leaves.insert(i, (key, leaf))
|
||||
return leaf
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
""" Adds the given item to the table. Maintains sort order. """
|
||||
if isinstance(key, int):
|
||||
leaves = self._id_leaves
|
||||
else:
|
||||
leaves = self._name_leaves
|
||||
|
||||
if not isinstance(value, ResourceTable):
|
||||
self._descs_size += 16
|
||||
|
||||
value._ident = self._ident + (key,)
|
||||
i = 0
|
||||
while i < len(leaves):
|
||||
idname, leaf = leaves[i]
|
||||
if idname >= key:
|
||||
if key == idname:
|
||||
if not isinstance(leaves[i][1], ResourceTable):
|
||||
self._descs_size -= 16
|
||||
leaves[i] = (key, value)
|
||||
return
|
||||
break
|
||||
i += 1
|
||||
if not isinstance(key, int):
|
||||
self._strings_size += _padded(len(key) * 2 + 2, 4)
|
||||
leaves.insert(i, (key, value))
|
||||
|
||||
def __len__(self):
|
||||
return len(self._name_leaves) + len(self._id_leaves)
|
||||
|
||||
def __iter__(self):
|
||||
keys = []
|
||||
for name, leaf in self._name_leaves:
|
||||
keys.append(name)
|
||||
for id, leaf in self._id_leaves:
|
||||
keys.append(id)
|
||||
return iter(keys)
|
||||
|
||||
def items(self):
|
||||
return self._name_leaves + self._id_leaves
|
||||
|
||||
def count_resources(self):
|
||||
"""Counts all of the resources."""
|
||||
count = 0
|
||||
for key, leaf in self._name_leaves + self._id_leaves:
|
||||
if isinstance(leaf, ResourceTable):
|
||||
count += leaf.count_resources()
|
||||
else:
|
||||
count += 1
|
||||
return count
|
||||
|
||||
def get_nested_tables(self):
|
||||
"""Returns all tables in this table and subtables."""
|
||||
# First we yield child tables, then nested tables. This is the
|
||||
# order in which pack_into assumes the tables will be written.
|
||||
for key, leaf in self._name_leaves + self._id_leaves:
|
||||
if isinstance(leaf, ResourceTable):
|
||||
yield leaf
|
||||
|
||||
for key, leaf in self._name_leaves + self._id_leaves:
|
||||
if isinstance(leaf, ResourceTable):
|
||||
for table in leaf.get_nested_tables():
|
||||
yield table
|
||||
|
||||
def pack_header(self, data, offs):
|
||||
self._header.pack_into(data, offs, self.flags, self.timdat,
|
||||
self.version[0], self.version[1],
|
||||
len(self._name_leaves), len(self._id_leaves))
|
||||
|
||||
def unpack_from(self, mem, addr=0, offs=0):
|
||||
start = addr + offs
|
||||
self.flags, self.timdat, majver, minver, nnames, nids = \
|
||||
self._header.unpack(mem[start:start+16])
|
||||
self.version = (majver, minver)
|
||||
start += 16
|
||||
|
||||
# Subtables/entries specified by string name.
|
||||
self._name_leaves = []
|
||||
for i in range(nnames):
|
||||
name_p, data = unpack('<II', mem[start:start+8])
|
||||
if name_p & 0x80000000:
|
||||
name = _unpack_wstring(mem, addr + (name_p & 0x7fffffff))
|
||||
else:
|
||||
# Not sure what to do with this; I don't have a file with this.
|
||||
name = str(name_p)
|
||||
|
||||
if data & 0x80000000:
|
||||
entry = ResourceTable(self._ident + (name,))
|
||||
entry.unpack_from(mem, addr, data & 0x7fffffff)
|
||||
else:
|
||||
entry = self._unpack_data_entry(mem, addr + data, ident=self._ident+(name,))
|
||||
self._descs_size += 16
|
||||
self._name_leaves.append((name, entry))
|
||||
self._strings_size += _padded(len(name) * 2 + 2, 4)
|
||||
start += 8
|
||||
|
||||
# Subtables/entries specified by integer ID.
|
||||
self._id_leaves = []
|
||||
for i in range(nids):
|
||||
id, data = unpack('<II', mem[start:start+8])
|
||||
if data & 0x80000000:
|
||||
entry = ResourceTable(self._ident + (id,))
|
||||
entry.unpack_from(mem, addr, data & 0x7fffffff)
|
||||
else:
|
||||
entry = self._unpack_data_entry(mem, addr + data, ident=self._ident+(id,))
|
||||
self._descs_size += 16
|
||||
self._id_leaves.append((id, entry))
|
||||
start += 8
|
||||
|
||||
def _unpack_data_entry(self, mem, addr, ident):
|
||||
rva, size, code_page = unpack('<III', mem[addr:addr+12])
|
||||
type, name, lang = ident
|
||||
#print("%s/%s/%s: %s [%s]" % (type, name, lang, size, code_page))
|
||||
|
||||
data = mem[rva:rva+size]
|
||||
|
||||
if type == VersionInfoResource.type:
|
||||
entry = VersionInfoResource()
|
||||
entry.unpack_from(data)
|
||||
elif type == IconGroupResource.type:
|
||||
entry = IconGroupResource()
|
||||
entry.unpack_from(data)
|
||||
else:
|
||||
entry = DataResource()
|
||||
entry.data = data
|
||||
entry.code_page = code_page
|
||||
|
||||
|
||||
class PEFile(object):
|
||||
|
||||
imports = ()
|
||||
|
||||
def open(self, fn, mode='r'):
|
||||
if 'b' not in mode:
|
||||
mode += 'b'
|
||||
self.fp = open(fn, mode)
|
||||
self.read(self.fp)
|
||||
|
||||
def close(self):
|
||||
self.fp.close()
|
||||
|
||||
def read(self, fp):
|
||||
""" Reads a PE file from the given file object, which must be opened
|
||||
in binary mode. """
|
||||
|
||||
# Read position of header.
|
||||
fp.seek(0x3c)
|
||||
offset, = unpack('<I', fp.read(4))
|
||||
|
||||
fp.seek(offset)
|
||||
if fp.read(4) != b'PE\0\0':
|
||||
raise ValueError("Invalid PE file.")
|
||||
|
||||
# Read the COFF header.
|
||||
self.machine, nscns, timdat, symptr, nsyms, opthdr, flags = \
|
||||
unpack('<HHIIIHH', fp.read(20))
|
||||
|
||||
if nscns == 0:
|
||||
raise ValueError("No sections found.")
|
||||
|
||||
if not opthdr:
|
||||
raise ValueError("No opthdr found.")
|
||||
|
||||
# Read part of the opthdr.
|
||||
magic, self.code_size, self.initialized_size, self.uninitialized_size = \
|
||||
unpack('<HxxIII', fp.read(16))
|
||||
|
||||
# Read alignments.
|
||||
fp.seek(16, 1)
|
||||
self.section_alignment, self.file_alignment = unpack('<II', fp.read(8))
|
||||
|
||||
# Read header/image sizes.
|
||||
fp.seek(16, 1)
|
||||
self.image_size, self.header_size = unpack('<II', fp.read(8))
|
||||
|
||||
if magic == 0x010b: # 32-bit.
|
||||
fp.seek(28, 1)
|
||||
elif magic == 0x20B: # 64-bit.
|
||||
fp.seek(44, 1)
|
||||
else:
|
||||
raise ValueError("unknown type 0x%x" % (magic))
|
||||
|
||||
self.rva_offset = fp.tell()
|
||||
numrvas, = unpack('<I', fp.read(4))
|
||||
|
||||
self.exp_rva = RVASize(0, 0)
|
||||
self.imp_rva = RVASize(0, 0)
|
||||
self.res_rva = RVASize(0, 0)
|
||||
|
||||
# Locate the relevant tables in memory.
|
||||
if numrvas >= 1:
|
||||
self.exp_rva = RVASize(*unpack('<II', fp.read(8)))
|
||||
if numrvas >= 2:
|
||||
self.imp_rva = RVASize(*unpack('<II', fp.read(8)))
|
||||
if numrvas >= 3:
|
||||
self.res_rva = RVASize(*unpack('<II', fp.read(8)))
|
||||
|
||||
# Skip the rest of the tables.
|
||||
if numrvas >= 4:
|
||||
fp.seek((numrvas - 3) * 8, 1)
|
||||
|
||||
# Loop through the sections to find the ones containing our tables.
|
||||
self.sections = []
|
||||
for i in range(nscns):
|
||||
section = Section()
|
||||
section.read_header(fp)
|
||||
self.sections.append(section)
|
||||
|
||||
self.sections.sort()
|
||||
|
||||
# Read the sections into some kind of virtual memory.
|
||||
self.vmem = bytearray(self.sections[-1].vaddr + self.sections[-1].size)
|
||||
memview = memoryview(self.vmem)
|
||||
|
||||
for section in self.sections:
|
||||
fp.seek(section.offset)
|
||||
fp.readinto(memview[section.vaddr:section.vaddr+section.size])
|
||||
|
||||
# Read the import table.
|
||||
start = self.imp_rva.addr
|
||||
dir = impdirtab(*unpack('<IIIII', self.vmem[start:start+20]))
|
||||
|
||||
imports = []
|
||||
while dir.name and dir.lookup:
|
||||
name = _unpack_zstring(self.vmem, dir.name)
|
||||
imports.append(name)
|
||||
|
||||
start += 20
|
||||
dir = impdirtab(*unpack('<IIIII', self.vmem[start:start+20]))
|
||||
|
||||
# Make it a tuple to indicate we don't support modifying it for now.
|
||||
self.imports = tuple(imports)
|
||||
|
||||
# Read the resource tables from the .rsrc section.
|
||||
self.resources = ResourceTable()
|
||||
if self.res_rva.addr and self.res_rva.size:
|
||||
self.resources.unpack_from(self.vmem, self.res_rva.addr)
|
||||
|
||||
def get_export_address(self, symbol_name):
|
||||
""" Finds the virtual address for a named export symbol. """
|
||||
|
||||
if isinstance(symbol_name, bytes):
|
||||
symbol_name = symbol_name.decode('ascii')
|
||||
|
||||
start = self.exp_rva.addr
|
||||
expdir = expdirtab(*unpack('<IIHHIIIIIII', self.vmem[start:start+40]))
|
||||
if expdir.nnames == 0 or expdir.ordinals == 0 or expdir.names == 0:
|
||||
return None
|
||||
|
||||
nptr = expdir.names
|
||||
optr = expdir.ordinals
|
||||
for i in range(expdir.nnames):
|
||||
name_rva, = unpack('<I', self.vmem[nptr:nptr+4])
|
||||
ordinal, = unpack('<H', self.vmem[optr:optr+2])
|
||||
if name_rva != 0:
|
||||
name = _unpack_zstring(self.vmem, name_rva)
|
||||
if name == symbol_name:
|
||||
assert ordinal >= 0 and ordinal < expdir.nentries
|
||||
start = expdir.entries + 4 * ordinal
|
||||
addr, = unpack('<I', self.vmem[start:start+4])
|
||||
return addr
|
||||
nptr += 4
|
||||
optr += 2
|
||||
|
||||
def get_address_offset(self, addr):
|
||||
""" Turns an address into a offset relative to the file beginning. """
|
||||
|
||||
section = self.get_address_section(addr)
|
||||
if section is not None:
|
||||
return (addr - section.vaddr) + section.offset
|
||||
|
||||
def get_address_section(self, addr):
|
||||
""" Returns the section that this virtual address belongs to. """
|
||||
|
||||
for section in self.sections:
|
||||
if addr >= section.vaddr and addr < section.vaddr + section.size:
|
||||
return section
|
||||
|
||||
def add_icon(self, icon, ordinal=2):
|
||||
""" Adds an icon resource from the given Icon object. Requires
|
||||
calling add_resource_section() afterwards. """
|
||||
|
||||
group = IconGroupResource()
|
||||
self.resources[group.type][ordinal][1033] = group
|
||||
|
||||
images = sorted(icon.images.items(), key=lambda x:-x[0])
|
||||
id = 1
|
||||
|
||||
# Write 8-bpp image headers for sizes under 256x256.
|
||||
for size, image in images:
|
||||
if size >= 256:
|
||||
continue
|
||||
|
||||
xorsize = size
|
||||
if xorsize % 4 != 0:
|
||||
xorsize += 4 - (xorsize % 4)
|
||||
andsize = (size + 7) >> 3
|
||||
if andsize % 4 != 0:
|
||||
andsize += 4 - (andsize % 4)
|
||||
datasize = 40 + 256 * 4 + (xorsize + andsize) * size
|
||||
group.add_icon(size, size, 1, 8, datasize, id)
|
||||
|
||||
buf = BytesIO()
|
||||
icon._write_bitmap(buf, image, size, 8)
|
||||
|
||||
res = DataResource()
|
||||
res.data = buf.getvalue()
|
||||
self.resources[3][id][1033] = res
|
||||
id += 1
|
||||
|
||||
# And now the 24/32 bpp versions.
|
||||
for size, image in images:
|
||||
if size > 256:
|
||||
continue
|
||||
|
||||
# Calculate the size so we can write the offset within the file.
|
||||
if image.hasAlpha():
|
||||
bpp = 32
|
||||
xorsize = size * 4
|
||||
else:
|
||||
bpp = 24
|
||||
xorsize = size * 3 + (-(size * 3) & 3)
|
||||
andsize = (size + 7) >> 3
|
||||
if andsize % 4 != 0:
|
||||
andsize += 4 - (andsize % 4)
|
||||
datasize = 40 + (xorsize + andsize) * size
|
||||
|
||||
buf = BytesIO()
|
||||
icon._write_bitmap(buf, image, size, bpp)
|
||||
|
||||
res = DataResource()
|
||||
res.data = buf.getvalue()
|
||||
self.resources[3][id][1033] = res
|
||||
group.add_icon(size, size, 1, bpp, datasize, id)
|
||||
id += 1
|
||||
|
||||
def add_section(self, name, flags, data):
|
||||
""" Adds a new section with the given name, flags and data. The
|
||||
virtual address space is automatically resized to fit the new data.
|
||||
|
||||
Returns the newly created Section object. """
|
||||
|
||||
if isinstance(name, unicode):
|
||||
name = name.encode('ascii')
|
||||
|
||||
section = Section()
|
||||
section.name = name
|
||||
section.flags = flags
|
||||
|
||||
# Put it at the end of all the other sections.
|
||||
section.offset = 0
|
||||
for s in self.sections:
|
||||
section.offset = max(section.offset, s.offset + s.size)
|
||||
|
||||
# Align the offset.
|
||||
section.offset = _padded(section.offset, self.file_alignment)
|
||||
|
||||
# Find a place to put it in the virtual address space.
|
||||
section.vaddr = len(self.vmem)
|
||||
align = section.vaddr % self.section_alignment
|
||||
if align:
|
||||
pad = self.section_alignment - align
|
||||
self.vmem += bytearray(pad)
|
||||
section.vaddr += pad
|
||||
|
||||
section.vsize = len(data)
|
||||
section.size = _padded(section.vsize, self.file_alignment)
|
||||
self.vmem += data
|
||||
self.sections.append(section)
|
||||
|
||||
# Update the size tallies from the opthdr.
|
||||
self.image_size += _padded(section.vsize, self.section_alignment)
|
||||
if flags & 0x20:
|
||||
self.code_size += section.size
|
||||
if flags & 0x40:
|
||||
self.initialized_size += section.size
|
||||
if flags & 0x80:
|
||||
self.uninitialized_size += section.size
|
||||
|
||||
return section
|
||||
|
||||
def add_version_info(self, file_ver, product_ver, data, lang=1033, codepage=1200):
|
||||
""" Adds a version info resource to the file. """
|
||||
|
||||
if "FileVersion" not in data:
|
||||
data["FileVersion"] = '.'.join(file_ver)
|
||||
if "ProductVersion" not in data:
|
||||
data["ProductVersion"] = '.'.join(product_ver)
|
||||
|
||||
assert len(file_ver) == 4
|
||||
assert len(product_ver) == 4
|
||||
|
||||
res = VersionInfoResource()
|
||||
res.file_version = file_ver
|
||||
res.product_version = product_ver
|
||||
res.string_info = {
|
||||
"%04x%04x" % (lang, codepage): data
|
||||
}
|
||||
res.var_info = {
|
||||
"Translation": bytearray(pack("<HH", lang, codepage))
|
||||
}
|
||||
|
||||
self.resources[16][1][lang] = res
|
||||
|
||||
def add_resource_section(self):
|
||||
""" Adds a resource section to the file containing the resources that
|
||||
were previously added via add_icon et al. Assumes the file does not
|
||||
contain a resource section yet. """
|
||||
|
||||
# Calculate how much space to reserve.
|
||||
tables = [self.resources] + list(self.resources.get_nested_tables())
|
||||
table_size = 0
|
||||
string_size = 0
|
||||
desc_size = 16 * self.resources.count_resources()
|
||||
|
||||
for table in tables:
|
||||
table._offset = table_size
|
||||
table_size += 16 + 8 * len(table)
|
||||
string_size += table._strings_size
|
||||
desc_size += table._descs_size
|
||||
|
||||
# Now write the actual data.
|
||||
tbl_offs = 0
|
||||
str_offs = table_size
|
||||
desc_offs = str_offs + string_size
|
||||
data_offs = desc_offs + desc_size
|
||||
data = bytearray(data_offs)
|
||||
data_addr = _padded(len(self.vmem), self.section_alignment) + data_offs
|
||||
|
||||
for table in tables:
|
||||
table.pack_header(data, tbl_offs)
|
||||
|
||||
tbl_offs += 16
|
||||
|
||||
for name, leaf in table._name_leaves:
|
||||
if isinstance(leaf, ResourceTable):
|
||||
pack_into('<II', data, tbl_offs, str_offs | 0x80000000, leaf._offset | 0x80000000)
|
||||
else:
|
||||
pack_into('<II', data, tbl_offs, str_offs | 0x80000000, desc_offs)
|
||||
resdata = leaf.get_data()
|
||||
pack_into('<IIII', data, desc_offs, data_addr, len(resdata), leaf.code_page, 0)
|
||||
data += resdata
|
||||
desc_offs += 16
|
||||
data_addr += len(resdata)
|
||||
align = len(resdata) & 3
|
||||
if align:
|
||||
data += bytearray(4 - align)
|
||||
data_addr += 4 - align
|
||||
tbl_offs += 8
|
||||
|
||||
# Pack the name into the string table.
|
||||
pack_into('<H', data, str_offs, len(name))
|
||||
str_offs += 2
|
||||
for c in name:
|
||||
pack_into('<H', data, str_offs, ord(c))
|
||||
str_offs += 2
|
||||
str_offs = _padded(str_offs, 4)
|
||||
|
||||
for id, leaf in table._id_leaves:
|
||||
if isinstance(leaf, ResourceTable):
|
||||
pack_into('<II', data, tbl_offs, id, leaf._offset | 0x80000000)
|
||||
else:
|
||||
pack_into('<II', data, tbl_offs, id, desc_offs)
|
||||
resdata = leaf.get_data()
|
||||
pack_into('<IIII', data, desc_offs, data_addr, len(resdata), leaf.code_page, 0)
|
||||
data += resdata
|
||||
desc_offs += 16
|
||||
data_addr += len(resdata)
|
||||
align = len(resdata) & 3
|
||||
if align:
|
||||
data += bytearray(4 - align)
|
||||
data_addr += 4 - align
|
||||
tbl_offs += 8
|
||||
|
||||
flags = 0x40000040 # readable, contains initialized data
|
||||
section = self.add_section('.rsrc', flags, data)
|
||||
self.res_rva = RVASize(section.vaddr, section.vsize)
|
||||
|
||||
def write_changes(self):
|
||||
""" Assuming the file was opened in read-write mode, writes back the
|
||||
changes made via this class to the .exe file. """
|
||||
|
||||
fp = self.fp
|
||||
# Read position of header.
|
||||
fp.seek(0x3c)
|
||||
offset, = unpack('<I', fp.read(4))
|
||||
|
||||
fp.seek(offset)
|
||||
if fp.read(4) != b'PE\0\0':
|
||||
raise ValueError("Invalid PE file.")
|
||||
|
||||
# Sync read/write pointer. Necessary before write. Bug in Python?
|
||||
fp.seek(fp.tell())
|
||||
|
||||
# Rewrite the first part of the COFF header.
|
||||
timdat = int(time.time())
|
||||
fp.write(pack('<HHI', self.machine, len(self.sections), timdat))
|
||||
|
||||
# Write calculated init and uninitialised sizes to the opthdr.
|
||||
fp.seek(16, 1)
|
||||
fp.write(pack('<III', self.code_size, self.initialized_size, self.uninitialized_size))
|
||||
|
||||
# Same for the image and header size.
|
||||
fp.seek(40, 1)
|
||||
fp.write(pack('<II', self.image_size, self.header_size))
|
||||
|
||||
# Write the modified RVA table.
|
||||
fp.seek(self.rva_offset)
|
||||
numrvas, = unpack('<I', fp.read(4))
|
||||
assert numrvas >= 3
|
||||
|
||||
fp.seek(self.rva_offset + 4)
|
||||
if numrvas >= 1:
|
||||
fp.write(pack('<II', *self.exp_rva))
|
||||
if numrvas >= 2:
|
||||
fp.write(pack('<II', *self.imp_rva))
|
||||
if numrvas >= 3:
|
||||
fp.write(pack('<II', *self.res_rva))
|
||||
|
||||
# Skip the rest of the tables.
|
||||
if numrvas >= 4:
|
||||
fp.seek((numrvas - 3) * 8, 1)
|
||||
|
||||
# Write the modified section headers.
|
||||
for section in self.sections:
|
||||
section.write_header(fp)
|
||||
assert fp.tell() <= self.header_size
|
||||
|
||||
# Write the section data of modified sections.
|
||||
for section in self.sections:
|
||||
if not section.modified:
|
||||
continue
|
||||
|
||||
fp.seek(section.offset)
|
||||
size = min(section.vsize, section.size)
|
||||
fp.write(self.vmem[section.vaddr:section.vaddr+size])
|
||||
|
||||
pad = section.size - size
|
||||
assert pad >= 0
|
||||
if pad > 0:
|
||||
fp.write(bytearray(pad))
|
||||
|
||||
section.modified = False
|
||||
|
|
@ -59,7 +59,7 @@ Options::
|
|||
import getopt
|
||||
import sys
|
||||
import os
|
||||
from direct.showutil import FreezeTool
|
||||
from . import FreezeTool
|
||||
|
||||
def usage(code, msg = ''):
|
||||
if __doc__:
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,13 @@ clunky approach. - Josh
|
|||
"""
|
||||
|
||||
from .FilterManager import FilterManager
|
||||
from .filterBloomI import BLOOM_I
|
||||
from .filterBloomX import BLOOM_X
|
||||
from .filterBloomY import BLOOM_Y
|
||||
from .filterBlurX import BLUR_X
|
||||
from .filterBlurY import BLUR_Y
|
||||
from .filterCopy import COPY
|
||||
from .filterDown4 import DOWN_4
|
||||
from panda3d.core import LVecBase4, LPoint2
|
||||
from panda3d.core import Filename
|
||||
from panda3d.core import AuxBitplaneAttrib
|
||||
|
|
@ -102,12 +109,6 @@ class CommonFilters:
|
|||
self.task = None
|
||||
self.cleanup()
|
||||
|
||||
def loadShader(self, name):
|
||||
fn = os.path.join(os.path.abspath(os.path.dirname(__file__)), name)
|
||||
fn = Filename.fromOsSpecific(fn)
|
||||
fn.makeTrueCase()
|
||||
return Shader.load(fn)
|
||||
|
||||
def cleanup(self):
|
||||
self.manager.cleanup()
|
||||
self.textures = {}
|
||||
|
|
@ -187,9 +188,9 @@ class CommonFilters:
|
|||
self.blur.append(self.manager.renderQuadInto("filter-blur0", colortex=blur0,div=2))
|
||||
self.blur.append(self.manager.renderQuadInto("filter-blur1", colortex=blur1))
|
||||
self.blur[0].setShaderInput("src", self.textures["color"])
|
||||
self.blur[0].setShader(self.loadShader("filter-blurx.sha"))
|
||||
self.blur[0].setShader(Shader.make(BLUR_X, Shader.SL_Cg))
|
||||
self.blur[1].setShaderInput("src", blur0)
|
||||
self.blur[1].setShader(self.loadShader("filter-blury.sha"))
|
||||
self.blur[1].setShader(Shader.make(BLUR_Y, Shader.SL_Cg))
|
||||
|
||||
if ("AmbientOcclusion" in configuration):
|
||||
ssao0=self.textures["ssao0"]
|
||||
|
|
@ -203,9 +204,9 @@ class CommonFilters:
|
|||
self.ssao[0].setShaderInput("random", loader.loadTexture("maps/random.rgb"))
|
||||
self.ssao[0].setShader(Shader.make(SSAO_BODY % configuration["AmbientOcclusion"].numsamples, Shader.SL_Cg))
|
||||
self.ssao[1].setShaderInput("src", ssao0)
|
||||
self.ssao[1].setShader(self.loadShader("filter-blurx.sha"))
|
||||
self.ssao[1].setShader(Shader.make(BLUR_X, Shader.SL_Cg))
|
||||
self.ssao[2].setShaderInput("src", ssao1)
|
||||
self.ssao[2].setShader(self.loadShader("filter-blury.sha"))
|
||||
self.ssao[2].setShader(Shader.make(BLUR_Y, Shader.SL_Cg))
|
||||
|
||||
if ("Bloom" in configuration):
|
||||
bloomconf = configuration["Bloom"]
|
||||
|
|
@ -215,25 +216,28 @@ class CommonFilters:
|
|||
bloom3=self.textures["bloom3"]
|
||||
if (bloomconf.size == "large"):
|
||||
scale=8
|
||||
downsampler="filter-down4"
|
||||
downsamplerName="filter-down4"
|
||||
downsampler=DOWN_4
|
||||
elif (bloomconf.size == "medium"):
|
||||
scale=4
|
||||
downsampler="filter-copy"
|
||||
downsamplerName="filter-copy"
|
||||
downsampler=COPY
|
||||
else:
|
||||
scale=2
|
||||
downsampler="filter-copy"
|
||||
downsamplerName="filter-copy"
|
||||
downsampler=COPY
|
||||
self.bloom.append(self.manager.renderQuadInto("filter-bloomi", colortex=bloom0, div=2, align=scale))
|
||||
self.bloom.append(self.manager.renderQuadInto(downsampler, colortex=bloom1, div=scale, align=scale))
|
||||
self.bloom.append(self.manager.renderQuadInto(downsamplerName, colortex=bloom1, div=scale, align=scale))
|
||||
self.bloom.append(self.manager.renderQuadInto("filter-bloomx", colortex=bloom2, div=scale, align=scale))
|
||||
self.bloom.append(self.manager.renderQuadInto("filter-bloomy", colortex=bloom3, div=scale, align=scale))
|
||||
self.bloom[0].setShaderInput("src", self.textures["color"])
|
||||
self.bloom[0].setShader(self.loadShader("filter-bloomi.sha"))
|
||||
self.bloom[0].setShader(Shader.make(BLOOM_I, Shader.SL_Cg))
|
||||
self.bloom[1].setShaderInput("src", bloom0)
|
||||
self.bloom[1].setShader(self.loadShader(downsampler + ".sha"))
|
||||
self.bloom[1].setShader(Shader.make(downsampler, Shader.SL_Cg))
|
||||
self.bloom[2].setShaderInput("src", bloom1)
|
||||
self.bloom[2].setShader(self.loadShader("filter-bloomx.sha"))
|
||||
self.bloom[2].setShader(Shader.make(BLOOM_X, Shader.SL_Cg))
|
||||
self.bloom[3].setShaderInput("src", bloom2)
|
||||
self.bloom[3].setShader(self.loadShader("filter-bloomy.sha"))
|
||||
self.bloom[3].setShader(Shader.make(BLOOM_Y, Shader.SL_Cg))
|
||||
|
||||
texcoords = {}
|
||||
texcoordPadding = {}
|
||||
|
|
@ -558,7 +562,6 @@ class CommonFilters:
|
|||
set_cartoon_ink = setCartoonInk
|
||||
del_bloom = delBloom
|
||||
del_ambient_occlusion = delAmbientOcclusion
|
||||
load_shader = loadShader
|
||||
set_blur_sharpen = setBlurSharpen
|
||||
del_blur_sharpen = delBlurSharpen
|
||||
del_volumetric_lighting = delVolumetricLighting
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
BLOOM_I = """
|
||||
//Cg
|
||||
//
|
||||
// blend.rgb
|
||||
|
|
@ -23,7 +24,7 @@
|
|||
// trigger.y
|
||||
//
|
||||
// Must be equal to (1.0/(maxtrigger-mintrigger)) where
|
||||
//
|
||||
//
|
||||
// mintrigger is the minimum brightness to trigger a bloom,
|
||||
// and maxtrigger is the brightness at which the bloom
|
||||
// reaches maximum intensity.
|
||||
|
|
@ -83,3 +84,4 @@ void fshader(float2 l_texcoordNW : TEXCOORD0,
|
|||
o_color = (colorNW + colorNE + colorSW + colorSE) * 0.25;
|
||||
}
|
||||
|
||||
"""
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
BLOOM_X = """
|
||||
//Cg
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
|
|
@ -46,3 +47,4 @@ void fshader(float4 l_texcoord0 : TEXCOORD0,
|
|||
color += 50 * tex2D(k_src, l_texcoord2.zw);
|
||||
o_color = color / 1200.0;
|
||||
}
|
||||
"""
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
BLOOM_Y = """
|
||||
//Cg
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
|
|
@ -37,3 +38,4 @@ void fshader(float4 l_texcoord0 : TEXCOORD0,
|
|||
o_color = color / 1200.0;
|
||||
o_color = o_color * k_intensity;
|
||||
}
|
||||
"""
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
BLUR_X = """
|
||||
//Cg
|
||||
//
|
||||
//Cg profile arbvp1 arbfp1
|
||||
|
|
@ -33,3 +34,4 @@ void fshader(float2 l_texcoord0 : TEXCOORD0,
|
|||
o_color.w = 1;
|
||||
}
|
||||
|
||||
"""
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
BLUR_Y = """
|
||||
//Cg
|
||||
//
|
||||
//Cg profile arbvp1 arbfp1
|
||||
|
|
@ -32,4 +33,4 @@ void fshader(float2 l_texcoord0 : TEXCOORD0,
|
|||
o_color /= 7;
|
||||
o_color.w = 1;
|
||||
}
|
||||
|
||||
"""
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
COPY = """
|
||||
//Cg
|
||||
|
||||
|
||||
|
|
@ -17,4 +18,4 @@ void fshader(float2 l_texcoord : TEXCOORD0,
|
|||
{
|
||||
o_color = tex2D(k_src, l_texcoord);
|
||||
}
|
||||
|
||||
"""
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
DOWN_4 = """
|
||||
//Cg
|
||||
|
||||
void vshader(float4 vtx_position : POSITION,
|
||||
|
|
@ -30,4 +31,4 @@ void fshader(float2 l_texcoordNW : TEXCOORD0,
|
|||
float4 colorSE = tex2D(k_src, l_texcoordSE);
|
||||
o_color = (colorNW + colorNE + colorSW + colorSE);
|
||||
}
|
||||
|
||||
"""
|
||||
|
|
@ -19,7 +19,7 @@ from direct.p3d.SeqValue import SeqValue
|
|||
from direct.p3d.HostInfo import HostInfo
|
||||
from direct.showbase import Loader
|
||||
from direct.showbase import AppRunnerGlobal
|
||||
from direct.showutil import FreezeTool
|
||||
from direct.dist import FreezeTool
|
||||
from direct.directnotify.DirectNotifyGlobal import *
|
||||
|
||||
vfs = VirtualFileSystem.getGlobalPtr()
|
||||
|
|
|
|||
|
|
@ -71,10 +71,6 @@ class panda3d(package):
|
|||
if sys.version_info < (3, 0):
|
||||
module('encodings.string_escape')
|
||||
|
||||
# Pick up the shader files that appear in direct/src/filter.
|
||||
import direct
|
||||
file(Filename(direct.__path__[0], 'filter/*.sha'), newDir = 'direct/filter')
|
||||
|
||||
# pandac.PandaModules pulls in other Panda3D libs automatically.
|
||||
# Exclude these Panda3D libs; they are big and many applications don't
|
||||
# use them. We define them as separate, optional packages, below,
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 144 KiB |
|
|
@ -170,6 +170,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.trackball = None
|
||||
self.texmem = None
|
||||
self.showVertices = None
|
||||
self.deviceButtonThrowers = []
|
||||
|
||||
## This is a NodePath pointing to the Camera object set up for the 3D scene.
|
||||
## This is usually a child of self.camera.
|
||||
|
|
@ -294,6 +295,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
## The global job manager, as imported from JobManagerGlobal.
|
||||
self.jobMgr = jobMgr
|
||||
|
||||
|
||||
## Particle manager
|
||||
self.particleMgr = None
|
||||
self.particleMgrEnabled = 0
|
||||
|
|
@ -303,6 +305,11 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.physicsMgrEnabled = 0
|
||||
self.physicsMgrAngular = 0
|
||||
|
||||
## This is the global input device manager, which keeps track of
|
||||
## connected input devices.
|
||||
self.devices = InputDeviceManager.getGlobalPtr()
|
||||
self.__inputDeviceNodes = {}
|
||||
|
||||
self.createStats()
|
||||
|
||||
self.AppHasAudioFocus = 1
|
||||
|
|
@ -1670,6 +1677,57 @@ class ShowBase(DirectObject.DirectObject):
|
|||
return self.mouseWatcherNode.getModifierButtons().isDown(
|
||||
KeyboardButton.meta())
|
||||
|
||||
def attachInputDevice(self, device, prefix=None):
|
||||
"""
|
||||
This function attaches an input device to the data graph, which will
|
||||
cause the device to be polled and generate events. If a prefix is
|
||||
given and not None, it is used to prefix events generated by this
|
||||
device, separated by a hyphen.
|
||||
|
||||
If you call this, you should consider calling detachInputDevice when
|
||||
you are done with the device or when it is disconnected.
|
||||
"""
|
||||
|
||||
# Protect against the same device being attached multiple times.
|
||||
assert device not in self.__inputDeviceNodes
|
||||
|
||||
idn = self.dataRoot.attachNewNode(InputDeviceNode(device, device.name))
|
||||
|
||||
# Setup the button thrower to generate events for the device.
|
||||
bt = idn.attachNewNode(ButtonThrower(device.name))
|
||||
if prefix is not None:
|
||||
bt.node().setPrefix(prefix + '-')
|
||||
|
||||
assert self.notify.debug("Attached input device {0} with prefix {1}".format(device, prefix))
|
||||
self.__inputDeviceNodes[device] = idn
|
||||
self.deviceButtonThrowers.append(bt)
|
||||
|
||||
def detachInputDevice(self, device):
|
||||
"""
|
||||
This should be called after attaching an input device using
|
||||
attachInputDevice and the device is disconnected or you no longer wish
|
||||
to keep polling this device for events.
|
||||
|
||||
You do not strictly need to call this if you expect the device to be
|
||||
reconnected (but be careful that you don't reattach it).
|
||||
"""
|
||||
|
||||
if device not in self.__inputDeviceNodes:
|
||||
assert device in self.__inputDeviceNodes
|
||||
return
|
||||
|
||||
assert self.notify.debug("Detached device {0}".format(device.name))
|
||||
|
||||
# Remove the ButtonThrower from the deviceButtonThrowers list.
|
||||
idn = self.__inputDeviceNodes[device]
|
||||
for bt in self.deviceButtonThrowers:
|
||||
if idn.isAncestorOf(bt):
|
||||
self.deviceButtonThrowers.remove(bt)
|
||||
break
|
||||
|
||||
idn.removeNode()
|
||||
del self.__inputDeviceNodes[device]
|
||||
|
||||
def addAngularIntegrator(self):
|
||||
if not self.physicsMgrAngular:
|
||||
physics = importlib.import_module('panda3d.physics')
|
||||
|
|
@ -1859,6 +1917,9 @@ class ShowBase(DirectObject.DirectObject):
|
|||
return Task.cont
|
||||
|
||||
def __dataLoop(self, state):
|
||||
# Check if there were newly connected devices.
|
||||
self.devices.update()
|
||||
|
||||
# traverse the data graph. This reads all the control
|
||||
# inputs (from the mouse and keyboard, for instance) and also
|
||||
# directly acts upon them (for instance, to move the avatar).
|
||||
|
|
@ -3074,6 +3135,8 @@ class ShowBase(DirectObject.DirectObject):
|
|||
setup_mouse = setupMouse
|
||||
setup_mouse_cb = setupMouseCB
|
||||
enable_software_mouse_pointer = enableSoftwareMousePointer
|
||||
detach_input_device = detachInputDevice
|
||||
attach_input_device = attachInputDevice
|
||||
add_angular_integrator = addAngularIntegrator
|
||||
enable_particles = enableParticles
|
||||
disable_particles = disableParticles
|
||||
|
|
|
|||
|
|
@ -89,6 +89,8 @@ class Transitions:
|
|||
self.fade.setBin('unsorted', 0)
|
||||
self.fade.setColor(0,0,0,0)
|
||||
|
||||
self.fade.setScale(max(base.a2dRight, base.a2dTop))
|
||||
|
||||
def getFadeInIval(self, t=0.5, finishIval=None, blendType='noBlend'):
|
||||
"""
|
||||
Returns an interval without starting it. This is particularly useful in
|
||||
|
|
@ -97,8 +99,7 @@ class Transitions:
|
|||
#self.noTransitions() masad: this creates a one frame pop, is it necessary?
|
||||
self.loadFade()
|
||||
|
||||
parent = aspect2d if self.fadeModel else render2d
|
||||
transitionIval = Sequence(Func(self.fade.reparentTo, parent, DGG.FADE_SORT_INDEX),
|
||||
transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX),
|
||||
Func(self.fade.showThrough), # in case aspect2d is hidden for some reason
|
||||
self.lerpFunc(self.fade, t,
|
||||
self.alphaOff,
|
||||
|
|
@ -120,8 +121,7 @@ class Transitions:
|
|||
self.noTransitions()
|
||||
self.loadFade()
|
||||
|
||||
parent = aspect2d if self.fadeModel else render2d
|
||||
transitionIval = Sequence(Func(self.fade.reparentTo, parent, DGG.FADE_SORT_INDEX),
|
||||
transitionIval = Sequence(Func(self.fade.reparentTo, aspect2d, DGG.FADE_SORT_INDEX),
|
||||
Func(self.fade.showThrough), # in case aspect2d is hidden for some reason
|
||||
self.lerpFunc(self.fade, t,
|
||||
self.alphaOn,
|
||||
|
|
@ -181,8 +181,7 @@ class Transitions:
|
|||
self.noTransitions()
|
||||
self.loadFade()
|
||||
|
||||
parent = aspect2d if self.fadeModel else render2d
|
||||
self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX)
|
||||
self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
|
||||
self.fade.setColor(self.alphaOn)
|
||||
elif ConfigVariableBool('no-loading-screen', False):
|
||||
if finishIval:
|
||||
|
|
@ -215,8 +214,7 @@ class Transitions:
|
|||
self.noTransitions()
|
||||
self.loadFade()
|
||||
|
||||
parent = aspect2d if self.fadeModel else render2d
|
||||
self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX)
|
||||
self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
|
||||
self.fade.setColor(self.alphaOn[0],
|
||||
self.alphaOn[1],
|
||||
self.alphaOn[2],
|
||||
|
|
@ -232,8 +230,7 @@ class Transitions:
|
|||
self.noTransitions()
|
||||
self.loadFade()
|
||||
|
||||
parent = aspect2d if self.fadeModel else render2d
|
||||
self.fade.reparentTo(parent, DGG.FADE_SORT_INDEX)
|
||||
self.fade.reparentTo(aspect2d, DGG.FADE_SORT_INDEX)
|
||||
self.fade.setColor(color)
|
||||
|
||||
def noFade(self):
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -194,7 +194,6 @@ it will show you the available command-line options:
|
|||
--use-wx --no-wx (enable/disable use of WX)
|
||||
--use-fltk --no-fltk (enable/disable use of FLTK)
|
||||
--use-rocket --no-rocket (enable/disable use of ROCKET)
|
||||
--use-awesomium --no-awesomium (enable/disable use of AWESOMIUM)
|
||||
--use-carbon --no-carbon (enable/disable use of CARBON)
|
||||
--use-cocoa --no-cocoa (enable/disable use of COCOA)
|
||||
--use-x11 --no-x11 (enable/disable use of X11)
|
||||
|
|
|
|||
148
doc/ReleaseNotes
|
|
@ -1,3 +1,151 @@
|
|||
------------------------ RELEASE 1.10.0 -----------------------
|
||||
|
||||
This is a major release with significant changes. Please review the
|
||||
changes when upgrading. The list below is by no means exhaustive, but
|
||||
should contain the most important changes.
|
||||
|
||||
General
|
||||
* Experimental ability to build for Android
|
||||
* New input framework to natively support gamepads, joysticks, etc.
|
||||
* Multi-threaded render pipeline is a lot more stable now
|
||||
* New setuptools-based deployment pipeline
|
||||
* Improvements to mouselook smoothness
|
||||
* Cache is now at $XDG_CACHE_HOME/panda3d (~/.cache/panda3d), not ~/.panda3d
|
||||
* Addition of unit test suite
|
||||
* Many improvements to thread safety
|
||||
* Many performance improvements
|
||||
* Tons of bugfixes
|
||||
* Big style cleanup of C++ source code
|
||||
|
||||
Python API
|
||||
* Complete support for Python 3
|
||||
* Support for coroutines and async/await
|
||||
* Property interfaces have been added for many settings
|
||||
* More flexible handling for keyboard arguments in C++ APIs
|
||||
* Python bindings are completely separated out of the C++ libraries.
|
||||
* Interrogate binding generator has many improvements.
|
||||
* Use of pandac.PandaModules is discouraged, use panda3d.core et al
|
||||
* Use of libRocket is discouraged due to lack of Python 3 support
|
||||
* Tasks are now sorted in addition order when lacking a sort value
|
||||
* Fixes iris/fade transitions for extreme aspect ratios
|
||||
* WeakNodePath is now exposed to Python
|
||||
* WindowProperties.size(x, y) deprecated; use WindowProperties(size=(x, y))
|
||||
* Calling bare run() is deprecated, use base.run() instead
|
||||
* downcastTo*() methods have been removed, they were already no-ops
|
||||
|
||||
Rendering
|
||||
* Add new shader-based terrain rendering method (ShaderTerrainMesh)
|
||||
* The default ColorAttrib mode is now T_vertex
|
||||
* The ColorAttrib T_off mode now properly disables vertex colors entirely
|
||||
* Make handling of color attributes more consistent between renderers
|
||||
* Ability to create an OpenGL core profile context; set "gl-version 3 2"
|
||||
* Experimental support for reverse-Z rendering for best depth precision
|
||||
* sRGB framebuffers supported more widely
|
||||
* Support for infinite near/far clip in lens
|
||||
* Add some PBR material parameters to material class
|
||||
* Addition of more built-in GLSL shader inputs; see manual.
|
||||
* Add p3d_FragData[] GLSL output for MRT in GLSL 1.30
|
||||
* Add flag enabling vertex shader control over point size
|
||||
* Support signed ints and double-precision floats in vertex data with GLSL
|
||||
* Support unsigned 11/10/10-bit floating-point textures and vertex data
|
||||
* Support for SSBOs via ShaderBuffer class
|
||||
* Support OpenGL FBO buffers without any attachments
|
||||
* Support passing uint variables to GLSL shader
|
||||
* Allow rendering objects with empty vertex data (for vertex pulling)
|
||||
* Add LogicOpAttrib, for supporting logical operator blending
|
||||
* Improvements to OpenGL ES support
|
||||
* Support for geometry with adjacency information
|
||||
* Change default alpha blending to improve blending rendered result
|
||||
* New method for obtaining native OpenGL texture object
|
||||
* Support windowless offscreen rendering on macOS
|
||||
* Panda resets OpenGL state better before and after draw callbacks
|
||||
* OpenGL renderer better supports debugging tools like apitrace
|
||||
* Support fixed-depth billboards, useful for 2D tags that don't change size
|
||||
|
||||
Shader generator
|
||||
* Significant performance improvements
|
||||
* Support for point light shadows
|
||||
* Hardware skinning support
|
||||
* Changes to match fixed-function pipeline better
|
||||
* Fixes for normal vector normalization
|
||||
* Support multiple normal maps (uses Reoriented Normal Mapping)
|
||||
* Tracks modifications to materials and texture stages automatically
|
||||
|
||||
Lighting
|
||||
* Allow specifying light color based on color temperature
|
||||
* Setting specular color of a light separately is deprecated
|
||||
* New GLSL inputs to make implementing lighting in shaders much easier
|
||||
* Add representation for sphere light and rectangle light
|
||||
* Efficiency improvements for passing light information to shader
|
||||
* Interocular distance for shadow cameras now always defaults to 0
|
||||
* Add low-level lighting module from RenderPipeline
|
||||
|
||||
Textures
|
||||
* Support cube map arrays
|
||||
* Support buffer textures
|
||||
* Many more texture formats supported
|
||||
* BC4 and BC5 compression modes supported
|
||||
* Proper depth textures supported in DirectX 9 renderer
|
||||
* set_ram_image(_as) directly supports buffer protocol
|
||||
* TexturePeeker supports more formats and component types
|
||||
|
||||
Text
|
||||
* Dramatic improvements to text rendering performance
|
||||
* Support for HarfBuzz for higher-quality text shaping and kerning
|
||||
* Support for right-to-left text
|
||||
* Support for signed-distance-field rendering in egg-mkfont
|
||||
|
||||
Audio/video
|
||||
* The default unit for audio is now 1 meter for each Panda unit.
|
||||
* Native .flac loader
|
||||
* Support videos with alpha channel in ffmpeg
|
||||
* OpenAL stability improvements, especially on macOS
|
||||
* Support loading .opus files with libopusfile
|
||||
* Fix various memory leaks
|
||||
|
||||
Physics / collisions
|
||||
* CollisionTube is renamed to CollisionCapsule.
|
||||
* Box-box collision test is improved to work well with the Pusher
|
||||
* More box tests for collision system: box-into-plane, box-into-poly
|
||||
* Capsule (tube) can be used as "from" shape into plane, sphere, capsule, box
|
||||
* Bullet objects are serializable to .bam files.
|
||||
* Bullet bindings are now thread safe.
|
||||
* Bullet debug drawer is more efficient; no longer inherits GeomNode.
|
||||
* Various fixes to bullet vehicle wheel synchronization
|
||||
* PhysX bindings are deprecated.
|
||||
|
||||
Pipeline / loading
|
||||
* Support for Assimp library to load a broad variety of model formats
|
||||
* Ability to specify min-lod, max-lod, lod-bias in .egg file
|
||||
* Egg file materials support PBR-style material parameterization
|
||||
* Support loading more DDS files, including DX10-style ones
|
||||
* Add support for OpenEXR and HDR textures
|
||||
* Support line/point thickness in bam2egg
|
||||
* bam2egg no longer inserts a vestigial ModelNode at the top
|
||||
* bam2egg supports depth test, offset, cull bin attributes
|
||||
* Accept a .gz file wherever a .pz file is accepted
|
||||
* egg-palettize supports mirror and border-color wrap modes
|
||||
* More robust checks against memory corruptions when loading bad .bam files
|
||||
* Support for Maya 2017 and 2018
|
||||
* Support preprocessing GLSL shaders created with Shader.make
|
||||
|
||||
Build
|
||||
* We now require using MSVC 2015 or 2017 to compile on Windows.
|
||||
* At least GCC 4.8 is now required.
|
||||
* With GCC/clang, enabling C++11 is now required.
|
||||
* Allow building with more recent ffmpeg versions
|
||||
* Support for old FFMpeg versions (before 1.1) dropped.
|
||||
* The ppremake build system has been removed.
|
||||
* Support for OpenSSL versions before 0.9.7 has been dropped.
|
||||
|
||||
C++
|
||||
* Use of NULL is replaced with nullptr
|
||||
* WeakPointerTo now requires use of lock() method for thread safety
|
||||
* Mutex et al now satisfy C++11 Lockable constraints
|
||||
* Panda headers no longer contain `using namespace std;`
|
||||
* PN_int32 et al have been removed, use stdint.h types instead
|
||||
* The need to link with pystub and add Python include dirs is removed.
|
||||
|
||||
------------------------ RELEASE 1.9.4 ------------------------
|
||||
|
||||
One of the bugfixes in the last 1.9.3 release introduced a regression,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include "globPattern.h"
|
||||
#include "string_utils.h"
|
||||
#include <ctype.h>
|
||||
|
||||
using std::string;
|
||||
|
|
@ -199,9 +200,7 @@ r_match_files(const Filename &prefix, const string &suffix,
|
|||
next_glob = *this;
|
||||
}
|
||||
|
||||
vector_string::const_iterator fi;
|
||||
for (fi = dir_files.begin(); fi != dir_files.end(); ++fi) {
|
||||
const string &local_file = (*fi);
|
||||
for (const string &local_file : dir_files) {
|
||||
if (_pattern[0] == '.' || (local_file.empty() || local_file[0] != '.')) {
|
||||
if (matches(local_file)) {
|
||||
// We have a match; continue.
|
||||
|
|
@ -227,6 +226,126 @@ r_match_files(const Filename &prefix, const string &suffix,
|
|||
return num_matched;
|
||||
}
|
||||
|
||||
/**
|
||||
* Treats the GlobPattern as a filename pattern, and returns true if the given
|
||||
* filename matches the pattern. Unlike matches(), this will not match slash
|
||||
* characters for single asterisk characters, and it will ignore path
|
||||
* components that only contain a dot.
|
||||
*/
|
||||
bool GlobPattern::
|
||||
matches_file(Filename candidate) const {
|
||||
if (_pattern.empty()) {
|
||||
// Special case.
|
||||
return candidate.empty();
|
||||
}
|
||||
|
||||
// Either both must be absolute, or both must be relative.
|
||||
if ((_pattern[0] != '/') != candidate.is_local()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return r_matches_file(_pattern, candidate);
|
||||
}
|
||||
|
||||
/**
|
||||
* The recursive implementation of matches_file().
|
||||
*/
|
||||
bool GlobPattern::
|
||||
r_matches_file(const string &pattern, const Filename &candidate) const {
|
||||
// Split off the next bit of pattern.
|
||||
std::string next_pattern;
|
||||
GlobPattern glob;
|
||||
glob.set_case_sensitive(get_case_sensitive());
|
||||
glob.set_nomatch_chars(get_nomatch_chars());
|
||||
|
||||
bool pattern_end;
|
||||
size_t slash = pattern.find('/');
|
||||
if (slash == string::npos) {
|
||||
glob.set_pattern(pattern);
|
||||
pattern_end = true;
|
||||
} else {
|
||||
glob.set_pattern(pattern.substr(0, slash));
|
||||
next_pattern = pattern.substr(slash + 1);
|
||||
pattern_end = false;
|
||||
|
||||
if (slash == 0 || (slash == 1 && pattern[0] == '.')) {
|
||||
// Ignore // and /./ in patterns
|
||||
return r_matches_file(next_pattern, candidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Also split off the next component in the candidate filename.
|
||||
std::string part;
|
||||
Filename next_candidate;
|
||||
|
||||
bool candidate_end;
|
||||
size_t fn_slash = ((const std::string &)candidate).find('/');
|
||||
if (fn_slash == string::npos) {
|
||||
part = candidate;
|
||||
candidate_end = true;
|
||||
} else {
|
||||
part = candidate.substr(0, fn_slash);
|
||||
next_candidate = candidate.substr(fn_slash + 1);
|
||||
candidate_end = false;
|
||||
|
||||
// Ignore // and /./ in filenames.
|
||||
if (fn_slash == 0 || part == ".") {
|
||||
return r_matches_file(pattern, next_candidate);
|
||||
}
|
||||
}
|
||||
|
||||
// Now check if the current part matches the current pattern.
|
||||
bool part_matches;
|
||||
if (glob.get_pattern() == "**") {
|
||||
// This matches any number of parts.
|
||||
if (pattern_end) {
|
||||
// We might as well stop checking here; it matches whatever might come.
|
||||
return true;
|
||||
}
|
||||
// We branch out to three options: either we match nothing, we match this
|
||||
// part only, or we match this part and maybe more.
|
||||
return r_matches_file(next_pattern, candidate)
|
||||
|| (!candidate_end && r_matches_file(next_pattern, next_candidate))
|
||||
|| (!candidate_end && r_matches_file(pattern, next_candidate));
|
||||
}
|
||||
else if (glob.get_pattern() == "*" && _nomatch_chars.empty()) {
|
||||
// Matches any part (faster version of below)
|
||||
part_matches = true;
|
||||
}
|
||||
else if ((glob.get_pattern() == "." && part.empty())
|
||||
|| (glob.get_pattern().empty() && part == ".")) {
|
||||
// So that /path/. matches /path/, and vice versa.
|
||||
part_matches = true;
|
||||
}
|
||||
else if (glob.has_glob_characters()) {
|
||||
part_matches = glob.matches(part);
|
||||
}
|
||||
else if (get_case_sensitive()) {
|
||||
part_matches = (part == glob.get_pattern());
|
||||
}
|
||||
else {
|
||||
part_matches = (cmp_nocase(part, glob.get_pattern()) == 0);
|
||||
}
|
||||
|
||||
if (!part_matches) {
|
||||
// It doesn't match, so we end our search here.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (candidate_end && pattern_end) {
|
||||
// We've reached the end of both candidate and pattern, so it matches.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pattern_end != candidate_end) {
|
||||
// One of them has ended, but the other hasn't, so it's not a match.
|
||||
return false;
|
||||
}
|
||||
|
||||
// It matches; move on to the next part.
|
||||
return r_matches_file(next_pattern, next_candidate);
|
||||
}
|
||||
|
||||
/**
|
||||
* The recursive implementation of matches(). This returns true if the
|
||||
* pattern substring [pi, pend) matches the candidate substring [ci, cend),
|
||||
|
|
|
|||
|
|
@ -52,6 +52,7 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(nomatch_chars, get_nomatch_chars, set_nomatch_chars);
|
||||
|
||||
INLINE bool matches(const std::string &candidate) const;
|
||||
bool matches_file(Filename candidate) const;
|
||||
|
||||
INLINE void output(std::ostream &out) const;
|
||||
|
||||
|
|
@ -74,6 +75,7 @@ private:
|
|||
|
||||
int r_match_files(const Filename &prefix, const std::string &suffix,
|
||||
vector_string &results, const Filename &cwd);
|
||||
bool r_matches_file(const std::string &suffix, const Filename &candidate) const;
|
||||
|
||||
std::string _pattern;
|
||||
bool _case_sensitive;
|
||||
|
|
|
|||
|
|
@ -1532,13 +1532,7 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
|
|||
<< " nullptr, nullptr, nullptr, nullptr\n"
|
||||
<< "};\n"
|
||||
<< "\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << def->module_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << def->module_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" PyObject *PyInit_" << def->module_name << "();\n"
|
||||
<< "#endif\n"
|
||||
<< "extern \"C\" EXPORT_CLASS PyObject *PyInit_" << def->module_name << "();\n"
|
||||
<< "\n"
|
||||
<< "PyObject *PyInit_" << def->module_name << "() {\n"
|
||||
<< " LibraryDef *refs[] = {&" << def->library_name << "_moddef, nullptr};\n"
|
||||
|
|
@ -1549,13 +1543,7 @@ write_module(ostream &out, ostream *out_h, InterrogateModuleDef *def) {
|
|||
<< "\n"
|
||||
<< "#else // Python 2 case\n"
|
||||
<< "\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) void init" << def->module_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) void init" << def->module_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" void init" << def->module_name << "();\n"
|
||||
<< "#endif\n"
|
||||
<< "extern \"C\" EXPORT_CLASS void init" << def->module_name << "();\n"
|
||||
<< "\n"
|
||||
<< "void init" << def->module_name << "() {\n"
|
||||
<< " LibraryDef *refs[] = {&" << def->library_name << "_moddef, nullptr};\n"
|
||||
|
|
@ -4078,13 +4066,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 +4079,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 +4094,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 +4105,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 +4651,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 +4661,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 +4691,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 +4735,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 +4943,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 +5272,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 +5310,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 +5439,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 +5516,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 +5533,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 +5594,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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -656,13 +656,13 @@ get_preferred_name(CPPType *type) {
|
|||
*/
|
||||
string InterrogateBuilder::
|
||||
hash_string(const string &name, int shift_offset) {
|
||||
int hash = 0;
|
||||
unsigned int hash = 0;
|
||||
|
||||
int shift = 0;
|
||||
unsigned int shift = 0;
|
||||
string::const_iterator ni;
|
||||
for (ni = name.begin(); ni != name.end(); ++ni) {
|
||||
int c = (int)(unsigned char)(*ni);
|
||||
int shifted_c = (c << shift) & 0xffffff;
|
||||
unsigned int c = (unsigned char)*ni;
|
||||
unsigned int shifted_c = (c << shift) & 0xffffff;
|
||||
if (shift > 16) {
|
||||
// We actually want a circular shift, not an arithmetic shift.
|
||||
shifted_c |= ((c >> (24 - shift)) & 0xff) ;
|
||||
|
|
@ -675,10 +675,9 @@ hash_string(const string &name, int shift_offset) {
|
|||
// bits back at the bottom, to scramble up the bits a bit. This helps
|
||||
// reduce hash conflicts from names that are similar to each other, by
|
||||
// separating adjacent hash codes.
|
||||
int prime = 4999;
|
||||
int low_order = (hash * prime) & 0xffffff;
|
||||
int high_order = (int)((double)hash * (double)prime / (double)(1 << 24));
|
||||
hash = low_order ^ high_order;
|
||||
const unsigned int prime = 4999;
|
||||
unsigned long long product = (unsigned long long)hash * prime;
|
||||
hash = (product ^ (product >> 24)) & 0xffffff;
|
||||
|
||||
// Also add in the additional_number, times some prime factor. hash = (hash
|
||||
// + additional_number * 1657) & 0xffffff;
|
||||
|
|
@ -690,10 +689,9 @@ hash_string(const string &name, int shift_offset) {
|
|||
// deal, since we have to resolve hash conflicts anyway.
|
||||
|
||||
string result;
|
||||
int extract_h = hash;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int value = (extract_h & 0x3f);
|
||||
extract_h >>= 6;
|
||||
unsigned int value = (hash & 0x3f);
|
||||
hash >>= 6;
|
||||
if (value < 26) {
|
||||
result += (char)('A' + value);
|
||||
|
||||
|
|
@ -2024,6 +2022,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,24 +295,10 @@ int write_python_table_native(std::ostream &out) {
|
|||
|
||||
out.put('\n');
|
||||
|
||||
out << "#if PY_MAJOR_VERSION >= 3 || !defined(NDEBUG)\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) PyObject *PyInit_" << library_name << "();\n"
|
||||
out << "#if PY_MAJOR_VERSION >= 3\n"
|
||||
<< "extern \"C\" EXPORT_CLASS PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" PyObject *PyInit_" << library_name << "();\n"
|
||||
<< "#endif\n"
|
||||
<< "#endif\n";
|
||||
|
||||
out << "#if PY_MAJOR_VERSION < 3 || !defined(NDEBUG)\n"
|
||||
<< "#ifdef _WIN32\n"
|
||||
<< "extern \"C\" __declspec(dllexport) void init" << library_name << "();\n"
|
||||
<< "#elif __GNUC__ >= 4\n"
|
||||
<< "extern \"C\" __attribute__((visibility(\"default\"))) void init" << library_name << "();\n"
|
||||
<< "#else\n"
|
||||
<< "extern \"C\" void init" << library_name << "();\n"
|
||||
<< "#endif\n"
|
||||
<< "extern \"C\" EXPORT_CLASS void init" << library_name << "();\n"
|
||||
<< "#endif\n";
|
||||
|
||||
out << "\n"
|
||||
|
|
@ -361,14 +347,6 @@ int write_python_table_native(std::ostream &out) {
|
|||
<< "}\n"
|
||||
<< "\n"
|
||||
|
||||
<< "#ifndef NDEBUG\n"
|
||||
<< "void init" << library_name << "() {\n"
|
||||
<< " PyErr_SetString(PyExc_ImportError, \"" << module_name << " was "
|
||||
<< "compiled for Python \" PY_VERSION \", which is incompatible "
|
||||
<< "with Python 2\");\n"
|
||||
<< "}\n"
|
||||
<< "#endif\n"
|
||||
|
||||
<< "#else // Python 2 case\n"
|
||||
<< "\n"
|
||||
<< "void init" << library_name << "() {\n";
|
||||
|
|
@ -402,15 +380,6 @@ int write_python_table_native(std::ostream &out) {
|
|||
|
||||
out << " }\n"
|
||||
<< "}\n"
|
||||
<< "\n"
|
||||
<< "#ifndef NDEBUG\n"
|
||||
<< "PyObject *PyInit_" << library_name << "() {\n"
|
||||
<< " PyErr_SetString(PyExc_ImportError, \"" << module_name << " was "
|
||||
<< "compiled for Python \" PY_VERSION \", which is incompatible "
|
||||
<< "with Python 3\");\n"
|
||||
<< " return nullptr;\n"
|
||||
<< "}\n"
|
||||
<< "#endif\n"
|
||||
<< "#endif\n"
|
||||
<< "\n";
|
||||
|
||||
|
|
|
|||
|
|
@ -15,6 +15,16 @@
|
|||
|
||||
#ifdef HAVE_PYTHON
|
||||
|
||||
static PyMemberDef standard_type_members[] = {
|
||||
{(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
|
||||
{(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
|
||||
{(char *)"this_const", T_BOOL, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"},
|
||||
// {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature),
|
||||
// READONLY, (char *)"A type check signature"},
|
||||
{(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"},
|
||||
{nullptr} /* Sentinel */
|
||||
};
|
||||
|
||||
static PyObject *GetSuperBase(PyObject *self) {
|
||||
Dtool_PyTypedObject *super_base = Dtool_GetSuperBase();
|
||||
Py_XINCREF((PyTypeObject *)super_base); // order is important .. this is used for static functions
|
||||
|
|
|
|||
|
|
@ -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";
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -31,6 +31,14 @@
|
|||
|
||||
#include <Python.h>
|
||||
|
||||
#ifndef LINK_ALL_STATIC
|
||||
# define EXPCL_PYPANDA
|
||||
#elif defined(__GNUC__)
|
||||
# define EXPCL_PYPANDA __attribute__((weak))
|
||||
#else
|
||||
# define EXPCL_PYPANDA extern inline
|
||||
#endif
|
||||
|
||||
/* Python 2.4 */
|
||||
|
||||
// 2.4 macros which aren't available in 2.3
|
||||
|
|
@ -99,7 +107,7 @@ typedef int Py_ssize_t;
|
|||
// PyInt_FromSize_t automatically picks the right type.
|
||||
# define PyLongOrInt_AS_LONG PyInt_AsLong
|
||||
|
||||
size_t PyLongOrInt_AsSize_t(PyObject *);
|
||||
EXPCL_PYPANDA size_t PyLongOrInt_AsSize_t(PyObject *);
|
||||
#endif
|
||||
|
||||
// Which character to use in PyArg_ParseTuple et al for a byte string.
|
||||
|
|
|
|||
|
|
@ -12,16 +12,6 @@
|
|||
|
||||
using std::string;
|
||||
|
||||
PyMemberDef standard_type_members[] = {
|
||||
{(char *)"this", (sizeof(void*) == sizeof(int)) ? T_UINT : T_ULONGLONG, offsetof(Dtool_PyInstDef, _ptr_to_object), READONLY, (char *)"C++ 'this' pointer, if any"},
|
||||
{(char *)"this_ownership", T_BOOL, offsetof(Dtool_PyInstDef, _memory_rules), READONLY, (char *)"C++ 'this' ownership rules"},
|
||||
{(char *)"this_const", T_BOOL, offsetof(Dtool_PyInstDef, _is_const), READONLY, (char *)"C++ 'this' const flag"},
|
||||
// {(char *)"this_signature", T_INT, offsetof(Dtool_PyInstDef, _signature),
|
||||
// READONLY, (char *)"A type check signature"},
|
||||
{(char *)"this_metatype", T_OBJECT, offsetof(Dtool_PyInstDef, _My_Type), READONLY, (char *)"The dtool meta object"},
|
||||
{nullptr} /* Sentinel */
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
|
|
@ -296,6 +286,43 @@ PyObject *_Dtool_Return(PyObject *value) {
|
|||
}
|
||||
|
||||
#if PY_VERSION_HEX < 0x03040000
|
||||
/**
|
||||
* This function converts an int value to the appropriate enum instance.
|
||||
*/
|
||||
static PyObject *Dtool_EnumType_New(PyTypeObject *subtype, PyObject *args, PyObject *kwds) {
|
||||
PyObject *arg;
|
||||
if (!Dtool_ExtractArg(&arg, args, kwds, "value")) {
|
||||
return PyErr_Format(PyExc_TypeError,
|
||||
"%s() missing 1 required argument: 'value'",
|
||||
subtype->tp_name);
|
||||
}
|
||||
|
||||
if (Py_TYPE(arg) == subtype) {
|
||||
Py_INCREF(arg);
|
||||
return arg;
|
||||
}
|
||||
|
||||
PyObject *value2member = PyDict_GetItemString(subtype->tp_dict, "_value2member_map_");
|
||||
nassertr_always(value2member != nullptr, nullptr);
|
||||
|
||||
PyObject *member = PyDict_GetItem(value2member, arg);
|
||||
if (member != nullptr) {
|
||||
Py_INCREF(member);
|
||||
return member;
|
||||
}
|
||||
|
||||
PyObject *repr = PyObject_Repr(arg);
|
||||
PyErr_Format(PyExc_ValueError, "%s is not a valid %s",
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyUnicode_AS_STRING(repr),
|
||||
#else
|
||||
PyString_AS_STRING(repr),
|
||||
#endif
|
||||
subtype->tp_name);
|
||||
Py_DECREF(repr);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
static PyObject *Dtool_EnumType_Str(PyObject *self) {
|
||||
PyObject *name = PyObject_GetAttrString(self, "name");
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
|
@ -347,6 +374,7 @@ PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, const cha
|
|||
static PyObject *name_sunder_str;
|
||||
static PyObject *value_str;
|
||||
static PyObject *value_sunder_str;
|
||||
static PyObject *value2member_map_sunder_str;
|
||||
// Emulate something vaguely like the enum module.
|
||||
if (enum_class == nullptr) {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
|
@ -354,11 +382,13 @@ PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, const cha
|
|||
value_str = PyUnicode_InternFromString("value");
|
||||
name_sunder_str = PyUnicode_InternFromString("_name_");
|
||||
value_sunder_str = PyUnicode_InternFromString("_value_");
|
||||
value2member_map_sunder_str = PyUnicode_InternFromString("_value2member_map_");
|
||||
#else
|
||||
name_str = PyString_InternFromString("name");
|
||||
value_str = PyString_InternFromString("value");
|
||||
name_sunder_str = PyString_InternFromString("_name_");
|
||||
value_sunder_str = PyString_InternFromString("_value_");
|
||||
value2member_map_sunder_str = PyString_InternFromString("_value2member_map_");
|
||||
#endif
|
||||
PyObject *name_value_tuple = PyTuple_New(4);
|
||||
PyTuple_SET_ITEM(name_value_tuple, 0, name_str);
|
||||
|
|
@ -375,27 +405,39 @@ PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names, const cha
|
|||
enum_class = PyObject_CallFunction((PyObject *)&PyType_Type, (char *)"s()N", "Enum", slots_dict);
|
||||
nassertr(enum_class != nullptr, nullptr);
|
||||
}
|
||||
PyObject *result = PyObject_CallFunction((PyObject *)&PyType_Type, (char *)"s(O)N", name, enum_class, PyDict_New());
|
||||
|
||||
// Create a subclass of this generic Enum class we just created.
|
||||
PyObject *value2member = PyDict_New();
|
||||
PyObject *dict = PyDict_New();
|
||||
PyDict_SetItem(dict, value2member_map_sunder_str, value2member);
|
||||
PyObject *result = PyObject_CallFunction((PyObject *)&PyType_Type, (char *)"s(O)N", name, enum_class, dict);
|
||||
nassertr(result != nullptr, nullptr);
|
||||
|
||||
((PyTypeObject *)result)->tp_new = Dtool_EnumType_New;
|
||||
((PyTypeObject *)result)->tp_str = Dtool_EnumType_Str;
|
||||
((PyTypeObject *)result)->tp_repr = Dtool_EnumType_Repr;
|
||||
|
||||
// Copy the names as instances of the above to the class dict.
|
||||
PyObject *empty_tuple = PyTuple_New(0);
|
||||
|
||||
// Copy the names as instances of the above to the class dict, and create a
|
||||
// reverse mapping in the _value2member_map_ dict.
|
||||
Py_ssize_t size = PyTuple_GET_SIZE(names);
|
||||
for (Py_ssize_t i = 0; i < size; ++i) {
|
||||
PyObject *item = PyTuple_GET_ITEM(names, i);
|
||||
PyObject *name = PyTuple_GET_ITEM(item, 0);
|
||||
PyObject *value = PyTuple_GET_ITEM(item, 1);
|
||||
PyObject *member = _PyObject_CallNoArg(result);
|
||||
PyObject *member = PyType_GenericNew((PyTypeObject *)result, empty_tuple, nullptr);
|
||||
PyObject_SetAttr(member, name_str, name);
|
||||
PyObject_SetAttr(member, name_sunder_str, name);
|
||||
PyObject_SetAttr(member, value_str, value);
|
||||
PyObject_SetAttr(member, value_sunder_str, value);
|
||||
PyObject_SetAttr(result, name, member);
|
||||
PyDict_SetItem(value2member, value, member);
|
||||
Py_DECREF(member);
|
||||
}
|
||||
Py_DECREF(names);
|
||||
Py_DECREF(value2member);
|
||||
Py_DECREF(empty_tuple);
|
||||
#endif
|
||||
|
||||
if (module != nullptr) {
|
||||
|
|
@ -588,46 +630,48 @@ PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulen
|
|||
<< "Python " << version << "\n";
|
||||
}
|
||||
|
||||
// Grab the __main__ module.
|
||||
PyObject *main_module = PyImport_ImportModule("__main__");
|
||||
if (main_module == nullptr) {
|
||||
interrogatedb_cat.warning() << "Unable to import __main__\n";
|
||||
}
|
||||
|
||||
// Extract the __file__ attribute, if present.
|
||||
Filename main_dir;
|
||||
PyObject *file_attr = nullptr;
|
||||
if (main_module != nullptr) {
|
||||
file_attr = PyObject_GetAttrString(main_module, "__file__");
|
||||
}
|
||||
if (file_attr == nullptr) {
|
||||
// Must be running in the interactive interpreter. Use the CWD.
|
||||
main_dir = ExecutionEnvironment::get_cwd();
|
||||
} else {
|
||||
if (!ExecutionEnvironment::has_environment_variable("MAIN_DIR")) {
|
||||
// Grab the __main__ module.
|
||||
PyObject *main_module = PyImport_ImportModule("__main__");
|
||||
if (main_module == NULL) {
|
||||
interrogatedb_cat.warning() << "Unable to import __main__\n";
|
||||
}
|
||||
|
||||
// Extract the __file__ attribute, if present.
|
||||
Filename main_dir;
|
||||
PyObject *file_attr = nullptr;
|
||||
if (main_module != nullptr) {
|
||||
file_attr = PyObject_GetAttrString(main_module, "__file__");
|
||||
}
|
||||
if (file_attr == nullptr) {
|
||||
// Must be running in the interactive interpreter. Use the CWD.
|
||||
main_dir = ExecutionEnvironment::get_cwd();
|
||||
} else {
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
Py_ssize_t length;
|
||||
wchar_t *buffer = PyUnicode_AsWideCharString(file_attr, &length);
|
||||
if (buffer != nullptr) {
|
||||
main_dir = Filename::from_os_specific_w(std::wstring(buffer, length));
|
||||
main_dir.make_absolute();
|
||||
main_dir = main_dir.get_dirname();
|
||||
PyMem_Free(buffer);
|
||||
}
|
||||
Py_ssize_t length;
|
||||
wchar_t *buffer = PyUnicode_AsWideCharString(file_attr, &length);
|
||||
if (buffer != nullptr) {
|
||||
main_dir = Filename::from_os_specific_w(std::wstring(buffer, length));
|
||||
main_dir.make_absolute();
|
||||
main_dir = main_dir.get_dirname();
|
||||
PyMem_Free(buffer);
|
||||
}
|
||||
#else
|
||||
char *buffer;
|
||||
Py_ssize_t length;
|
||||
if (PyString_AsStringAndSize(file_attr, &buffer, &length) != -1) {
|
||||
main_dir = Filename::from_os_specific(std::string(buffer, length));
|
||||
main_dir.make_absolute();
|
||||
main_dir = main_dir.get_dirname();
|
||||
}
|
||||
char *buffer;
|
||||
Py_ssize_t length;
|
||||
if (PyString_AsStringAndSize(file_attr, &buffer, &length) != -1) {
|
||||
main_dir = Filename::from_os_specific(std::string(buffer, length));
|
||||
main_dir.make_absolute();
|
||||
main_dir = main_dir.get_dirname();
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
interrogatedb_cat.warning() << "Invalid string for __main__.__file__\n";
|
||||
else {
|
||||
interrogatedb_cat.warning() << "Invalid string for __main__.__file__\n";
|
||||
}
|
||||
}
|
||||
ExecutionEnvironment::shadow_environment_variable("MAIN_DIR", main_dir.to_os_specific());
|
||||
PyErr_Clear();
|
||||
}
|
||||
ExecutionEnvironment::shadow_environment_variable("MAIN_DIR", main_dir.to_os_specific());
|
||||
PyErr_Clear();
|
||||
initialized_main_dir = true;
|
||||
|
||||
// Also, while we are at it, initialize the thread swap hook.
|
||||
|
|
@ -673,7 +717,8 @@ PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args) {
|
|||
|
||||
// We do expose a dictionay for dtool classes .. this should be removed at
|
||||
// some point..
|
||||
PyObject *Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
|
||||
EXPCL_PYPANDA PyObject *
|
||||
Dtool_AddToDictionary(PyObject *self1, PyObject *args) {
|
||||
PyObject *self;
|
||||
PyObject *subject;
|
||||
PyObject *key;
|
||||
|
|
|
|||
|
|
@ -67,9 +67,6 @@ struct Dtool_PyInstDef {
|
|||
bool _is_const;
|
||||
};
|
||||
|
||||
// A Offset Dictionary Defining How to read the Above Object..
|
||||
extern PyMemberDef standard_type_members[];
|
||||
|
||||
// The Class Definition Structor For a Dtool python type.
|
||||
struct Dtool_PyTypedObject {
|
||||
// Standard Python Features..
|
||||
|
|
@ -182,19 +179,19 @@ static void Dtool_FreeInstance_##CLASS_NAME(PyObject *self) {\
|
|||
|
||||
typedef std::map<std::string, Dtool_PyTypedObject *> Dtool_TypeMap;
|
||||
|
||||
Dtool_TypeMap *Dtool_GetGlobalTypeMap();
|
||||
EXPCL_PYPANDA Dtool_TypeMap *Dtool_GetGlobalTypeMap();
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer);
|
||||
EXPCL_PYPANDA void DTOOL_Call_ExtractThisPointerForType(PyObject *self, Dtool_PyTypedObject *classdef, void **answer);
|
||||
|
||||
void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const std::string &function_name, bool const_ok, bool report_errors);
|
||||
EXPCL_PYPANDA void *DTOOL_Call_GetPointerThisClass(PyObject *self, Dtool_PyTypedObject *classdef, int param, const std::string &function_name, bool const_ok, bool report_errors);
|
||||
|
||||
bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
|
||||
EXPCL_PYPANDA bool Dtool_Call_ExtractThisPointer(PyObject *self, Dtool_PyTypedObject &classdef, void **answer);
|
||||
|
||||
bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
|
||||
void **answer, const char *method_name);
|
||||
EXPCL_PYPANDA bool Dtool_Call_ExtractThisPointer_NonConst(PyObject *self, Dtool_PyTypedObject &classdef,
|
||||
void **answer, const char *method_name);
|
||||
|
||||
template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into);
|
||||
template<class T> INLINE bool DtoolInstance_GetPointer(PyObject *self, T *&into, Dtool_PyTypedObject &classdef);
|
||||
|
|
@ -204,7 +201,7 @@ INLINE int DtoolInstance_ComparePointers(PyObject *v1, PyObject *v2);
|
|||
INLINE PyObject *DtoolInstance_RichComparePointers(PyObject *v1, PyObject *v2, int op);
|
||||
|
||||
// Functions related to error reporting.
|
||||
bool _Dtool_CheckErrorOccurred();
|
||||
EXPCL_PYPANDA bool _Dtool_CheckErrorOccurred();
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define Dtool_CheckErrorOccurred() (UNLIKELY(_PyErr_OCCURRED() != nullptr))
|
||||
|
|
@ -212,12 +209,12 @@ bool _Dtool_CheckErrorOccurred();
|
|||
#define Dtool_CheckErrorOccurred() (UNLIKELY(_Dtool_CheckErrorOccurred()))
|
||||
#endif
|
||||
|
||||
PyObject *Dtool_Raise_AssertionError();
|
||||
PyObject *Dtool_Raise_TypeError(const char *message);
|
||||
PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name);
|
||||
PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute);
|
||||
EXPCL_PYPANDA PyObject *Dtool_Raise_AssertionError();
|
||||
EXPCL_PYPANDA PyObject *Dtool_Raise_TypeError(const char *message);
|
||||
EXPCL_PYPANDA PyObject *Dtool_Raise_ArgTypeError(PyObject *obj, int param, const char *function_name, const char *type_name);
|
||||
EXPCL_PYPANDA PyObject *Dtool_Raise_AttributeError(PyObject *obj, const char *attribute);
|
||||
|
||||
PyObject *_Dtool_Raise_BadArgumentsError();
|
||||
EXPCL_PYPANDA PyObject *_Dtool_Raise_BadArgumentsError();
|
||||
#ifdef NDEBUG
|
||||
// Define it to a function that just prints a generic message.
|
||||
#define Dtool_Raise_BadArgumentsError(x) _Dtool_Raise_BadArgumentsError()
|
||||
|
|
@ -229,9 +226,9 @@ PyObject *_Dtool_Raise_BadArgumentsError();
|
|||
// These functions are similar to Dtool_WrapValue, except that they also
|
||||
// contain code for checking assertions and exceptions when compiling with
|
||||
// NDEBUG mode on.
|
||||
PyObject *_Dtool_Return_None();
|
||||
PyObject *Dtool_Return_Bool(bool value);
|
||||
PyObject *_Dtool_Return(PyObject *value);
|
||||
EXPCL_PYPANDA PyObject *_Dtool_Return_None();
|
||||
EXPCL_PYPANDA PyObject *Dtool_Return_Bool(bool value);
|
||||
EXPCL_PYPANDA PyObject *_Dtool_Return(PyObject *value);
|
||||
|
||||
#ifdef NDEBUG
|
||||
#define Dtool_Return_None() (LIKELY(_PyErr_OCCURRED() == nullptr) ? (Py_INCREF(Py_None), Py_None) : nullptr)
|
||||
|
|
@ -244,19 +241,19 @@ PyObject *_Dtool_Return(PyObject *value);
|
|||
/**
|
||||
* Wrapper around Python 3.4's enum library, which does not have a C API.
|
||||
*/
|
||||
PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names,
|
||||
const char *module = nullptr);
|
||||
EXPCL_PYPANDA PyTypeObject *Dtool_EnumType_Create(const char *name, PyObject *names,
|
||||
const char *module = nullptr);
|
||||
INLINE long Dtool_EnumValue_AsLong(PyObject *value);
|
||||
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int RunTimeType);
|
||||
EXPCL_PYPANDA PyObject *DTool_CreatePyInstanceTyped(void *local_this_in, Dtool_PyTypedObject &known_class_type, bool memory_rules, bool is_const, int RunTimeType);
|
||||
|
||||
// DTool_CreatePyInstance .. wrapper function to finalize the existance of a
|
||||
// general dtool py instance..
|
||||
PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const);
|
||||
EXPCL_PYPANDA PyObject *DTool_CreatePyInstance(void *local_this, Dtool_PyTypedObject &in_classdef, bool memory_rules, bool is_const);
|
||||
|
||||
// These template methods allow use when the Dtool_PyTypedObject is not known.
|
||||
// They require a get_class_type() to be defined for the class.
|
||||
|
|
@ -323,26 +320,26 @@ struct LibraryDef {
|
|||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def);
|
||||
EXPCL_PYPANDA PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], PyModuleDef *module_def);
|
||||
#else
|
||||
PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename);
|
||||
EXPCL_PYPANDA PyObject *Dtool_PyModuleInitHelper(const LibraryDef *defs[], const char *modulename);
|
||||
#endif
|
||||
|
||||
// HACK.... Be carefull Dtool_BorrowThisReference This function can be used to
|
||||
// grab the "THIS" pointer from an object and use it Required to support fom
|
||||
// historical inharatence in the for of "is this instance of"..
|
||||
PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args);
|
||||
EXPCL_PYPANDA PyObject *Dtool_BorrowThisReference(PyObject *self, PyObject *args);
|
||||
|
||||
#define DTOOL_PyObject_HashPointer DtoolInstance_HashPointer
|
||||
#define DTOOL_PyObject_ComparePointers DtoolInstance_ComparePointers
|
||||
|
||||
PyObject *
|
||||
EXPCL_PYPANDA PyObject *
|
||||
copy_from_make_copy(PyObject *self, PyObject *noargs);
|
||||
|
||||
PyObject *
|
||||
EXPCL_PYPANDA PyObject *
|
||||
copy_from_copy_constructor(PyObject *self, PyObject *noargs);
|
||||
|
||||
PyObject *
|
||||
EXPCL_PYPANDA PyObject *
|
||||
map_deepcopy_to_copy(PyObject *self, PyObject *args);
|
||||
|
||||
/**
|
||||
|
|
@ -351,14 +348,14 @@ map_deepcopy_to_copy(PyObject *self, PyObject *args);
|
|||
*/
|
||||
ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args);
|
||||
ALWAYS_INLINE bool Dtool_CheckNoArgs(PyObject *args, PyObject *kwds);
|
||||
bool Dtool_ExtractArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds, const char *keyword);
|
||||
bool Dtool_ExtractArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds);
|
||||
bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds, const char *keyword);
|
||||
bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds);
|
||||
EXPCL_PYPANDA bool Dtool_ExtractArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds, const char *keyword);
|
||||
EXPCL_PYPANDA bool Dtool_ExtractArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds);
|
||||
EXPCL_PYPANDA bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds, const char *keyword);
|
||||
EXPCL_PYPANDA bool Dtool_ExtractOptionalArg(PyObject **result, PyObject *args,
|
||||
PyObject *kwds);
|
||||
|
||||
/**
|
||||
* These functions convert a C++ value into the corresponding Python object.
|
||||
|
|
@ -393,7 +390,7 @@ ALWAYS_INLINE PyObject *Dtool_WrapValue(Py_buffer *value);
|
|||
template<class T1, class T2>
|
||||
ALWAYS_INLINE PyObject *Dtool_WrapValue(const std::pair<T1, T2> &value);
|
||||
|
||||
Dtool_PyTypedObject *Dtool_GetSuperBase();
|
||||
EXPCL_PYPANDA Dtool_PyTypedObject *Dtool_GetSuperBase();
|
||||
|
||||
#include "py_panda.I"
|
||||
|
||||
|
|
|
|||
|
|
@ -49,12 +49,12 @@ struct Dtool_GeneratorWrapper {
|
|||
iternextfunc _iternext_func;
|
||||
};
|
||||
|
||||
Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name);
|
||||
Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name);
|
||||
Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name);
|
||||
Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name);
|
||||
PyObject *Dtool_NewGenerator(PyObject *self, iternextfunc func);
|
||||
PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
|
||||
EXPCL_PYPANDA Dtool_SequenceWrapper *Dtool_NewSequenceWrapper(PyObject *self, const char *name);
|
||||
EXPCL_PYPANDA Dtool_MutableSequenceWrapper *Dtool_NewMutableSequenceWrapper(PyObject *self, const char *name);
|
||||
EXPCL_PYPANDA Dtool_MappingWrapper *Dtool_NewMappingWrapper(PyObject *self, const char *name);
|
||||
EXPCL_PYPANDA Dtool_MappingWrapper *Dtool_NewMutableMappingWrapper(PyObject *self, const char *name);
|
||||
EXPCL_PYPANDA PyObject *Dtool_NewGenerator(PyObject *self, iternextfunc func);
|
||||
EXPCL_PYPANDA PyObject *Dtool_NewStaticProperty(PyTypeObject *obj, const PyGetSetDef *getset);
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
typedef struct _XINPUT_STATE XINPUT_STATE, *PXINPUT_STATE;
|
||||
typedef struct _XINPUT_CAPABILITIES XINPUT_CAPABILITIES, *PXINPUT_CAPABILITIES;
|
||||
typedef struct _XINPUT_VIBRATION XINPUT_VIBRATION, *PXINPUT_VIBRATION;
|
||||
typedef struct _XINPUT_GAMEPAD XINPUT_GAMEPAD, *PXINPUT_GAMEPAD;
|
||||
typedef struct _XINPUT_KEYSTROKE XINPUT_KEYSTROKE, *PXINPUT_KEYSTROKE;
|
||||
|
|
@ -38,8 +38,10 @@ typedef unsigned long ULONG_PTR;
|
|||
// http://msdn.microsoft.com/en-us/library/cc230309.aspx
|
||||
typedef bool BOOL;
|
||||
typedef unsigned long DWORD;
|
||||
typedef unsigned short WORD;
|
||||
typedef long LONG;
|
||||
typedef long UINT;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned long ULONG;
|
||||
typedef long long LONGLONG;
|
||||
typedef long HRESULT;
|
||||
|
|
|
|||
|
|
@ -38,6 +38,10 @@
|
|||
#include <algorithm>
|
||||
#include <ctype.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
using std::string;
|
||||
|
||||
ConfigPageManager *ConfigPageManager::_global_ptr = nullptr;
|
||||
|
|
@ -93,11 +97,60 @@ reload_implicit_pages() {
|
|||
}
|
||||
_implicit_pages.clear();
|
||||
|
||||
// If we are running inside a deployed application, see if it exposes
|
||||
// information about how the PRC data should be initialized.
|
||||
struct BlobInfo {
|
||||
uint64_t blob_offset;
|
||||
uint64_t blob_size;
|
||||
uint16_t version;
|
||||
uint16_t num_pointers;
|
||||
uint16_t codepage;
|
||||
uint16_t flags;
|
||||
uint64_t reserved;
|
||||
const void *module_table;
|
||||
const char *prc_data;
|
||||
const char *default_prc_dir;
|
||||
const char *prc_dir_envvars;
|
||||
const char *prc_path_envvars;
|
||||
const char *prc_patterns;
|
||||
const char *prc_encrypted_patterns;
|
||||
const char *prc_encryption_key;
|
||||
const char *prc_executable_patterns;
|
||||
const char *prc_executable_args_envvar;
|
||||
const char *main_dir;
|
||||
const char *log_filename;
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
const BlobInfo *blobinfo = (const BlobInfo *)GetProcAddress(GetModuleHandle(NULL), "blobinfo");
|
||||
#elif defined(RTLD_MAIN_ONLY)
|
||||
const BlobInfo *blobinfo = (const BlobInfo *)dlsym(RTLD_MAIN_ONLY, "blobinfo");
|
||||
//#elif defined(RTLD_SELF)
|
||||
// const BlobInfo *blobinfo = (const BlobInfo *)dlsym(RTLD_SELF, "blobinfo");
|
||||
#else
|
||||
const BlobInfo *blobinfo = (const BlobInfo *)dlsym(dlopen(NULL, RTLD_NOW), "blobinfo");
|
||||
#endif
|
||||
if (blobinfo != nullptr && (blobinfo->version == 0 || blobinfo->num_pointers < 10)) {
|
||||
blobinfo = nullptr;
|
||||
}
|
||||
|
||||
if (blobinfo != nullptr) {
|
||||
if (blobinfo->num_pointers >= 11 && blobinfo->main_dir != nullptr) {
|
||||
ExecutionEnvironment::set_environment_variable("MAIN_DIR", blobinfo->main_dir);
|
||||
} else {
|
||||
// Make sure that py_panda.cxx won't override MAIN_DIR.
|
||||
ExecutionEnvironment::set_environment_variable("MAIN_DIR",
|
||||
ExecutionEnvironment::get_environment_variable("MAIN_DIR"));
|
||||
}
|
||||
}
|
||||
|
||||
// PRC_PATTERNS lists one or more filename templates separated by spaces.
|
||||
// Pull them out and store them in _prc_patterns.
|
||||
_prc_patterns.clear();
|
||||
|
||||
string prc_patterns = PRC_PATTERNS;
|
||||
if (blobinfo != nullptr && blobinfo->prc_patterns != nullptr) {
|
||||
prc_patterns = blobinfo->prc_patterns;
|
||||
}
|
||||
if (!prc_patterns.empty()) {
|
||||
vector_string pat_list;
|
||||
ConfigDeclaration::extract_words(prc_patterns, pat_list);
|
||||
|
|
@ -117,6 +170,9 @@ reload_implicit_pages() {
|
|||
_prc_encrypted_patterns.clear();
|
||||
|
||||
string prc_encrypted_patterns = PRC_ENCRYPTED_PATTERNS;
|
||||
if (blobinfo != nullptr && blobinfo->prc_encrypted_patterns != nullptr) {
|
||||
prc_encrypted_patterns = blobinfo->prc_encrypted_patterns;
|
||||
}
|
||||
if (!prc_encrypted_patterns.empty()) {
|
||||
vector_string pat_list;
|
||||
ConfigDeclaration::extract_words(prc_encrypted_patterns, pat_list);
|
||||
|
|
@ -134,6 +190,9 @@ reload_implicit_pages() {
|
|||
_prc_executable_patterns.clear();
|
||||
|
||||
string prc_executable_patterns = PRC_EXECUTABLE_PATTERNS;
|
||||
if (blobinfo != nullptr && blobinfo->prc_executable_patterns != nullptr) {
|
||||
prc_executable_patterns = blobinfo->prc_executable_patterns;
|
||||
}
|
||||
if (!prc_executable_patterns.empty()) {
|
||||
vector_string pat_list;
|
||||
ConfigDeclaration::extract_words(prc_executable_patterns, pat_list);
|
||||
|
|
@ -154,6 +213,9 @@ reload_implicit_pages() {
|
|||
// spaces. Pull them out, and each of those contains the name of a single
|
||||
// directory to search. Add it to the search path.
|
||||
string prc_dir_envvars = PRC_DIR_ENVVARS;
|
||||
if (blobinfo != nullptr && blobinfo->prc_dir_envvars != nullptr) {
|
||||
prc_dir_envvars = blobinfo->prc_dir_envvars;
|
||||
}
|
||||
if (!prc_dir_envvars.empty()) {
|
||||
vector_string prc_dir_envvar_list;
|
||||
ConfigDeclaration::extract_words(prc_dir_envvars, prc_dir_envvar_list);
|
||||
|
|
@ -173,6 +235,9 @@ reload_implicit_pages() {
|
|||
// spaces. Pull them out, and then each one of those contains a list of
|
||||
// directories to search. Add each of those to the search path.
|
||||
string prc_path_envvars = PRC_PATH_ENVVARS;
|
||||
if (blobinfo != nullptr && blobinfo->prc_path_envvars != nullptr) {
|
||||
prc_path_envvars = blobinfo->prc_path_envvars;
|
||||
}
|
||||
if (!prc_path_envvars.empty()) {
|
||||
vector_string prc_path_envvar_list;
|
||||
ConfigDeclaration::extract_words(prc_path_envvars, prc_path_envvar_list);
|
||||
|
|
@ -204,7 +269,7 @@ reload_implicit_pages() {
|
|||
* DEFAULT_PATHSEP.
|
||||
*/
|
||||
string prc_path2_envvars = PRC_PATH2_ENVVARS;
|
||||
if (!prc_path2_envvars.empty()) {
|
||||
if (!prc_path2_envvars.empty() && blobinfo == nullptr) {
|
||||
vector_string prc_path_envvar_list;
|
||||
ConfigDeclaration::extract_words(prc_path2_envvars, prc_path_envvar_list);
|
||||
for (size_t i = 0; i < prc_path_envvar_list.size(); ++i) {
|
||||
|
|
@ -228,6 +293,9 @@ reload_implicit_pages() {
|
|||
// If nothing's on the search path (PRC_DIR and PRC_PATH were not
|
||||
// defined), then use the DEFAULT_PRC_DIR.
|
||||
string default_prc_dir = DEFAULT_PRC_DIR;
|
||||
if (blobinfo != nullptr && blobinfo->default_prc_dir != nullptr) {
|
||||
default_prc_dir = blobinfo->default_prc_dir;
|
||||
}
|
||||
if (!default_prc_dir.empty()) {
|
||||
// It's already from-os-specific by ppremake.
|
||||
Filename prc_dir_filename = default_prc_dir;
|
||||
|
|
@ -300,12 +368,24 @@ reload_implicit_pages() {
|
|||
}
|
||||
}
|
||||
|
||||
int i = 1;
|
||||
|
||||
// If prc_data is predefined, we load it as an implicit page.
|
||||
if (blobinfo != nullptr && blobinfo->prc_data != nullptr) {
|
||||
ConfigPage *page = new ConfigPage("builtin", true, i);
|
||||
++i;
|
||||
_implicit_pages.push_back(page);
|
||||
_pages_sorted = false;
|
||||
|
||||
std::istringstream in(blobinfo->prc_data);
|
||||
page->read_prc(in);
|
||||
}
|
||||
|
||||
// Now we have a list of filenames in order from most important to least
|
||||
// important. Walk through the list in reverse order to load their
|
||||
// contents, because we want the first file in the list (the most important)
|
||||
// to be on the top of the stack.
|
||||
ConfigFiles::reverse_iterator ci;
|
||||
int i = 1;
|
||||
for (ci = config_files.rbegin(); ci != config_files.rend(); ++ci) {
|
||||
const ConfigFile &file = (*ci);
|
||||
Filename filename = file._filename;
|
||||
|
|
@ -316,6 +396,9 @@ reload_implicit_pages() {
|
|||
string command = filename.to_os_specific();
|
||||
|
||||
string envvar = PRC_EXECUTABLE_ARGS_ENVVAR;
|
||||
if (blobinfo != nullptr && blobinfo->prc_executable_args_envvar != nullptr) {
|
||||
envvar = blobinfo->prc_executable_args_envvar;
|
||||
}
|
||||
if (!envvar.empty()) {
|
||||
string args = ExecutionEnvironment::get_environment_variable(envvar);
|
||||
if (!args.empty()) {
|
||||
|
|
@ -346,7 +429,11 @@ reload_implicit_pages() {
|
|||
_implicit_pages.push_back(page);
|
||||
_pages_sorted = false;
|
||||
|
||||
page->read_encrypted_prc(in, PRC_ENCRYPTION_KEY);
|
||||
if (blobinfo != nullptr && blobinfo->prc_encryption_key != nullptr) {
|
||||
page->read_encrypted_prc(in, blobinfo->prc_encryption_key);
|
||||
} else {
|
||||
page->read_encrypted_prc(in, PRC_ENCRYPTION_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
} else if ((file._file_flags & FF_read) != 0) {
|
||||
|
|
|
|||
|
|
@ -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,228 +116,41 @@ 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\filter
|
||||
File /r /x CVS /x Opt?-Win32 "${BUILT}\direct\filter\*.sha"
|
||||
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}"
|
||||
File /nonfatal /r "${BUILT}\panda3d\awesomium${EXT_SUFFIX}"
|
||||
File /nonfatal /r "${BUILT}\panda3d\direct${EXT_SUFFIX}"
|
||||
File /nonfatal /r "${BUILT}\panda3d\egg${EXT_SUFFIX}"
|
||||
File /nonfatal /r "${BUILT}\panda3d\fx${EXT_SUFFIX}"
|
||||
|
|
@ -380,92 +197,349 @@ SectionGroup "Python support"
|
|||
File /r "${BUILT}\pandac\input\*"
|
||||
SetOutPath $INSTDIR\Pmw
|
||||
File /nonfatal /r /x CVS "${BUILT}\Pmw\*"
|
||||
SetOutPath $INSTDIR\panda3d.dist-info
|
||||
File /nonfatal /r "${BUILT}\panda3d.dist-info\*"
|
||||
|
||||
!ifdef REGVIEW
|
||||
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 /x deploy-stub.exe /x deploy-stubw.exe "${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
|
||||
|
|
@ -475,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
|
||||
|
|
@ -492,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
|
||||
|
|
@ -502,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.
|
||||
|
|
@ -512,9 +584,10 @@ Function ConfirmPythonSelection
|
|||
|
||||
SkipCheck:
|
||||
FunctionEnd
|
||||
!endif
|
||||
|
||||
Section "C++ support" SecHeadersLibs
|
||||
SectionIn 1
|
||||
SectionIn 1 2
|
||||
|
||||
SetDetailsPrint both
|
||||
DetailPrint "Installing header files..."
|
||||
|
|
@ -533,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
|
||||
|
|
@ -600,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..."
|
||||
|
|
@ -615,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..."
|
||||
|
|
@ -738,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..."
|
||||
|
|
@ -813,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)
|
||||
|
|
|
|||
|
|
@ -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,19 +207,28 @@ 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")
|
||||
|
||||
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:
|
||||
oscmd("echo '"+libdir+"/panda3d'> "+destdir+"/etc/ld.so.conf.d/panda3d.conf")
|
||||
|
||||
oscmd("cp "+outputdir+"/bin/* "+destdir+prefix+"/bin/")
|
||||
for base in os.listdir(outputdir+"/lib"):
|
||||
if (not base.endswith(".a")) or base == "libp3pystub.a":
|
||||
# We really need to specify -R in order not to follow symlinks on non-GNU
|
||||
oscmd("cp -R -P "+outputdir+"/lib/"+base+" "+destdir+libdir+"/panda3d/"+base)
|
||||
|
||||
for base in os.listdir(outputdir+"/bin"):
|
||||
if not base.startswith("deploy-stub"):
|
||||
oscmd("cp -R -P "+outputdir+"/bin/"+base+" "+destdir+prefix+"/bin/"+base)
|
||||
|
||||
DeleteVCS(destdir+prefix+"/share/panda3d")
|
||||
DeleteBuildFiles(destdir+prefix+"/share/panda3d")
|
||||
DeleteEmptyDirs(destdir+prefix+"/share/panda3d")
|
||||
|
|
@ -300,6 +302,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)
|
||||
|
||||
|
|
@ -308,6 +312,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!")
|
||||
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -3578,25 +3578,6 @@
|
|||
<File RelativePath="..\panda\src\net\datagram_ui.cxx"></File>
|
||||
<File RelativePath="..\panda\src\net\netAddress.cxx"></File>
|
||||
</Filter>
|
||||
<Filter Name="awesomium">
|
||||
<File RelativePath="..\panda\src\awesomium\WebBrowserTexture.cxx"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awesomium_includes.h"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\pandaawesomium_composite1.cxx"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebViewListener.cxx"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebViewListener.h"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebCore.h"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\WebBrowserTexture.h"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebCore.cxx"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\AwMouseAndKeyboard.h"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebViewListener.I"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebView.h"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\config_awesomium.h"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebCore.I"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebView.I"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\awWebView.cxx"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\AwMouseAndKeyboard.cxx"></File>
|
||||
<File RelativePath="..\panda\src\awesomium\config_awesomium.cxx"></File>
|
||||
</Filter>
|
||||
<Filter Name="movies">
|
||||
<File RelativePath="..\panda\src\movies\ffmpegVideoCursor.h"></File>
|
||||
<File RelativePath="..\panda\src\movies\movies_composite.cxx"></File>
|
||||
|
|
|
|||
|
|
@ -3362,8 +3362,13 @@ def CalcLocation(fn, ipath):
|
|||
|
||||
|
||||
def FindLocation(fn, ipath, pyabi=None):
|
||||
if (GetLinkAllStatic() and fn.endswith(".dll")):
|
||||
fn = fn[:-4] + ".lib"
|
||||
if GetLinkAllStatic():
|
||||
if fn.endswith(".dll"):
|
||||
fn = fn[:-4] + ".lib"
|
||||
elif fn.endswith(".pyd"):
|
||||
fn = "libpy.panda3d." \
|
||||
+ os.path.splitext(fn[:-4] + GetExtensionSuffix())[0] + ".lib"
|
||||
|
||||
loc = CalcLocation(fn, ipath)
|
||||
base, ext = os.path.splitext(fn)
|
||||
|
||||
|
|
@ -3383,6 +3388,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
|
||||
|
|
@ -3513,11 +3583,15 @@ def TargetAdd(target, dummy=0, opts=[], input=[], dep=[], ipath=None, winrc=None
|
|||
if winrc and GetTarget() == 'windows':
|
||||
TargetAdd(target, input=WriteResourceFile(target.split("/")[-1].split(".")[0], **winrc))
|
||||
|
||||
if target.endswith(".in"):
|
||||
ext = os.path.splitext(target)[1]
|
||||
if ext == ".in":
|
||||
if not CrossCompiling():
|
||||
t.deps[FindLocation("interrogate.exe", [])] = 1
|
||||
t.deps[FindLocation("dtool_have_python.dat", [])] = 1
|
||||
|
||||
if ext in (".obj", ".tlb", ".res", ".plugin", ".app") or ext in SUFFIX_DLL or ext in SUFFIX_LIB:
|
||||
t.deps[FindLocation("platform.dat", [])] = 1
|
||||
|
||||
if target.endswith(".obj") and any(x.endswith(".in") for x in input):
|
||||
if not CrossCompiling():
|
||||
t.deps[FindLocation("interrogate_module.exe", [])] = 1
|
||||
|
|
|
|||
|
|
@ -24,14 +24,6 @@ from makepandacore import ColorText, LocateBinary, ParsePandaVersion, GetExtensi
|
|||
from base64 import urlsafe_b64encode
|
||||
|
||||
|
||||
default_platform = get_platform()
|
||||
|
||||
if default_platform.startswith("linux-"):
|
||||
# Is this manylinux1?
|
||||
if (os.path.isfile("/lib/libc-2.5.so") or os.path.isfile("/lib64/libc-2.5.so")) and os.path.isdir("/opt/python"):
|
||||
default_platform = default_platform.replace("linux", "manylinux1")
|
||||
|
||||
|
||||
def get_abi_tag():
|
||||
if sys.version_info >= (3, 0):
|
||||
soabi = get_config_var('SOABI')
|
||||
|
|
@ -68,26 +60,32 @@ def is_elf_file(path):
|
|||
open(path, 'rb').read(4) == b'\x7FELF'
|
||||
|
||||
|
||||
def is_mach_o_file(path):
|
||||
def is_macho_or_fat_file(path):
|
||||
base = os.path.basename(path)
|
||||
return os.path.isfile(path) and '.' not in base and \
|
||||
open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA',
|
||||
b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE',
|
||||
b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE')
|
||||
open(path, 'rb').read(4) in (b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE',
|
||||
b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE',
|
||||
b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\xCA',
|
||||
b'\xCA\xFE\xBA\xBF', b'\xBF\xBA\xFE\xCA')
|
||||
|
||||
def is_fat_file(path):
|
||||
return os.path.isfile(path) and \
|
||||
open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA')
|
||||
open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\xCA',
|
||||
b'\xCA\xFE\xBA\xBF', b'\xBF\xBA\xFE\xCA')
|
||||
|
||||
|
||||
def get_python_ext_module_dir():
|
||||
import _ctypes
|
||||
return os.path.dirname(_ctypes.__file__)
|
||||
|
||||
|
||||
if sys.platform in ('win32', 'cygwin'):
|
||||
is_executable = is_exe_file
|
||||
elif sys.platform == 'darwin':
|
||||
is_executable = is_mach_o_file
|
||||
is_executable = is_macho_or_fat_file
|
||||
else:
|
||||
is_executable = is_elf_file
|
||||
|
||||
|
||||
# Other global parameters
|
||||
PY_VERSION = "cp{0}{1}".format(*sys.version_info)
|
||||
ABI_TAG = get_abi_tag()
|
||||
|
|
@ -96,6 +94,24 @@ EXCLUDE_EXT = [".pyc", ".pyo", ".N", ".prebuilt", ".xcf", ".plist", ".vcproj", "
|
|||
# Plug-ins to install.
|
||||
PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "pandadx9", "p3tinydisplay", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"]
|
||||
|
||||
# Libraries included in manylinux ABI that should be ignored. See PEP 513/571.
|
||||
MANYLINUX_LIBS = [
|
||||
"libgcc_s.so.1", "libstdc++.so.6", "libm.so.6", "libdl.so.2", "librt.so.1",
|
||||
"libcrypt.so.1", "libc.so.6", "libnsl.so.1", "libutil.so.1",
|
||||
"libpthread.so.0", "libresolv.so.2", "libX11.so.6", "libXext.so.6",
|
||||
"libXrender.so.1", "libICE.so.6", "libSM.so.6", "libGL.so.1",
|
||||
"libgobject-2.0.so.0", "libgthread-2.0.so.0", "libglib-2.0.so.0",
|
||||
|
||||
# These are not mentioned in manylinux1 spec but should nonetheless always
|
||||
# be excluded.
|
||||
"linux-vdso.so.1", "linux-gate.so.1", "ld-linux.so.2",
|
||||
]
|
||||
|
||||
# Binaries to never scan for dependencies on non-Windows systems.
|
||||
IGNORE_UNIX_DEPS_OF = [
|
||||
"panda3d_tools/pstats",
|
||||
]
|
||||
|
||||
WHEEL_DATA = """Wheel-Version: 1.0
|
||||
Generator: makepanda
|
||||
Root-Is-Purelib: false
|
||||
|
|
@ -265,6 +281,7 @@ class WheelFile(object):
|
|||
# Used to locate dependency libraries.
|
||||
self.lib_path = []
|
||||
self.dep_paths = {}
|
||||
self.ignore_deps = set()
|
||||
|
||||
def consider_add_dependency(self, target_path, dep, search_path=None):
|
||||
"""Considers adding a dependency library.
|
||||
|
|
@ -277,29 +294,38 @@ class WheelFile(object):
|
|||
|
||||
self.dep_paths[dep] = None
|
||||
|
||||
if dep.lower().startswith("python") or os.path.basename(dep).startswith("libpython"):
|
||||
# Don't include the Python library.
|
||||
if dep in self.ignore_deps or dep.lower().startswith("python") or os.path.basename(dep).startswith("libpython"):
|
||||
# Don't include the Python library, or any other explicit ignore.
|
||||
if GetVerbose():
|
||||
print("Ignoring {0} (explicitly ignored)".format(dep))
|
||||
return
|
||||
|
||||
if sys.platform == "darwin" and dep.endswith(".so"):
|
||||
# Temporary hack for 1.9, which had link deps on modules.
|
||||
return
|
||||
|
||||
source_path = None
|
||||
if sys.platform == "darwin" and dep.startswith("/System/"):
|
||||
return
|
||||
|
||||
if search_path is None:
|
||||
search_path = self.lib_path
|
||||
if dep.startswith('/'):
|
||||
source_path = dep
|
||||
else:
|
||||
source_path = None
|
||||
|
||||
for lib_dir in search_path:
|
||||
# Ignore static stuff.
|
||||
path = os.path.join(lib_dir, dep)
|
||||
if os.path.isfile(path):
|
||||
source_path = os.path.normpath(path)
|
||||
break
|
||||
if search_path is None:
|
||||
search_path = self.lib_path
|
||||
|
||||
for lib_dir in search_path:
|
||||
# Ignore static stuff.
|
||||
path = os.path.join(lib_dir, dep)
|
||||
if os.path.isfile(path):
|
||||
source_path = os.path.normpath(path)
|
||||
break
|
||||
|
||||
if not source_path:
|
||||
# Couldn't find library in the panda3d lib dir.
|
||||
#print("Ignoring %s" % (dep))
|
||||
if GetVerbose():
|
||||
print("Ignoring {0} (not in search path)".format(dep))
|
||||
return
|
||||
|
||||
self.dep_paths[dep] = target_path
|
||||
|
|
@ -309,20 +335,19 @@ class WheelFile(object):
|
|||
def write_file(self, target_path, source_path):
|
||||
"""Adds the given file to the .whl file."""
|
||||
|
||||
orig_source_path = source_path
|
||||
|
||||
# If this is a .so file, we should set the rpath appropriately.
|
||||
temp = None
|
||||
ext = os.path.splitext(source_path)[1]
|
||||
basename, ext = os.path.splitext(source_path)
|
||||
if ext in ('.so', '.dylib') or '.so.' in os.path.basename(source_path) or \
|
||||
(not ext and is_executable(source_path)):
|
||||
# Scan and add Unix dependencies.
|
||||
deps = scan_dependencies(source_path)
|
||||
for dep in deps:
|
||||
# Only include dependencies with relative path. Otherwise we
|
||||
# end up overwriting system files like /lib/ld-linux.so.2!
|
||||
# Yes, it happened to me.
|
||||
if '/' not in dep:
|
||||
target_dep = os.path.dirname(target_path) + '/' + dep
|
||||
self.consider_add_dependency(target_dep, dep)
|
||||
|
||||
# Scan Unix dependencies.
|
||||
if target_path not in IGNORE_UNIX_DEPS_OF:
|
||||
deps = scan_dependencies(source_path)
|
||||
else:
|
||||
deps = []
|
||||
|
||||
suffix = ''
|
||||
if '.so' in os.path.basename(source_path):
|
||||
|
|
@ -333,7 +358,10 @@ class WheelFile(object):
|
|||
temp = tempfile.NamedTemporaryFile(suffix=suffix, prefix='whl', delete=False)
|
||||
|
||||
# On macOS, if no fat wheel was requested, extract the right architecture.
|
||||
if sys.platform == "darwin" and is_fat_file(source_path) and not self.platform.endswith("_intel"):
|
||||
if sys.platform == "darwin" and is_fat_file(source_path) \
|
||||
and not self.platform.endswith("_intel") \
|
||||
and "_fat" not in self.platform:
|
||||
|
||||
if self.platform.endswith("_x86_64"):
|
||||
arch = 'x86_64'
|
||||
else:
|
||||
|
|
@ -343,26 +371,55 @@ class WheelFile(object):
|
|||
# Otherwise, just copy it over.
|
||||
temp.write(open(source_path, 'rb').read())
|
||||
|
||||
os.fchmod(temp.fileno(), os.fstat(temp.fileno()).st_mode | 0o111)
|
||||
temp.close()
|
||||
os.chmod(temp.name, os.stat(temp.name).st_mode | 0o711)
|
||||
|
||||
# Fix things like @loader_path/../lib references
|
||||
# Now add dependencies. On macOS, fix @loader_path references.
|
||||
if sys.platform == "darwin":
|
||||
if source_path.endswith('deploy-stubw'):
|
||||
deps_path = '@executable_path/../Frameworks'
|
||||
else:
|
||||
deps_path = '@loader_path'
|
||||
loader_path = [os.path.dirname(source_path)]
|
||||
for dep in deps:
|
||||
if '@loader_path' not in dep:
|
||||
if dep.endswith('/Python'):
|
||||
# If this references the Python framework, change it
|
||||
# to reference libpython instead.
|
||||
new_dep = deps_path + '/libpython{0}.{1}.dylib'.format(*sys.version_info)
|
||||
|
||||
elif '@loader_path' in dep:
|
||||
dep_path = dep.replace('@loader_path', '.')
|
||||
target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep)
|
||||
target_dep = self.consider_add_dependency(target_dep, dep_path, loader_path)
|
||||
if not target_dep:
|
||||
# It won't be included, so no use adjusting the path.
|
||||
continue
|
||||
new_dep = os.path.join(deps_path, os.path.relpath(target_dep, os.path.dirname(target_path)))
|
||||
|
||||
elif dep.startswith('/Library/Frameworks/Python.framework/'):
|
||||
# Add this dependency if it's in the Python directory.
|
||||
target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep)
|
||||
target_dep = self.consider_add_dependency(target_dep, dep, loader_path)
|
||||
if not target_dep:
|
||||
# It won't be included, so no use adjusting the path.
|
||||
continue
|
||||
new_dep = os.path.join(deps_path, os.path.relpath(target_dep, os.path.dirname(target_path)))
|
||||
|
||||
else:
|
||||
if '/' in dep:
|
||||
if GetVerbose():
|
||||
print("Ignoring dependency %s" % (dep))
|
||||
continue
|
||||
|
||||
dep_path = dep.replace('@loader_path', '.')
|
||||
target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep)
|
||||
target_dep = self.consider_add_dependency(target_dep, dep_path, loader_path)
|
||||
if not target_dep:
|
||||
# It won't be included, so no use adjusting the path.
|
||||
continue
|
||||
|
||||
new_dep = os.path.join('@loader_path', os.path.relpath(target_dep, os.path.dirname(target_path)))
|
||||
subprocess.call(["install_name_tool", "-change", dep, new_dep, temp.name])
|
||||
else:
|
||||
# On other unixes, we just add dependencies normally.
|
||||
for dep in deps:
|
||||
# Only include dependencies with relative path, for now.
|
||||
if '/' not in dep:
|
||||
target_dep = os.path.dirname(target_path) + '/' + dep
|
||||
self.consider_add_dependency(target_dep, dep)
|
||||
|
||||
subprocess.call(["strip", "-s", temp.name])
|
||||
subprocess.call(["patchelf", "--set-rpath", "$ORIGIN", temp.name])
|
||||
|
||||
|
|
@ -392,7 +449,7 @@ class WheelFile(object):
|
|||
self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, size))
|
||||
|
||||
if GetVerbose():
|
||||
print("Adding %s from %s" % (target_path, source_path))
|
||||
print("Adding {0} from {1}".format(target_path, orig_source_path))
|
||||
self.zip_file.write(source_path, target_path)
|
||||
|
||||
#if temp:
|
||||
|
|
@ -433,11 +490,24 @@ class WheelFile(object):
|
|||
self.zip_file.close()
|
||||
|
||||
|
||||
def makewheel(version, output_dir, platform=default_platform):
|
||||
def makewheel(version, output_dir, platform=None):
|
||||
if sys.platform not in ("win32", "darwin") and not sys.platform.startswith("cygwin"):
|
||||
if not LocateBinary("patchelf"):
|
||||
raise Exception("patchelf is required when building a Linux wheel.")
|
||||
|
||||
if platform is None:
|
||||
# Determine the platform from the build.
|
||||
platform_dat = os.path.join(output_dir, 'tmp', 'platform.dat')
|
||||
if os.path.isfile(platform_dat):
|
||||
platform = open(platform_dat, 'r').read().strip()
|
||||
else:
|
||||
print("Could not find platform.dat in build directory")
|
||||
platform = get_platform()
|
||||
if platform.startswith("linux-"):
|
||||
# Is this manylinux1?
|
||||
if os.path.isfile("/lib/libc-2.5.so") and os.path.isdir("/opt/python"):
|
||||
platform = platform.replace("linux", "manylinux1")
|
||||
|
||||
platform = platform.replace('-', '_').replace('.', '_')
|
||||
|
||||
# Global filepaths
|
||||
|
|
@ -483,6 +553,21 @@ def makewheel(version, output_dir, platform=default_platform):
|
|||
whl = WheelFile('panda3d', version, platform)
|
||||
whl.lib_path = [libs_dir]
|
||||
|
||||
if sys.platform == "win32":
|
||||
whl.lib_path.append(join(output_dir, "python", "DLLs"))
|
||||
|
||||
if platform.startswith("manylinux"):
|
||||
# On manylinux1, we pick up all libraries except for the ones specified
|
||||
# by the manylinux1 ABI.
|
||||
whl.lib_path.append("/usr/local/lib")
|
||||
|
||||
if platform.endswith("_x86_64"):
|
||||
whl.lib_path += ["/lib64", "/usr/lib64"]
|
||||
else:
|
||||
whl.lib_path += ["/lib", "/usr/lib"]
|
||||
|
||||
whl.ignore_deps.update(MANYLINUX_LIBS)
|
||||
|
||||
# Add the trees with Python modules.
|
||||
whl.write_directory('direct', direct_dir)
|
||||
|
||||
|
|
@ -493,6 +578,7 @@ def makewheel(version, output_dir, platform=default_platform):
|
|||
__version__ = '{0}'
|
||||
""".format(version))
|
||||
|
||||
# Copy the extension modules from the panda3d directory.
|
||||
ext_suffix = GetExtensionSuffix()
|
||||
|
||||
for file in os.listdir(panda3d_dir):
|
||||
|
|
@ -509,6 +595,23 @@ __version__ = '{0}'
|
|||
|
||||
whl.write_file(target_path, source_path)
|
||||
|
||||
# And copy the extension modules from the Python installation into the
|
||||
# deploy_libs directory, for use by deploy-ng.
|
||||
ext_suffix = '.pyd' if sys.platform in ('win32', 'cygwin') else '.so'
|
||||
ext_mod_dir = get_python_ext_module_dir()
|
||||
|
||||
for file in os.listdir(ext_mod_dir):
|
||||
if file.endswith(ext_suffix):
|
||||
source_path = os.path.join(ext_mod_dir, file)
|
||||
|
||||
if file.endswith('.pyd') and platform.startswith('cygwin'):
|
||||
# Rename it to .dll for cygwin Python to be able to load it.
|
||||
target_path = 'deploy_libs/' + os.path.splitext(file)[0] + '.dll'
|
||||
else:
|
||||
target_path = 'deploy_libs/' + file
|
||||
|
||||
whl.write_file(target_path, source_path)
|
||||
|
||||
# Add plug-ins.
|
||||
for lib in PLUGIN_LIBS:
|
||||
plugin_name = 'lib' + lib
|
||||
|
|
@ -540,7 +643,7 @@ __version__ = '{0}'
|
|||
# Add a panda3d-tools directory containing the executables.
|
||||
entry_points = '[console_scripts]\n'
|
||||
entry_points += 'eggcacher = direct.directscripts.eggcacher:main\n'
|
||||
entry_points += 'pfreeze = direct.showutil.pfreeze:main\n'
|
||||
entry_points += 'pfreeze = direct.dist.pfreeze:main\n'
|
||||
tools_init = ''
|
||||
for file in os.listdir(bin_dir):
|
||||
basename = os.path.splitext(file)[0]
|
||||
|
|
@ -557,6 +660,9 @@ __version__ = '{0}'
|
|||
funcname = basename.replace('-', '_')
|
||||
entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname)
|
||||
tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file)
|
||||
entry_points += '[distutils.commands]\n'
|
||||
entry_points += 'build_apps = direct.dist.commands:build_apps\n'
|
||||
entry_points += 'bdist_apps = direct.dist.commands:bdist_apps\n'
|
||||
|
||||
whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init))
|
||||
|
||||
|
|
@ -570,6 +676,18 @@ __version__ = '{0}'
|
|||
whl.write_file(info_dir + '/README.md', readme_src)
|
||||
whl.write_file_data(info_dir + '/top_level.txt', 'direct\npanda3d\npandac\npanda3d_tools\n')
|
||||
|
||||
# Add libpython for deployment
|
||||
if sys.platform in ('win32', 'cygwin'):
|
||||
pylib_name = 'python{0}{1}.dll'.format(*sys.version_info)
|
||||
pylib_path = os.path.join(get_config_var('BINDIR'), pylib_name)
|
||||
elif sys.platform == 'darwin':
|
||||
pylib_name = 'libpython{0}.{1}.dylib'.format(*sys.version_info)
|
||||
pylib_path = os.path.join(get_config_var('LIBDIR'), pylib_name)
|
||||
else:
|
||||
pylib_name = get_config_var('LDLIBRARY')
|
||||
pylib_path = os.path.join(get_config_var('LIBDIR'), pylib_name)
|
||||
whl.write_file('deploy_libs/' + pylib_name, pylib_path)
|
||||
|
||||
whl.close()
|
||||
|
||||
|
||||
|
|
@ -580,7 +698,7 @@ if __name__ == "__main__":
|
|||
parser.add_option('', '--version', dest = 'version', help = 'Panda3D version number (default: %s)' % (version), default = version)
|
||||
parser.add_option('', '--outputdir', dest = 'outputdir', help = 'Makepanda\'s output directory (default: built)', default = 'built')
|
||||
parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
|
||||
parser.add_option('', '--platform', dest = 'platform', help = 'Override platform tag (default: %s)' % (default_platform), default = get_platform())
|
||||
parser.add_option('', '--platform', dest = 'platform', help = 'Override platform tag', default = None)
|
||||
(options, args) = parser.parse_args()
|
||||
|
||||
SetVerbose(options.verbose)
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
|
|
@ -62,6 +62,7 @@ import direct.directutil.LargeBlobSenderConsts
|
|||
import direct.directutil.Mopath
|
||||
import direct.directutil.Verify
|
||||
import direct.directutil.WeightedChoice
|
||||
import direct.dist.FreezeTool
|
||||
import direct.distributed.AsyncRequest
|
||||
import direct.distributed.CRCache
|
||||
import direct.distributed.CRDataCache
|
||||
|
|
@ -234,7 +235,6 @@ import direct.showbase.VFSImporter
|
|||
import direct.showbase.WxGlobal
|
||||
import direct.showutil.BuildGeometry
|
||||
import direct.showutil.Effects
|
||||
import direct.showutil.FreezeTool
|
||||
import direct.showutil.Rope
|
||||
import direct.showutil.TexMemWatcher
|
||||
import direct.showutil.TexViewer
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 151 KiB After Width: | Height: | Size: 151 KiB |
|
|
@ -55,9 +55,9 @@ AndroidGraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
|||
|
||||
_app = panda_android_app;
|
||||
|
||||
GraphicsWindowInputDevice device =
|
||||
GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
|
||||
PT(GraphicsWindowInputDevice) device = GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
|
||||
add_input_device(device);
|
||||
_input = device;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -486,22 +486,22 @@ handle_key_event(const AInputEvent *event) {
|
|||
/*
|
||||
int32_t meta = AKeyEvent_getMetaState(event);
|
||||
if (meta | AMETA_ALT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.alt());
|
||||
_input->button_down(KeyboardButton.alt());
|
||||
}
|
||||
if (meta | AMETA_ALT_LEFT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.lalt());
|
||||
_input->button_down(KeyboardButton.lalt());
|
||||
}
|
||||
if (meta | AMETA_ALT_RIGHT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.ralt());
|
||||
_input->button_down(KeyboardButton.ralt());
|
||||
}
|
||||
if (meta | AMETA_SHIFT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.shift());
|
||||
_input->button_down(KeyboardButton.shift());
|
||||
}
|
||||
if (meta | AMETA_SHIFT_LEFT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.lshift());
|
||||
_input->button_down(KeyboardButton.lshift());
|
||||
}
|
||||
if (meta | AMETA_SHIFT_RIGHT_ON) {
|
||||
_input_devices[0].button_down(KeyboardButton.rshift());
|
||||
_input->button_down(KeyboardButton.rshift());
|
||||
}*/
|
||||
|
||||
int32_t keycode = AKeyEvent_getKeyCode(event);
|
||||
|
|
@ -517,12 +517,12 @@ handle_key_event(const AInputEvent *event) {
|
|||
int32_t action = AKeyEvent_getAction(event);
|
||||
if (action == AKEY_EVENT_ACTION_DOWN) {
|
||||
if (AKeyEvent_getRepeatCount(event) > 0) {
|
||||
_input_devices[0].button_resume_down(button);
|
||||
_input->button_resume_down(button);
|
||||
} else {
|
||||
_input_devices[0].button_down(button);
|
||||
_input->button_down(button);
|
||||
}
|
||||
} else if (action == AKEY_EVENT_ACTION_UP) {
|
||||
_input_devices[0].button_up(button);
|
||||
_input->button_up(button);
|
||||
}
|
||||
// TODO AKEY_EVENT_ACTION_MULTIPLE
|
||||
|
||||
|
|
@ -549,16 +549,16 @@ handle_motion_event(const AInputEvent *event) {
|
|||
if (changed != 0) {
|
||||
if (changed & AMOTION_EVENT_BUTTON_PRIMARY) {
|
||||
if (button_state & AMOTION_EVENT_BUTTON_PRIMARY) {
|
||||
_input_devices[0].button_down(MouseButton::one());
|
||||
_input->button_down(MouseButton::one());
|
||||
} else {
|
||||
_input_devices[0].button_up(MouseButton::one());
|
||||
_input->button_up(MouseButton::one());
|
||||
}
|
||||
}
|
||||
if (changed & AMOTION_EVENT_BUTTON_SECONDARY) {
|
||||
if (button_state & AMOTION_EVENT_BUTTON_SECONDARY) {
|
||||
_input_devices[0].button_down(MouseButton::three());
|
||||
_input->button_down(MouseButton::three());
|
||||
} else {
|
||||
_input_devices[0].button_up(MouseButton::three());
|
||||
_input->button_up(MouseButton::three());
|
||||
}
|
||||
}
|
||||
_mouse_button_state = button_state;
|
||||
|
|
@ -568,7 +568,7 @@ handle_motion_event(const AInputEvent *event) {
|
|||
float x = AMotionEvent_getX(event, 0) - _app->contentRect.left;
|
||||
float y = AMotionEvent_getY(event, 0) - _app->contentRect.top;
|
||||
|
||||
_input_devices[0].set_pointer_in_window(x, y);
|
||||
_input->set_pointer_in_window(x, y);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -73,7 +73,7 @@ private:
|
|||
|
||||
int32_t _mouse_button_state;
|
||||
|
||||
const ARect *rect;
|
||||
GraphicsWindowInputDevice *_input;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ OpenALAudioSound(OpenALAudioManager* manager,
|
|||
_loops_completed(0),
|
||||
_source(0),
|
||||
_manager(manager),
|
||||
_volume(manager->get_volume()),
|
||||
_volume(1.0f),
|
||||
_balance(0),
|
||||
_play_rate(1.0),
|
||||
_positional(positional),
|
||||
|
|
|
|||
|
|
@ -1,47 +0,0 @@
|
|||
/**
|
||||
* 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 AwMouseAndKeyboard.cxx
|
||||
* @author Bei Yang
|
||||
* @date 2010-03
|
||||
*/
|
||||
|
||||
#include "config_awesomium.h"
|
||||
#include "AwMouseAndKeyboard.h"
|
||||
#include "dataNodeTransmit.h"
|
||||
|
||||
TypeHandle AwMouseAndKeyboard::_type_handle;
|
||||
|
||||
AwMouseAndKeyboard::AwMouseAndKeyboard(const std::string &name):
|
||||
DataNode(name)
|
||||
{
|
||||
_button_events_input = define_input("button_events", ButtonEventList::get_class_type());
|
||||
_button_events_output = define_output("button_events", ButtonEventList::get_class_type());
|
||||
}
|
||||
|
||||
|
||||
void AwMouseAndKeyboard::do_transmit_data(DataGraphTraverser *trav, const DataNodeTransmit &input, DataNodeTransmit &output){
|
||||
|
||||
if (input.has_data(_button_events_input)) {
|
||||
const ButtonEventList *button_events;
|
||||
DCAST_INTO_V(button_events, input.get_data(_button_events_input).get_ptr());
|
||||
|
||||
int num_events = button_events->get_num_events();
|
||||
for (int i = 0; i < num_events; i++) {
|
||||
const ButtonEvent &be = button_events->get_event(i);
|
||||
std::string event_name = be._button.get_name();
|
||||
printf("Button Event! : %s with code %i and index %i ", event_name.c_str(), be._keycode, be._button.get_index());
|
||||
if(be._type == ButtonEvent::T_down) printf("down");
|
||||
if(be._type == ButtonEvent::T_repeat) printf("repeat");
|
||||
if(be._type == ButtonEvent::T_up) printf("up");
|
||||
if(be._type == ButtonEvent::T_resume_down) printf("T_resume_down");
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,8 +0,0 @@
|
|||
See http://www.sirikata.com/wiki/index.php?title=Compiling_Awesomium
|
||||
|
||||
But the Chromium revision 22725.
|
||||
The awesomium git repository used is at: http://github.com/pathorn/awesomium/network
|
||||
The version of awesomium is from the master August 7 checkin, tree fc3239b4f49031285682cb5d78256d56e9001b66
|
||||
|
||||
Any method that had a wstring in the parameter, a second method was created which just accepts all std::string. This fixes the VC7 - VC9 linker error.
|
||||
|
||||
|
|
@ -1,194 +0,0 @@
|
|||
/**
|
||||
* 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 WebBrowserTexture.cxx
|
||||
* @author bei yang
|
||||
* @date 2010-03
|
||||
*/
|
||||
|
||||
#include "config_awesomium.h"
|
||||
#include "WebBrowserTexture.h"
|
||||
|
||||
TypeHandle WebBrowserTexture::_type_handle;
|
||||
|
||||
/**
|
||||
* Copy constructor for web browser texture. The behavior of copying a
|
||||
* webtexture is that will be the same as a standard texture copy. However,
|
||||
* the content will remain the system until set_web_view is called.
|
||||
*/
|
||||
WebBrowserTexture::WebBrowserTexture(const WebBrowserTexture ©):
|
||||
Texture(copy)
|
||||
{
|
||||
// this kind of assumes that the previous texture was initialized properly
|
||||
_aw_web_view = copy._aw_web_view;
|
||||
_update_active = copy._update_active;
|
||||
_flip_texture_active = copy._flip_texture_active;
|
||||
}
|
||||
|
||||
/**
|
||||
* This initializes a web browser texture with the given AwWebView class.
|
||||
*/
|
||||
WebBrowserTexture::WebBrowserTexture(const std::string &name, AwWebView* aw_web_view):
|
||||
Texture(name),
|
||||
_update_active(true),
|
||||
_flip_texture_active(false)
|
||||
{
|
||||
set_web_view(aw_web_view);
|
||||
set_minfilter(FT_linear);
|
||||
set_magfilter(FT_linear);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard destructor... doesn't do anything. All destructing happens in
|
||||
* parent texture class.
|
||||
*/
|
||||
WebBrowserTexture::~WebBrowserTexture()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Standard destructor... doesn't do anything. All destructing happens in
|
||||
* parent texture class.
|
||||
*/
|
||||
bool WebBrowserTexture::get_keep_ram_image() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A WebBrowserTexture must always keep its ram image. This is essentially a
|
||||
* sub.
|
||||
*/
|
||||
void WebBrowserTexture::do_reload_ram_image() {
|
||||
// A MovieTexture should never dump its RAM image. Therefore, this is not
|
||||
// needed.
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be overridden by derived classes to return true if cull_callback()
|
||||
* has been defined. Otherwise, returns false to indicate cull_callback()
|
||||
* does not need to be called for this node during the cull traversal.
|
||||
*
|
||||
* This one returns true because it uses the cull traverser method to do the
|
||||
* texture udpate.
|
||||
*/
|
||||
bool WebBrowserTexture::has_cull_callback() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the internal AwWebView of this texture. After calling this, the
|
||||
* texture will automatically set it's width and height to match the AwWebView
|
||||
* at the next time it is culled and rendered.
|
||||
*/
|
||||
void WebBrowserTexture::set_web_view(AwWebView* aw_web_view){
|
||||
_aw_web_view = aw_web_view;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current internal AwWebView of this texture.
|
||||
*/
|
||||
AwWebView* WebBrowserTexture::get_web_view() const{
|
||||
return _aw_web_view;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives the ability to toggle updating this texture or not. This can be
|
||||
* disabled to improve performance so that only the one that needs to be
|
||||
* active is active.
|
||||
*/
|
||||
void WebBrowserTexture::set_update_active(bool active_flag){
|
||||
_update_active = active_flag;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets whether or not this texture is updating itself every time it is
|
||||
* rendered.
|
||||
*/
|
||||
bool WebBrowserTexture::get_update_active() const{
|
||||
return _update_active;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This toggles on/off automatic flipping of the of the texture at a source
|
||||
* level. Awesomium renders things that are flipped vertically. This enables
|
||||
* automatic flipping of that.
|
||||
*
|
||||
* Since it is doing byte manipulation, this can get rather slow. Turning
|
||||
* this on should be avoided. Instead, flipping should be taken care of via
|
||||
* UV coordinates or shaders.
|
||||
*/
|
||||
void WebBrowserTexture::set_flip_texture_active(bool active_flag){
|
||||
_flip_texture_active = active_flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether automatic texture flipping is enabled.
|
||||
*/
|
||||
bool WebBrowserTexture::get_flip_texture_active() const {
|
||||
return _flip_texture_active;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This function will be called during the cull traversal to update the
|
||||
* WebBrowserTexture. This method calls the render method of AwWebView but
|
||||
* does not call the update method of AwWebCore.
|
||||
*/
|
||||
bool WebBrowserTexture::cull_callback(CullTraverser *trav, const CullTraverserData &data) const{
|
||||
// see if we are in a state where udpates can happen. else just return
|
||||
if( !_update_active ) return true;
|
||||
if( _aw_web_view == nullptr ) return true;
|
||||
|
||||
// do we even need to update?
|
||||
if( !_aw_web_view->is_dirty() ) return true;
|
||||
|
||||
// see if we're the same size, if not we need to make sure this texture
|
||||
// matches the webview
|
||||
if( _aw_web_view->get_width() != get_x_size() || _aw_web_view->get_height() != get_y_size() || get_texture_type() != TT_2d_texture){
|
||||
// these casts are so dirty especially when the method itself is
|
||||
// labled as const. Really Texture::cull_callback should be not const
|
||||
// first clean up
|
||||
((WebBrowserTexture*)this)->clear_ram_mipmap_images();
|
||||
((WebBrowserTexture*)this)->clear_ram_image();
|
||||
// now set up the texture again
|
||||
((WebBrowserTexture*)this)->setup_2d_texture( _aw_web_view->get_width(), _aw_web_view->get_height(), T_unsigned_byte, F_rgba );
|
||||
// should be good to go at this point
|
||||
}
|
||||
|
||||
// get the pointer
|
||||
PTA_uchar ram_image = ((WebBrowserTexture*)this)->modify_ram_image();
|
||||
unsigned char* cp_data = ram_image.p();
|
||||
// render it
|
||||
_aw_web_view->render((void*)cp_data, get_x_size()*4, 4);
|
||||
|
||||
if(_flip_texture_active){
|
||||
// flips the texture around... this is super slow. Really this should
|
||||
// never be enabled. However beginners might find this useful
|
||||
size_t width = get_x_size();
|
||||
size_t height = get_y_size();
|
||||
for(size_t i=0; i < height/2; i++){
|
||||
for(size_t j=0; j < width; j++){
|
||||
unsigned char tmp[4];
|
||||
size_t a_pos = j+width*i;
|
||||
size_t b_pos = j + width*(height-i-1);
|
||||
memcpy(tmp,&cp_data[4*a_pos], 4); //tmp = a
|
||||
memcpy(&cp_data[4*a_pos], &cp_data[4*b_pos], 4); //a = b
|
||||
memcpy(&cp_data[4*b_pos], tmp, 4); //b = tmp
|
||||
}
|
||||
}
|
||||
}
|
||||
// success
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1,77 +0,0 @@
|
|||
/**
|
||||
* 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 WebBrowserTexture.h
|
||||
* @author Bei Yang
|
||||
* @date 2010-08-03
|
||||
*/
|
||||
|
||||
#ifndef WebBrowserTexture_H
|
||||
#define WebBrowserTexture_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "texture.h"
|
||||
#include "awWebView.h"
|
||||
|
||||
|
||||
/**
|
||||
* A Wrapper class for Awesomium webview. This implements most of Awesomium's
|
||||
* features and updates on the cull_traverser callback much much like a movie
|
||||
* texture.
|
||||
*
|
||||
* The use of class means that you will have to follow Awesomium license
|
||||
* agreement give below http://www.khrona.com/products/awesomium/licensing
|
||||
*/
|
||||
class EXPCL_PANDAAWESOMIUM WebBrowserTexture : public Texture {
|
||||
protected:
|
||||
AwWebView* _aw_web_view;
|
||||
bool _update_active;
|
||||
bool _flip_texture_active;
|
||||
|
||||
// Constructors & Destructors ------------
|
||||
private:
|
||||
WebBrowserTexture(const WebBrowserTexture ©);
|
||||
PUBLISHED:
|
||||
WebBrowserTexture(const std::string &name, AwWebView* aw_web_view = nullptr);
|
||||
virtual ~WebBrowserTexture();
|
||||
|
||||
|
||||
// methods --------------
|
||||
protected:
|
||||
bool get_keep_ram_image() const;
|
||||
void do_reload_ram_image();
|
||||
public:
|
||||
virtual bool has_cull_callback() const;
|
||||
virtual bool cull_callback(CullTraverser *trav, const CullTraverserData &data) const;
|
||||
PUBLISHED:
|
||||
void set_web_view(AwWebView* aw_web_view);
|
||||
AwWebView* get_web_view() const;
|
||||
void set_update_active(bool active_flag);
|
||||
bool get_update_active() const;
|
||||
void set_flip_texture_active(bool active_flag);
|
||||
bool get_flip_texture_active() const;
|
||||
|
||||
// Type handles ----------------
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
Texture::init_type();
|
||||
register_type(_type_handle, "WebBrowserTexture",
|
||||
Texture::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
#endif
|
||||
|
|
@ -1,48 +0,0 @@
|
|||
/**
|
||||
* 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 awWebCore.I
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
INLINE void AwWebCore::
|
||||
setBaseDirectory(const std::string& baseDirectory) {
|
||||
WebCore::setBaseDirectory(baseDirectory);
|
||||
}
|
||||
|
||||
INLINE void AwWebCore::
|
||||
setCustomResponsePage(int statusCode, const std::string& filePath) {
|
||||
WebCore::setCustomResponsePage(statusCode, filePath);
|
||||
}
|
||||
|
||||
INLINE void AwWebCore::
|
||||
update() {
|
||||
WebCore::update();
|
||||
}
|
||||
|
||||
INLINE const std::string& AwWebCore::
|
||||
getBaseDirectory() const {
|
||||
return WebCore::getBaseDirectory();
|
||||
}
|
||||
|
||||
INLINE bool AwWebCore::
|
||||
arePluginsEnabled() const {
|
||||
return WebCore::arePluginsEnabled();
|
||||
}
|
||||
|
||||
|
||||
INLINE void AwWebCore::
|
||||
pause(){
|
||||
WebCore::pause();
|
||||
}
|
||||
|
||||
INLINE void AwWebCore::
|
||||
resume() {
|
||||
WebCore::resume();
|
||||
}
|
||||
|
|
@ -1,56 +0,0 @@
|
|||
/**
|
||||
* 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 awWebCore.cxx
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
#include "config_awesomium.h"
|
||||
#include "awWebCore.h"
|
||||
|
||||
#include <WebCore.h>
|
||||
|
||||
TypeHandle AwWebCore::_type_handle;
|
||||
|
||||
AwWebCore::
|
||||
AwWebCore(AwWebCore::LogLevel level, bool enablePlugins , AwWebCore::PixelFormat pixelFormat)
|
||||
#ifndef CPPPARSER
|
||||
:
|
||||
WebCore(static_cast<Awesomium::LogLevel>(level), enablePlugins, static_cast<Awesomium::PixelFormat>(pixelFormat))
|
||||
#endif
|
||||
{
|
||||
awesomium_cat.info() << "constructing webcore\n";
|
||||
}
|
||||
|
||||
AwWebCore::
|
||||
~AwWebCore() {
|
||||
awesomium_cat.info() << "destructor webcore\n";
|
||||
}
|
||||
|
||||
Awesomium::WebCore& AwWebCore::
|
||||
Get() {
|
||||
return WebCore::Get();
|
||||
}
|
||||
|
||||
Awesomium::WebCore* AwWebCore::
|
||||
GetPointer() {
|
||||
return WebCore::GetPointer();
|
||||
}
|
||||
|
||||
AwWebView * AwWebCore::
|
||||
createWebView(int width, int height, bool isTransparent , bool enableAsyncRendering , int maxAsyncRenderPerSec ) {
|
||||
Awesomium::WebView * newView = WebCore::createWebView(width, height, isTransparent, enableAsyncRendering, maxAsyncRenderPerSec);
|
||||
AwWebView * result = new AwWebView(newView);
|
||||
return result;
|
||||
}
|
||||
|
||||
AwWebCore::PixelFormat AwWebCore::
|
||||
getPixelFormat() const {
|
||||
return ( static_cast<AwWebCore::PixelFormat>( WebCore::getPixelFormat()) );
|
||||
}
|
||||
|
|
@ -1,94 +0,0 @@
|
|||
/**
|
||||
* 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 awWebCore.h
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
#ifndef AWWEBCORE_H
|
||||
#define AWWEBCORE_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "luse.h"
|
||||
|
||||
#include "awesomium_includes.h"
|
||||
|
||||
class AwWebView;
|
||||
/**
|
||||
* Thin wrappings arround WebCore.h
|
||||
*/
|
||||
class EXPCL_PANDAAWESOMIUM AwWebCore : public TypedReferenceCount, public Awesomium::WebCore {
|
||||
PUBLISHED:
|
||||
/**
|
||||
* An enumeration of the three verbosity settings for the Awesomium Log.
|
||||
*/
|
||||
enum LogLevel
|
||||
{
|
||||
LOG_NONE , // No log is created
|
||||
LOG_NORMAL , // Logs only errors
|
||||
LOG_VERBOSE // Logs everything
|
||||
};
|
||||
|
||||
/**
|
||||
* An enumeration of the two output pixel formats that WebView::render will use.
|
||||
*/
|
||||
enum PixelFormat
|
||||
{
|
||||
PF_BGRA, // BGRA byte ordering [Blue, Green, Red, Alpha]
|
||||
PF_RGBA // RGBA byte ordering [Red, Green, Blue, Alpha]
|
||||
};
|
||||
|
||||
AwWebCore(LogLevel level = LOG_NORMAL, bool enablePlugins = true, PixelFormat pixelFormat = PF_BGRA);
|
||||
|
||||
virtual ~AwWebCore();
|
||||
|
||||
static Awesomium::WebCore& Get();
|
||||
|
||||
static Awesomium::WebCore* GetPointer();
|
||||
|
||||
INLINE void setBaseDirectory(const std::string& baseDirectory);
|
||||
|
||||
AwWebView * createWebView(int width, int height, bool isTransparent = false, bool enableAsyncRendering = false, int maxAsyncRenderPerSec = 70);
|
||||
|
||||
INLINE void setCustomResponsePage(int statusCode, const std::string& filePath);
|
||||
|
||||
INLINE void update();
|
||||
|
||||
INLINE const std::string& getBaseDirectory() const;
|
||||
|
||||
AwWebCore::PixelFormat getPixelFormat() const;
|
||||
|
||||
INLINE bool arePluginsEnabled() const;
|
||||
|
||||
INLINE void pause();
|
||||
|
||||
INLINE void resume();
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "AwWebCore",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "awWebCore.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,82 +0,0 @@
|
|||
/**
|
||||
* 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 awWebView.I
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
INLINE void AwWebView::
|
||||
destroy(void)
|
||||
{
|
||||
_myWebView->destroy();
|
||||
}
|
||||
|
||||
|
||||
INLINE void AwWebView::
|
||||
setListener(Awesomium::WebViewListener * listener) {
|
||||
_myWebView->setListener(listener);
|
||||
}
|
||||
|
||||
INLINE Awesomium::WebViewListener* AwWebView::
|
||||
getListener() {
|
||||
return _myWebView->getListener();
|
||||
}
|
||||
|
||||
INLINE void AwWebView::
|
||||
goToHistoryOffset(int offset) {
|
||||
_myWebView->goToHistoryOffset(offset);
|
||||
}
|
||||
|
||||
INLINE void AwWebView::
|
||||
executeJavascript2(const std::string& javascript, const std::string& frameName ) {
|
||||
_myWebView->executeJavascript2(javascript, frameName);
|
||||
}
|
||||
|
||||
INLINE Awesomium::FutureJSValue AwWebView::
|
||||
executeJavascriptWithResult2(const std::string& javascript, const std::string& frameName ) {
|
||||
return _myWebView->executeJavascriptWithResult2(javascript, frameName);
|
||||
}
|
||||
|
||||
INLINE void AwWebView::
|
||||
setProperty(const std::string& name, const Awesomium::JSValue& value) {
|
||||
_myWebView->setProperty(name, value);
|
||||
}
|
||||
|
||||
INLINE void AwWebView::
|
||||
setCallback(const std::string& name) {
|
||||
_myWebView->setCallback(name);
|
||||
}
|
||||
|
||||
INLINE bool AwWebView::
|
||||
isDirty() {
|
||||
return _myWebView->isDirty();
|
||||
}
|
||||
|
||||
INLINE void AwWebView::
|
||||
render( size_t destination, int destRowSpan, int destDepth)
|
||||
{
|
||||
_myWebView->render( reinterpret_cast<unsigned char *>(destination), destRowSpan, destDepth, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
INLINE void AwWebView::
|
||||
injectMouseUp(AwWebView::MouseButton button) {
|
||||
_myWebView->injectMouseUp(static_cast<Awesomium::MouseButton>(button));
|
||||
}
|
||||
|
||||
INLINE void AwWebView::
|
||||
injectMouseWheelXY(int scrollAmountX, int scrollAmountY){
|
||||
_myWebView->injectMouseWheelXY(scrollAmountX, scrollAmountY);
|
||||
}
|
||||
|
||||
INLINE void AwWebView::
|
||||
injectKeyEvent(bool press, int modifiers, int windowsCode, int nativeCode) {
|
||||
_myWebView->injectKeyEvent(press, modifiers, windowsCode, nativeCode);
|
||||
}
|
||||
|
|
@ -1,74 +0,0 @@
|
|||
/**
|
||||
* 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 awWebView.cxx
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
#include "config_awesomium.h"
|
||||
#include "awWebView.h"
|
||||
|
||||
TypeHandle AwWebView::_type_handle;
|
||||
|
||||
AwWebView::
|
||||
AwWebView(Awesomium::WebView * webViewPtr) {
|
||||
_myWebView = webViewPtr;
|
||||
|
||||
}
|
||||
|
||||
AwWebView::
|
||||
~AwWebView() {
|
||||
}
|
||||
|
||||
|
||||
void AwWebView::
|
||||
loadURL2(const std::string& url, const std::string& frameName , const std::string& username , const std::string& password )
|
||||
{
|
||||
_myWebView->loadURL2(url, frameName, username, password);
|
||||
|
||||
}
|
||||
|
||||
void AwWebView::
|
||||
loadHTML2(const std::string& html, const std::string& frameName )
|
||||
{
|
||||
_myWebView->loadHTML2(html, frameName);
|
||||
}
|
||||
|
||||
|
||||
void AwWebView::
|
||||
loadFile2(const std::string& file, const std::string& frameName )
|
||||
{
|
||||
_myWebView->loadFile2(file, frameName);
|
||||
}
|
||||
|
||||
|
||||
void AwWebView::
|
||||
render(size_t destination, int destRowSpan, int destDepth, AwWebView::Rect * renderedRect) {
|
||||
if (renderedRect) {
|
||||
Awesomium::Rect rect(renderedRect->x, renderedRect->y, renderedRect->width, renderedRect->height);
|
||||
_myWebView->Awesomium::WebView::render( reinterpret_cast<unsigned char *>(destination), destRowSpan, destDepth, &rect);
|
||||
}
|
||||
else
|
||||
{
|
||||
AwWebView::render(destination, destRowSpan, destDepth, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void AwWebView::
|
||||
injectMouseDown(AwWebView::MouseButton button) {
|
||||
awesomium_cat.debug() <<"got mouse down " << button << "\n";
|
||||
_myWebView->injectMouseDown(static_cast<Awesomium::MouseButton>(button));
|
||||
}
|
||||
|
||||
|
||||
void AwWebView::
|
||||
injectMouseMove(int x, int y) {
|
||||
// awesomium_cat.debug() <<"got mouse move " << x << " " << y << "\n";
|
||||
_myWebView->injectMouseMove(x,y);
|
||||
}
|
||||
|
|
@ -1,131 +0,0 @@
|
|||
/**
|
||||
* 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 awWebView.h
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
#ifndef AWWEBVIEW_H
|
||||
#define AWWEBVIEW_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "luse.h"
|
||||
|
||||
#include "awesomium_includes.h"
|
||||
|
||||
class WebViewListener;
|
||||
|
||||
/**
|
||||
* Thin bindings, wraps a WebView * returned from WebCore.createWebView
|
||||
*/
|
||||
class EXPCL_PANDAAWESOMIUM AwWebView : public TypedReferenceCount{
|
||||
PUBLISHED:
|
||||
|
||||
/**
|
||||
* Mouse button enumerations, used with WebView::injectMouseDown
|
||||
* and WebView::injectMouseUp
|
||||
*/
|
||||
enum MouseButton {
|
||||
LEFT_MOUSE_BTN,
|
||||
MIDDLE_MOUSE_BTN,
|
||||
RIGHT_MOUSE_BTN
|
||||
};
|
||||
|
||||
/**
|
||||
* A simple rectangle class, used with WebView::render
|
||||
*/
|
||||
struct Rect {
|
||||
int x, y, width, height;
|
||||
|
||||
Rect();
|
||||
Rect(int x, int y, int width, int height);
|
||||
bool isEmpty() const;
|
||||
};
|
||||
|
||||
|
||||
PUBLISHED:
|
||||
AwWebView(Awesomium::WebView * webView);
|
||||
|
||||
virtual ~AwWebView();
|
||||
|
||||
INLINE void destroy(void);
|
||||
|
||||
INLINE void setListener(Awesomium::WebViewListener * listener);
|
||||
|
||||
INLINE Awesomium::WebViewListener* getListener();
|
||||
|
||||
// VC7 linker doesn't like wstring from VS2008, hence using the all regular
|
||||
// string version
|
||||
void loadURL2(const std::string& url, const std::string& frameName ="", const std::string& username="" , const std::string& password="");
|
||||
|
||||
// VC7 linker doesn't like wstring from VS2008, hence using the all regular
|
||||
// string version
|
||||
void loadHTML2(const std::string& html, const std::string& frameName = "");
|
||||
|
||||
// VC7 linker doesn't like wstring from VS2008, hence using the all regular
|
||||
// string version
|
||||
void loadFile2(const std::string& file, const std::string& frameName = "" );
|
||||
|
||||
INLINE void goToHistoryOffset(int offset);
|
||||
|
||||
// VC7 linker doesn't like wstring from VS2008, hence using the all regular
|
||||
// string version
|
||||
INLINE void executeJavascript2(const std::string& javascript, const std::string& frameName = "" );
|
||||
|
||||
INLINE Awesomium::FutureJSValue executeJavascriptWithResult2(const std::string& javascript, const std::string& frameName = "");
|
||||
|
||||
INLINE void setProperty(const std::string& name, const Awesomium::JSValue& value);
|
||||
|
||||
INLINE void setCallback(const std::string& name);
|
||||
|
||||
INLINE bool isDirty();
|
||||
|
||||
INLINE void render(size_t destination, int destRowSpan, int destDepth);
|
||||
|
||||
void render(size_t destination, int destRowSpan, int destDepth, AwWebView::Rect * renderedRect);
|
||||
|
||||
void injectMouseMove(int x, int y);
|
||||
|
||||
void injectMouseDown(AwWebView::MouseButton button);
|
||||
|
||||
INLINE void injectMouseUp(AwWebView::MouseButton button);
|
||||
|
||||
INLINE void injectMouseWheelXY(int scrollAmountX, int scrollAmountY);
|
||||
|
||||
INLINE void injectMouseWheel(int scrollAmountY) {
|
||||
injectMouseWheelXY(0, scrollAmountY);
|
||||
}
|
||||
|
||||
INLINE void injectKeyEvent(bool press, int modifiers, int windowsCode, int nativeCode=0);
|
||||
|
||||
private:
|
||||
Awesomium::WebView * _myWebView;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "AwWebView",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
#include "awWebView.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
/**
|
||||
* 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 awWebViewListener.cxx
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
#include "config_awesomium.h"
|
||||
#include "awWebViewListener.h"
|
||||
|
||||
TypeHandle AwWebViewListener::_type_handle;
|
||||
|
||||
AwWebViewListener::
|
||||
AwWebViewListener() {
|
||||
awesomium_cat.info() << "constructing WebViewListner" ;
|
||||
}
|
||||
|
||||
void AwWebViewListener::onBeginNavigation(const std::string& url, const std::wstring& frameName){
|
||||
}
|
||||
|
||||
void AwWebViewListener::onBeginLoading(const std::string& url, const std::wstring& frameName, int statusCode, const std::wstring& mimeType) {
|
||||
awesomium_cat.info() << "onBeginLoading" ;
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired when all loads have finished for a WebView.
|
||||
*/
|
||||
void AwWebViewListener::onFinishLoading() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired when a Client callback has been invoked via Javascript from a page.
|
||||
*
|
||||
* @param name The name of the client callback that was invoked (specifically, "Client._this_name_here_(...)").
|
||||
*
|
||||
* @param args The arguments passed to the callback.
|
||||
*/
|
||||
void AwWebViewListener::onCallback(const std::string& name, const Awesomium::JSArguments& args) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired when a page title is received.
|
||||
*
|
||||
* @param title The page title.
|
||||
*
|
||||
* @param frameName The name of the frame that this event originated from.
|
||||
*/
|
||||
void AwWebViewListener::onReceiveTitle(const std::wstring& title, const std::wstring& frameName) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired when a tooltip has changed state.
|
||||
*
|
||||
* @param tooltip The tooltip text (or, is an empty string when the tooltip should disappear).
|
||||
*/
|
||||
void AwWebViewListener::onChangeTooltip(const std::wstring& tooltip) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired when keyboard focus has changed.
|
||||
*
|
||||
* @param isFocused Whether or not the keyboard is currently focused.
|
||||
*/
|
||||
void AwWebViewListener::onChangeKeyboardFocus(bool isFocused) {
|
||||
}
|
||||
|
||||
/**
|
||||
* This event is fired when the target URL has changed. This is usually the result of
|
||||
* hovering over a link on the page.
|
||||
*
|
||||
* @param url The updated target URL (or empty if the target URL is cleared).
|
||||
*/
|
||||
void AwWebViewListener::onChangeTargetURL(const std::string& url) {
|
||||
}
|
||||
|
|
@ -1,123 +0,0 @@
|
|||
/**
|
||||
* 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 awWebViewListener.h
|
||||
* @author rurbino
|
||||
* @date 2009-10-12
|
||||
*/
|
||||
|
||||
#ifndef AWWEBVIEWLISTENER_H
|
||||
#define AWWEBVIEWLISTENER_H
|
||||
|
||||
#include "pandabase.h"
|
||||
#include "typedReferenceCount.h"
|
||||
#include "luse.h"
|
||||
|
||||
#include "awesomium_includes.h"
|
||||
|
||||
/**
|
||||
* Thin bindings, wraps a WebViewListener
|
||||
*/
|
||||
class EXPCL_PANDAAWESOMIUM AwWebViewListener : public TypedReferenceCount, public Awesomium::WebCore {
|
||||
PUBLISHED:
|
||||
|
||||
|
||||
PUBLISHED:
|
||||
AwWebViewListener();
|
||||
|
||||
virtual ~AwWebViewListener() {}
|
||||
|
||||
/**
|
||||
* This event is fired when a WebView begins navigating to a new URL.
|
||||
*
|
||||
* @param url The URL that is being navigated to.
|
||||
*
|
||||
* @param frameName The name of the frame that this event originated from.
|
||||
*/
|
||||
void onBeginNavigation(const std::string& url, const std::wstring& frameName) ;
|
||||
|
||||
/**
|
||||
* This event is fired when a WebView begins to actually receive data from a server.
|
||||
*
|
||||
* @param url The URL of the frame that is being loaded.
|
||||
*
|
||||
* @param frameName The name of the frame that this event originated from.
|
||||
*
|
||||
* @param statusCode The HTTP status code returned by the server.
|
||||
*
|
||||
* @param mimeType The mime-type of the content that is being loaded.
|
||||
*/
|
||||
void onBeginLoading(const std::string& url, const std::wstring& frameName, int statusCode, const std::wstring& mimeType);
|
||||
|
||||
/**
|
||||
* This event is fired when all loads have finished for a WebView.
|
||||
*/
|
||||
void onFinishLoading();
|
||||
|
||||
/**
|
||||
* This event is fired when a Client callback has been invoked via Javascript from a page.
|
||||
*
|
||||
* @param name The name of the client callback that was invoked (specifically, "Client._this_name_here_(...)").
|
||||
*
|
||||
* @param args The arguments passed to the callback.
|
||||
*/
|
||||
void onCallback(const std::string& name, const Awesomium::JSArguments& args);
|
||||
|
||||
/**
|
||||
* This event is fired when a page title is received.
|
||||
*
|
||||
* @param title The page title.
|
||||
*
|
||||
* @param frameName The name of the frame that this event originated from.
|
||||
*/
|
||||
void onReceiveTitle(const std::wstring& title, const std::wstring& frameName) ;
|
||||
|
||||
/**
|
||||
* This event is fired when a tooltip has changed state.
|
||||
*
|
||||
* @param tooltip The tooltip text (or, is an empty string when the tooltip should disappear).
|
||||
*/
|
||||
void onChangeTooltip(const std::wstring& tooltip);
|
||||
|
||||
/**
|
||||
* This event is fired when keyboard focus has changed.
|
||||
*
|
||||
* @param isFocused Whether or not the keyboard is currently focused.
|
||||
*/
|
||||
void onChangeKeyboardFocus(bool isFocused) ;
|
||||
|
||||
/**
|
||||
* This event is fired when the target URL has changed. This is usually the result of
|
||||
* hovering over a link on the page.
|
||||
*
|
||||
* @param url The updated target URL (or empty if the target URL is cleared).
|
||||
*/
|
||||
void onChangeTargetURL(const std::string& url) ;
|
||||
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "AwWebViewListener",
|
||||
TypedReferenceCount::get_class_type());
|
||||
}
|
||||
virtual TypeHandle get_type() const {
|
||||
return get_class_type();
|
||||
}
|
||||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
private:
|
||||
static TypeHandle _type_handle;
|
||||
};
|
||||
|
||||
// #include "awWebViewListener.I"
|
||||
|
||||
#endif
|
||||