From a05405c4752c084c91bb86df6c43c1bfa31c4ee4 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 21 Feb 2021 10:15:33 +0100 Subject: [PATCH 1/7] pgraph: API reference improvements for NodePath --- panda/src/pgraph/nodePath.I | 26 ++++++++++++++++------- panda/src/pgraph/nodePath.cxx | 40 +++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/panda/src/pgraph/nodePath.I b/panda/src/pgraph/nodePath.I index 1e0c6b3ab0..0034b2a8d7 100644 --- a/panda/src/pgraph/nodePath.I +++ b/panda/src/pgraph/nodePath.I @@ -998,7 +998,8 @@ compose_color_scale(PN_stdfloat sr, PN_stdfloat sg, PN_stdfloat sb, PN_stdfloat } /** - * Sets the red scale component of the transform + * Sets the red component of the color scale. + * @see set_color_scale() */ INLINE void NodePath:: set_sr(PN_stdfloat sr) { @@ -1009,7 +1010,8 @@ set_sr(PN_stdfloat sr) { } /** - * Sets the alpha scale component of the transform + * Sets the green component of the color scale. + * @see set_color_scale() */ INLINE void NodePath:: set_sg(PN_stdfloat sg) { @@ -1020,7 +1022,8 @@ set_sg(PN_stdfloat sg) { } /** - * Sets the blue scale component of the transform + * Sets the blue component of the color scale. + * @see set_color_scale() */ INLINE void NodePath:: set_sb(PN_stdfloat sb) { @@ -1031,7 +1034,8 @@ set_sb(PN_stdfloat sb) { } /** - * Sets the alpha scale component of the transform + * Sets the alpha component of the color scale. + * @see set_color_scale() */ INLINE void NodePath:: set_sa(PN_stdfloat sa) { @@ -1042,7 +1046,8 @@ set_sa(PN_stdfloat sa) { } /** - * Gets the red scale component of the transform + * Gets the red component of the color scale. + * @see get_color_scale() */ INLINE PN_stdfloat NodePath:: get_sr() const { @@ -1050,7 +1055,8 @@ get_sr() const { } /** - * Gets the green scale component of the transform + * Gets the green component of the color scale. + * @see get_color_scale() */ INLINE PN_stdfloat NodePath:: get_sg() const { @@ -1058,7 +1064,8 @@ get_sg() const { } /** - * Gets the blue scale component of the transform + * Gets the blue component of the color scale. + * @see get_color_scale() */ INLINE PN_stdfloat NodePath:: get_sb() const { @@ -1066,7 +1073,8 @@ get_sb() const { } /** - * Gets the alpha scale component of the transform + * Gets the alpha component of the color scale. + * @see get_color_scale() */ INLINE PN_stdfloat NodePath:: get_sa() const { @@ -1838,6 +1846,8 @@ show_through(DrawMask camera_mask) { * invisible to all cameras. It remains part of the scene graph, its bounding * volume still contributes to its parent's bounding volume, and it will still * be involved in collision tests. + * + * To undo this, call show(). */ INLINE void NodePath:: hide() { diff --git a/panda/src/pgraph/nodePath.cxx b/panda/src/pgraph/nodePath.cxx index f955b9c380..5c7dbbbdaf 100644 --- a/panda/src/pgraph/nodePath.cxx +++ b/panda/src/pgraph/nodePath.cxx @@ -959,6 +959,11 @@ set_pos(const LVecBase3 &pos) { node()->reset_prev_transform(); } +/** + * Sets the X component of the position transform, leaving other components + * untouched. + * @see set_pos() + */ void NodePath:: set_x(PN_stdfloat x) { nassertv_always(!is_empty()); @@ -967,6 +972,11 @@ set_x(PN_stdfloat x) { set_pos(pos); } +/** + * Sets the Y component of the position transform, leaving other components + * untouched. + * @see set_pos() + */ void NodePath:: set_y(PN_stdfloat y) { nassertv_always(!is_empty()); @@ -975,6 +985,11 @@ set_y(PN_stdfloat y) { set_pos(pos); } +/** + * Sets the Z component of the position transform, leaving other components + * untouched. + * @see set_pos() + */ void NodePath:: set_z(PN_stdfloat z) { nassertv_always(!is_empty()); @@ -1127,6 +1142,11 @@ set_scale(const LVecBase3 &scale) { set_transform(transform->set_scale(scale)); } +/** + * Sets the x-scale component of the transform, leaving other components + * untouched. + * @see set_scale() + */ void NodePath:: set_sx(PN_stdfloat sx) { nassertv_always(!is_empty()); @@ -1136,6 +1156,11 @@ set_sx(PN_stdfloat sx) { set_transform(transform->set_scale(scale)); } +/** + * Sets the y-scale component of the transform, leaving other components + * untouched. + * @see set_scale() + */ void NodePath:: set_sy(PN_stdfloat sy) { nassertv_always(!is_empty()); @@ -1145,6 +1170,11 @@ set_sy(PN_stdfloat sy) { set_transform(transform->set_scale(scale)); } +/** + * Sets the z-scale component of the transform, leaving other components + * untouched. + * @see set_scale() + */ void NodePath:: set_sz(PN_stdfloat sz) { nassertv_always(!is_empty()); @@ -4214,6 +4244,8 @@ get_material() const { /** * Recursively searches the scene graph for references to the given material, * and replaces them with the new material. + * + * @since 1.10.0 */ void NodePath:: replace_material(Material *mat, Material *new_mat) { @@ -4936,6 +4968,8 @@ get_transparency() const { * Specifically sets or disables a logical operation on this particular node. * If no other nodes override, this will cause geometry to be rendered without * color blending but instead using the given logical operator. + * + * @since 1.10.0 */ void NodePath:: set_logic_op(LogicOpAttrib::Operation op, int priority) { @@ -4948,6 +4982,8 @@ set_logic_op(LogicOpAttrib::Operation op, int priority) { * Completely removes any logical operation that may have been set on this * node via set_logic_op(). The geometry at this level and below will * subsequently be rendered using standard color blending. + * + * @since 1.10.0 */ void NodePath:: clear_logic_op() { @@ -4960,6 +4996,8 @@ clear_logic_op() { * particular node via set_logic_op(). If this returns true, then * get_logic_op() may be called to determine whether a logical operation has * been explicitly disabled for this node or set to particular operation. + * + * @since 1.10.0 */ bool NodePath:: has_logic_op() const { @@ -4974,6 +5012,8 @@ has_logic_op() const { * has_logic_op(). This does not necessarily imply that the geometry will * or will not be rendered with the given logical operation, as there may be * other nodes that override. + * + * @since 1.10.0 */ LogicOpAttrib::Operation NodePath:: get_logic_op() const { From 5c4909b4ab28b8243a0c301cde44bdc34118b0b9 Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 21 Feb 2021 10:15:54 +0100 Subject: [PATCH 2/7] pgui: Some code cleanup for PGItem --- panda/src/pgui/pgItem.cxx | 49 +++++++++++++------------------- panda/src/pgui/pgScrollFrame.cxx | 3 +- panda/src/pgui/pgSliderBar.cxx | 3 +- 3 files changed, 21 insertions(+), 34 deletions(-) diff --git a/panda/src/pgui/pgItem.cxx b/panda/src/pgui/pgItem.cxx index aeff5bff25..6f023b8647 100644 --- a/panda/src/pgui/pgItem.cxx +++ b/panda/src/pgui/pgItem.cxx @@ -347,9 +347,8 @@ void PGItem:: r_prepare_scene(GraphicsStateGuardianBase *gsg, const RenderState *node_state, GeomTransformer &transformer, Thread *current_thread) { LightReMutexHolder holder(_lock); - StateDefs::iterator di; - for (di = _state_defs.begin(); di != _state_defs.end(); ++di) { - NodePath &root = (*di)._root; + for (StateDef &def : _state_defs) { + NodePath &root = def._root; if (!root.is_empty()) { PandaNode *child = root.node(); CPT(RenderState) child_state = node_state->compose(child->get_state()); @@ -375,9 +374,8 @@ xform(const LMatrix4 &mat) { _frame.set(ll[0], ur[0], ll[2], ur[2]); // Transform the individual states and their frame styles. - StateDefs::iterator di; - for (di = _state_defs.begin(); di != _state_defs.end(); ++di) { - NodePath &root = (*di)._root; + for (StateDef &def : _state_defs) { + NodePath &root = def._root; // Apply the matrix to the previous transform. root.set_transform(root.get_transform()->compose(TransformState::make_mat(mat))); @@ -386,8 +384,8 @@ xform(const LMatrix4 &mat) { gr.apply_attribs(root.node()); // Transform the frame style too. - if ((*di)._frame_style.xform(mat)) { - (*di)._frame_stale = true; + if (def._frame_style.xform(mat)) { + def._frame_stale = true; } } mark_internal_bounds_stale(); @@ -767,9 +765,7 @@ move(const MouseWatcherParameter ¶m) { */ void PGItem:: background_press(const MouseWatcherParameter ¶m) { - BackgroundFocus::const_iterator fi; - for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) { - PGItem *item = *fi; + for (PGItem *item : _background_focus) { if (!item->get_focus()) { item->press(param, true); } @@ -781,9 +777,7 @@ background_press(const MouseWatcherParameter ¶m) { */ void PGItem:: background_release(const MouseWatcherParameter ¶m) { - BackgroundFocus::const_iterator fi; - for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) { - PGItem *item = *fi; + for (PGItem *item : _background_focus) { if (!item->get_focus()) { item->release(param, true); } @@ -795,9 +789,7 @@ background_release(const MouseWatcherParameter ¶m) { */ void PGItem:: background_keystroke(const MouseWatcherParameter ¶m) { - BackgroundFocus::const_iterator fi; - for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) { - PGItem *item = *fi; + for (PGItem *item : _background_focus) { if (!item->get_focus()) { item->keystroke(param, true); } @@ -809,9 +801,7 @@ background_keystroke(const MouseWatcherParameter ¶m) { */ void PGItem:: background_candidate(const MouseWatcherParameter ¶m) { - BackgroundFocus::const_iterator fi; - for (fi = _background_focus.begin(); fi != _background_focus.end(); ++fi) { - PGItem *item = *fi; + for (PGItem *item : _background_focus) { if (!item->get_focus()) { item->candidate(param, true); } @@ -1165,11 +1155,10 @@ mouse_to_local(const LPoint2 &mouse_point) const { } /** - * Called when the user changes the frame size. + * Called when the user changes the frame size. Assumes the lock is held. */ void PGItem:: frame_changed() { - LightReMutexHolder holder(_lock); mark_frames_stale(); if (_notify != nullptr) { _notify->item_frame_changed(this); @@ -1202,6 +1191,7 @@ do_get_state_def(int state) { /** * Ensures there is a slot in the array for the given state definition. + * Assumes the lock is already held. */ void PGItem:: slot_state_def(int state) { @@ -1212,6 +1202,7 @@ slot_state_def(int state) { /** * Generates a new instance of the frame geometry for the indicated state. + * Assumes the lock is already held. */ void PGItem:: update_frame(int state) { @@ -1234,15 +1225,14 @@ update_frame(int state) { /** * Marks all the frames in all states stale, so that they will be regenerated - * the next time each state is requested. + * the next time each state is requested. Assumes the lock is already held. */ void PGItem:: mark_frames_stale() { - StateDefs::iterator di; - for (di = _state_defs.begin(); di != _state_defs.end(); ++di) { + for (StateDef &def : _state_defs) { // Remove the old frame, if any. - (*di)._frame.remove_node(); - (*di)._frame_stale = true; + def._frame.remove_node(); + def._frame_stale = true; } mark_internal_bounds_stale(); } @@ -1294,9 +1284,8 @@ clip_frame(ClipPoints &source_points, const LPlane &plane) const { LPoint2 last_point(source_points.back()); bool last_is_in = is_right(last_point - from2d, delta2d); bool all_in = last_is_in; - ClipPoints::const_iterator pi; - for (pi = source_points.begin(); pi != source_points.end(); ++pi) { - LPoint2 this_point(*pi); + + for (LPoint2 this_point : source_points) { bool this_is_in = is_right(this_point - from2d, delta2d); // There appears to be a compiler bug in gcc 4.0: we need to extract this diff --git a/panda/src/pgui/pgScrollFrame.cxx b/panda/src/pgui/pgScrollFrame.cxx index 9631f66685..60920b88f8 100644 --- a/panda/src/pgui/pgScrollFrame.cxx +++ b/panda/src/pgui/pgScrollFrame.cxx @@ -284,11 +284,10 @@ remanage() { } /** - * Called when the user changes the frame size. + * Called when the user changes the frame size. Assumes the lock is held. */ void PGScrollFrame:: frame_changed() { - LightReMutexHolder holder(_lock); PGVirtualFrame::frame_changed(); _needs_remanage = true; _needs_recompute_clip = true; diff --git a/panda/src/pgui/pgSliderBar.cxx b/panda/src/pgui/pgSliderBar.cxx index e085f0f91d..e666d2a496 100644 --- a/panda/src/pgui/pgSliderBar.cxx +++ b/panda/src/pgui/pgSliderBar.cxx @@ -551,11 +551,10 @@ recompute() { } /** - * Called when the user changes the frame size. + * Called when the user changes the frame size. Assumes the lock is held. */ void PGSliderBar:: frame_changed() { - LightReMutexHolder holder(_lock); PGItem::frame_changed(); _needs_remanage = true; _needs_recompute = true; From f2e488fd6b39a6fca54c0be79378955157a266de Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 21 Feb 2021 11:00:22 +0100 Subject: [PATCH 3/7] pgui: Workaround for text disappearing in multithreaded pipeline The text could appear from a DirectButton or other GUI element if updating eg. the text_fg property. --- panda/src/pgui/pgItem.cxx | 69 ++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 12 deletions(-) diff --git a/panda/src/pgui/pgItem.cxx b/panda/src/pgui/pgItem.cxx index 6f023b8647..663522204a 100644 --- a/panda/src/pgui/pgItem.cxx +++ b/panda/src/pgui/pgItem.cxx @@ -124,6 +124,13 @@ PGItem(const PGItem ©) : new_sd._frame_style = old_sd._frame_style; _state_defs.push_back(new_sd); + +#ifdef THREADED_PIPELINE + if (Pipeline::get_render_pipeline()->get_num_stages() > 1) { + ((PGItem &)copy).update_frame((int)i); + update_frame((int)i); + } +#endif } } @@ -199,8 +206,10 @@ cull_callback(CullTraverser *trav, CullTraverserData &data) { if (state >= 0 && (size_t)state < _state_defs.size()) { StateDef &state_def = _state_defs[state]; if (!state_def._root.is_empty()) { - if (state_def._frame_stale) { - update_frame(state); + if (Thread::get_current_pipeline_stage() == 0) { + if (state_def._frame_stale) { + update_frame(state); + } } state_def_root = state_def._root.node(); @@ -374,7 +383,8 @@ xform(const LMatrix4 &mat) { _frame.set(ll[0], ur[0], ll[2], ur[2]); // Transform the individual states and their frame styles. - for (StateDef &def : _state_defs) { + for (size_t state = 0; state < _state_defs.size(); ++state) { + StateDef &def = _state_defs[state]; NodePath &root = def._root; // Apply the matrix to the previous transform. root.set_transform(root.get_transform()->compose(TransformState::make_mat(mat))); @@ -385,7 +395,15 @@ xform(const LMatrix4 &mat) { // Transform the frame style too. if (def._frame_style.xform(mat)) { - def._frame_stale = true; +#ifdef THREADED_PIPELINE + if (Pipeline::get_render_pipeline()->get_num_stages() > 1) { + update_frame((int)state); + } + else +#endif + { + def._frame_stale = true; + } } } mark_internal_bounds_stale(); @@ -942,6 +960,12 @@ clear_state_def(int state) { _state_defs[state]._frame_stale = true; mark_internal_bounds_stale(); + +#ifdef THREADED_PIPELINE + if (Pipeline::get_render_pipeline()->get_num_stages() > 1) { + update_frame(state); + } +#endif } /** @@ -981,15 +1005,24 @@ get_frame_style(int state) { void PGItem:: set_frame_style(int state, const PGFrameStyle &style) { LightReMutexHolder holder(_lock); - // Get the state def node, mainly to ensure that this state is slotted and - // listed as having been defined. - NodePath &root = do_get_state_def(state); - nassertv(!root.is_empty()); + + slot_state_def(state); + + if (_state_defs[state]._root.is_empty()) { + // Create a new node. + _state_defs[state]._root = NodePath("state_" + format_string(state)); + } _state_defs[state]._frame_style = style; _state_defs[state]._frame_stale = true; mark_internal_bounds_stale(); + +#ifdef THREADED_PIPELINE + if (Pipeline::get_render_pipeline()->get_num_stages() > 1) { + update_frame(state); + } +#endif } #ifdef HAVE_AUDIO @@ -1229,10 +1262,22 @@ update_frame(int state) { */ void PGItem:: mark_frames_stale() { - for (StateDef &def : _state_defs) { - // Remove the old frame, if any. - def._frame.remove_node(); - def._frame_stale = true; +#ifdef THREADED_PIPELINE + // If we are using the threaded pipeline, we must update the frame geometry + // immediately on the App thread, since this class isn't pipeline-cycled. + if (Pipeline::get_render_pipeline()->get_num_stages() > 1) { + for (int state = 0; state < (int)_state_defs.size(); ++state) { + update_frame(state); + } + } + else +#endif + { + for (StateDef &def : _state_defs) { + // Remove the old frame, if any. + def._frame.remove_node(); + def._frame_stale = true; + } } mark_internal_bounds_stale(); } From b1dbd0fa9cb2b07015cb1b786d9819abd9b1c116 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 22 Feb 2021 10:57:50 +0100 Subject: [PATCH 4/7] Update BACKERS.md [skip ci] --- BACKERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/BACKERS.md b/BACKERS.md index 7f34cbabbe..1c5a10d555 100644 --- a/BACKERS.md +++ b/BACKERS.md @@ -32,6 +32,7 @@ This is a list of all the people who are contributing financially to Panda3D. I * Eric Thomson * Kyle Roach * Brian Lach +* C0MPU73R ## Backers From 18cb4a7ccc20ee9e46c52f5d332149c2b89afa1e Mon Sep 17 00:00:00 2001 From: rdb Date: Sun, 21 Feb 2021 12:14:36 +0100 Subject: [PATCH 5/7] vorbis: Disable cross-lapped seeking by default, to reduce clicking Fixes #1108 --- panda/src/movies/config_movies.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda/src/movies/config_movies.cxx b/panda/src/movies/config_movies.cxx index f6e889b6e8..ae93590c42 100644 --- a/panda/src/movies/config_movies.cxx +++ b/panda/src/movies/config_movies.cxx @@ -68,7 +68,7 @@ ConfigVariableBool vorbis_enable_seek "using the Ogg Vorbis decoder.")); ConfigVariableBool vorbis_seek_lap -("vorbis-seek-lap", true, +("vorbis-seek-lap", false, PRC_DESC("If this is set to true, the Ogg Vorbis decoder will automatically " "crosslap the transition from the previous playback position into " "the new playback position when seeking in order to eliminate " From 601ca323f58a08b8b4fa953a5118a646cc5f0628 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 22 Feb 2021 18:13:34 +0100 Subject: [PATCH 6/7] interrogate: Support __truediv__, __floordiv__, etc. special methods --- .../interfaceMakerPythonNative.cxx | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index 18cbc3a22a..788ba7fa42 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -333,6 +333,18 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, return true; } + if (method_name == "__truediv__") { + def._answer_location = "nb_true_divide"; + def._wrapper_type = WT_binary_operator; + return true; + } + + if (method_name == "__floordiv__") { + def._answer_location = "nb_floor_divide"; + def._wrapper_type = WT_binary_operator; + return true; + } + if (method_name == "operator %") { def._answer_location = "nb_remainder"; def._wrapper_type = WT_binary_operator; @@ -405,6 +417,18 @@ get_slotted_function_def(Object *obj, Function *func, FunctionRemap *remap, return true; } + if (method_name == "__itruediv__") { + def._answer_location = "nb_inplace_true_divide"; + def._wrapper_type = WT_binary_operator; + return true; + } + + if (method_name == "__ifloordiv__") { + def._answer_location = "nb_inplace_floor_divide"; + def._wrapper_type = WT_binary_operator; + return true; + } + if (method_name == "operator %=") { def._answer_location = "nb_inplace_remainder"; def._wrapper_type = WT_inplace_binary_operator; From 9d9337dc4d349825ee45008c440c27add9469399 Mon Sep 17 00:00:00 2001 From: rdb Date: Mon, 22 Feb 2021 18:14:12 +0100 Subject: [PATCH 7/7] dtoolutil: Fix Filename division operator in Python 3 --- dtool/src/dtoolutil/filename.h | 1 + dtool/src/dtoolutil/filename_ext.cxx | 9 +++++++++ dtool/src/dtoolutil/filename_ext.h | 3 +++ 3 files changed, 13 insertions(+) diff --git a/dtool/src/dtoolutil/filename.h b/dtool/src/dtoolutil/filename.h index 66b38356a6..99d94af5a6 100644 --- a/dtool/src/dtoolutil/filename.h +++ b/dtool/src/dtoolutil/filename.h @@ -122,6 +122,7 @@ PUBLISHED: INLINE Filename operator + (const std::string &other) const; INLINE Filename operator / (const Filename &other) const; + EXTENSION(Filename __truediv__(const Filename &other) const); // Or, you can use any of these. INLINE std::string get_fullpath() const; diff --git a/dtool/src/dtoolutil/filename_ext.cxx b/dtool/src/dtoolutil/filename_ext.cxx index e60bf83a90..c7b7e30606 100644 --- a/dtool/src/dtoolutil/filename_ext.cxx +++ b/dtool/src/dtoolutil/filename_ext.cxx @@ -184,6 +184,15 @@ __fspath__() const { return PyUnicode_FromWideChar(filename.data(), (Py_ssize_t)filename.size()); } +/** + * Returns a new Filename that is composed of the other filename added to the + * end of this filename, with an intervening slash added if necessary. + */ +Filename Extension:: +__truediv__(const Filename &other) const { + return Filename(*_this, other); +} + /** * This variant on scan_directory returns a Python list of strings on success, * or None on failure. diff --git a/dtool/src/dtoolutil/filename_ext.h b/dtool/src/dtoolutil/filename_ext.h index 1ebeaacc52..6567d0995f 100644 --- a/dtool/src/dtoolutil/filename_ext.h +++ b/dtool/src/dtoolutil/filename_ext.h @@ -34,6 +34,9 @@ public: PyObject *__reduce__(PyObject *self) const; PyObject *__repr__() const; PyObject *__fspath__() const; + + Filename __truediv__(const Filename &other) const; + PyObject *scan_directory() const; };