diff --git a/direct/src/dist/commands.py b/direct/src/dist/commands.py index 644b3774c6..1b70a70268 100644 --- a/direct/src/dist/commands.py +++ b/direct/src/dist/commands.py @@ -270,6 +270,7 @@ class build_apps(setuptools.Command): 'libbz2.so.*', 'libz.so.*', 'liblzma.so.*', 'librt.so.*', 'libutil.so.*', # macOS + '/usr/lib/libc++.1.dylib', '/usr/lib/libstdc++.*.dylib', '/usr/lib/libz.*.dylib', '/usr/lib/libobjc.*.dylib', diff --git a/direct/src/showbase/Audio3DManager.py b/direct/src/showbase/Audio3DManager.py index e0f38c1d2a..78389c63ba 100644 --- a/direct/src/showbase/Audio3DManager.py +++ b/direct/src/showbase/Audio3DManager.py @@ -35,7 +35,7 @@ class Audio3DManager: def setDistanceFactor(self, factor): """ Control the scale that sets the distance units for 3D spacialized audio. - Default is 1.0 which is adjust in panda to be feet. + Default is 1.0 which is adjust in panda to be meters. When you change this, don't forget that this effects the scale of setSoundMinDistance """ self.audio_manager.audio3dSetDistanceFactor(factor) @@ -43,7 +43,7 @@ class Audio3DManager: def getDistanceFactor(self): """ Control the scale that sets the distance units for 3D spacialized audio. - Default is 1.0 which is adjust in panda to be feet. + Default is 1.0 which is adjust in panda to be meters. """ return self.audio_manager.audio3dGetDistanceFactor() diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 824d20f3f3..5d8963a3ea 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -1,6 +1,33 @@ """ This module contains ShowBase, an application framework responsible for opening a graphical display, setting up input devices and creating -the scene graph. """ +the scene graph. + +The simplest way to open a ShowBase instance is to execute this code: + +.. code-block:: python + + from direct.showbase.ShowBase import ShowBase + + base = ShowBase() + base.run() + +A common approach is to create your own subclass inheriting from ShowBase. + +Built-in global variables +------------------------- + +Some key variables used in all Panda3D scripts are actually attributes of the +ShowBase instance. When creating an instance of this class, it will write many +of these variables to the built-in scope of the Python interpreter, so that +they are accessible to any Python module. + +While these are handy for prototyping, we do not recommend using them in bigger +projects, as it can make the code confusing to read to other Python developers, +to whom it may not be obvious where these variables are originating. + +Some of these built-in variables are documented further in the +:mod:`~direct.showbase.ShowBaseGlobal` module. +""" __all__ = ['ShowBase', 'WindowControls'] @@ -1109,8 +1136,8 @@ class ShowBase(DirectObject.DirectObject): 2-d objects and gui elements that are superimposed over the 3-d geometry in the window. """ - # We've already created aspect2d in ShowBaseGlobal, for the - # benefit of creating DirectGui elements before ShowBase. + # We've already created render2d and aspect2d in ShowBaseGlobal, + # for the benefit of creating DirectGui elements before ShowBase. from . import ShowBaseGlobal ## This is the root of the 2-D scene graph. @@ -1134,10 +1161,6 @@ class ShowBase(DirectObject.DirectObject): self.render2d.setMaterialOff(1) self.render2d.setTwoSided(1) - # We've already created aspect2d in ShowBaseGlobal, for the - # benefit of creating DirectGui elements before ShowBase. - from . import ShowBaseGlobal - ## The normal 2-d DisplayRegion has an aspect ratio that ## matches the window, but its coordinate system is square. ## This means anything we parent to render2d gets stretched. diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 0fdbf0104e..c6e451851f 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -17,17 +17,39 @@ from . import DConfig as config __dev__ = config.GetBool('want-dev', __debug__) -#: The global instance of the :class:`panda3d.core.VirtualFileSystem`. +#: The global instance of the :class:`~panda3d.core.VirtualFileSystem`, as +#: obtained using :meth:`panda3d.core.VirtualFileSystem.getGlobalPtr()`. vfs = VirtualFileSystem.getGlobalPtr() + +#: The default Panda3D output stream for notifications and logging, as +#: obtained using :meth:`panda3d.core.Notify.out()`. ostream = Notify.out() + +#: The clock object used by default for rendering and animation, obtained using +#: :meth:`panda3d.core.ClockObject.getGlobalClock()`. globalClock = ClockObject.getGlobalClock() + +#: See :meth:`panda3d.core.ConfigPageManager.getGlobalPtr()`. cpMgr = ConfigPageManager.getGlobalPtr() + +#: See :meth:`panda3d.core.ConfigVariableManager.getGlobalPtr()`. cvMgr = ConfigVariableManager.getGlobalPtr() + +#: See :meth:`panda3d.core.PandaSystem.getGlobalPtr()`. pandaSystem = PandaSystem.getGlobalPtr() -# This is defined here so GUI elements can be instantiated before ShowBase. +#: The root of the 2-D scene graph. The coordinate system of this node runs +#: from -1 to 1, with the X axis running from left to right and the Z axis from +#: bottom to top. render2d = NodePath("render2d") + +#: The root of the 2-D scene graph used for GUI rendering. Unlike render2d, +#: which may result in elements being stretched in windows that do not have a +#: square aspect ratio, this node is scaled automatically to ensure that nodes +#: parented to it do not appear stretched. aspect2d = render2d.attachNewNode(PGTop("aspect2d")) + +#: A dummy scene graph that is not being rendered by anything. hidden = NodePath("hidden") # Set direct notify categories now that we have config diff --git a/makepanda/makewheel.py b/makepanda/makewheel.py index de97b0031d..04475fc0bb 100644 --- a/makepanda/makewheel.py +++ b/makepanda/makewheel.py @@ -407,6 +407,7 @@ class WheelFile(object): deps_path = '@executable_path/../Frameworks' else: deps_path = '@loader_path' + remove_signature = False loader_path = [os.path.dirname(source_path)] for dep in deps: if dep.endswith('/Python'): @@ -439,6 +440,11 @@ class WheelFile(object): continue subprocess.call(["install_name_tool", "-change", dep, new_dep, temp.name]) + remove_signature = True + + # Remove the codesign signature if we modified the library. + if remove_signature: + subprocess.call(["codesign", "--remove-signature", temp.name]) else: # On other unixes, we just add dependencies normally. for dep in deps: diff --git a/panda/src/display/graphicsStateGuardian.cxx b/panda/src/display/graphicsStateGuardian.cxx index c36eea42ae..5b872fdc7f 100644 --- a/panda/src/display/graphicsStateGuardian.cxx +++ b/panda/src/display/graphicsStateGuardian.cxx @@ -1075,7 +1075,7 @@ fetch_specified_part(Shader::ShaderMatInput part, InternalName *name, _target_rs->get_attrib_def(FogAttrib::get_class_slot()); Fog *fog = target_fog->get_fog(); if (fog == nullptr) { - into[0] = LMatrix4::ones_mat(); + into[0].set(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1); return; } PN_stdfloat start, end; diff --git a/panda/src/express/datagram.h b/panda/src/express/datagram.h index 9611645eed..e0590427f0 100644 --- a/panda/src/express/datagram.h +++ b/panda/src/express/datagram.h @@ -97,6 +97,7 @@ public: PUBLISHED: EXTENSION(INLINE PyObject *get_message() const); EXTENSION(INLINE PyObject *__bytes__() const); + EXTENSION(PyObject *__reduce__() const); INLINE size_t get_length() const; diff --git a/panda/src/express/datagram_ext.I b/panda/src/express/datagram_ext.I index a35c5410b2..9c997e64f6 100644 --- a/panda/src/express/datagram_ext.I +++ b/panda/src/express/datagram_ext.I @@ -33,3 +33,29 @@ PyObject *Extension:: __bytes__() const { return get_message(); } + +/** + * This special Python method is implemented to provide support for the pickle + * module. + */ +INLINE PyObject *Extension:: +__reduce__() const { + // We should return at least a 2-tuple, (Class, (args)): the necessary class + // object whose constructor we should call (e.g. this), and the arguments + // necessary to reconstruct this object. + PyObject *args; + if (_this->get_length() > 0) { + args = PyTuple_New(1); + PyTuple_SET_ITEM(args, 0, get_message()); + } else { + args = PyTuple_New(0); + } + + extern struct Dtool_PyTypedObject Dtool_Datagram; + Py_INCREF((PyObject *)&Dtool_Datagram._PyType); + + PyObject *result = PyTuple_New(2); + PyTuple_SET_ITEM(result, 0, (PyObject *)&Dtool_Datagram._PyType); + PyTuple_SET_ITEM(result, 1, args); + return result; +} diff --git a/panda/src/express/datagram_ext.h b/panda/src/express/datagram_ext.h index 35f2e32bc6..ebaf2dd778 100644 --- a/panda/src/express/datagram_ext.h +++ b/panda/src/express/datagram_ext.h @@ -31,6 +31,7 @@ class Extension : public ExtensionBase { public: INLINE PyObject *get_message() const; INLINE PyObject *__bytes__() const; + INLINE PyObject *__reduce__() const; }; #include "datagram_ext.I" diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 68741bc508..5ee98c62f7 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -8489,6 +8489,10 @@ make_shadow_buffer(LightLensNode *light, Texture *tex, GraphicsOutput *host) { flags |= GraphicsPipe::BF_size_square; } + if (host != nullptr) { + host = host->get_host(); + } + CLP(GraphicsBuffer) *sbuffer = new CLP(GraphicsBuffer)(get_engine(), get_pipe(), light->get_name(), fbp, props, flags, this, host); sbuffer->add_render_texture(tex, GraphicsOutput::RTM_bind_or_copy, GraphicsOutput::RTP_depth); get_engine()->add_window(sbuffer, light->get_shadow_buffer_sort()); diff --git a/panda/src/pgraph/geomTransformer.cxx b/panda/src/pgraph/geomTransformer.cxx index fe6b022d2d..a150f6ff4a 100644 --- a/panda/src/pgraph/geomTransformer.cxx +++ b/panda/src/pgraph/geomTransformer.cxx @@ -1338,7 +1338,7 @@ append_vdata(const GeomVertexData *vdata, int vertex_offset) { // The TransformBlendTable. This one is the easiest, because we can // modify it directly, and it will uniquify blend objects for us. - // We have few special optimizations to handle the TransformBlendTable, + // We have a few special optimizations to handle the TransformBlendTable, // since it's a very common case and therefore worth spending a bit of // effort to optimize deeply. diff --git a/panda/src/tform/mouseWatcher.cxx b/panda/src/tform/mouseWatcher.cxx index 44258bfe45..54caa1cd88 100644 --- a/panda/src/tform/mouseWatcher.cxx +++ b/panda/src/tform/mouseWatcher.cxx @@ -742,7 +742,6 @@ clear_current_regions() { } } -#ifndef NDEBUG /** * The protected implementation of show_regions(). This assumes the lock is * already held. @@ -750,6 +749,7 @@ clear_current_regions() { void MouseWatcher:: do_show_regions(const NodePath &render2d, const string &bin_name, int draw_order) { +#ifndef NDEBUG MouseWatcherBase::do_show_regions(render2d, bin_name, draw_order); _show_regions_render2d = render2d; _show_regions_bin_name = bin_name; @@ -758,16 +758,16 @@ do_show_regions(const NodePath &render2d, const string &bin_name, for (MouseWatcherGroup *group : _groups) { group->show_regions(render2d, bin_name, draw_order); } -} #endif // NDEBUG +} -#ifndef NDEBUG /** * The protected implementation of hide_regions(). This assumes the lock is * already held. */ void MouseWatcher:: do_hide_regions() { +#ifndef NDEBUG MouseWatcherBase::do_hide_regions(); _show_regions_render2d = NodePath(); _show_regions_bin_name = string(); @@ -776,8 +776,8 @@ do_hide_regions() { for (MouseWatcherGroup *group : _groups) { group->hide_regions(); } -} #endif // NDEBUG +} /** * Computes the list of regions that are in both regions_a and regions_b, as diff --git a/panda/src/tform/mouseWatcher.h b/panda/src/tform/mouseWatcher.h index f81da04ba7..a1005d2a32 100644 --- a/panda/src/tform/mouseWatcher.h +++ b/panda/src/tform/mouseWatcher.h @@ -157,11 +157,9 @@ protected: void set_current_regions(Regions ®ions); void clear_current_regions(); -#ifndef NDEBUG virtual void do_show_regions(const NodePath &render2d, const std::string &bin_name, int draw_order); virtual void do_hide_regions(); -#endif // NDEBUG static void intersect_regions(Regions &only_a, Regions &only_b, @@ -260,11 +258,9 @@ private: }; InactivityState _inactivity_state; -#ifndef NDEBUG NodePath _show_regions_render2d; std::string _show_regions_bin_name; int _show_regions_draw_order; -#endif protected: // Inherited from DataNode diff --git a/pandatool/src/deploy-stub/deploy-stub.c b/pandatool/src/deploy-stub/deploy-stub.c index e30482654e..7255b911b8 100644 --- a/pandatool/src/deploy-stub/deploy-stub.c +++ b/pandatool/src/deploy-stub/deploy-stub.c @@ -522,6 +522,10 @@ int Py_FrozenMain(int argc, char **argv) // for ConfigPageManager to read out and assign to MAIN_DIR. sprintf(buffer, "%s/../Resources", dir); set_main_dir(buffer); + + // Finally, chdir to it, so that regular Python files are read from the + // right location. + chdir(buffer); #endif n = PyImport_ImportFrozenModule("__main__"); diff --git a/tests/putil/test_datagram.py b/tests/putil/test_datagram.py index 5a654b75ed..ad8ef9857c 100644 --- a/tests/putil/test_datagram.py +++ b/tests/putil/test_datagram.py @@ -101,6 +101,16 @@ def test_datagram_get_message(): assert dg.get_message() == b'abc\x00\xff123' +def test_datagram_pickle(): + import pickle + + dg = core.Datagram() + assert pickle.loads(pickle.dumps(dg, -1)) == dg + + dg = core.Datagram(b'abc\x00') + assert pickle.loads(pickle.dumps(dg, -1)) == dg + + def test_iterator(datagram_small): """This tests Datagram/DatagramIterator, and sort of serves as a self-check of the test fixtures too."""