From 8a0f43815675ecfe7cfb5d5f41297abf71a1f60e Mon Sep 17 00:00:00 2001 From: Donny Lawrence Date: Mon, 3 Dec 2018 23:05:05 -0500 Subject: [PATCH 01/16] Get rid of the flickering that occurs on Mojave as a result of changes in the way AppKit handles view layers. --- panda/src/cocoadisplay/cocoaPandaView.mm | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/panda/src/cocoadisplay/cocoaPandaView.mm b/panda/src/cocoadisplay/cocoaPandaView.mm index c3471ec36b..6a3f48b39a 100644 --- a/panda/src/cocoadisplay/cocoaPandaView.mm +++ b/panda/src/cocoadisplay/cocoaPandaView.mm @@ -26,6 +26,10 @@ [self setCanDrawConcurrently:YES]; #endif + // If a layer ends up becoming attached to the view, tell AppKit we'll manage + // the redrawing since we're doing things our own way. + self.layerContentsRedrawPolicy = NSViewLayerContentsRedrawNever; + cocoadisplay_cat.debug() << "Created CocoaPandaView " << self << " for GraphicsWindow " << window << "\n"; _graphicsWindow = window; @@ -167,4 +171,15 @@ - (BOOL) isOpaque { return YES; } + +-(void)setLayer:(CALayer*)layer +{ + [super setLayer:layer]; + + // Starting in macOS 10.14, a CALayer will still be attached to a view even + // if `wantsLayer` is false. If we don't update the context now, only a + // black screen will be rendered until the context is updated some other + // way (like through a window resize event). + [_context update]; +} @end From 301957c59188ae6d83276e4796a1f421f95b9daa Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 4 Dec 2018 12:36:03 +0100 Subject: [PATCH 02/16] gobj: improve performance of GeomPrimitive::make_nonindexed() It now no longer has to create two GeomVertexArrayDataHandle objects for every vertex it visits. --- panda/src/gobj/geomPrimitive.cxx | 27 ++++++++---- panda/src/gobj/geomVertexData.cxx | 68 ++++++++++++++++++++----------- panda/src/gobj/geomVertexData.h | 3 ++ 3 files changed, 66 insertions(+), 32 deletions(-) diff --git a/panda/src/gobj/geomPrimitive.cxx b/panda/src/gobj/geomPrimitive.cxx index 011d66b132..2cd5e2739a 100644 --- a/panda/src/gobj/geomPrimitive.cxx +++ b/panda/src/gobj/geomPrimitive.cxx @@ -538,15 +538,26 @@ offset_vertices(int offset, int begin_row, int end_row) { void GeomPrimitive:: make_nonindexed(GeomVertexData *dest, const GeomVertexData *source) { Thread *current_thread = Thread::get_current_thread(); - int num_vertices = get_num_vertices(); - int dest_start = dest->get_num_rows(); - int strip_cut_index = get_strip_cut_index(); - dest->set_num_rows(dest_start + num_vertices); - for (int i = 0; i < num_vertices; ++i) { - int v = get_vertex(i); - nassertd(v != strip_cut_index) continue; - dest->copy_row_from(dest_start + i, source, v, current_thread); + int num_vertices, dest_start; + { + GeomPrimitivePipelineReader reader(this, current_thread); + num_vertices = reader.get_num_vertices(); + int strip_cut_index = reader.get_strip_cut_index(); + + GeomVertexDataPipelineWriter data_writer(dest, false, current_thread); + data_writer.check_array_writers(); + dest_start = data_writer.get_num_rows(); + data_writer.set_num_rows(dest_start + num_vertices); + + GeomVertexDataPipelineReader data_reader(source, current_thread); + data_reader.check_array_readers(); + + for (int i = 0; i < num_vertices; ++i) { + int v = reader.get_vertex(i); + nassertd(v != strip_cut_index) continue; + data_writer.copy_row_from(dest_start + i, data_reader, v); + } } set_nonindexed_vertices(dest_start, num_vertices); diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index 45522427c2..d7bf35ba9d 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -686,32 +686,13 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, void GeomVertexData:: copy_row_from(int dest_row, const GeomVertexData *source, int source_row, Thread *current_thread) { - const GeomVertexFormat *source_format = source->get_format(); - const GeomVertexFormat *dest_format = get_format(); - nassertv(source_format == dest_format); - nassertv(source_row >= 0 && source_row < source->get_num_rows()); - if (dest_row >= get_num_rows()) { - // Implicitly add enough rows to get to the indicated row. - set_num_rows(dest_row + 1); - } + GeomVertexDataPipelineReader reader(source, current_thread); + reader.check_array_readers(); - int num_arrays = source_format->get_num_arrays(); - - for (int i = 0; i < num_arrays; ++i) { - PT(GeomVertexArrayDataHandle) dest_handle = modify_array_handle(i); - unsigned char *dest_array_data = dest_handle->get_write_pointer(); - - CPT(GeomVertexArrayDataHandle) source_array_handle = source->get_array_handle(i); - const unsigned char *source_array_data = source_array_handle->get_read_pointer(true); - - const GeomVertexArrayFormat *array_format = source_format->get_array(i); - int stride = array_format->get_stride(); - - memcpy(dest_array_data + stride * dest_row, - source_array_data + stride * source_row, - stride); - } + GeomVertexDataPipelineWriter writer(this, true, current_thread); + writer.check_array_writers(); + writer.copy_row_from(dest_row, reader, source_row); } /** @@ -2601,6 +2582,45 @@ set_array(size_t i, const GeomVertexArrayData *array) { } } +/** + * Copies a single row of the data from the other array into the indicated row + * of this array. In this case, the source format must exactly match the + * destination format. + * + * Don't call this in a downstream thread unless you don't mind it blowing + * away other changes you might have recently made in an upstream thread. + */ +void GeomVertexDataPipelineWriter:: +copy_row_from(int dest_row, const GeomVertexDataPipelineReader &source, + int source_row) { + const GeomVertexFormat *source_format = source.get_format(); + const GeomVertexFormat *dest_format = get_format(); + nassertv(source_format == dest_format); + nassertv(source_row >= 0 && source_row < source.get_num_rows()); + nassertv(_got_array_writers); + + if (dest_row >= get_num_rows()) { + // Implicitly add enough rows to get to the indicated row. + set_num_rows(dest_row + 1); + } + + size_t num_arrays = source_format->get_num_arrays(); + for (size_t i = 0; i < num_arrays; ++i) { + GeomVertexArrayDataHandle *dest_handle = get_array_writer(i); + unsigned char *dest_array_data = dest_handle->get_write_pointer(); + + const GeomVertexArrayDataHandle *source_array_handle = source.get_array_reader(i); + const unsigned char *source_array_data = source_array_handle->get_read_pointer(true); + + const GeomVertexArrayFormat *array_format = source_format->get_array(i); + int stride = array_format->get_stride(); + + memcpy(dest_array_data + stride * dest_row, + source_array_data + stride * source_row, + stride); + } +} + /** * */ diff --git a/panda/src/gobj/geomVertexData.h b/panda/src/gobj/geomVertexData.h index 9b861c1cbc..2b267045c5 100644 --- a/panda/src/gobj/geomVertexData.h +++ b/panda/src/gobj/geomVertexData.h @@ -526,6 +526,9 @@ public: bool unclean_set_num_rows(int n); bool reserve_num_rows(int n); + void copy_row_from(int dest_row, const GeomVertexDataPipelineReader &source, + int source_row); + private: void make_array_writers(); void delete_array_writers(); From 3c6b6e47ec91195c23e3cf60ab8dcdffd468439d Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 4 Dec 2018 12:43:55 +0100 Subject: [PATCH 03/16] glgsg: don't call glLineWidth with higher value than maximum Officially, in core profile OpenGL 3.2+, calling it with a value higher than 1.0 is an error, but many vendors seem to let us. Apple's implementation does not. It appears that checking the maximum line width is a way to deal with this. Fixes #466 --- .../glstuff/glGraphicsStateGuardian_src.cxx | 24 ++++++++++++++++++- .../src/glstuff/glGraphicsStateGuardian_src.h | 2 ++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 14fec5d146..62d74ce5bc 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -771,6 +771,28 @@ reset() { _supported_geom_rendering |= Geom::GR_point_sprite; } + // Determine whether we support wide lines (and how wide they can be). + { + GLfloat aliased_range[2] = {1.0f, 1.0f}; + glGetFloatv(GL_ALIASED_LINE_WIDTH_RANGE, aliased_range); + + _max_line_width = aliased_range[1]; + +#ifdef SUPPORT_FIXED_FUNCTION + if (has_fixed_function_pipeline()) { +#ifndef OPENGLES + GLfloat range[2] = {1.0f, 1.0f}; + glGetFloatv(GL_LINE_WIDTH_RANGE, range); + _max_line_width = std::max(_max_line_width, range[1]); +#endif + + GLfloat smooth_range[2] = {1.0f, 1.0f}; + glGetFloatv(GL_SMOOTH_LINE_WIDTH_RANGE, smooth_range); + _max_line_width = std::max(_max_line_width, smooth_range[1]); + } +#endif + } + #ifdef OPENGLES_1 // OpenGL ES 1.0 does not support primitive restart indices. @@ -7352,7 +7374,7 @@ do_issue_render_mode() { GLCAT.spam() << "setting thickness to " << thickness << "\n"; } - glLineWidth(thickness); + glLineWidth(std::min(thickness, _max_line_width)); #ifndef OPENGLES_2 glPointSize(thickness); #endif diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 4329938d06..3fd89c8ad1 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -685,6 +685,8 @@ protected: #endif #endif + GLfloat _max_line_width; + #ifdef HAVE_CG CGcontext _cg_context; #endif From fb8a2f2af0b3b695885197616c514eef15ecbec8 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 4 Dec 2018 12:51:19 +0100 Subject: [PATCH 04/16] Revert "openal: Grab volume from manager instead of assuming max volume." This reverts commit 7fb30ae070b1b8a65c5996334153ded33c2ce1f9. See #64 for discussion. --- panda/src/audiotraits/openalAudioSound.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/audiotraits/openalAudioSound.cxx b/panda/src/audiotraits/openalAudioSound.cxx index 8d41a61fa3..9244b7509f 100644 --- a/panda/src/audiotraits/openalAudioSound.cxx +++ b/panda/src/audiotraits/openalAudioSound.cxx @@ -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), From 3adc7d977edec50c116f20a82dd66608017a99f5 Mon Sep 17 00:00:00 2001 From: rdb Date: Tue, 4 Dec 2018 16:16:05 +0100 Subject: [PATCH 05/16] glgsg: fix compilation in double-precision mode --- panda/src/glstuff/glGraphicsStateGuardian_src.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 62d74ce5bc..7974a9345c 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -7374,7 +7374,7 @@ do_issue_render_mode() { GLCAT.spam() << "setting thickness to " << thickness << "\n"; } - glLineWidth(std::min(thickness, _max_line_width)); + glLineWidth(std::min((GLfloat)thickness, _max_line_width)); #ifndef OPENGLES_2 glPointSize(thickness); #endif From b38faadf5f835c11d5697ee46b382207edf1d142 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 6 Dec 2018 22:29:09 +0100 Subject: [PATCH 06/16] bullet: restore behavior of in_contact flag c18abad8c3373aff134dd02d099d476d094b0b69 added a call that resets the m_isInContact flag, so this resets it, for better or worse. We may want to revisit whether #349 was indeed the right fix to #250. Fixes #453 --- panda/src/bullet/bulletVehicle.cxx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/panda/src/bullet/bulletVehicle.cxx b/panda/src/bullet/bulletVehicle.cxx index f4321cd911..ba7ee35d6d 100644 --- a/panda/src/bullet/bulletVehicle.cxx +++ b/panda/src/bullet/bulletVehicle.cxx @@ -235,10 +235,13 @@ void BulletVehicle:: do_sync_b2p() { for (int i=0; i < _vehicle->getNumWheels(); i++) { - // synchronize the wheels with the (interpolated) chassis worldtransform - _vehicle->updateWheelTransform(i, true); + btWheelInfo &info = _vehicle->getWheelInfo(i); - btWheelInfo info = _vehicle->getWheelInfo(i); + // synchronize the wheels with the (interpolated) chassis worldtransform. + // It resets the m_isInContact flag, so restore that afterwards. + bool in_contact = info.m_raycastInfo.m_isInContact; + _vehicle->updateWheelTransform(i, true); + info.m_raycastInfo.m_isInContact = in_contact; PandaNode *node = (PandaNode *)info.m_clientInfo; if (node) { From 89236ac1360e5f0249d425e61d537deef40e71c3 Mon Sep 17 00:00:00 2001 From: rdb Date: Thu, 6 Dec 2018 23:24:45 +0100 Subject: [PATCH 07/16] pgraph: fixed-depth billboards, bam additions (6.43) This makes it possible to use BillboardEffect to specify a fixed distance to the camera, in order to keep them at a fixed apparent size. This also enables serialization to .bam of the reference NodePaths of BillboardEffect and CompassEffect. --- panda/src/pgraph/billboardEffect.I | 9 ++++++ panda/src/pgraph/billboardEffect.cxx | 45 ++++++++++++++++++++++++---- panda/src/pgraph/billboardEffect.h | 9 ++++-- panda/src/pgraph/compassEffect.cxx | 25 ++++++++++++++-- panda/src/pgraph/compassEffect.h | 2 ++ panda/src/pgraph/nodePath.I | 2 +- panda/src/pgraph/nodePath.cxx | 4 +-- panda/src/pgraph/nodePath.h | 4 +-- panda/src/putil/bam.h | 3 +- 9 files changed, 88 insertions(+), 15 deletions(-) diff --git a/panda/src/pgraph/billboardEffect.I b/panda/src/pgraph/billboardEffect.I index d94d8135f7..b6ee6f31b0 100644 --- a/panda/src/pgraph/billboardEffect.I +++ b/panda/src/pgraph/billboardEffect.I @@ -86,6 +86,15 @@ get_axial_rotate() const { return _axial_rotate; } +/** + * Returns true if this billboard always appears at a fixed distance from the + * camera. + */ +INLINE bool BillboardEffect:: +get_fixed_depth() const { + return _fixed_depth; +} + /** * Returns the distance toward the camera (or the look_at_point) the billboard * is moved towards, after rotating. This can be used to ensure the billboard diff --git a/panda/src/pgraph/billboardEffect.cxx b/panda/src/pgraph/billboardEffect.cxx index c5843bb667..60c6e72c97 100644 --- a/panda/src/pgraph/billboardEffect.cxx +++ b/panda/src/pgraph/billboardEffect.cxx @@ -29,7 +29,7 @@ TypeHandle BillboardEffect::_type_handle; CPT(RenderEffect) BillboardEffect:: make(const LVector3 &up_vector, bool eye_relative, bool axial_rotate, PN_stdfloat offset, const NodePath &look_at, - const LPoint3 &look_at_point) { + const LPoint3 &look_at_point, bool fixed_depth) { BillboardEffect *effect = new BillboardEffect; effect->_up_vector = up_vector; effect->_eye_relative = eye_relative; @@ -37,6 +37,7 @@ make(const LVector3 &up_vector, bool eye_relative, effect->_offset = offset; effect->_look_at = look_at; effect->_look_at_point = look_at_point; + effect->_fixed_depth = fixed_depth; effect->_off = false; return return_new(effect); } @@ -82,7 +83,9 @@ output(std::ostream &out) const { if (_eye_relative) { out << " eye"; } - if (_offset != 0.0f) { + if (_fixed_depth) { + out << " depth " << -_offset; + } else if (_offset != 0.0f) { out << " offset " << _offset; } if (!_look_at.is_empty()) { @@ -201,6 +204,9 @@ compare_to_impl(const RenderEffect *other) const { if (_eye_relative != ta->_eye_relative) { return (int)_eye_relative - (int)ta->_eye_relative; } + if (_fixed_depth != ta->_fixed_depth) { + return (int)_fixed_depth - (int)ta->_fixed_depth; + } if (_offset != ta->_offset) { return _offset < ta->_offset ? -1 : 1; } @@ -274,11 +280,17 @@ compute_billboard(CPT(TransformState) &node_transform, // Also slide the billboard geometry towards the camera according to the // offset factor. - if (_offset != 0.0f) { + if (_offset != 0.0f || _fixed_depth) { LVector3 translate(rel_mat(3, 0), rel_mat(3, 1), rel_mat(3, 2)); + LPoint3 pos; + if (_fixed_depth) { + pos = translate / rel_mat(3, 3); + } else { + pos.fill(0.0f); + } translate.normalize(); translate *= _offset; - rotate.set_row(3, translate); + rotate.set_row(3, pos + translate); } node_transform = translate->compose(TransformState::make_mat(rotate))->compose(node_transform); @@ -307,7 +319,25 @@ write_datagram(BamWriter *manager, Datagram &dg) { dg.add_stdfloat(_offset); _look_at_point.write_datagram(dg); - // *** We don't write out the _look_at NodePath right now. Maybe we should. + if (manager->get_file_minor_ver() >= 43) { + _look_at.write_datagram(manager, dg); + dg.add_bool(_fixed_depth); + } +} + +/** + * Receives an array of pointers, one for each time manager->read_pointer() + * was called in fillin(). Returns the number of pointers processed. + */ +int BillboardEffect:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = RenderEffect::complete_pointers(p_list, manager); + + if (manager->get_file_minor_ver() >= 43) { + pi += _look_at.complete_pointers(p_list + pi, manager); + } + + return pi; } /** @@ -341,4 +371,9 @@ fillin(DatagramIterator &scan, BamReader *manager) { _axial_rotate = scan.get_bool(); _offset = scan.get_stdfloat(); _look_at_point.read_datagram(scan); + + if (manager->get_file_minor_ver() >= 43) { + _look_at.fillin(scan, manager); + _fixed_depth = scan.get_stdfloat(); + } } diff --git a/panda/src/pgraph/billboardEffect.h b/panda/src/pgraph/billboardEffect.h index f83ecc5323..d080cec0d4 100644 --- a/panda/src/pgraph/billboardEffect.h +++ b/panda/src/pgraph/billboardEffect.h @@ -34,7 +34,8 @@ PUBLISHED: bool axial_rotate, PN_stdfloat offset, const NodePath &look_at, - const LPoint3 &look_at_point); + const LPoint3 &look_at_point, + bool fixed_depth = false); INLINE static CPT(RenderEffect) make_axis(); INLINE static CPT(RenderEffect) make_point_eye(); INLINE static CPT(RenderEffect) make_point_world(); @@ -43,6 +44,7 @@ PUBLISHED: INLINE const LVector3 &get_up_vector() const; INLINE bool get_eye_relative() const; INLINE bool get_axial_rotate() const; + INLINE bool get_fixed_depth() const; INLINE PN_stdfloat get_offset() const; INLINE const NodePath &get_look_at() const; INLINE const LPoint3 &get_look_at_point() const; @@ -72,9 +74,10 @@ private: private: bool _off; - LVector3 _up_vector; bool _eye_relative; bool _axial_rotate; + bool _fixed_depth; + LVector3 _up_vector; PN_stdfloat _offset; NodePath _look_at; LPoint3 _look_at_point; @@ -82,6 +85,8 @@ private: public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, + BamReader *manager); protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); diff --git a/panda/src/pgraph/compassEffect.cxx b/panda/src/pgraph/compassEffect.cxx index 41bd9af880..fe39b03bf3 100644 --- a/panda/src/pgraph/compassEffect.cxx +++ b/panda/src/pgraph/compassEffect.cxx @@ -284,8 +284,25 @@ void CompassEffect:: write_datagram(BamWriter *manager, Datagram &dg) { RenderEffect::write_datagram(manager, dg); dg.add_uint16(_properties); - // *** We don't write out the _reference NodePath right now. Maybe we - // should. + + if (manager->get_file_minor_ver() >= 43) { + _reference.write_datagram(manager, dg); + } +} + +/** + * Receives an array of pointers, one for each time manager->read_pointer() + * was called in fillin(). Returns the number of pointers processed. + */ +int CompassEffect:: +complete_pointers(TypedWritable **p_list, BamReader *manager) { + int pi = RenderEffect::complete_pointers(p_list, manager); + + if (manager->get_file_minor_ver() >= 43) { + pi += _reference.complete_pointers(p_list + pi, manager); + } + + return pi; } /** @@ -313,4 +330,8 @@ void CompassEffect:: fillin(DatagramIterator &scan, BamReader *manager) { RenderEffect::fillin(scan, manager); _properties = scan.get_uint16(); + + if (manager->get_file_minor_ver() >= 43) { + _reference.fillin(scan, manager); + } } diff --git a/panda/src/pgraph/compassEffect.h b/panda/src/pgraph/compassEffect.h index adba81f9e6..a8aada7a59 100644 --- a/panda/src/pgraph/compassEffect.h +++ b/panda/src/pgraph/compassEffect.h @@ -90,6 +90,8 @@ private: public: static void register_with_read_factory(); virtual void write_datagram(BamWriter *manager, Datagram &dg); + virtual int complete_pointers(TypedWritable **plist, + BamReader *manager); protected: static TypedWritable *make_from_bam(const FactoryParams ¶ms); diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index 5b7e80f7b7..8ca3153da5 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -1752,7 +1752,7 @@ set_billboard_axis(PN_stdfloat offset) { * the camera. */ INLINE void NodePath:: -set_billboard_point_eye(PN_stdfloat offset) { +set_billboard_point_eye(PN_stdfloat offset, bool fixed_depth) { set_billboard_point_eye(NodePath(), offset); } diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 0f2639bccc..9d473304b6 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -4744,11 +4744,11 @@ set_billboard_axis(const NodePath &camera, PN_stdfloat offset) { * the camera, towards a specified "camera" instead of to the viewing camera. */ void NodePath:: -set_billboard_point_eye(const NodePath &camera, PN_stdfloat offset) { +set_billboard_point_eye(const NodePath &camera, PN_stdfloat offset, bool fixed_depth) { nassertv_always(!is_empty()); CPT(RenderEffect) billboard = BillboardEffect::make (LVector3::up(), true, false, - offset, camera, LPoint3(0.0f, 0.0f, 0.0f)); + offset, camera, LPoint3(0.0f, 0.0f, 0.0f), fixed_depth); node()->set_effect(billboard); } diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index cf159972c5..9c047c0728 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -815,10 +815,10 @@ PUBLISHED: void do_billboard_point_eye(const NodePath &camera, PN_stdfloat offset); void do_billboard_point_world(const NodePath &camera, PN_stdfloat offset); INLINE void set_billboard_axis(PN_stdfloat offset = 0.0); - INLINE void set_billboard_point_eye(PN_stdfloat offset = 0.0); + INLINE void set_billboard_point_eye(PN_stdfloat offset = 0.0, bool fixed_depth = false); INLINE void set_billboard_point_world(PN_stdfloat offset = 0.0); void set_billboard_axis(const NodePath &camera, PN_stdfloat offset); - void set_billboard_point_eye(const NodePath &camera, PN_stdfloat offset); + void set_billboard_point_eye(const NodePath &camera, PN_stdfloat offset, bool fixed_depth = false); void set_billboard_point_world(const NodePath &camera, PN_stdfloat offset); void clear_billboard(); bool has_billboard() const; diff --git a/panda/src/putil/bam.h b/panda/src/putil/bam.h index ad7d000fd2..96f41cbf98 100644 --- a/panda/src/putil/bam.h +++ b/panda/src/putil/bam.h @@ -32,7 +32,7 @@ static const unsigned short _bam_major_ver = 6; // Bumped to major version 6 on 2006-02-11 to factor out PandaNode::CData. static const unsigned short _bam_first_minor_ver = 14; -static const unsigned short _bam_minor_ver = 42; +static const unsigned short _bam_minor_ver = 43; // Bumped to minor version 14 on 2007-12-19 to change default ColorAttrib. // Bumped to minor version 15 on 2008-04-09 to add TextureAttrib::_implicit_sort. // Bumped to minor version 16 on 2008-05-13 to add Texture::_quality_level. @@ -62,5 +62,6 @@ static const unsigned short _bam_minor_ver = 42; // Bumped to minor version 40 on 2016-01-11 to make NodePaths writable. // Bumped to minor version 41 on 2016-03-02 to change LensNode, Lens, and Camera. // Bumped to minor version 42 on 2016-04-08 to expand ColorBlendAttrib. +// Bumped to minor version 43 on 2018-12-06 to expand BillboardEffect and CompassEffect. #endif From ca9ad5f1740c1235b9ddbdbbe38027d6bcf7a9b8 Mon Sep 17 00:00:00 2001 From: rdb Date: Fri, 7 Dec 2018 00:57:21 +0100 Subject: [PATCH 08/16] pgraph: fix ignored fixed_depth parameter --- panda/src/pgraph/nodePath.I | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index 8ca3153da5..1e0c6b3ab0 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -1753,7 +1753,7 @@ set_billboard_axis(PN_stdfloat offset) { */ INLINE void NodePath:: set_billboard_point_eye(PN_stdfloat offset, bool fixed_depth) { - set_billboard_point_eye(NodePath(), offset); + set_billboard_point_eye(NodePath(), offset, fixed_depth); } /** From a5ad186a663c15d1d3cf3832a3c2ee95417ee917 Mon Sep 17 00:00:00 2001 From: Mitchell Stokes Date: Sat, 8 Dec 2018 17:21:59 -0800 Subject: [PATCH 09/16] x11display: Do not grab the mouse in confined mode when the window does not have focus --- panda/src/x11display/x11GraphicsWindow.cxx | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/panda/src/x11display/x11GraphicsWindow.cxx b/panda/src/x11display/x11GraphicsWindow.cxx index caaacc4a9c..ad0f8e44dd 100644 --- a/panda/src/x11display/x11GraphicsWindow.cxx +++ b/panda/src/x11display/x11GraphicsWindow.cxx @@ -508,6 +508,26 @@ process_events() { changed_properties = true; } + if (properties.has_foreground() && _properties.get_mouse_mode() == WindowProperties::M_confined) { + // Focus has changed, let's let go of the pointer if we've grabbed or re-grab it if needed + if (properties.get_foreground()) { + // Window is going to the foreground, re-grab the pointer + X11_Cursor cursor = None; + if (_properties.get_cursor_hidden()) { + x11GraphicsPipe *x11_pipe; + DCAST_INTO_V(x11_pipe, _pipe); + cursor = x11_pipe->get_hidden_cursor(); + } + + XGrabPointer(_display, _xwindow, True, 0, GrabModeAsync, GrabModeAsync, + _xwindow, cursor, CurrentTime); + } + else { + // window is leaving the foreground, ungrab the pointer + XUngrabPointer(_display, CurrentTime); + } + } + if (changed_properties) { system_changed_properties(properties); } From 825058805a02cf05480aa830326b096df5cd36aa Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Dec 2018 15:18:09 +0100 Subject: [PATCH 10/16] dtoolutil: add GlobPattern::matches_file() and unit test This is used similar to matches() but for file paths: it does not match slashes for * characters and has special support for /**/ and ignores // and /./ patterns. --- dtool/src/dtoolutil/globPattern.cxx | 125 +++++++++++++++++++++++++++- dtool/src/dtoolutil/globPattern.h | 2 + tests/dtoolutil/test_globpattern.py | 85 +++++++++++++++++++ 3 files changed, 209 insertions(+), 3 deletions(-) create mode 100644 tests/dtoolutil/test_globpattern.py diff --git a/dtool/src/dtoolutil/globPattern.cxx b/dtool/src/dtoolutil/globPattern.cxx index 982fe3bb1d..d2ea916466 100644 --- a/dtool/src/dtoolutil/globPattern.cxx +++ b/dtool/src/dtoolutil/globPattern.cxx @@ -12,6 +12,7 @@ */ #include "globPattern.h" +#include "string_utils.h" #include 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), diff --git a/dtool/src/dtoolutil/globPattern.h b/dtool/src/dtoolutil/globPattern.h index 27dfb67777..af181691ab 100644 --- a/dtool/src/dtoolutil/globPattern.h +++ b/dtool/src/dtoolutil/globPattern.h @@ -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; diff --git a/tests/dtoolutil/test_globpattern.py b/tests/dtoolutil/test_globpattern.py new file mode 100644 index 0000000000..d653c97142 --- /dev/null +++ b/tests/dtoolutil/test_globpattern.py @@ -0,0 +1,85 @@ +from panda3d.core import GlobPattern + + +def test_globpattern_matches_file(): + patt = GlobPattern('/a/b/c') + assert patt.matches_file('/a/b/c') + assert patt.matches_file('///a////b//c') + assert patt.matches_file('/a/b/././c') + assert not patt.matches_file('') + assert not patt.matches_file('/') + assert not patt.matches_file('/a/b/d') + assert not patt.matches_file('/A/b/c') + assert not patt.matches_file('/a/b/c/') + assert not patt.matches_file('/a/b/c/.') + assert not patt.matches_file('a/b/c') + assert not patt.matches_file('./a/b/c') + + # Test regular pattern + patt = GlobPattern('*a') + assert patt.matches_file('a') + assert patt.matches_file('aa') + assert patt.matches_file('xa') + assert not patt.matches_file('A') + assert not patt.matches_file('ax') + assert not patt.matches_file('xax') + + # Test path ending in directory + for patt in GlobPattern('/a/b/c/'), \ + GlobPattern('/a/b/c/.'), \ + GlobPattern('/a/b//c//'), \ + GlobPattern('/a/b/./c/./'): + assert patt.matches_file('/a/b/c/') + assert patt.matches_file('///a////b//c//') + assert patt.matches_file('/a/b/././c/') + assert patt.matches_file('/a/b/c/.') + assert not patt.matches_file('/a/b/c') + assert not patt.matches_file('/a/b/c/./d') + assert not patt.matches_file('a/b/c/') + assert not patt.matches_file('./a/b/c/') + + # Test globstar in middle + for patt in GlobPattern('/a/**/c'), GlobPattern('/a/**/**/c'): + assert patt.matches_file('/a/c') + assert patt.matches_file('/a/b/c') + assert patt.matches_file('/a/b/d/c') + assert not patt.matches_file('/a/b/c/d') + assert not patt.matches_file('/d/b/c') + assert not patt.matches_file('/a/b/d') + + # Test globstar in beginning + for patt in GlobPattern('/**/b/c'), GlobPattern('/**/**/**/b/c'): + assert patt.matches_file('/a/b/c') + assert patt.matches_file('/a/d/b/c') + assert patt.matches_file('/a/b/c') + assert patt.matches_file('/a/b/c/./b//c') + assert not patt.matches_file('/a/b/c/d') + assert not patt.matches_file('/a/c') + assert not patt.matches_file('/a/b/d') + + # Test globstar at end + for patt in GlobPattern('/a/b/**'), \ + GlobPattern('/a/b/**/**'), \ + GlobPattern('/a/b//**//**/**'): + assert patt.matches_file('/a/b/') + assert patt.matches_file('/a/b/.') + assert patt.matches_file('/a/b//') + assert patt.matches_file('/a/b/c') + assert patt.matches_file('/a/b/c/d/e/f/g/h') + assert patt.matches_file('/a/b/d/c') + assert not patt.matches_file('/a/') + assert not patt.matches_file('/a/c/b') + + # Test multiple globstars at multiple locations + patt = GlobPattern('/a/**/b/**/c') + assert patt.matches_file('/a/b/c') + assert patt.matches_file('/a/./b/./c') + assert patt.matches_file('/a//b//c') + assert patt.matches_file('/a/x/y/b/c') + assert patt.matches_file('/a/b/x/y/c') + assert patt.matches_file('/a/b/c/a/b/c') + assert patt.matches_file('/a/x/y/b/x/y/c') + assert not patt.matches_file('/a/b/x') + assert not patt.matches_file('/a/b/c/x') + assert not patt.matches_file('/a/b/c/') + assert not patt.matches_file('/a/b/c/.') From 4213e0a50a2190c479959ce87b976173f50c536b Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Dec 2018 15:39:28 +0100 Subject: [PATCH 11/16] Remove awesomium (see #440) --- doc/INSTALL | 1 - makepanda/installer.nsi | 1 - makepanda/makepanda.py | 33 +-- makepanda/makepanda.vcproj | 19 -- panda/src/awesomium/AwMouseAndKeyboard.cxx | 47 ----- panda/src/awesomium/AwMouseAndKeyboard.h | 61 ------ panda/src/awesomium/ReadMe.txt | 8 - panda/src/awesomium/WebBrowserTexture.cxx | 194 ------------------ panda/src/awesomium/WebBrowserTexture.h | 77 ------- panda/src/awesomium/awWebCore.I | 48 ----- panda/src/awesomium/awWebCore.cxx | 56 ----- panda/src/awesomium/awWebCore.h | 94 --------- panda/src/awesomium/awWebView.I | 82 -------- panda/src/awesomium/awWebView.cxx | 74 ------- panda/src/awesomium/awWebView.h | 131 ------------ panda/src/awesomium/awWebViewListener.I | 12 -- panda/src/awesomium/awWebViewListener.cxx | 80 -------- panda/src/awesomium/awWebViewListener.h | 123 ----------- panda/src/awesomium/awesomium_includes.h | 21 -- panda/src/awesomium/config_awesomium.cxx | 51 ----- panda/src/awesomium/config_awesomium.h | 26 --- .../awesomium/pandaawesomium_composite1.cxx | 4 - panda/src/pandabase/pandasymbols.h | 8 - 23 files changed, 1 insertion(+), 1250 deletions(-) delete mode 100644 panda/src/awesomium/AwMouseAndKeyboard.cxx delete mode 100644 panda/src/awesomium/AwMouseAndKeyboard.h delete mode 100644 panda/src/awesomium/ReadMe.txt delete mode 100644 panda/src/awesomium/WebBrowserTexture.cxx delete mode 100644 panda/src/awesomium/WebBrowserTexture.h delete mode 100644 panda/src/awesomium/awWebCore.I delete mode 100644 panda/src/awesomium/awWebCore.cxx delete mode 100644 panda/src/awesomium/awWebCore.h delete mode 100644 panda/src/awesomium/awWebView.I delete mode 100644 panda/src/awesomium/awWebView.cxx delete mode 100644 panda/src/awesomium/awWebView.h delete mode 100644 panda/src/awesomium/awWebViewListener.I delete mode 100644 panda/src/awesomium/awWebViewListener.cxx delete mode 100644 panda/src/awesomium/awWebViewListener.h delete mode 100644 panda/src/awesomium/awesomium_includes.h delete mode 100644 panda/src/awesomium/config_awesomium.cxx delete mode 100644 panda/src/awesomium/config_awesomium.h delete mode 100644 panda/src/awesomium/pandaawesomium_composite1.cxx diff --git a/doc/INSTALL b/doc/INSTALL index 4157e03957..6a9606391e 100644 --- a/doc/INSTALL +++ b/doc/INSTALL @@ -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) diff --git a/makepanda/installer.nsi b/makepanda/installer.nsi index fc10ce927c..8bc608cf6f 100644 --- a/makepanda/installer.nsi +++ b/makepanda/installer.nsi @@ -333,7 +333,6 @@ SectionGroup "Python support" 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}" diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 43c42e5fd9..ff6787f987 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -91,7 +91,7 @@ PkgListSet(["PYTHON", "DIRECT", # Python support "ARTOOLKIT", "OPENCV", "DIRECTCAM", "VISION", # Augmented Reality "GTK2", # GTK2 is used for PStats on Unix "MFC", "WX", "FLTK", # Used for web plug-in only - "ROCKET", "AWESOMIUM", # GUI libraries + "ROCKET", # GUI libraries "CARBON", "COCOA", # Mac OS X toolkits "X11", # Unix platform support "PANDATOOL", "PVIEW", "DEPLOYTOOLS", # Toolchain @@ -677,7 +677,6 @@ if (COMPILER == "MSVC"): if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/cvaux.lib") if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/ml.lib") if (PkgSkip("OPENCV")==0): LibName("OPENCV", GetThirdpartyDir() + "opencv/lib/cxcore.lib") - if (PkgSkip("AWESOMIUM")==0):LibName("AWESOMIUM",GetThirdpartyDir() + "awesomium/lib/Awesomium.lib") if (PkgSkip("FFMPEG")==0): LibName("FFMPEG", GetThirdpartyDir() + "ffmpeg/lib/avcodec.lib") if (PkgSkip("FFMPEG")==0): LibName("FFMPEG", GetThirdpartyDir() + "ffmpeg/lib/avformat.lib") if (PkgSkip("FFMPEG")==0): LibName("FFMPEG", GetThirdpartyDir() + "ffmpeg/lib/avutil.lib") @@ -797,7 +796,6 @@ if (COMPILER == "MSVC"): LibName("BULLET", GetThirdpartyDir() + "bullet/lib/BulletSoftBody" + suffix) if (COMPILER=="GCC"): - PkgDisable("AWESOMIUM") if GetTarget() != "darwin": PkgDisable("CARBON") PkgDisable("COCOA") @@ -2850,8 +2848,6 @@ if not PkgSkip("SKEL"): panda_modules.append('skel') if not PkgSkip("EGG"): panda_modules.append('egg') -if not PkgSkip("AWESOMIUM"): - panda_modules.append('awesomium') if not PkgSkip("ODE"): panda_modules.append('ode') if not PkgSkip("VRPN"): @@ -3197,7 +3193,6 @@ CopyAllHeaders('panda/src/text') CopyAllHeaders('panda/src/grutil') if (PkgSkip("VISION")==0): CopyAllHeaders('panda/src/vision') -CopyAllHeaders('panda/src/awesomium') if (PkgSkip("FFMPEG")==0): CopyAllHeaders('panda/src/ffmpeg') CopyAllHeaders('panda/src/tform') @@ -4372,32 +4367,6 @@ if (PkgSkip("ROCKET") == 0) and (not RUNTIME): PyTargetAdd('rocket.pyd', input=COMMON_PANDA_LIBS) PyTargetAdd('rocket.pyd', opts=['ROCKET']) -# -# DIRECTORY: panda/src/p3awesomium -# -if PkgSkip("AWESOMIUM") == 0 and not RUNTIME: - OPTS=['DIR:panda/src/awesomium', 'BUILDING:PANDAAWESOMIUM', 'AWESOMIUM'] - TargetAdd('pandaawesomium_composite1.obj', opts=OPTS, input='pandaawesomium_composite1.cxx') - TargetAdd('libp3awesomium.dll', input='pandaawesomium_composite1.obj') - TargetAdd('libp3awesomium.dll', input=COMMON_PANDA_LIBS) - TargetAdd('libp3awesomium.dll', opts=OPTS) - - OPTS=['DIR:panda/src/awesomium', 'AWESOMIUM'] - IGATEFILES=GetDirectoryContents('panda/src/awesomium', ["*.h", "*_composite1.cxx"]) - TargetAdd('libp3awesomium.in', opts=OPTS, input=IGATEFILES) - TargetAdd('libp3awesomium.in', opts=['IMOD:panda3d.awesomium', 'ILIB:libp3awesomium', 'SRCDIR:panda/src/awesomium']) - - - PyTargetAdd('awesomium_module.obj', input='libp3awesomium.in') - PyTargetAdd('awesomium_module.obj', opts=OPTS) - PyTargetAdd('awesomium_module.obj', opts=['IMOD:panda3d.awesomium', 'ILIB:awesomium', 'IMPORT:panda3d.core']) - - PyTargetAdd('awesomium.pyd', input='awesomium_module.obj') - PyTargetAdd('awesomium.pyd', input='libp3awesomium_igate.obj') - PyTargetAdd('awesomium.pyd', input='libp3awesomium.dll') - PyTargetAdd('awesomium.pyd', input='libp3interrogatedb.dll') - PyTargetAdd('awesomium.pyd', input=COMMON_PANDA_LIBS) - # # DIRECTORY: panda/src/p3skel # diff --git a/makepanda/makepanda.vcproj b/makepanda/makepanda.vcproj index c4c34db4e3..ad7f219650 100644 --- a/makepanda/makepanda.vcproj +++ b/makepanda/makepanda.vcproj @@ -3578,25 +3578,6 @@ - - - - - - - - - - - - - - - - - - - diff --git a/panda/src/awesomium/AwMouseAndKeyboard.cxx b/panda/src/awesomium/AwMouseAndKeyboard.cxx deleted file mode 100644 index 9948c0d49d..0000000000 --- a/panda/src/awesomium/AwMouseAndKeyboard.cxx +++ /dev/null @@ -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"); - } - } - -} diff --git a/panda/src/awesomium/AwMouseAndKeyboard.h b/panda/src/awesomium/AwMouseAndKeyboard.h deleted file mode 100644 index e338939001..0000000000 --- a/panda/src/awesomium/AwMouseAndKeyboard.h +++ /dev/null @@ -1,61 +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.h - * @author rurbino - * @date 2009-10-12 - */ - -#ifndef AWWEBKEYBOARDMOUSE_H -#define AWWEBKEYBOARDMOUSE_H - -#include "pandabase.h" -#include "typedReferenceCount.h" -#include "luse.h" - -#include "mouseAndKeyboard.h" - - -/** - * Thin wrappings arround WebCore.h - */ -class EXPCL_PANDAAWESOMIUM AwMouseAndKeyboard : public DataNode { -// member data data -protected: - // inputs adn output indices... initialized in constructor - int _button_events_input; - int _button_events_output; - -PUBLISHED: - AwMouseAndKeyboard(const std::string &name); - -protected: - // Inherited from DataNode - virtual void do_transmit_data(DataGraphTraverser *trav, - const DataNodeTransmit &input, - DataNodeTransmit &output); - -public: - static TypeHandle get_class_type() { - return _type_handle; - } - static void init_type() { - MouseAndKeyboard::init_type(); - register_type(_type_handle, "AwMouseAndKeyboard", - DataNode::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 diff --git a/panda/src/awesomium/ReadMe.txt b/panda/src/awesomium/ReadMe.txt deleted file mode 100644 index faa064455a..0000000000 --- a/panda/src/awesomium/ReadMe.txt +++ /dev/null @@ -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. - diff --git a/panda/src/awesomium/WebBrowserTexture.cxx b/panda/src/awesomium/WebBrowserTexture.cxx deleted file mode 100644 index 1051a33e36..0000000000 --- a/panda/src/awesomium/WebBrowserTexture.cxx +++ /dev/null @@ -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; -} diff --git a/panda/src/awesomium/WebBrowserTexture.h b/panda/src/awesomium/WebBrowserTexture.h deleted file mode 100644 index 3c9e6aaa08..0000000000 --- a/panda/src/awesomium/WebBrowserTexture.h +++ /dev/null @@ -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 diff --git a/panda/src/awesomium/awWebCore.I b/panda/src/awesomium/awWebCore.I deleted file mode 100644 index 7829f6a370..0000000000 --- a/panda/src/awesomium/awWebCore.I +++ /dev/null @@ -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(); -} diff --git a/panda/src/awesomium/awWebCore.cxx b/panda/src/awesomium/awWebCore.cxx deleted file mode 100644 index adc5989367..0000000000 --- a/panda/src/awesomium/awWebCore.cxx +++ /dev/null @@ -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 - -TypeHandle AwWebCore::_type_handle; - -AwWebCore:: -AwWebCore(AwWebCore::LogLevel level, bool enablePlugins , AwWebCore::PixelFormat pixelFormat) -#ifndef CPPPARSER -: - WebCore(static_cast(level), enablePlugins, static_cast(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( WebCore::getPixelFormat()) ); -} diff --git a/panda/src/awesomium/awWebCore.h b/panda/src/awesomium/awWebCore.h deleted file mode 100644 index db3160bf21..0000000000 --- a/panda/src/awesomium/awWebCore.h +++ /dev/null @@ -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 diff --git a/panda/src/awesomium/awWebView.I b/panda/src/awesomium/awWebView.I deleted file mode 100644 index c7ecf913e7..0000000000 --- a/panda/src/awesomium/awWebView.I +++ /dev/null @@ -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(destination), destRowSpan, destDepth, 0); -} - - - -INLINE void AwWebView:: -injectMouseUp(AwWebView::MouseButton button) { - _myWebView->injectMouseUp(static_cast(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); -} diff --git a/panda/src/awesomium/awWebView.cxx b/panda/src/awesomium/awWebView.cxx deleted file mode 100644 index ebc3a63f89..0000000000 --- a/panda/src/awesomium/awWebView.cxx +++ /dev/null @@ -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(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(button)); -} - - -void AwWebView:: -injectMouseMove(int x, int y) { - // awesomium_cat.debug() <<"got mouse move " << x << " " << y << "\n"; - _myWebView->injectMouseMove(x,y); -} diff --git a/panda/src/awesomium/awWebView.h b/panda/src/awesomium/awWebView.h deleted file mode 100644 index ad5c9d223c..0000000000 --- a/panda/src/awesomium/awWebView.h +++ /dev/null @@ -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 diff --git a/panda/src/awesomium/awWebViewListener.I b/panda/src/awesomium/awWebViewListener.I deleted file mode 100644 index 10b7745aef..0000000000 --- a/panda/src/awesomium/awWebViewListener.I +++ /dev/null @@ -1,12 +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.I - * @author rurbino - * @date 2009-10-12 - */ diff --git a/panda/src/awesomium/awWebViewListener.cxx b/panda/src/awesomium/awWebViewListener.cxx deleted file mode 100644 index 0af38b5da8..0000000000 --- a/panda/src/awesomium/awWebViewListener.cxx +++ /dev/null @@ -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) { -} diff --git a/panda/src/awesomium/awWebViewListener.h b/panda/src/awesomium/awWebViewListener.h deleted file mode 100644 index 924754762d..0000000000 --- a/panda/src/awesomium/awWebViewListener.h +++ /dev/null @@ -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 diff --git a/panda/src/awesomium/awesomium_includes.h b/panda/src/awesomium/awesomium_includes.h deleted file mode 100644 index 27b8b9b9b0..0000000000 --- a/panda/src/awesomium/awesomium_includes.h +++ /dev/null @@ -1,21 +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 awesomium_includes.h - * @author rurbino - * @date 2010-10-08 - */ - -#ifndef _AWESOMIUM_INCLUDES_H_ -#define _AWESOMIUM_INCLUDES_H_ - -#include -#include -#include - -#endif diff --git a/panda/src/awesomium/config_awesomium.cxx b/panda/src/awesomium/config_awesomium.cxx deleted file mode 100644 index 35987d0e27..0000000000 --- a/panda/src/awesomium/config_awesomium.cxx +++ /dev/null @@ -1,51 +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 config_awesomium.cxx - * @author rurbino - * @date 2009-10-12 - */ - -#include "config_awesomium.h" -#include "awWebCore.h" -#include "awWebView.h" -#include "awWebViewListener.h" -#include "dconfig.h" - - -#if !defined(CPPPARSER) && !defined(LINK_ALL_STATIC) && !defined(BUILDING_PANDAAWESOMIUM) - #error Buildsystem error: BUILDING_PANDAAWESOMIUM not defined -#endif - -Configure(config_awesomium); -NotifyCategoryDef(awesomium, ""); - - -ConfigureFn(config_awesomium) { - init_libawesomium(); -} - -/** - * Initializes the library. This must be called at least once before any of - * the functions or classes in this library can be used. Normally it will be - * called by the static initializers and need not be called explicitly, but - * special cases exist. - */ -void -init_libawesomium() { - static bool initialized = false; - if (initialized) { - return; - } - initialized = true; - - AwWebCore::init_type(); - AwWebView::init_type(); - AwWebViewListener::init_type(); - -} diff --git a/panda/src/awesomium/config_awesomium.h b/panda/src/awesomium/config_awesomium.h deleted file mode 100644 index e02f047e16..0000000000 --- a/panda/src/awesomium/config_awesomium.h +++ /dev/null @@ -1,26 +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 config_awesomium.h - * @author rurbino - * @date 2009-10-12 - */ - -#ifndef CONFIG_AWESOMIUM_H -#define CONFIG_AWESOMIUM_H - -#include "pandabase.h" -#include "notifyCategoryProxy.h" - -#include "dconfig.h" - -NotifyCategoryDecl(awesomium, EXPCL_PANDAAWESOMIUM, EXPTP_PANDAAWESOMIUM); - -extern EXPCL_PANDAAWESOMIUM void init_libawesomium(); - -#endif /* CONFIG_AWESOMIUM_H */ diff --git a/panda/src/awesomium/pandaawesomium_composite1.cxx b/panda/src/awesomium/pandaawesomium_composite1.cxx deleted file mode 100644 index 1b0ef139ec..0000000000 --- a/panda/src/awesomium/pandaawesomium_composite1.cxx +++ /dev/null @@ -1,4 +0,0 @@ -#include "config_awesomium.cxx" -#include "awWebCore.cxx" -#include "awWebView.cxx" -#include "awWebViewListener.cxx" diff --git a/panda/src/pandabase/pandasymbols.h b/panda/src/pandabase/pandasymbols.h index ef83b4314e..3f529dab27 100644 --- a/panda/src/pandabase/pandasymbols.h +++ b/panda/src/pandabase/pandasymbols.h @@ -476,14 +476,6 @@ #define EXPTP_PANDA_WGLDISPLAY IMPORT_TEMPL #endif -#ifdef BUILDING_PANDAAWESOMIUM - #define EXPCL_PANDAAWESOMIUM EXPORT_CLASS - #define EXPTP_PANDAAWESOMIUM EXPORT_TEMPL -#else - #define EXPCL_PANDAAWESOMIUM IMPORT_CLASS - #define EXPTP_PANDAAWESOMIUM IMPORT_TEMPL -#endif - #ifdef BUILDING_PANDAGL #define EXPCL_PANDAGL EXPORT_CLASS #define EXPTP_PANDAGL EXPORT_TEMPL From b674104c1f59613ef23d6d41c9dd3ecbd0be347b Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Dec 2018 15:53:40 +0100 Subject: [PATCH 12/16] makepanda: don't error for harmless use of removed options Let's show a warning when an option has been removed but its presence would not have affected the build in an important way. For options like --use-awesomium we should still show an error since it invokes behavior we no longer support, but it should be harmless to specify --no-awesomium. --- makepanda/makepanda.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index ff6787f987..4ee16763a3 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -171,14 +171,22 @@ def parseopts(args): global COMPRESSOR,THREADCOUNT,OSXTARGET,OSX_ARCHS,HOST_URL global DEBVERSION,WHLVERSION,RPMRELEASE,GIT_COMMIT,P3DSUFFIX,RTDIST_VERSION global STRDXSDKVERSION, WINDOWS_SDK, MSVC_VERSION, BOOUSEINTELCOMPILER + + # Options for which to display a deprecation warning. + removedopts = [ + "use-touchinput", "no-touchinput", "no-awesomium", "no-directscripts", + ] + + # All recognized options. longopts = [ "help","distributor=","verbose","runtime","osxtarget=","tests", "optimize=","everything","nothing","installer","wheel","rtdist","nocolor", "version=","lzma","no-python","threads=","outputdir=","override=", "static","host=","debversion=","rpmrelease=","p3dsuffix=","rtdist-version=", "directx-sdk=", "windows-sdk=", "msvc-version=", "clean", "use-icl", - "universal", "target=", "arch=", "git-commit=", "no-directscripts", - "use-touchinput", "no-touchinput"] + "universal", "target=", "arch=", "git-commit=", + ] + removedopts + anything = 0 optimize = "" target = None @@ -190,6 +198,7 @@ def parseopts(args): longopts.append("no-" + pkg.lower()) longopts.append(pkg.lower() + "-incdir=") longopts.append(pkg.lower() + "-libdir=") + try: opts, extras = getopt.getopt(args, "", longopts) for option, value in opts: @@ -230,7 +239,6 @@ def parseopts(args): # Backward compatibility, OPENGL was renamed to GL elif (option=="--use-opengl"): PkgEnable("GL") elif (option=="--no-opengl"): PkgDisable("GL") - elif (option=="--no-directscripts"): pass elif (option=="--directx-sdk"): STRDXSDKVERSION = value.strip().lower() if STRDXSDKVERSION == '': @@ -242,6 +250,8 @@ def parseopts(args): MSVC_VERSION = value.strip().lower() elif (option=="--use-icl"): BOOUSEINTELCOMPILER = True elif (option=="--clean"): clean_build = True + elif (option[2:] in removedopts): + Warn("Ignoring removed option %s" % (option)) else: for pkg in PkgListGet(): if option == "--use-" + pkg.lower(): From b474ef6b1e0ce3e268008a631f9a666e1ae20e98 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Dec 2018 17:01:35 +0100 Subject: [PATCH 13/16] makepanda: split out installer code into separate makepackage.py --- makepanda/makepackage.py | 964 +++++++++++++++++++++++++++++++++++++++ makepanda/makepanda.py | 896 +----------------------------------- 2 files changed, 984 insertions(+), 876 deletions(-) create mode 100755 makepanda/makepackage.py diff --git a/makepanda/makepackage.py b/makepanda/makepackage.py new file mode 100755 index 0000000000..dc3da45e19 --- /dev/null +++ b/makepanda/makepackage.py @@ -0,0 +1,964 @@ +#!/usr/bin/env python + +from makepandacore import * +from installpanda import * +import sys +import os +import shutil + + +INSTALLER_DEB_FILE = """ +Package: panda3dMAJOR +Version: VERSION +Section: libdevel +Priority: optional +Architecture: ARCH +Essential: no +Depends: DEPENDS +Recommends: RECOMMENDS +Provides: panda3d, pythonPV-panda3d +Conflicts: panda3d, pythonPV-panda3d +Replaces: panda3d, pythonPV-panda3d +Maintainer: rdb +Installed-Size: INSTSIZE +Description: Panda3D free 3D engine SDK + Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. + Panda3D's intended game-development language is Python. The engine itself is written in C++, and utilizes an automatic wrapper-generator to expose the complete functionality of the engine in a Python interface. + . + This package contains the SDK for development with Panda3D. + +""" + +RUNTIME_INSTALLER_DEB_FILE = """ +Package: panda3d-runtime +Version: VERSION +Section: web +Priority: optional +Architecture: ARCH +Essential: no +Depends: DEPENDS +Provides: panda3d-runtime +Maintainer: rdb +Installed-Size: INSTSIZE +Description: Runtime binary and browser plugin for the Panda3D Game Engine + This package contains the runtime distribution and browser plugin of the Panda3D engine. It allows you view webpages that contain Panda3D content and to run games created with Panda3D that are packaged as .p3d file. + +""" + + +# We're not putting "python" in the "Requires" field, +# since the rpm-based distros don't have a common +# naming for the Python package. +INSTALLER_SPEC_FILE = """ +Summary: The Panda3D free 3D engine SDK +Name: panda3d +Version: VERSION +Release: RPMRELEASE +License: BSD License +Group: Development/Libraries +BuildRoot: PANDASOURCE/targetroot +%description +Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. +Panda3D's intended game-development language is Python. The engine itself is written in C++, and utilizes an automatic wrapper-generator to expose the complete functionality of the engine in a Python interface. + +This package contains the SDK for development with Panda3D, install panda3d-runtime for the runtime files. +%post +/sbin/ldconfig +%postun +/sbin/ldconfig +%files +%defattr(-,root,root) +/etc/Confauto.prc +/etc/Config.prc +/usr/share/panda3d +/etc/ld.so.conf.d/panda3d.conf +/usr/%_lib/panda3d +""" + PYTHON_SITEPACKAGES + """ +/usr/include/panda3d +""" +INSTALLER_SPEC_FILE_PVIEW = \ +"""/usr/share/applications/pview.desktop +/usr/share/mime-info/panda3d.mime +/usr/share/mime-info/panda3d.keys +/usr/share/mime/packages/panda3d.xml +/usr/share/application-registry/panda3d.applications +""" + +RUNTIME_INSTALLER_SPEC_FILE = """ +Summary: Runtime binary and browser plugin for the Panda3D Game Engine +Name: panda3d-runtime +Version: VERSION +Release: RPMRELEASE +License: BSD License +Group: Productivity/Graphics/Other +BuildRoot: PANDASOURCE/targetroot +%description +This package contains the runtime distribution and browser plugin of the Panda3D engine. It allows you view webpages that contain Panda3D content and to run games created with Panda3D that are packaged as .p3d file. +%files +%defattr(-,root,root) +/usr/bin/panda3d +/usr/%_lib/nppanda3d.so +/usr/%_lib/mozilla/plugins/nppanda3d.so +/usr/%_lib/mozilla-firefox/plugins/nppanda3d.so +/usr/%_lib/xulrunner-addons/plugins/nppanda3d.so +/usr/share/mime-info/panda3d-runtime.mime +/usr/share/mime-info/panda3d-runtime.keys +/usr/share/mime/packages/panda3d-runtime.xml +/usr/share/application-registry/panda3d-runtime.applications +/usr/share/applications/*.desktop +""" + +# plist file for Mac OSX +Info_plist = """ + + + + CFBundleIdentifier + {package_id} + CFBundleShortVersionString + {version} + IFPkgFlagRelocatable + + IFPkgFlagAuthorizationAction + RootAuthorization + IFPkgFlagAllowBackRev + + + +""" + +# FreeBSD pkg-descr +INSTALLER_PKG_DESCR_FILE = """ +Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. +Panda3D's intended game-development language is Python. The engine itself is written in C++, and utilizes an automatic wrapper-generator to expose the complete functionality of the engine in a Python interface. + +This package contains the SDK for development with Panda3D, install panda3d-runtime for the runtime files. + +WWW: https://www.panda3d.org/ +""" + +# FreeBSD pkg-descr +RUNTIME_INSTALLER_PKG_DESCR_FILE = """ +Runtime binary and browser plugin for the Panda3D Game Engine + +This package contains the runtime distribution and browser plugin of the Panda3D engine. It allows you view webpages that contain Panda3D content and to run games created with Panda3D that are packaged as .p3d file. + +WWW: https://www.panda3d.org/ +""" + +# FreeBSD PKG Manifest template file +INSTALLER_PKG_MANIFEST_FILE = """ +name: NAME +version: VERSION +arch: ARCH +origin: ORIGIN +comment: "Panda3D free 3D engine SDK" +www: https://www.panda3d.org +maintainer: rdb +prefix: /usr/local +flatsize: INSTSIZEMB +deps: {DEPENDS} +""" + + +def MakeInstallerNSIS(version, file, title, installdir, runtime=False, compressor="lzma", **kwargs): + outputdir = GetOutputDir() + + if os.path.isfile(file): + os.remove(file) + elif os.path.isdir(file): + shutil.rmtree(file) + + if "PYTHONVERSION" in SDK: + pyver = SDK["PYTHONVERSION"][6:9] + else: + pyver = "%d.%d" % (sys.version_info[:2]) + + if GetTargetArch() == 'x64': + regview = '64' + else: + regview = '32' + if int(pyver[0]) == 3 and int(pyver[2]) >= 5: + pyver += '-32' + + if runtime: + # Invoke the make_installer script. + AddToPathEnv("PATH", outputdir + "\\bin") + AddToPathEnv("PATH", outputdir + "\\plugins") + + cmd = sys.executable + " -B -u " + os.path.join("direct", "src", "plugin_installer", "make_installer.py") + cmd += " --version %s --regview %s" % (version, regview) + + if GetTargetArch() == 'x64': + cmd += " --install \"$PROGRAMFILES64\\Panda3D\" " + else: + cmd += " --install \"$PROGRAMFILES32\\Panda3D\" " + + oscmd(cmd) + shutil.move(os.path.join("direct", "src", "plugin_installer", "p3d-setup.exe"), file) + return + + print("Building "+title+" installer at %s" % (file)) + if compressor != "lzma": + print("Note: you are using zlib, which is faster, but lzma gives better compression.") + if os.path.exists("nsis-output.exe"): + os.remove("nsis-output.exe") + WriteFile(outputdir+"/tmp/__init__.py", "") + + nsis_defs = { + 'COMPRESSOR': compressor, + 'TITLE' : title, + 'INSTALLDIR': installdir, + 'OUTFILE' : '..\\' + file, + 'BUILT' : '..\\' + outputdir, + 'SOURCE' : '..', + 'PYVER' : pyver, + 'REGVIEW' : regview, + 'EXT_SUFFIX': GetExtensionSuffix(), + } + + if GetHost() == 'windows': + cmd = os.path.join(GetThirdpartyBase(), 'win-nsis', 'makensis') + ' /V2' + for item in nsis_defs.items(): + cmd += ' /D%s="%s"' % item + else: + cmd = 'makensis -V2' + for item in nsis_defs.items(): + cmd += ' -D%s="%s"' % item + + cmd += ' "makepanda\\installer.nsi"' + oscmd(cmd) + + +def MakeDebugSymbolArchive(zipname, dirname): + outputdir = GetOutputDir() + + import zipfile + zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) + + for fn in glob.glob(os.path.join(outputdir, 'bin', '*.pdb')): + zip.write(fn, dirname + '/bin/' + os.path.basename(fn)) + + for fn in glob.glob(os.path.join(outputdir, 'panda3d', '*.pdb')): + zip.write(fn, dirname + '/panda3d/' + os.path.basename(fn)) + + for fn in glob.glob(os.path.join(outputdir, 'plugins', '*.pdb')): + zip.write(fn, dirname + '/plugins/' + os.path.basename(fn)) + + for fn in glob.glob(os.path.join(outputdir, 'python', '*.pdb')): + zip.write(fn, dirname + '/python/' + os.path.basename(fn)) + + for fn in glob.glob(os.path.join(outputdir, 'python', 'DLLs', '*.pdb')): + zip.write(fn, dirname + '/python/DLLs/' + os.path.basename(fn)) + + zip.close() + + +def MakeInstallerLinux(version, debversion=None, runtime=False, **kwargs): + outputdir = GetOutputDir() + + if not runtime and not PkgSkip("PYTHON"): + if "PYTHONVERSION" in SDK: + PYTHONV = SDK["PYTHONVERSION"].rstrip('dmu') + else: + PYTHONV = "python%d.%d" % (sys.version_info[:2]) + else: + PYTHONV = "python" + PV = PYTHONV.replace("python", "") + + major_version = '.'.join(version.split('.')[:2]) + if not debversion: + debversion = version + + # Clean and set up a directory to install Panda3D into + oscmd("rm -rf targetroot data.tar.gz control.tar.gz panda3d.spec") + oscmd("mkdir --mode=0755 targetroot") + + dpkg_present = False + if os.path.exists("/usr/bin/dpkg-architecture") and os.path.exists("/usr/bin/dpkg-deb"): + dpkg_present = True + rpmbuild_present = False + if os.path.exists("/usr/bin/rpmbuild"): + rpmbuild_present = True + + if dpkg_present and rpmbuild_present: + Warn("both dpkg and rpmbuild present.") + + if dpkg_present: + # Invoke installpanda.py to install it into a temporary dir + lib_dir = GetDebLibDir() + if runtime: + InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=lib_dir) + else: + InstallPanda(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=lib_dir) + oscmd("chmod -R 755 targetroot/usr/share/panda3d") + oscmd("mkdir -m 0755 -p targetroot/usr/share/man/man1") + oscmd("install -m 0644 doc/man/*.1 targetroot/usr/share/man/man1/") + + oscmd("dpkg --print-architecture > "+outputdir+"/tmp/architecture.txt") + pkg_arch = ReadFile(outputdir+"/tmp/architecture.txt").strip() + if runtime: + txt = RUNTIME_INSTALLER_DEB_FILE[1:] + else: + txt = INSTALLER_DEB_FILE[1:] + txt = txt.replace("VERSION", debversion).replace("ARCH", pkg_arch).replace("PV", PV).replace("MAJOR", major_version) + txt = txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") / 1024)) + oscmd("mkdir --mode=0755 -p targetroot/DEBIAN") + oscmd("cd targetroot && (find usr -type f -exec md5sum {} ;) > DEBIAN/md5sums") + if not runtime: + oscmd("cd targetroot && (find etc -type f -exec md5sum {} ;) >> DEBIAN/md5sums") + WriteFile("targetroot/DEBIAN/conffiles","/etc/Config.prc\n") + WriteFile("targetroot/DEBIAN/postinst","#!/bin/sh\necho running ldconfig\nldconfig\n") + oscmd("cp targetroot/DEBIAN/postinst targetroot/DEBIAN/postrm") + + # Determine the package name and the locations that + # dpkg-shlibdeps should look in for executables. + pkg_version = debversion + if runtime: + pkg_name = "panda3d-runtime" + lib_pattern = "debian/%s/usr/%s/*.so" % (pkg_name, lib_dir) + else: + pkg_name = "panda3d" + major_version + lib_pattern = "debian/%s/usr/%s/panda3d/*.so*" % (pkg_name, lib_dir) + bin_pattern = "debian/%s/usr/bin/*" % (pkg_name) + + # dpkg-shlibdeps looks in the debian/{pkg_name}/DEBIAN/shlibs directory + # and also expects a debian/control file, so we create this dummy set-up. + oscmd("mkdir targetroot/debian") + oscmd("ln -s .. targetroot/debian/" + pkg_name) + WriteFile("targetroot/debian/control", "") + + dpkg_shlibdeps = "dpkg-shlibdeps" + if GetVerbose(): + dpkg_shlibdeps += " -v" + + if runtime: + # The runtime doesn't export any useful symbols, so just query the dependencies. + oscmd("cd targetroot && %(dpkg_shlibdeps)s -x%(pkg_name)s %(lib_pattern)s %(bin_pattern)s*" % locals()) + depends = ReadFile("targetroot/debian/substvars").replace("shlibs:Depends=", "").strip() + recommends = "" + else: + pkg_name = "panda3d" + major_version + pkg_dir = "debian/panda3d" + major_version + + # Generate a symbols file so that other packages can know which symbols we export. + oscmd("cd targetroot && dpkg-gensymbols -q -ODEBIAN/symbols -v%(pkg_version)s -p%(pkg_name)s -e%(lib_pattern)s" % locals()) + + # Library dependencies are required, binary dependencies are recommended. + # We explicitly exclude libphysx-extras since we don't want to depend on PhysX. + oscmd("cd targetroot && LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_dep --ignore-missing-info -x%(pkg_name)s -xlibphysx-extras %(lib_pattern)s" % locals()) + oscmd("cd targetroot && LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_rec --ignore-missing-info -x%(pkg_name)s %(bin_pattern)s" % locals()) + + # Parse the substvars files generated by dpkg-shlibdeps. + depends = ReadFile("targetroot/debian/substvars_dep").replace("shlibs:Depends=", "").strip() + recommends = ReadFile("targetroot/debian/substvars_rec").replace("shlibs:Depends=", "").strip() + if PkgSkip("PYTHON")==0: + depends += ", " + PYTHONV + recommends += ", python-wxversion, python-profiler (>= " + PV + "), python-pmw, python-tk (>= " + PV + ")" + if PkgSkip("NVIDIACG")==0: + depends += ", nvidia-cg-toolkit" + + # Write back the dependencies, and delete the dummy set-up. + txt = txt.replace("DEPENDS", depends.strip(', ')) + txt = txt.replace("RECOMMENDS", recommends.strip(', ')) + WriteFile("targetroot/DEBIAN/control", txt) + oscmd("rm -rf targetroot/debian") + + # Package it all up into a .deb file. + oscmd("chmod -R 755 targetroot/DEBIAN") + oscmd("chmod 644 targetroot/DEBIAN/control targetroot/DEBIAN/md5sums") + if not runtime: + oscmd("chmod 644 targetroot/DEBIAN/conffiles targetroot/DEBIAN/symbols") + oscmd("fakeroot dpkg-deb -b targetroot %s_%s_%s.deb" % (pkg_name, pkg_version, pkg_arch)) + + elif rpmbuild_present: + # Invoke installpanda.py to install it into a temporary dir + if runtime: + InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=GetRPMLibDir()) + else: + InstallPanda(destdir="targetroot", prefix="/usr", outputdir=outputdir, libdir=GetRPMLibDir()) + oscmd("chmod -R 755 targetroot/usr/share/panda3d") + + oscmd("rpm -E '%_target_cpu' > "+outputdir+"/tmp/architecture.txt") + arch = ReadFile(outputdir+"/tmp/architecture.txt").strip() + pandasource = os.path.abspath(os.getcwd()) + + if runtime: + txt = RUNTIME_INSTALLER_SPEC_FILE[1:] + else: + txt = INSTALLER_SPEC_FILE[1:] + + # Add the MIME associations if we have pview + if not PkgSkip("PVIEW"): + txt += INSTALLER_SPEC_FILE_PVIEW + + # Add the binaries in /usr/bin explicitly to the spec file + for base in os.listdir(outputdir + "/bin"): + txt += "/usr/bin/%s\n" % (base) + + # Write out the spec file. + txt = txt.replace("VERSION", version) + txt = txt.replace("RPMRELEASE", rpmrelease) + txt = txt.replace("PANDASOURCE", pandasource) + txt = txt.replace("PV", PV) + WriteFile("panda3d.spec", txt) + + oscmd("fakeroot rpmbuild --define '_rpmdir "+pandasource+"' --buildroot '"+os.path.abspath("targetroot")+"' -bb panda3d.spec") + if runtime: + oscmd("mv "+arch+"/panda3d-runtime-"+version+"-"+rpmrelease+"."+arch+".rpm .") + else: + oscmd("mv "+arch+"/panda3d-"+version+"-"+rpmrelease+"."+arch+".rpm .") + oscmd("rm -rf "+arch, True) + + else: + exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!") + + +def MakeInstallerOSX(version, runtime=False, **kwargs): + outputdir = GetOutputDir() + + if runtime: + # Invoke the make_installer script. + AddToPathEnv("DYLD_LIBRARY_PATH", outputdir + "/plugins") + cmdstr = sys.executable + " " + if sys.version_info >= (2, 6): + cmdstr += "-B " + + cmdstr += "direct/src/plugin_installer/make_installer.py --version %s" % version + oscmd(cmdstr) + return + + if "PYTHONVERSION" in SDK: + pyver = SDK["PYTHONVERSION"][6:9] + else: + pyver = "%d.%d" % (sys.version_info[:2]) + + dmg_name = "Panda3D-" + version + if not pyver.startswith("2."): + dmg_name += "-py" + pyver + dmg_name += ".dmg" + + import compileall + if (os.path.isfile(dmg_name)): oscmd("rm -f %s" % dmg_name) + if (os.path.exists("dstroot")): oscmd("rm -rf dstroot") + if (os.path.exists("Panda3D-rw.dmg")): oscmd('rm -f Panda3D-rw.dmg') + + oscmd("mkdir -p dstroot/base/Developer/Panda3D/lib") + oscmd("mkdir -p dstroot/base/Developer/Panda3D/etc") + oscmd("cp %s/etc/Config.prc dstroot/base/Developer/Panda3D/etc/Config.prc" % outputdir) + oscmd("cp %s/etc/Confauto.prc dstroot/base/Developer/Panda3D/etc/Confauto.prc" % outputdir) + oscmd("cp -R %s/models dstroot/base/Developer/Panda3D/models" % outputdir) + oscmd("cp -R doc/LICENSE dstroot/base/Developer/Panda3D/LICENSE") + oscmd("cp -R doc/ReleaseNotes dstroot/base/Developer/Panda3D/ReleaseNotes") + oscmd("cp -R %s/Frameworks dstroot/base/Developer/Panda3D/Frameworks" % outputdir) + if os.path.isdir(outputdir+"/plugins"): + oscmd("cp -R %s/plugins dstroot/base/Developer/Panda3D/plugins" % outputdir) + + # Libraries that shouldn't be in base, but are instead in other modules. + no_base_libs = ['libp3ffmpeg', 'libp3fmod_audio', 'libfmodex', 'libfmodexL'] + + for base in os.listdir(outputdir+"/lib"): + if not base.endswith(".a") and base.split('.')[0] not in no_base_libs: + libname = "dstroot/base/Developer/Panda3D/lib/" + base + # We really need to specify -R in order not to follow symlinks + # On OSX, just specifying -P is not enough to do that. + oscmd("cp -R -P " + outputdir + "/lib/" + base + " " + libname) + + oscmd("mkdir -p dstroot/tools/Developer/Panda3D/bin") + oscmd("mkdir -p dstroot/tools/Developer/Tools") + oscmd("ln -s ../Panda3D/bin dstroot/tools/Developer/Tools/Panda3D") + oscmd("mkdir -p dstroot/tools/etc/paths.d") + # Trailing newline is important, works around a bug in OSX + WriteFile("dstroot/tools/etc/paths.d/Panda3D", "/Developer/Panda3D/bin\n") + + oscmd("mkdir -m 0755 -p dstroot/tools/usr/local/share/man/man1") + oscmd("install -m 0644 doc/man/*.1 dstroot/tools/usr/local/share/man/man1/") + + for base in os.listdir(outputdir+"/bin"): + binname = "dstroot/tools/Developer/Panda3D/bin/" + base + # OSX needs the -R argument to copy symbolic links correctly, it doesn't have -d. How weird. + oscmd("cp -R " + outputdir + "/bin/" + base + " " + binname) + + if not PkgSkip("PYTHON"): + pyexec = SDK.get("PYTHONEXEC", sys.executable) + oscmd("mkdir -p dstroot/pythoncode/usr/local/bin") + oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/panda3d") + oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % pyver) + WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % pyver, "/Developer/Panda3D") + oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % outputdir) + oscmd("cp -R %s/direct dstroot/pythoncode/Developer/Panda3D/direct" % outputdir) + oscmd("ln -s %s dstroot/pythoncode/usr/local/bin/ppython" % pyexec) + oscmd("cp -R %s/*.so dstroot/pythoncode/Developer/Panda3D/" % outputdir, True) + oscmd("cp -R %s/*.py dstroot/pythoncode/Developer/Panda3D/" % outputdir, True) + if os.path.isdir(outputdir+"/Pmw"): + oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % outputdir) + compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/Pmw") + WriteFile("dstroot/pythoncode/Developer/Panda3D/direct/__init__.py", "") + for base in os.listdir("dstroot/pythoncode/Developer/Panda3D/direct"): + if ((base != "extensions") and (base != "extensions_native")): + compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/direct/"+base) + + suffix = GetExtensionSuffix() + for base in os.listdir(outputdir+"/panda3d"): + if base.endswith('.py') or (base.endswith(suffix) and '.' not in base[:-len(suffix)]): + libname = "dstroot/pythoncode/Developer/Panda3D/panda3d/" + base + # We really need to specify -R in order not to follow symlinks + # On OSX, just specifying -P is not enough to do that. + oscmd("cp -R -P " + outputdir + "/panda3d/" + base + " " + libname) + + if not PkgSkip("FFMPEG"): + oscmd("mkdir -p dstroot/ffmpeg/Developer/Panda3D/lib") + oscmd("cp -R %s/lib/libp3ffmpeg.* dstroot/ffmpeg/Developer/Panda3D/lib/" % outputdir) + + #if not PkgSkip("OPENAL"): + # oscmd("mkdir -p dstroot/openal/Developer/Panda3D/lib") + # oscmd("cp -R %s/lib/libp3openal_audio.* dstroot/openal/Developer/Panda3D/lib/" % outputdir) + + if not PkgSkip("FMODEX"): + oscmd("mkdir -p dstroot/fmodex/Developer/Panda3D/lib") + oscmd("cp -R %s/lib/libp3fmod_audio.* dstroot/fmodex/Developer/Panda3D/lib/" % outputdir) + oscmd("cp -R %s/lib/libfmodex* dstroot/fmodex/Developer/Panda3D/lib/" % outputdir) + + oscmd("mkdir -p dstroot/headers/Developer/Panda3D/lib") + oscmd("cp -R %s/include dstroot/headers/Developer/Panda3D/include" % outputdir) + if os.path.isfile(outputdir + "/lib/libp3pystub.a"): + oscmd("cp -R -P %s/lib/libp3pystub.a dstroot/headers/Developer/Panda3D/lib/" % outputdir) + + if os.path.isdir("samples"): + oscmd("mkdir -p dstroot/samples/Developer/Examples/Panda3D") + oscmd("cp -R samples/* dstroot/samples/Developer/Examples/Panda3D/") + + oscmd("chmod -R 0775 dstroot/*") + DeleteVCS("dstroot") + DeleteBuildFiles("dstroot") + # We need to be root to perform a chown. Bleh. + # Fortunately PackageMaker does it for us, on 10.5 and above. + #oscmd("chown -R root:admin dstroot/*", True) + + oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/") + oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Resources/en.lproj/") + + pkgs = ["base", "tools", "headers"] + if not PkgSkip("PYTHON"): pkgs.append("pythoncode") + if not PkgSkip("FFMPEG"): pkgs.append("ffmpeg") + #if not PkgSkip("OPENAL"): pkgs.append("openal") + if not PkgSkip("FMODEX"): pkgs.append("fmodex") + if os.path.isdir("samples"): pkgs.append("samples") + for pkg in pkgs: + identifier = "org.panda3d.panda3d.%s.pkg" % pkg + plist = open("/tmp/Info_plist", "w") + plist.write(Info_plist.format(package_id=identifier, version=version)) + plist.close() + if not os.path.isdir("dstroot/" + pkg): + os.makedirs("dstroot/" + pkg) + + if os.path.exists("/usr/bin/pkgbuild"): + # This new package builder is used in Lion and above. + cmd = '/usr/bin/pkgbuild --identifier ' + identifier + ' --version ' + version + ' --root dstroot/' + pkg + '/ dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg' + + # In older versions, we use PackageMaker. Apple keeps changing its location. + elif os.path.exists("/Developer/usr/bin/packagemaker"): + cmd = '/Developer/usr/bin/packagemaker --info /tmp/Info_plist --version ' + version + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' + elif os.path.exists("/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"): + cmd = '/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + version + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' + elif os.path.exists("/Developer/Tools/PackageMaker.app/Contents/MacOS/PackageMaker"): + cmd = '/Developer/Tools/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + version + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' + elif os.path.exists("/Developer/Tools/packagemaker"): + cmd = '/Developer/Tools/packagemaker -build -f dstroot/' + pkg + '/ -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg -i /tmp/Info_plist' + elif os.path.exists("/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"): + cmd = '/Applications/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + version + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' + else: + exit("Neither pkgbuild nor PackageMaker could be found!") + oscmd(cmd) + + if os.path.isfile("/tmp/Info_plist"): + oscmd("rm -f /tmp/Info_plist") + + # Now that we've built all of the individual packages, build the metapackage. + dist = open("dstroot/Panda3D/Panda3D.mpkg/Contents/distribution.dist", "w") + dist.write('\n') + dist.write('\n') + dist.write(' Panda3D SDK %s\n' % (version)) + dist.write(' \n') + dist.write(' %s\n' % ReadFile("doc/LICENSE")) + dist.write(' \n') + for pkg in pkgs: + dist.write(' \n' % (pkg)) + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + + if not PkgSkip("PYTHON"): + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + + if not PkgSkip("FFMPEG"): + dist.write(' \n') + elif PkgSkip("VORBIS"): + dist.write(' It is not required for loading .wav or .opus files, which Panda3D can read out of the box.">\n') + elif PkgSkip("OPUS"): + dist.write(' It is not required for loading .wav or .ogg files, which Panda3D can read out of the box.">\n') + else: + dist.write(' It is not required for loading .wav, .ogg or .opus files, which Panda3D can read out of the box.">\n') + dist.write(' \n') + dist.write(' \n') + + #if not PkgSkip("OPENAL"): + # dist.write(' \n') + # dist.write(' \n') + # dist.write(' \n') + + if not PkgSkip("FMODEX"): + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + + if os.path.isdir("samples"): + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + + dist.write(' \n') + dist.write(' \n') + dist.write(' \n') + for pkg in pkgs: + size = GetDirectorySize("dstroot/" + pkg) // 1024 + dist.write(' file:./Contents/Packages/%s.pkg\n' % (pkg, size, pkg)) + dist.write('\n') + dist.close() + + oscmd('hdiutil create Panda3D-rw.dmg -volname "Panda3D SDK %s" -srcfolder dstroot/Panda3D' % (version)) + oscmd('hdiutil convert Panda3D-rw.dmg -format UDBZ -o %s' % (dmg_name)) + oscmd('rm -f Panda3D-rw.dmg') + + +def MakeInstallerFreeBSD(version, runtime=False, **kwargs): + outputdir = GetOutputDir() + + oscmd("rm -rf targetroot +DESC pkg-plist +MANIFEST") + oscmd("mkdir targetroot") + + # Invoke installpanda.py to install it into a temporary dir + if runtime: + InstallRuntime(destdir="targetroot", prefix="/usr/local", outputdir=outputdir) + else: + InstallPanda(destdir="targetroot", prefix="/usr/local", outputdir=outputdir) + + if not os.path.exists("/usr/sbin/pkg"): + exit("Cannot create an installer without pkg") + + plist_txt = '' + for root, dirs, files in os.walk("targetroot/usr/local/", True): + for f in files: + plist_txt += os.path.join(root, f)[21:] + "\n" + + if not runtime: + plist_txt += "@postexec /sbin/ldconfig -m /usr/local/lib/panda3d\n" + plist_txt += "@postunexec /sbin/ldconfig -R\n" + + for remdir in ("lib/panda3d", "share/panda3d", "include/panda3d"): + for root, dirs, files in os.walk("targetroot/usr/local/" + remdir, False): + for d in dirs: + plist_txt += "@dir %s\n" % os.path.join(root, d)[21:] + plist_txt += "@dir %s\n" % remdir + + oscmd("echo \"`pkg config abi | tr '[:upper:]' '[:lower:]' | cut -d: -f1,2`:*\" > " + outputdir + "/tmp/architecture.txt") + pkg_arch = ReadFile(outputdir+"/tmp/architecture.txt").strip() + + dependencies = '' + if not PkgSkip("PYTHON"): + # If this version of Python was installed from a package or ports, let's mark it as dependency. + oscmd("rm -f %s/tmp/python_dep" % outputdir) + + if "PYTHONVERSION" in SDK: + pyver_nodot = SDK["PYTHONVERSION"][6:9:2] + else: + pyver_nodot = "%d%d" % (sys.version_info[:2]) + + oscmd("pkg query \"\n\t%%n : {\n\t\torigin : %%o,\n\t\tversion : %%v\n\t},\n\" python%s > %s/tmp/python_dep" % (pyver_nodot, outputdir), True) + if os.path.isfile(outputdir + "/tmp/python_dep"): + python_pkg = ReadFile(outputdir + "/tmp/python_dep") + if python_pkg: + dependencies += python_pkg + + manifest_txt = INSTALLER_PKG_MANIFEST_FILE[1:].replace("NAME", 'panda3d' if not runtime else 'panda3d-runtime') + manifest_txt = manifest_txt.replace("VERSION", version) + manifest_txt = manifest_txt.replace("ARCH", pkg_arch) + manifest_txt = manifest_txt.replace("ORIGIN", 'devel/panda3d' if not runtime else 'graphics/panda3d-runtime') + manifest_txt = manifest_txt.replace("DEPENDS", dependencies) + manifest_txt = manifest_txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") / 1024 / 1024)) + + WriteFile("pkg-plist", plist_txt) + WriteFile("+DESC", INSTALLER_PKG_DESCR_FILE[1:] if not runtime else RUNTIME_INSTALLER_PKG_DESCR_FILE[1:]) + WriteFile("+MANIFEST", manifest_txt) + oscmd("pkg create -p pkg-plist -r %s -m . -o . %s" % (os.path.abspath("targetroot"), "--verbose" if GetVerbose() else "--quiet")) + + +def MakeInstallerAndroid(version, **kwargs): + outputdir = GetOutputDir() + oscmd("rm -rf apkroot") + oscmd("mkdir apkroot") + + # Also remove the temporary apks. + apk_unaligned = os.path.join(outputdir, "tmp", "panda3d-unaligned.apk") + apk_unsigned = os.path.join(outputdir, "tmp", "panda3d-unsigned.apk") + if os.path.exists(apk_unaligned): + os.unlink(apk_unaligned) + if os.path.exists(apk_unsigned): + os.unlink(apk_unsigned) + + # Compile the Java classes into a Dalvik executable. + dx_cmd = "dx --dex --output=apkroot/classes.dex " + if GetOptimize() <= 2: + dx_cmd += "--debug " + if GetVerbose(): + dx_cmd += "--verbose " + if "ANDROID_API" in SDK: + dx_cmd += "--min-sdk-version=%d " % (SDK["ANDROID_API"]) + dx_cmd += os.path.join(outputdir, "classes") + oscmd(dx_cmd) + + # Copy the libraries one by one. In case of library dependencies, strip + # off any suffix (eg. libfile.so.1.0), as Android does not support them. + source_dir = os.path.join(outputdir, "lib") + target_dir = os.path.join("apkroot", "lib", SDK["ANDROID_ABI"]) + oscmd("mkdir -p %s" % (target_dir)) + + # Determine the library directories we should look in. + libpath = [source_dir] + for dir in os.environ.get("LD_LIBRARY_PATH", "").split(':'): + dir = os.path.expandvars(dir) + dir = os.path.expanduser(dir) + if os.path.isdir(dir): + dir = os.path.realpath(dir) + if not dir.startswith("/system") and not dir.startswith("/vendor"): + libpath.append(dir) + + def copy_library(source, base): + # Copy file to destination, stripping version suffix. + target = os.path.join(target_dir, base) + if not target.endswith('.so'): + target = target.rpartition('.so.')[0] + '.so' + + if os.path.isfile(target): + # Already processed. + return + + oscmd("cp %s %s" % (source, target)) + + # Walk through the library dependencies. + oscmd("ldd %s | grep .so > %s/tmp/otool-libs.txt" % (target, outputdir), True) + for line in open(outputdir + "/tmp/otool-libs.txt", "r"): + line = line.strip() + if not line: + continue + if '.so.' in line: + dep = line.rpartition('.so.')[0] + '.so' + oscmd("patchelf --replace-needed %s %s %s" % (line, dep, target), True) + else: + dep = line + + # Find it on the LD_LIBRARY_PATH. + for dir in libpath: + fulldep = os.path.join(dir, dep) + if os.path.isfile(fulldep): + copy_library(os.path.realpath(fulldep), dep) + break + + # Now copy every lib in the lib dir, and its dependencies. + for base in os.listdir(source_dir): + if not base.startswith('lib'): + continue + if not base.endswith('.so') and '.so.' not in base: + continue + + source = os.path.join(source_dir, base) + if os.path.islink(source): + continue + copy_library(source, base) + + # Same for Python extension modules. However, Android is strict about + # library naming, so we have a special naming scheme for these, in + # conjunction with a custom import hook to find these modules. + if not PkgSkip("PYTHON"): + suffix = GetExtensionSuffix() + source_dir = os.path.join(outputdir, "panda3d") + for base in os.listdir(source_dir): + if not base.endswith(suffix): + continue + modname = base[:-len(suffix)] + if '.' not in modname: + source = os.path.join(source_dir, base) + copy_library(source, "libpy.panda3d.{}.so".format(modname)) + + # Same for standard Python modules. + import _ctypes + source_dir = os.path.dirname(_ctypes.__file__) + for base in os.listdir(source_dir): + if not base.endswith('.so'): + continue + modname = base.partition('.')[0] + source = os.path.join(source_dir, base) + copy_library(source, "libpy.{}.so".format(modname)) + + def copy_python_tree(source_root, target_root): + for source_dir, dirs, files in os.walk(source_root): + if 'site-packages' in dirs: + dirs.remove('site-packages') + + if not any(base.endswith('.py') for base in files): + continue + + target_dir = os.path.join(target_root, os.path.relpath(source_dir, source_root)) + target_dir = os.path.normpath(target_dir) + os.makedirs(target_dir, 0o755) + + for base in files: + if base.endswith('.py'): + target = os.path.join(target_dir, base) + shutil.copy(os.path.join(source_dir, base), target) + + # Copy the Python standard library to the .apk as well. + from distutils.sysconfig import get_python_lib + stdlib_source = get_python_lib(False, True) + stdlib_target = os.path.join("apkroot", "lib", "python{0}.{1}".format(*sys.version_info)) + copy_python_tree(stdlib_source, stdlib_target) + + # But also copy over our custom site.py. + shutil.copy("panda/src/android/site.py", os.path.join(stdlib_target, "site.py")) + + # And now make a site-packages directory containing our direct/panda3d/pandac modules. + for tree in "panda3d", "direct", "pandac": + copy_python_tree(os.path.join(outputdir, tree), os.path.join(stdlib_target, "site-packages", tree)) + + # Copy the models and config files to the virtual assets filesystem. + oscmd("mkdir apkroot/assets") + oscmd("cp -R %s apkroot/assets/models" % (os.path.join(outputdir, "models"))) + oscmd("cp -R %s apkroot/assets/etc" % (os.path.join(outputdir, "etc"))) + + # Make an empty res folder. It's needed for the apk to be installable, apparently. + oscmd("mkdir apkroot/res") + + # Now package up the application + oscmd("cp panda/src/android/pview_manifest.xml apkroot/AndroidManifest.xml") + aapt_cmd = "aapt package" + aapt_cmd += " -F %s" % (apk_unaligned) + aapt_cmd += " -M apkroot/AndroidManifest.xml" + aapt_cmd += " -A apkroot/assets -S apkroot/res" + aapt_cmd += " -I $PREFIX/share/aapt/android.jar" + oscmd(aapt_cmd) + + # And add all the libraries to it. + oscmd("cd apkroot && aapt add ../%s classes.dex" % (apk_unaligned)) + for path, dirs, files in os.walk('apkroot/lib'): + if files: + rel = os.path.relpath(path, 'apkroot') + oscmd("cd apkroot && aapt add ../%s %s/*" % (apk_unaligned, rel)) + + # Now align the .apk, which is necessary for Android to load it. + oscmd("zipalign -v -p 4 %s %s" % (apk_unaligned, apk_unsigned)) + + # Finally, sign it using a debug key. This is generated if it doesn't exist. + oscmd("apksigner debug.ks %s panda3d.apk" % (apk_unsigned)) + + # Clean up. + oscmd("rm -rf apkroot") + os.unlink(apk_unaligned) + os.unlink(apk_unsigned) + + +def MakeInstaller(version, **kwargs): + target = GetTarget() + if target == 'windows': + fn = "Panda3D-" + dir = "Panda3D-" + version + + runtime = kwargs.get('runtime', False) + if runtime: + fn += "Runtime-" + title = "Panda3D " + version + else: + title = "Panda3D SDK " + version + + fn += version + + if "PYTHONVERSION" in SDK: + pyver = SDK["PYTHONVERSION"][6:9] + else: + pyver = "%d.%d" % (sys.version_info[:2]) + + if not runtime and pyver != "2.7": + fn += '-py' + pyver + + if GetOptimize() <= 2: + fn += "-dbg" + if GetTargetArch() == 'x64': + fn += '-x64' + dir += '-x64' + + MakeInstallerNSIS(version, fn + '.exe', title, 'C:\\' + dir, **kwargs) + if not runtime: + MakeDebugSymbolArchive(fn + '-pdb.zip', dir) + elif target == 'linux': + MakeInstallerLinux(version, **kwargs) + elif target == 'darwin': + MakeInstallerOSX(version, **kwargs) + elif target == 'freebsd': + MakeInstallerFreeBSD(version, **kwargs) + elif target == 'android': + MakeInstallerAndroid(version, **kwargs) + else: + exit("Do not know how to make an installer for this platform") + + +if __name__ == "__main__": + version = ParsePandaVersion("dtool/PandaVersion.pp") + + parser = OptionParser() + parser.add_option('', '--version', dest='version', help='Panda3D version number (default: %s)' % (version), default=version) + parser.add_option('', '--debversion', dest='debversion', help='Version number for .deb file', default=None) + parser.add_option('', '--rpmrelease', dest='rpmrelease', help='Release number for .rpm file', default='1') + 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('', '--runtime', dest='runtime', help='Runtime instead of SDK', action='store_true', default=False) + parser.add_option('', '--lzma', dest='compressor', help='Use LZMA compression', action='store_const', const='lzma', default='zlib') + (options, args) = parser.parse_args() + + SetVerbose(options.verbose) + SetOutputDir(options.outputdir) + + # Read out the optimize option. + opt = ReadFile(os.path.join(options.outputdir, "tmp", "optimize.dat")) + SetOptimize(int(opt.strip())) + + # Read out whether we should set PkgSkip("PYTHON") and some others. + # Temporary hack; needs better solution. + pkg_list = "PYTHON", "NVIDIACG", "FFMPEG", "OPENAL", "FMODEX", "PVIEW", "NVIDIACG", "VORBIS", "OPUS" + PkgListSet(pkg_list) + for pkg in pkg_list: + dat_path = "dtool_have_%s.dat" % (pkg.lower()) + content = ReadFile(os.path.join(options.outputdir, "tmp", dat_path)) + if int(content.strip()): + PkgEnable(pkg) + else: + PkgDisable(pkg) + + # Parse the version. + match = re.match(r'^\d+\.\d+\.\d+', options.version) + if not match: + exit("version requires three digits") + + MakeInstaller(version=match.group(), + outputdir=options.outputdir, + optimize=GetOptimize(), + compressor=options.compressor, + debversion=options.debversion, + rpmrelease=options.rpmrelease, + runtime=options.runtime) diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 4ee16763a3..cb9ab10e0c 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -23,7 +23,6 @@ except: exit(1) from makepandacore import * -from installpanda import * import time import os import sys @@ -2592,6 +2591,11 @@ def WriteConfigSettings(): if (PkgSkip(x)): ConditionalWriteFile(GetOutputDir() + '/tmp/dtool_have_'+x.lower()+'.dat', "0\n") else: ConditionalWriteFile(GetOutputDir() + '/tmp/dtool_have_'+x.lower()+'.dat', "1\n") + # This is useful for tools like makepackage that need to know things about + # the build parameters. + ConditionalWriteFile(GetOutputDir() + '/tmp/optimize.dat', str(GetOptimize())) + + WriteConfigSettings() WarnConflictingFiles() @@ -6715,17 +6719,18 @@ def SequentialMake(tasklist): JustBuilt(task[2], task[3]) i += 1 + def RunDependencyQueue(tasklist): if (THREADCOUNT!=0): ParallelMake(tasklist) else: SequentialMake(tasklist) + try: RunDependencyQueue(DEPENDENCYQUEUE) -except: +finally: SaveDependencyCache() - raise # Run the test suite. if RUNTESTS: @@ -6747,879 +6752,18 @@ if RUNTESTS: # ########################################################################################## -def MakeInstallerNSIS(file, title, installdir): - if (os.path.isfile(file)): - os.remove(file) - elif (os.path.isdir(file)): - shutil.rmtree(file) - - pyver = SDK["PYTHONVERSION"][6:9] - if GetTargetArch() == 'x64': - regview = '64' - else: - regview = '32' - if int(pyver[0]) == 3 and int(pyver[2]) >= 5: - pyver += '-32' - - if (RUNTIME): - # Invoke the make_installer script. - AddToPathEnv("PATH", GetOutputDir() + "\\bin") - AddToPathEnv("PATH", GetOutputDir() + "\\plugins") - - cmd = sys.executable + " -B -u " + os.path.join("direct", "src", "plugin_installer", "make_installer.py") - cmd += " --version %s --regview %s" % (VERSION, regview) - - if GetTargetArch() == 'x64': - cmd += " --install \"$PROGRAMFILES64\\Panda3D\" " - else: - cmd += " --install \"$PROGRAMFILES32\\Panda3D\" " - - oscmd(cmd) - shutil.move(os.path.join("direct", "src", "plugin_installer", "p3d-setup.exe"), file) - return - - print("Building "+title+" installer at %s" % (file)) - if (COMPRESSOR != "lzma"): - print("Note: you are using zlib, which is faster, but lzma gives better compression.") - if (os.path.exists("nsis-output.exe")): - os.remove("nsis-output.exe") - WriteFile(GetOutputDir()+"/tmp/__init__.py", "") - - nsis_defs = { - 'COMPRESSOR' : COMPRESSOR, - 'TITLE' : title, - 'INSTALLDIR' : installdir, - 'OUTFILE' : '..\\' + file, - 'BUILT' : '..\\' + GetOutputDir(), - 'SOURCE' : '..', - 'PYVER' : pyver, - 'REGVIEW' : regview, - 'EXT_SUFFIX' : GetExtensionSuffix(), - } - - if GetHost() == 'windows': - cmd = os.path.join(GetThirdpartyBase(), 'win-nsis', 'makensis') + ' /V2' - for item in nsis_defs.items(): - cmd += ' /D%s="%s"' % item - else: - cmd = 'makensis -V2' - for item in nsis_defs.items(): - cmd += ' -D%s="%s"' % item - - cmd += ' "makepanda\\installer.nsi"' - oscmd(cmd) - -def MakeDebugSymbolArchive(zipname, dirname): - import zipfile - zip = zipfile.ZipFile(zipname, 'w', zipfile.ZIP_DEFLATED) - - for fn in glob.glob(os.path.join(GetOutputDir(), 'bin', '*.pdb')): - zip.write(fn, dirname + '/bin/' + os.path.basename(fn)) - - for fn in glob.glob(os.path.join(GetOutputDir(), 'panda3d', '*.pdb')): - zip.write(fn, dirname + '/panda3d/' + os.path.basename(fn)) - - for fn in glob.glob(os.path.join(GetOutputDir(), 'plugins', '*.pdb')): - zip.write(fn, dirname + '/plugins/' + os.path.basename(fn)) - - for fn in glob.glob(os.path.join(GetOutputDir(), 'python', '*.pdb')): - zip.write(fn, dirname + '/python/' + os.path.basename(fn)) - - for fn in glob.glob(os.path.join(GetOutputDir(), 'python', 'DLLs', '*.pdb')): - zip.write(fn, dirname + '/python/DLLs/' + os.path.basename(fn)) - - zip.close() - -INSTALLER_DEB_FILE=""" -Package: panda3dMAJOR -Version: VERSION -Section: libdevel -Priority: optional -Architecture: ARCH -Essential: no -Depends: DEPENDS -Recommends: RECOMMENDS -Provides: panda3d, pythonPV-panda3d -Conflicts: panda3d, pythonPV-panda3d -Replaces: panda3d, pythonPV-panda3d -Maintainer: rdb -Installed-Size: INSTSIZE -Description: Panda3D free 3D engine SDK - Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. - Panda3D's intended game-development language is Python. The engine itself is written in C++, and utilizes an automatic wrapper-generator to expose the complete functionality of the engine in a Python interface. - . - This package contains the SDK for development with Panda3D. - -""" - -RUNTIME_INSTALLER_DEB_FILE=""" -Package: panda3d-runtime -Version: VERSION -Section: web -Priority: optional -Architecture: ARCH -Essential: no -Depends: DEPENDS -Provides: panda3d-runtime -Maintainer: rdb -Installed-Size: INSTSIZE -Description: Runtime binary and browser plugin for the Panda3D Game Engine - This package contains the runtime distribution and browser plugin of the Panda3D engine. It allows you view webpages that contain Panda3D content and to run games created with Panda3D that are packaged as .p3d file. - -""" - - -# We're not putting "python" in the "Requires" field, -# since the rpm-based distros don't have a common -# naming for the Python package. -INSTALLER_SPEC_FILE=""" -Summary: The Panda3D free 3D engine SDK -Name: panda3d -Version: VERSION -Release: RPMRELEASE -License: BSD License -Group: Development/Libraries -BuildRoot: PANDASOURCE/targetroot -%description -Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. -Panda3D's intended game-development language is Python. The engine itself is written in C++, and utilizes an automatic wrapper-generator to expose the complete functionality of the engine in a Python interface. - -This package contains the SDK for development with Panda3D, install panda3d-runtime for the runtime files. -%post -/sbin/ldconfig -%postun -/sbin/ldconfig -%files -%defattr(-,root,root) -/etc/Confauto.prc -/etc/Config.prc -/usr/share/panda3d -/etc/ld.so.conf.d/panda3d.conf -/usr/%_lib/panda3d -""" + PYTHON_SITEPACKAGES + """ -/usr/include/panda3d -""" -if not PkgSkip("PVIEW"): - INSTALLER_SPEC_FILE += \ -"""/usr/share/applications/pview.desktop -/usr/share/mime-info/panda3d.mime -/usr/share/mime-info/panda3d.keys -/usr/share/mime/packages/panda3d.xml -/usr/share/application-registry/panda3d.applications -""" - -RUNTIME_INSTALLER_SPEC_FILE=""" -Summary: Runtime binary and browser plugin for the Panda3D Game Engine -Name: panda3d-runtime -Version: VERSION -Release: RPMRELEASE -License: BSD License -Group: Productivity/Graphics/Other -BuildRoot: PANDASOURCE/targetroot -%description -This package contains the runtime distribution and browser plugin of the Panda3D engine. It allows you view webpages that contain Panda3D content and to run games created with Panda3D that are packaged as .p3d file. -%files -%defattr(-,root,root) -/usr/bin/panda3d -/usr/%_lib/nppanda3d.so -/usr/%_lib/mozilla/plugins/nppanda3d.so -/usr/%_lib/mozilla-firefox/plugins/nppanda3d.so -/usr/%_lib/xulrunner-addons/plugins/nppanda3d.so -/usr/share/mime-info/panda3d-runtime.mime -/usr/share/mime-info/panda3d-runtime.keys -/usr/share/mime/packages/panda3d-runtime.xml -/usr/share/application-registry/panda3d-runtime.applications -/usr/share/applications/*.desktop -""" - -# plist file for Mac OSX -Info_plist = """ - - - - CFBundleIdentifier - %(package_id)s - CFBundleShortVersionString - %(version)s - IFPkgFlagRelocatable - - IFPkgFlagAuthorizationAction - RootAuthorization - IFPkgFlagAllowBackRev - - - -""" - -# FreeBSD pkg-descr -INSTALLER_PKG_DESCR_FILE = """ -Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost. -Panda3D's intended game-development language is Python. The engine itself is written in C++, and utilizes an automatic wrapper-generator to expose the complete functionality of the engine in a Python interface. - -This package contains the SDK for development with Panda3D, install panda3d-runtime for the runtime files. - -WWW: https://www.panda3d.org/ -""" - -# FreeBSD pkg-descr -RUNTIME_INSTALLER_PKG_DESCR_FILE = """ -Runtime binary and browser plugin for the Panda3D Game Engine - -This package contains the runtime distribution and browser plugin of the Panda3D engine. It allows you view webpages that contain Panda3D content and to run games created with Panda3D that are packaged as .p3d file. - -WWW: https://www.panda3d.org/ -""" - -# FreeBSD PKG Manifest template file -INSTALLER_PKG_MANIFEST_FILE = """ -name: NAME -version: VERSION -arch: ARCH -origin: ORIGIN -comment: "Panda3D free 3D engine SDK" -www: https://www.panda3d.org -maintainer: rdb -prefix: /usr/local -flatsize: INSTSIZEMB -deps: {DEPENDS} -""" - -def MakeInstallerLinux(): - if not RUNTIME and not PkgSkip("PYTHON"): - PYTHONV = SDK["PYTHONVERSION"].rstrip('dmu') - else: - PYTHONV = "python" - PV = PYTHONV.replace("python", "") - - # Clean and set up a directory to install Panda3D into - oscmd("rm -rf targetroot data.tar.gz control.tar.gz panda3d.spec") - oscmd("mkdir --mode=0755 targetroot") - - dpkg_present = False - if os.path.exists("/usr/bin/dpkg-architecture") and os.path.exists("/usr/bin/dpkg-deb"): - dpkg_present = True - rpmbuild_present = False - if os.path.exists("/usr/bin/rpmbuild"): - rpmbuild_present = True - - if dpkg_present and rpmbuild_present: - Warn("both dpkg and rpmbuild present.") - - if dpkg_present: - # Invoke installpanda.py to install it into a temporary dir - lib_dir = GetDebLibDir() - if RUNTIME: - InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=lib_dir) - else: - InstallPanda(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=lib_dir) - oscmd("chmod -R 755 targetroot/usr/share/panda3d") - oscmd("mkdir -m 0755 -p targetroot/usr/share/man/man1") - oscmd("install -m 0644 doc/man/*.1 targetroot/usr/share/man/man1/") - - oscmd("dpkg --print-architecture > "+GetOutputDir()+"/tmp/architecture.txt") - pkg_arch = ReadFile(GetOutputDir()+"/tmp/architecture.txt").strip() - if (RUNTIME): - txt = RUNTIME_INSTALLER_DEB_FILE[1:] - else: - txt = INSTALLER_DEB_FILE[1:] - txt = txt.replace("VERSION", DEBVERSION).replace("ARCH", pkg_arch).replace("PV", PV).replace("MAJOR", MAJOR_VERSION) - txt = txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") / 1024)) - oscmd("mkdir --mode=0755 -p targetroot/DEBIAN") - oscmd("cd targetroot && (find usr -type f -exec md5sum {} ;) > DEBIAN/md5sums") - if (not RUNTIME): - oscmd("cd targetroot && (find etc -type f -exec md5sum {} ;) >> DEBIAN/md5sums") - WriteFile("targetroot/DEBIAN/conffiles","/etc/Config.prc\n") - WriteFile("targetroot/DEBIAN/postinst","#!/bin/sh\necho running ldconfig\nldconfig\n") - oscmd("cp targetroot/DEBIAN/postinst targetroot/DEBIAN/postrm") - - # Determine the package name and the locations that - # dpkg-shlibdeps should look in for executables. - pkg_version = DEBVERSION - if RUNTIME: - pkg_name = "panda3d-runtime" - lib_pattern = "debian/%s/usr/%s/*.so" % (pkg_name, lib_dir) - else: - pkg_name = "panda3d" + MAJOR_VERSION - lib_pattern = "debian/%s/usr/%s/panda3d/*.so*" % (pkg_name, lib_dir) - bin_pattern = "debian/%s/usr/bin/*" % (pkg_name) - - # dpkg-shlibdeps looks in the debian/{pkg_name}/DEBIAN/shlibs directory - # and also expects a debian/control file, so we create this dummy set-up. - oscmd("mkdir targetroot/debian") - oscmd("ln -s .. targetroot/debian/" + pkg_name) - WriteFile("targetroot/debian/control", "") - - dpkg_shlibdeps = "dpkg-shlibdeps" - if GetVerbose(): - dpkg_shlibdeps += " -v" - - if RUNTIME: - # The runtime doesn't export any useful symbols, so just query the dependencies. - oscmd("cd targetroot && %(dpkg_shlibdeps)s -x%(pkg_name)s %(lib_pattern)s %(bin_pattern)s*" % locals()) - depends = ReadFile("targetroot/debian/substvars").replace("shlibs:Depends=", "").strip() - recommends = "" - else: - pkg_name = "panda3d" + MAJOR_VERSION - pkg_dir = "debian/panda3d" + MAJOR_VERSION - - # Generate a symbols file so that other packages can know which symbols we export. - oscmd("cd targetroot && dpkg-gensymbols -q -ODEBIAN/symbols -v%(pkg_version)s -p%(pkg_name)s -e%(lib_pattern)s" % locals()) - - # Library dependencies are required, binary dependencies are recommended. - # We explicitly exclude libphysx-extras since we don't want to depend on PhysX. - oscmd("cd targetroot && LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_dep --ignore-missing-info -x%(pkg_name)s -xlibphysx-extras %(lib_pattern)s" % locals()) - oscmd("cd targetroot && LD_LIBRARY_PATH=usr/%(lib_dir)s/panda3d %(dpkg_shlibdeps)s -Tdebian/substvars_rec --ignore-missing-info -x%(pkg_name)s %(bin_pattern)s" % locals()) - - # Parse the substvars files generated by dpkg-shlibdeps. - depends = ReadFile("targetroot/debian/substvars_dep").replace("shlibs:Depends=", "").strip() - recommends = ReadFile("targetroot/debian/substvars_rec").replace("shlibs:Depends=", "").strip() - if PkgSkip("PYTHON")==0: - depends += ", " + PYTHONV - recommends += ", python-wxversion, python-profiler (>= " + PV + "), python-pmw, python-tk (>= " + PV + ")" - if PkgSkip("NVIDIACG")==0: - depends += ", nvidia-cg-toolkit" - - # Write back the dependencies, and delete the dummy set-up. - txt = txt.replace("DEPENDS", depends.strip(', ')) - txt = txt.replace("RECOMMENDS", recommends.strip(', ')) - WriteFile("targetroot/DEBIAN/control", txt) - oscmd("rm -rf targetroot/debian") - - # Package it all up into a .deb file. - oscmd("chmod -R 755 targetroot/DEBIAN") - oscmd("chmod 644 targetroot/DEBIAN/control targetroot/DEBIAN/md5sums") - if not RUNTIME: - oscmd("chmod 644 targetroot/DEBIAN/conffiles targetroot/DEBIAN/symbols") - oscmd("fakeroot dpkg-deb -b targetroot %s_%s_%s.deb" % (pkg_name, pkg_version, pkg_arch)) - - elif rpmbuild_present: - # Invoke installpanda.py to install it into a temporary dir - if RUNTIME: - InstallRuntime(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=GetRPMLibDir()) - else: - InstallPanda(destdir="targetroot", prefix="/usr", outputdir=GetOutputDir(), libdir=GetRPMLibDir()) - oscmd("chmod -R 755 targetroot/usr/share/panda3d") - - oscmd("rpm -E '%_target_cpu' > "+GetOutputDir()+"/tmp/architecture.txt") - ARCH = ReadFile(GetOutputDir()+"/tmp/architecture.txt").strip() - pandasource = os.path.abspath(os.getcwd()) - - if RUNTIME: - txt = RUNTIME_INSTALLER_SPEC_FILE[1:] - else: - txt = INSTALLER_SPEC_FILE[1:] - # Add the binaries in /usr/bin explicitly to the spec file - for base in os.listdir(GetOutputDir() + "/bin"): - txt += "/usr/bin/%s\n" % (base) - - # Write out the spec file. - txt = txt.replace("VERSION", VERSION) - txt = txt.replace("RPMRELEASE", RPMRELEASE) - txt = txt.replace("PANDASOURCE", pandasource) - txt = txt.replace("PV", PV) - WriteFile("panda3d.spec", txt) - - oscmd("fakeroot rpmbuild --define '_rpmdir "+pandasource+"' --buildroot '"+os.path.abspath("targetroot")+"' -bb panda3d.spec") - if (RUNTIME): - oscmd("mv "+ARCH+"/panda3d-runtime-"+VERSION+"-"+RPMRELEASE+"."+ARCH+".rpm .") - else: - oscmd("mv "+ARCH+"/panda3d-"+VERSION+"-"+RPMRELEASE+"."+ARCH+".rpm .") - oscmd("rm -rf "+ARCH, True) - - else: - exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!") - -def MakeInstallerOSX(): - if (RUNTIME): - # Invoke the make_installer script. - AddToPathEnv("DYLD_LIBRARY_PATH", GetOutputDir() + "/plugins") - cmdstr = sys.executable + " " - if sys.version_info >= (2, 6): - cmdstr += "-B " - - cmdstr += "direct/src/plugin_installer/make_installer.py --version %s" % VERSION - oscmd(cmdstr) - return - - dmg_name = "Panda3D-" + VERSION - if not SDK["PYTHONVERSION"].startswith("python2."): - dmg_name += '-py' + SDK["PYTHONVERSION"][6:9] - dmg_name += ".dmg" - - import compileall - if (os.path.isfile(dmg_name)): oscmd("rm -f %s" % dmg_name) - if (os.path.exists("dstroot")): oscmd("rm -rf dstroot") - if (os.path.exists("Panda3D-rw.dmg")): oscmd('rm -f Panda3D-rw.dmg') - - oscmd("mkdir -p dstroot/base/Developer/Panda3D/lib") - oscmd("mkdir -p dstroot/base/Developer/Panda3D/etc") - oscmd("cp %s/etc/Config.prc dstroot/base/Developer/Panda3D/etc/Config.prc" % GetOutputDir()) - oscmd("cp %s/etc/Confauto.prc dstroot/base/Developer/Panda3D/etc/Confauto.prc" % GetOutputDir()) - oscmd("cp -R %s/models dstroot/base/Developer/Panda3D/models" % GetOutputDir()) - oscmd("cp -R doc/LICENSE dstroot/base/Developer/Panda3D/LICENSE") - oscmd("cp -R doc/ReleaseNotes dstroot/base/Developer/Panda3D/ReleaseNotes") - oscmd("cp -R %s/Frameworks dstroot/base/Developer/Panda3D/Frameworks" % GetOutputDir()) - if os.path.isdir(GetOutputDir()+"/plugins"): - oscmd("cp -R %s/plugins dstroot/base/Developer/Panda3D/plugins" % GetOutputDir()) - - # Libraries that shouldn't be in base, but are instead in other modules. - no_base_libs = ['libp3ffmpeg', 'libp3fmod_audio', 'libfmodex', 'libfmodexL'] - - for base in os.listdir(GetOutputDir()+"/lib"): - if not base.endswith(".a") and base.split('.')[0] not in no_base_libs: - libname = "dstroot/base/Developer/Panda3D/lib/" + base - # We really need to specify -R in order not to follow symlinks - # On OSX, just specifying -P is not enough to do that. - oscmd("cp -R -P " + GetOutputDir() + "/lib/" + base + " " + libname) - - oscmd("mkdir -p dstroot/tools/Developer/Panda3D/bin") - oscmd("mkdir -p dstroot/tools/Developer/Tools") - oscmd("ln -s ../Panda3D/bin dstroot/tools/Developer/Tools/Panda3D") - oscmd("mkdir -p dstroot/tools/etc/paths.d") - # Trailing newline is important, works around a bug in OSX - WriteFile("dstroot/tools/etc/paths.d/Panda3D", "/Developer/Panda3D/bin\n") - - oscmd("mkdir -m 0755 -p dstroot/tools/usr/local/share/man/man1") - oscmd("install -m 0644 doc/man/*.1 dstroot/tools/usr/local/share/man/man1/") - - for base in os.listdir(GetOutputDir()+"/bin"): - binname = "dstroot/tools/Developer/Panda3D/bin/" + base - # OSX needs the -R argument to copy symbolic links correctly, it doesn't have -d. How weird. - oscmd("cp -R " + GetOutputDir() + "/bin/" + base + " " + binname) - - if PkgSkip("PYTHON")==0: - PV = SDK["PYTHONVERSION"][6:9] - oscmd("mkdir -p dstroot/pythoncode/usr/local/bin") - oscmd("mkdir -p dstroot/pythoncode/Developer/Panda3D/panda3d") - oscmd("mkdir -p dstroot/pythoncode/Library/Python/%s/site-packages" % PV) - WriteFile("dstroot/pythoncode/Library/Python/%s/site-packages/Panda3D.pth" % PV, "/Developer/Panda3D") - oscmd("cp -R %s/pandac dstroot/pythoncode/Developer/Panda3D/pandac" % GetOutputDir()) - oscmd("cp -R %s/direct dstroot/pythoncode/Developer/Panda3D/direct" % GetOutputDir()) - oscmd("ln -s %s dstroot/pythoncode/usr/local/bin/ppython" % SDK["PYTHONEXEC"]) - oscmd("cp -R %s/*.so dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir(), True) - oscmd("cp -R %s/*.py dstroot/pythoncode/Developer/Panda3D/" % GetOutputDir(), True) - if os.path.isdir(GetOutputDir()+"/Pmw"): - oscmd("cp -R %s/Pmw dstroot/pythoncode/Developer/Panda3D/Pmw" % GetOutputDir()) - compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/Pmw") - WriteFile("dstroot/pythoncode/Developer/Panda3D/direct/__init__.py", "") - for base in os.listdir("dstroot/pythoncode/Developer/Panda3D/direct"): - if ((base != "extensions") and (base != "extensions_native")): - compileall.compile_dir("dstroot/pythoncode/Developer/Panda3D/direct/"+base) - - suffix = GetExtensionSuffix() - for base in os.listdir(GetOutputDir()+"/panda3d"): - if base.endswith('.py') or (base.endswith(suffix) and '.' not in base[:-len(suffix)]): - libname = "dstroot/pythoncode/Developer/Panda3D/panda3d/" + base - # We really need to specify -R in order not to follow symlinks - # On OSX, just specifying -P is not enough to do that. - oscmd("cp -R -P " + GetOutputDir() + "/panda3d/" + base + " " + libname) - - if not PkgSkip("FFMPEG"): - oscmd("mkdir -p dstroot/ffmpeg/Developer/Panda3D/lib") - oscmd("cp -R %s/lib/libp3ffmpeg.* dstroot/ffmpeg/Developer/Panda3D/lib/" % GetOutputDir()) - - #if not PkgSkip("OPENAL"): - # oscmd("mkdir -p dstroot/openal/Developer/Panda3D/lib") - # oscmd("cp -R %s/lib/libp3openal_audio.* dstroot/openal/Developer/Panda3D/lib/" % GetOutputDir()) - - if not PkgSkip("FMODEX"): - oscmd("mkdir -p dstroot/fmodex/Developer/Panda3D/lib") - oscmd("cp -R %s/lib/libp3fmod_audio.* dstroot/fmodex/Developer/Panda3D/lib/" % GetOutputDir()) - oscmd("cp -R %s/lib/libfmodex* dstroot/fmodex/Developer/Panda3D/lib/" % GetOutputDir()) - - oscmd("mkdir -p dstroot/headers/Developer/Panda3D/lib") - oscmd("cp -R %s/include dstroot/headers/Developer/Panda3D/include" % GetOutputDir()) - if os.path.isfile(GetOutputDir() + "/lib/libp3pystub.a"): - oscmd("cp -R -P %s/lib/libp3pystub.a dstroot/headers/Developer/Panda3D/lib/" % GetOutputDir()) - - if os.path.isdir("samples"): - oscmd("mkdir -p dstroot/samples/Developer/Examples/Panda3D") - oscmd("cp -R samples/* dstroot/samples/Developer/Examples/Panda3D/") - - oscmd("chmod -R 0775 dstroot/*") - DeleteVCS("dstroot") - DeleteBuildFiles("dstroot") - # We need to be root to perform a chown. Bleh. - # Fortunately PackageMaker does it for us, on 10.5 and above. - #oscmd("chown -R root:admin dstroot/*", True) - - oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/") - oscmd("mkdir -p dstroot/Panda3D/Panda3D.mpkg/Contents/Resources/en.lproj/") - - pkgs = ["base", "tools", "headers"] - if not PkgSkip("PYTHON"): pkgs.append("pythoncode") - if not PkgSkip("FFMPEG"): pkgs.append("ffmpeg") - #if not PkgSkip("OPENAL"): pkgs.append("openal") - if not PkgSkip("FMODEX"): pkgs.append("fmodex") - if os.path.isdir("samples"): pkgs.append("samples") - for pkg in pkgs: - identifier = "org.panda3d.panda3d.%s.pkg" % pkg - plist = open("/tmp/Info_plist", "w") - plist.write(Info_plist % { "package_id" : identifier, "version" : VERSION }) - plist.close() - if not os.path.isdir("dstroot/" + pkg): - os.makedirs("dstroot/" + pkg) - - if OSXTARGET and OSXTARGET <= (10, 5): - target = '--target %d.%d' % (OSXTARGET) - else: - target = '' - - if os.path.exists("/usr/bin/pkgbuild"): - # This new package builder is used in Lion and above. - cmd = '/usr/bin/pkgbuild --identifier ' + identifier + ' --version ' + VERSION + ' --root dstroot/' + pkg + '/ dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg' - - # In older versions, we use PackageMaker. Apple keeps changing its location. - elif os.path.exists("/Developer/usr/bin/packagemaker"): - cmd = '/Developer/usr/bin/packagemaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' - elif os.path.exists("/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"): - cmd = '/Applications/Xcode.app/Contents/Applications/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' - elif os.path.exists("/Developer/Tools/PackageMaker.app/Contents/MacOS/PackageMaker"): - cmd = '/Developer/Tools/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' - elif os.path.exists("/Developer/Tools/packagemaker"): - cmd = '/Developer/Tools/packagemaker -build -f dstroot/' + pkg + '/ -p dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg -i /tmp/Info_plist' - elif os.path.exists("/Applications/PackageMaker.app/Contents/MacOS/PackageMaker"): - cmd = '/Applications/PackageMaker.app/Contents/MacOS/PackageMaker --info /tmp/Info_plist --version ' + VERSION + ' --out dstroot/Panda3D/Panda3D.mpkg/Contents/Packages/' + pkg + '.pkg ' + target + ' --domain system --root dstroot/' + pkg + '/ --no-relocate' - else: - exit("Neither pkgbuild nor PackageMaker could be found!") - oscmd(cmd) - - if os.path.isfile("/tmp/Info_plist"): - oscmd("rm -f /tmp/Info_plist") - - # Now that we've built all of the individual packages, build the metapackage. - dist = open("dstroot/Panda3D/Panda3D.mpkg/Contents/distribution.dist", "w") - dist.write('\n') - dist.write('\n') - dist.write(' Panda3D SDK %s\n' % (VERSION)) - dist.write(' \n') - dist.write(' %s\n' % ReadFile("doc/LICENSE")) - dist.write(' \n') - for pkg in pkgs: - dist.write(' \n' % (pkg)) - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - - if not PkgSkip("PYTHON"): - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - - if not PkgSkip("FFMPEG"): - dist.write(' \n') - elif PkgSkip("VORBIS"): - dist.write(' It is not required for loading .wav or .opus files, which Panda3D can read out of the box.">\n') - elif PkgSkip("OPUS"): - dist.write(' It is not required for loading .wav or .ogg files, which Panda3D can read out of the box.">\n') - else: - dist.write(' It is not required for loading .wav, .ogg or .opus files, which Panda3D can read out of the box.">\n') - dist.write(' \n') - dist.write(' \n') - - #if not PkgSkip("OPENAL"): - # dist.write(' \n') - # dist.write(' \n') - # dist.write(' \n') - - if not PkgSkip("FMODEX"): - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - - if os.path.isdir("samples"): - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - - dist.write(' \n') - dist.write(' \n') - dist.write(' \n') - for pkg in pkgs: - size = GetDirectorySize("dstroot/" + pkg) // 1024 - dist.write(' file:./Contents/Packages/%s.pkg\n' % (pkg, size, pkg)) - dist.write('\n') - dist.close() - - oscmd('hdiutil create Panda3D-rw.dmg -volname "Panda3D SDK %s" -srcfolder dstroot/Panda3D' % (VERSION)) - oscmd('hdiutil convert Panda3D-rw.dmg -format UDBZ -o %s' % (dmg_name)) - oscmd('rm -f Panda3D-rw.dmg') - -def MakeInstallerFreeBSD(): - oscmd("rm -rf targetroot +DESC pkg-plist +MANIFEST") - oscmd("mkdir targetroot") - - # Invoke installpanda.py to install it into a temporary dir - if RUNTIME: - InstallRuntime(destdir = "targetroot", prefix = "/usr/local", outputdir = GetOutputDir()) - else: - InstallPanda(destdir = "targetroot", prefix = "/usr/local", outputdir = GetOutputDir()) - - if not os.path.exists("/usr/sbin/pkg"): - exit("Cannot create an installer without pkg") - - plist_txt = '' - for root, dirs, files in os.walk("targetroot/usr/local/", True): - for f in files: - plist_txt += os.path.join(root, f)[21:] + "\n" - - if not RUNTIME: - plist_txt += "@postexec /sbin/ldconfig -m /usr/local/lib/panda3d\n" - plist_txt += "@postunexec /sbin/ldconfig -R\n" - - for remdir in ("lib/panda3d", "share/panda3d", "include/panda3d"): - for root, dirs, files in os.walk("targetroot/usr/local/" + remdir, False): - for d in dirs: - plist_txt += "@dir %s\n" % os.path.join(root, d)[21:] - plist_txt += "@dir %s\n" % remdir - - oscmd("echo \"`pkg config abi | tr '[:upper:]' '[:lower:]' | cut -d: -f1,2`:*\" > " + GetOutputDir() + "/tmp/architecture.txt") - pkg_arch = ReadFile(GetOutputDir()+"/tmp/architecture.txt").strip() - - dependencies = '' - if PkgSkip("PYTHON") == 0: - # If this version of Python was installed from a package or ports, let's mark it as dependency. - oscmd("rm -f %s/tmp/python_dep" % GetOutputDir()) - oscmd("pkg query \"\n\t%%n : {\n\t\torigin : %%o,\n\t\tversion : %%v\n\t},\n\" python%s > %s/tmp/python_dep" % (SDK["PYTHONVERSION"][6:9:2], GetOutputDir()), True) - if os.path.isfile(GetOutputDir() + "/tmp/python_dep"): - python_pkg = ReadFile(GetOutputDir() + "/tmp/python_dep") - if python_pkg: - dependencies += python_pkg - - manifest_txt = INSTALLER_PKG_MANIFEST_FILE[1:].replace("NAME", 'panda3d' if not RUNTIME else 'panda3d-runtime') - manifest_txt = manifest_txt.replace("VERSION", VERSION) - manifest_txt = manifest_txt.replace("ARCH", pkg_arch) - manifest_txt = manifest_txt.replace("ORIGIN", 'devel/panda3d' if not RUNTIME else 'graphics/panda3d-runtime') - manifest_txt = manifest_txt.replace("DEPENDS", dependencies) - manifest_txt = manifest_txt.replace("INSTSIZE", str(GetDirectorySize("targetroot") / 1024 / 1024)) - - WriteFile("pkg-plist", plist_txt) - WriteFile("+DESC", INSTALLER_PKG_DESCR_FILE[1:] if not RUNTIME else RUNTIME_INSTALLER_PKG_DESCR_FILE[1:]) - WriteFile("+MANIFEST", manifest_txt) - oscmd("pkg create -p pkg-plist -r %s -m . -o . %s" % (os.path.abspath("targetroot"), "--verbose" if GetVerbose() else "--quiet")) - -def MakeInstallerAndroid(): - oscmd("rm -rf apkroot") - oscmd("mkdir apkroot") - - # Also remove the temporary apks. - apk_unaligned = os.path.join(GetOutputDir(), "tmp", "panda3d-unaligned.apk") - apk_unsigned = os.path.join(GetOutputDir(), "tmp", "panda3d-unsigned.apk") - if os.path.exists(apk_unaligned): - os.unlink(apk_unaligned) - if os.path.exists(apk_unsigned): - os.unlink(apk_unsigned) - - # Compile the Java classes into a Dalvik executable. - dx_cmd = "dx --dex --output=apkroot/classes.dex " - if GetOptimize() <= 2: - dx_cmd += "--debug " - if GetVerbose(): - dx_cmd += "--verbose " - if "ANDROID_API" in SDK: - dx_cmd += "--min-sdk-version=%d " % (SDK["ANDROID_API"]) - dx_cmd += os.path.join(GetOutputDir(), "classes") - oscmd(dx_cmd) - - # Copy the libraries one by one. In case of library dependencies, strip - # off any suffix (eg. libfile.so.1.0), as Android does not support them. - source_dir = os.path.join(GetOutputDir(), "lib") - target_dir = os.path.join("apkroot", "lib", SDK["ANDROID_ABI"]) - oscmd("mkdir -p %s" % (target_dir)) - - # Determine the library directories we should look in. - libpath = [source_dir] - for dir in os.environ.get("LD_LIBRARY_PATH", "").split(':'): - dir = os.path.expandvars(dir) - dir = os.path.expanduser(dir) - if os.path.isdir(dir): - dir = os.path.realpath(dir) - if not dir.startswith("/system") and not dir.startswith("/vendor"): - libpath.append(dir) - - def copy_library(source, base): - # Copy file to destination, stripping version suffix. - target = os.path.join(target_dir, base) - if not target.endswith('.so'): - target = target.rpartition('.so.')[0] + '.so' - - if os.path.isfile(target): - # Already processed. - return - - oscmd("cp %s %s" % (source, target)) - - # Walk through the library dependencies. - oscmd("ldd %s | grep .so > %s/tmp/otool-libs.txt" % (target, GetOutputDir()), True) - for line in open(GetOutputDir() + "/tmp/otool-libs.txt", "r"): - line = line.strip() - if not line: - continue - if '.so.' in line: - dep = line.rpartition('.so.')[0] + '.so' - oscmd("patchelf --replace-needed %s %s %s" % (line, dep, target), True) - else: - dep = line - - # Find it on the LD_LIBRARY_PATH. - for dir in libpath: - fulldep = os.path.join(dir, dep) - if os.path.isfile(fulldep): - copy_library(os.path.realpath(fulldep), dep) - break - - # Now copy every lib in the lib dir, and its dependencies. - for base in os.listdir(source_dir): - if not base.startswith('lib'): - continue - if not base.endswith('.so') and '.so.' not in base: - continue - - source = os.path.join(source_dir, base) - if os.path.islink(source): - continue - copy_library(source, base) - - # Same for Python extension modules. However, Android is strict about - # library naming, so we have a special naming scheme for these, in - # conjunction with a custom import hook to find these modules. - if not PkgSkip("PYTHON"): - suffix = GetExtensionSuffix() - source_dir = os.path.join(GetOutputDir(), "panda3d") - for base in os.listdir(source_dir): - if not base.endswith(suffix): - continue - modname = base[:-len(suffix)] - if '.' not in modname: - source = os.path.join(source_dir, base) - copy_library(source, "libpy.panda3d.{}.so".format(modname)) - - # Same for standard Python modules. - import _ctypes - source_dir = os.path.dirname(_ctypes.__file__) - for base in os.listdir(source_dir): - if not base.endswith('.so'): - continue - modname = base.partition('.')[0] - source = os.path.join(source_dir, base) - copy_library(source, "libpy.{}.so".format(modname)) - - def copy_python_tree(source_root, target_root): - for source_dir, dirs, files in os.walk(source_root): - if 'site-packages' in dirs: - dirs.remove('site-packages') - - if not any(base.endswith('.py') for base in files): - continue - - target_dir = os.path.join(target_root, os.path.relpath(source_dir, source_root)) - target_dir = os.path.normpath(target_dir) - os.makedirs(target_dir, 0o755) - - for base in files: - if base.endswith('.py'): - target = os.path.join(target_dir, base) - shutil.copy(os.path.join(source_dir, base), target) - - # Copy the Python standard library to the .apk as well. - from distutils.sysconfig import get_python_lib - stdlib_source = get_python_lib(False, True) - stdlib_target = os.path.join("apkroot", "lib", "python{0}.{1}".format(*sys.version_info)) - copy_python_tree(stdlib_source, stdlib_target) - - # But also copy over our custom site.py. - shutil.copy("panda/src/android/site.py", os.path.join(stdlib_target, "site.py")) - - # And now make a site-packages directory containing our direct/panda3d/pandac modules. - for tree in "panda3d", "direct", "pandac": - copy_python_tree(os.path.join(GetOutputDir(), tree), os.path.join(stdlib_target, "site-packages", tree)) - - # Copy the models and config files to the virtual assets filesystem. - oscmd("mkdir apkroot/assets") - oscmd("cp -R %s apkroot/assets/models" % (os.path.join(GetOutputDir(), "models"))) - oscmd("cp -R %s apkroot/assets/etc" % (os.path.join(GetOutputDir(), "etc"))) - - # Make an empty res folder. It's needed for the apk to be installable, apparently. - oscmd("mkdir apkroot/res") - - # Now package up the application - oscmd("cp panda/src/android/pview_manifest.xml apkroot/AndroidManifest.xml") - aapt_cmd = "aapt package" - aapt_cmd += " -F %s" % (apk_unaligned) - aapt_cmd += " -M apkroot/AndroidManifest.xml" - aapt_cmd += " -A apkroot/assets -S apkroot/res" - aapt_cmd += " -I $PREFIX/share/aapt/android.jar" - oscmd(aapt_cmd) - - # And add all the libraries to it. - oscmd("cd apkroot && aapt add ../%s classes.dex" % (apk_unaligned)) - for path, dirs, files in os.walk('apkroot/lib'): - if files: - rel = os.path.relpath(path, 'apkroot') - oscmd("cd apkroot && aapt add ../%s %s/*" % (apk_unaligned, rel)) - - # Now align the .apk, which is necessary for Android to load it. - oscmd("zipalign -v -p 4 %s %s" % (apk_unaligned, apk_unsigned)) - - # Finally, sign it using a debug key. This is generated if it doesn't exist. - oscmd("apksigner debug.ks %s panda3d.apk" % (apk_unsigned)) - - # Clean up. - oscmd("rm -rf apkroot") - os.unlink(apk_unaligned) - os.unlink(apk_unsigned) - -try: - if INSTALLER: - ProgressOutput(100.0, "Building installer") - target = GetTarget() - if target == 'windows': - fn = "Panda3D-" - dir = "Panda3D-" + VERSION - - if RUNTIME: - fn += "Runtime-" - title = "Panda3D " + VERSION - else: - title = "Panda3D SDK " + VERSION - - fn += VERSION - - if not RUNTIME and SDK["PYTHONVERSION"] != "python2.7": - fn += '-py' + SDK["PYTHONVERSION"][6:] - - if GetOptimize() <= 2: - fn += "-dbg" - if GetTargetArch() == 'x64': - fn += '-x64' - dir += '-x64' - - MakeInstallerNSIS(fn + '.exe', title, 'C:\\' + dir) - if not RUNTIME: - MakeDebugSymbolArchive(fn + '-pdb.zip', dir) - elif (target == 'linux'): - MakeInstallerLinux() - elif (target == 'darwin'): - MakeInstallerOSX() - elif (target == 'freebsd'): - MakeInstallerFreeBSD() - elif (target == 'android'): - MakeInstallerAndroid() - else: - exit("Do not know how to make an installer for this platform") - - if WHEEL: - ProgressOutput(100.0, "Building wheel") - from makewheel import makewheel - makewheel(WHLVERSION, GetOutputDir()) -finally: - SaveDependencyCache() +if INSTALLER: + ProgressOutput(100.0, "Building installer") + from makepackage import MakeInstaller + MakeInstaller(version=VERSION, outputdir=GetOutputDir(), + optimize=GetOptimize(), compressor=COMPRESSOR, + debversion=DEBVERSION, rpmrelease=RPMRELEASE, + runtime=RUNTIME) + +if WHEEL: + ProgressOutput(100.0, "Building wheel") + from makewheel import makewheel + makewheel(WHLVERSION, GetOutputDir()) ########################################################################################## # From 68b798655727d1f49582b431a01fcfb7d0f98529 Mon Sep 17 00:00:00 2001 From: loblao <12ksit@gmail.com> Date: Sun, 9 Dec 2018 14:09:30 -0200 Subject: [PATCH 14/16] NodePath: Implement replace_material Closes #472 --- panda/src/pgraph/nodePath.cxx | 60 +++++++++++++++++++++++++++++++++++ panda/src/pgraph/nodePath.h | 3 ++ 2 files changed, 63 insertions(+) diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 9d473304b6..1832e18e5a 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -4163,6 +4163,20 @@ get_material() const { return nullptr; } +/** + * Recursively searches the scene graph for references to the given material, + * and replaces them with the new material. + */ +void NodePath:: +replace_material(Material *mat, Material *new_mat) { + nassertv_always(!is_empty()); + nassertv(mat != nullptr); + nassertv(new_mat != nullptr); + + CPT(RenderAttrib) new_attrib = MaterialAttrib::make(new_mat); + r_replace_material(node(), mat, (const MaterialAttrib *)new_attrib.p()); +} + /** * Sets the geometry at this level and below to render using the indicated * fog. @@ -6632,6 +6646,52 @@ r_find_all_materials(PandaNode *node, const RenderState *state, } } +/** + * + */ +void NodePath:: +r_replace_material(PandaNode *node, Material *mat, + const MaterialAttrib *new_attrib) { + // Consider the state of the node itself. + { + CPT(RenderState) node_state = node->get_state(); + const MaterialAttrib *ma; + if (node_state->get_attrib(ma)) { + if (mat == ma->get_material()) { + node->set_state(node_state->set_attrib(new_attrib)); + } + } + } + + // If this is a GeomNode, consider the state of any of its Geoms. + if (node->is_geom_node()) { + GeomNode *gnode; + DCAST_INTO_V(gnode, node); + + int num_geoms = gnode->get_num_geoms(); + for (int i = 0; i < num_geoms; i++) { + CPT(RenderState) geom_state = gnode->get_geom_state(i); + + // Look for a MaterialAttrib on the state. + const MaterialAttrib *ma; + if (geom_state->get_attrib(ma)) { + if (mat == ma->get_material()) { + // Replace it + gnode->set_geom_state(i, geom_state->set_attrib(new_attrib)); + } + } + } + } + + // Now consider children. + PandaNode::Children cr = node->get_children(); + size_t num_children = cr.get_num_children(); + for (size_t i = 0; i < num_children; ++i) { + PandaNode *child = cr.get_child(i); + r_replace_material(child, mat, new_attrib); + } +} + /** * Writes the contents of this object to the datagram for shipping out to a * Bam file. diff --git a/panda/src/pgraph/nodePath.h b/panda/src/pgraph/nodePath.h index 9c047c0728..3d5d4a6aa3 100644 --- a/panda/src/pgraph/nodePath.h +++ b/panda/src/pgraph/nodePath.h @@ -771,6 +771,7 @@ PUBLISHED: void clear_material(); bool has_material() const; PT(Material) get_material() const; + void replace_material(Material *mat, Material *new_mat); void set_fog(Fog *fog, int priority = 0); void set_fog_off(int priority = 0); @@ -1016,6 +1017,8 @@ private: const GlobPattern &glob) const; void r_find_all_materials(PandaNode *node, const RenderState *state, Materials &materials) const; + static void r_replace_material(PandaNode *node, Material *mat, + const MaterialAttrib *new_attrib); PT(NodePathComponent) _head; int _backup_key; From b5b77e59568eead1eee5b2407f124b432f91d7f3 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Dec 2018 20:16:55 +0100 Subject: [PATCH 15/16] pgraph: fix issues with serializing empty NodePaths --- panda/src/pgraph/config_pgraph.cxx | 1 + panda/src/pgraph/nodePath.cxx | 9 +++++++- tests/pgraph/test_nodepath.py | 34 ++++++++++++++++++++++++++---- 3 files changed, 39 insertions(+), 5 deletions(-) diff --git a/panda/src/pgraph/config_pgraph.cxx b/panda/src/pgraph/config_pgraph.cxx index e969dee72f..5729e22067 100644 --- a/panda/src/pgraph/config_pgraph.cxx +++ b/panda/src/pgraph/config_pgraph.cxx @@ -492,6 +492,7 @@ init_libpgraph() { ModelNode::register_with_read_factory(); ModelRoot::register_with_read_factory(); PandaNode::register_with_read_factory(); + ParamNodePath::register_with_read_factory(); PlaneNode::register_with_read_factory(); PolylightNode::register_with_read_factory(); PortalNode::register_with_read_factory(); diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index 1832e18e5a..8732168212 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -5691,7 +5691,9 @@ encode_to_bam_stream(vector_uchar &data, BamWriter *writer) const { // Tell the BamWriter which node is the root node, for making NodePaths // relative to when writing them out to the file. - writer->set_root_node(node()); + if (!is_empty()) { + writer->set_root_node(node()); + } // Write an initial Datagram to represent the error type and number of // nodes. @@ -6698,6 +6700,11 @@ r_replace_material(PandaNode *node, Material *mat, */ void NodePath:: write_datagram(BamWriter *manager, Datagram &dg) const { + if (is_empty()) { + manager->write_pointer(dg, nullptr); + return; + } + PandaNode *root = DCAST(PandaNode, manager->get_root_node()); // We have no root node to measure from. diff --git a/tests/pgraph/test_nodepath.py b/tests/pgraph/test_nodepath.py index 1b98da32d7..19a40021ca 100644 --- a/tests/pgraph/test_nodepath.py +++ b/tests/pgraph/test_nodepath.py @@ -2,13 +2,39 @@ import pytest, sys def test_nodepath_empty(): """Tests NodePath behavior for empty NodePaths.""" + from panda3d.core import NodePath, ParamNodePath + import pickle + + empty = NodePath() + assert empty.is_empty() + assert not empty + + # Try pickling, which uses __reduce__ + dumped = pickle.dumps(empty) + empty2 = pickle.loads(dumped) + assert empty2.is_empty() + assert not empty2 + assert empty == empty2 + + # Test write_datagram/fillin, which are invoked when the NodePath is being + # serialized indirectly, such as via ParamNodePath + dumped = pickle.dumps(ParamNodePath(empty)) + empty2 = pickle.loads(dumped).get_value() + assert empty2.is_empty() + assert not empty2 + assert empty == empty2 + +def test_nodepath_single(): + """Tests NodePath behavior for single-node NodePaths.""" from panda3d.core import NodePath - empty = NodePath('np') + np = NodePath('np') + assert not np.is_empty() + assert np - assert empty.get_pos() == (0, 0, 0) - assert empty.get_hpr() == (0, 0, 0) - assert empty.get_scale() == (1, 1, 1) + assert np.get_pos() == (0, 0, 0) + assert np.get_hpr() == (0, 0, 0) + assert np.get_scale() == (1, 1, 1) def test_nodepath_parent(): """Tests NodePath.reparentTo().""" From a17ac6516c36a25d28d940cc13bcf9c1480f20f7 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 9 Dec 2018 20:19:40 +0100 Subject: [PATCH 16/16] pgraph: fix regression in 89236ac1360e5f0249d425e61d537deef40e71c3 --- panda/src/pgraph/billboardEffect.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/pgraph/billboardEffect.cxx b/panda/src/pgraph/billboardEffect.cxx index 60c6e72c97..d6319021f1 100644 --- a/panda/src/pgraph/billboardEffect.cxx +++ b/panda/src/pgraph/billboardEffect.cxx @@ -374,6 +374,6 @@ fillin(DatagramIterator &scan, BamReader *manager) { if (manager->get_file_minor_ver() >= 43) { _look_at.fillin(scan, manager); - _fixed_depth = scan.get_stdfloat(); + _fixed_depth = scan.get_bool(); } }