diff --git a/BACKERS.md b/BACKERS.md index a42b006abe..4b5b5a5bb6 100644 --- a/BACKERS.md +++ b/BACKERS.md @@ -15,7 +15,6 @@ This is a list of all the people who are contributing financially to Panda3D. I * [Mitchell Stokes](https://opencollective.com/mitchell-stokes) * [Daniel Stokes](https://opencollective.com/daniel-stokes) * [David Rose](https://opencollective.com/david-rose) -* [Carnetsoft](https://cs-driving-simulator.com/) ## Benefactors @@ -23,14 +22,14 @@ This is a list of all the people who are contributing financially to Panda3D. I * Sam Edwards * Max Voss -* Will Nielsen ## Enthusiasts -![Benefactors](https://opencollective.com/panda3d/tiers/enthusiast.svg?avatarHeight=48&width=600) +![Enthusiasts](https://opencollective.com/panda3d/tiers/enthusiast.svg?avatarHeight=48&width=600) * Eric Thomson * Kyle Roach +* Brian Lach ## Backers diff --git a/direct/src/dist/pefile.py b/direct/src/dist/pefile.py index aa09c40667..686e4ed49a 100755 --- a/direct/src/dist/pefile.py +++ b/direct/src/dist/pefile.py @@ -242,7 +242,11 @@ class VersionInfoResource(object): length, value_length = unpack('= (3, 2): + dwords.frombytes(bytes(data[40:offset])) + else: + dwords.fromstring(bytes(data[40:offset])) + if len(dwords) > 0: self.signature = dwords[0] if len(dwords) > 1: diff --git a/direct/src/showbase/Loader.py b/direct/src/showbase/Loader.py index fd6424d917..711a40f30e 100644 --- a/direct/src/showbase/Loader.py +++ b/direct/src/showbase/Loader.py @@ -192,21 +192,21 @@ class Loader(DirectObject): pathname), the return value will be a NodePath to the model loaded if the load was successful, or None otherwise. If the input modelPath is a list of pathnames, the return value will - be a list of NodePaths and/or Nones. + be a list of `.NodePath` objects and/or Nones. loaderOptions may optionally be passed in to control details about the way the model is searched and loaded. See the - LoaderOptions class for more. + `.LoaderOptions` class for more. - The default is to look in the ModelPool (RAM) cache first, and - return a copy from that if the model can be found there. If - the bam cache is enabled (via the model-cache-dir config + The default is to look in the `.ModelPool` (RAM) cache first, + and return a copy from that if the model can be found there. + If the bam cache is enabled (via the `model-cache-dir` config variable), then that will be consulted next, and if both caches fail, the file will be loaded from disk. If noCache is True, then neither cache will be consulted or updated. If allowInstance is True, a shared instance may be returned - from the ModelPool. This is dangerous, since it is easy to + from the `.ModelPool`. This is dangerous, since it is easy to accidentally modify the shared instance, and invalidate future load attempts of the same model. Normally, you should leave allowInstance set to False, which will always return a unique @@ -214,10 +214,10 @@ class Loader(DirectObject): If okMissing is True, None is returned if the model is not found or cannot be read, and no error message is printed. - Otherwise, an IOError is raised if the model is not found or + Otherwise, an `IOError` is raised if the model is not found or cannot be read (similar to attempting to open a nonexistent - file). (If modelPath is a list of filenames, then IOError is - raised if *any* of the models could not be loaded.) + file). (If modelPath is a list of filenames, then `IOError` + is raised if *any* of the models could not be loaded.) If callback is not None, then the model load will be performed asynchronously. In this case, loadModel() will initiate a @@ -235,7 +235,7 @@ class Loader(DirectObject): True asynchronous model loading requires Panda to have been compiled with threading support enabled (you can test - Thread.isThreadingSupported()). In the absence of threading + `.Thread.isThreadingSupported()`). In the absence of threading support, the asynchronous interface still exists and still behaves exactly as described, except that loadModel() might not return immediately. @@ -420,7 +420,7 @@ class Loader(DirectObject): def saveModel(self, modelPath, node, loaderOptions = None, callback = None, extraArgs = [], priority = None, blocking = None): - """ Saves the model (a NodePath or PandaNode) to the indicated + """ Saves the model (a `NodePath` or `PandaNode`) to the indicated filename path. Returns true on success, false on failure. If a callback is used, the model is saved asynchronously, and the true/false status is passed to the callback function. """ @@ -508,8 +508,8 @@ class Loader(DirectObject): """ modelPath is a string. - This loads a special model as a TextFont object, for rendering - text with a TextNode. A font file must be either a special + This loads a special model as a `TextFont` object, for rendering + text with a `TextNode`. A font file must be either a special egg file (or bam file) generated with egg-mkfont, which is considered a static font, or a standard font file (like a TTF file) that is supported by FreeType, which is considered a @@ -573,7 +573,7 @@ class Loader(DirectObject): If color is not None, it should be a VBase4 specifying the foreground color of the font. Specifying this option breaks - TextNode.setColor(), so you almost never want to use this + `TextNode.setColor()`, so you almost never want to use this option; the default (white) is the most appropriate for a font, as it allows text to have any arbitrary color assigned at generation time. However, if you want to use a colored @@ -695,7 +695,8 @@ class Loader(DirectObject): texturePath is a string. Attempt to load a texture from the given file path using - TexturePool class. + `TexturePool` class. Returns a `Texture` object, or raises + `IOError` if the file could not be loaded. okMissing should be True to indicate the method should return None if the texture file is not found. If it is False, the @@ -713,17 +714,17 @@ class Loader(DirectObject): the texture and the number of expected mipmap images. If minfilter or magfilter is not None, they should be a symbol - like SamplerState.FTLinear or SamplerState.FTNearest. (minfilter - may be further one of the Mipmap filter type symbols.) These - specify the filter mode that will automatically be applied to - the texture when it is loaded. Note that this setting may + like `SamplerState.FTLinear` or `SamplerState.FTNearest`. + (minfilter may be further one of the Mipmap filter type symbols.) + These specify the filter mode that will automatically be applied + to the texture when it is loaded. Note that this setting may override the texture's existing settings, even if it has - already been loaded. See egg-texture-cards for a more robust + already been loaded. See `egg-texture-cards` for a more robust way to apply per-texture filter types and settings. If anisotropicDegree is not None, it specifies the anisotropic degree to apply to the texture when it is loaded. Like minfilter and - magfilter, egg-texture-cards may be a more robust way to apply + magfilter, `egg-texture-cards` may be a more robust way to apply this setting. If multiview is true, it indicates to load a multiview or @@ -769,7 +770,7 @@ class Loader(DirectObject): """ texturePattern is a string that contains a sequence of one or more hash characters ('#'), which will be filled in with the - z-height number. Returns a 3-D Texture object, suitable for + z-height number. Returns a 3-D `Texture` object, suitable for rendering volumetric textures. okMissing should be True to indicate the method should return @@ -826,7 +827,7 @@ class Loader(DirectObject): """ texturePattern is a string that contains a sequence of one or more hash characters ('#'), which will be filled in with the - z-height number. Returns a 2-D Texture array object, suitable + z-height number. Returns a 2-D `Texture` array object, suitable for rendering array of textures. okMissing should be True to indicate the method should return @@ -884,7 +885,7 @@ class Loader(DirectObject): texturePattern is a string that contains a sequence of one or more hash characters ('#'), which will be filled in with the face index number (0 through 6). Returns a six-face cube map - Texture object. + `Texture` object. okMissing should be True to indicate the method should return None if the texture file is not found. If it is False, the @@ -951,8 +952,8 @@ class Loader(DirectObject): """Loads one or more sound files, specifically designated as a "sound effect" file (that is, uses the sfxManager to load the sound). There is no distinction between sound effect files - and music files other than the particular AudioManager used to - load the sound file, but this distinction allows the sound + and music files other than the particular `AudioManager` used + to load the sound file, but this distinction allows the sound effects and/or the music files to be adjusted as a group, independently of the other group.""" @@ -965,8 +966,8 @@ class Loader(DirectObject): """Loads one or more sound files, specifically designated as a "music" file (that is, uses the musicManager to load the sound). There is no distinction between sound effect files - and music files other than the particular AudioManager used to - load the sound file, but this distinction allows the sound + and music files other than the particular `AudioManager` used + to load the sound file, but this distinction allows the sound effects and/or the music files to be adjusted as a group, independently of the other group.""" if(self.base.musicManager): @@ -1052,7 +1053,7 @@ class Loader(DirectObject): callback = None, extraArgs = []): """ Performs a model.flattenStrong() operation in a sub-thread (if threading is compiled into Panda). The model may be a - single NodePath, or it may be a list of NodePaths. + single `.NodePath`, or it may be a list of NodePaths. Each model is duplicated and flattened in the sub-thread. diff --git a/direct/src/showbase/ShowBase.py b/direct/src/showbase/ShowBase.py index 662ab42c16..c82876d05b 100644 --- a/direct/src/showbase/ShowBase.py +++ b/direct/src/showbase/ShowBase.py @@ -152,6 +152,7 @@ class ShowBase(DirectObject.DirectObject): self.wantStats = self.config.GetBool('want-pstats', 0) self.wantTk = False self.wantWx = False + self.wantDirect = False #: Fill this in with a function to invoke when the user "exits" #: the program by closing the main window. @@ -3264,7 +3265,12 @@ class ShowBase(DirectObject.DirectObject): def startDirect(self, fWantDirect = 1, fWantTk = 1, fWantWx = 0): self.startTk(fWantTk) self.startWx(fWantWx) + + if self.wantDirect == fWantDirect: + return + self.wantDirect = fWantDirect + if self.wantDirect: # Use importlib to prevent this import from being picked up # by modulefinder when packaging an application. diff --git a/panda/src/collide/collisionTraverser.h b/panda/src/collide/collisionTraverser.h index b1be66d49f..688f7e88a5 100644 --- a/panda/src/collide/collisionTraverser.h +++ b/panda/src/collide/collisionTraverser.h @@ -62,7 +62,7 @@ PUBLISHED: void clear_colliders(); MAKE_SEQ_PROPERTY(colliders, get_num_colliders, get_collider); - void traverse(const NodePath &root); + BLOCKING void traverse(const NodePath &root); #if defined(DO_COLLISION_RECORDING) || !defined(CPPPARSER) void set_recorder(CollisionRecorder *recorder); diff --git a/panda/src/display/standardMunger.cxx b/panda/src/display/standardMunger.cxx index 2dba4aa6c0..10b66762a9 100644 --- a/panda/src/display/standardMunger.cxx +++ b/panda/src/display/standardMunger.cxx @@ -123,8 +123,9 @@ munge_data_impl(const GeomVertexData *data) { } GeomVertexAnimationSpec animation = new_data->get_format()->get_animation(); - if (_shader_skinning || (_auto_shader && hardware_animated_vertices && - !basic_shaders_only && animation.get_animation_type() == AT_panda)) { + if ((_shader_skinning && animation.get_animation_type() != AT_none) || + (_auto_shader && hardware_animated_vertices && + !basic_shaders_only && animation.get_animation_type() == AT_panda)) { animation.set_hardware(4, true); } else if (hardware_animated_vertices && diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx index 2e5d32b859..477bd033f2 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.cxx +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.cxx @@ -1920,6 +1920,8 @@ reset() { get_extension_func("glUniform3uiv"); _glUniform4uiv = (PFNGLUNIFORM4UIVPROC) get_extension_func("glUniform4uiv"); + _glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) + get_extension_func("glVertexAttribI4ui"); } else if (has_extension("GL_EXT_gpu_shader4")) { _glBindFragDataLocation = (PFNGLBINDFRAGDATALOCATIONPROC) @@ -1934,10 +1936,13 @@ reset() { get_extension_func("glUniform3uivEXT"); _glUniform4uiv = (PFNGLUNIFORM4UIVPROC) get_extension_func("glUniform4uivEXT"); + _glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) + get_extension_func("glVertexAttribI4uiEXT"); } else { _glBindFragDataLocation = nullptr; _glVertexAttribIPointer = nullptr; + _glVertexAttribI4ui = nullptr; } if (is_at_least_gl_version(4, 1) || has_extension("GL_ARB_vertex_attrib_64bit")) { @@ -1966,8 +1971,11 @@ reset() { get_extension_func("glVertexAttribPointerARB"); _glBindFragDataLocation = nullptr; + _glVertexAttribI4ui = nullptr; _glVertexAttribIPointer = nullptr; _glVertexAttribLPointer = nullptr; + } else { + _glVertexAttribI4ui = nullptr; } #endif @@ -2014,8 +2022,11 @@ reset() { if (is_at_least_gles_version(3, 0)) { _glVertexAttribIPointer = (PFNGLVERTEXATTRIBIPOINTERPROC) get_extension_func("glVertexAttribIPointer"); + _glVertexAttribI4ui = (PFNGLVERTEXATTRIBI4UIPROC) + get_extension_func("glVertexAttribI4ui"); } else { _glVertexAttribIPointer = nullptr; + _glVertexAttribI4ui = nullptr; } if (has_extension("GL_EXT_blend_func_extended")) { diff --git a/panda/src/glstuff/glGraphicsStateGuardian_src.h b/panda/src/glstuff/glGraphicsStateGuardian_src.h index 58c50176a3..fdc35650c8 100644 --- a/panda/src/glstuff/glGraphicsStateGuardian_src.h +++ b/panda/src/glstuff/glGraphicsStateGuardian_src.h @@ -186,6 +186,7 @@ typedef void (APIENTRYP PFNGLUNIFORMMATRIX4FVPROC) (GLint location, GLsizei coun typedef void (APIENTRYP PFNGLVALIDATEPROGRAMPROC) (GLuint program); typedef void (APIENTRYP PFNGLVERTEXATTRIB4FVPROC) (GLuint index, const GLfloat *v); typedef void (APIENTRYP PFNGLVERTEXATTRIB4DVPROC) (GLuint index, const GLdouble *v); +typedef void (APIENTRYP PFNGLVERTEXATTRIBI4UIPROC) (GLuint index, GLuint x, GLuint y, GLuint z, GLuint w); typedef void (APIENTRYP PFNGLVERTEXATTRIBPOINTERPROC) (GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXATTRIBIPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); typedef void (APIENTRYP PFNGLVERTEXATTRIBLPOINTERPROC) (GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer); @@ -1015,6 +1016,7 @@ public: PFNGLVALIDATEPROGRAMPROC _glValidateProgram; PFNGLVERTEXATTRIB4FVPROC _glVertexAttrib4fv; PFNGLVERTEXATTRIB4DVPROC _glVertexAttrib4dv; + PFNGLVERTEXATTRIBI4UIPROC _glVertexAttribI4ui; PFNGLVERTEXATTRIBPOINTERPROC _glVertexAttribPointer; PFNGLVERTEXATTRIBIPOINTERPROC _glVertexAttribIPointer; PFNGLVERTEXATTRIBLPOINTERPROC _glVertexAttribLPointer; diff --git a/panda/src/glstuff/glShaderContext_src.cxx b/panda/src/glstuff/glShaderContext_src.cxx index eb9c534b44..7980247476 100644 --- a/panda/src/glstuff/glShaderContext_src.cxx +++ b/panda/src/glstuff/glShaderContext_src.cxx @@ -2461,6 +2461,10 @@ update_shader_vertex_arrays(ShaderContext *prev, bool force) { _glgsg->_glVertexAttrib4fv(p, _glgsg->_scene_graph_color.get_data()); #endif } + else if (name == InternalName::get_transform_index() && + _glgsg->_glVertexAttribI4ui != nullptr) { + _glgsg->_glVertexAttribI4ui(p, 0, 1, 2, 3); + } } } diff --git a/panda/src/gobj/geomVertexData.cxx b/panda/src/gobj/geomVertexData.cxx index d7bf35ba9d..d77ca492a1 100644 --- a/panda/src/gobj/geomVertexData.cxx +++ b/panda/src/gobj/geomVertexData.cxx @@ -659,7 +659,7 @@ copy_from(const GeomVertexData *source, bool keep_data_objects, for (size_t i = 0; i < blend.get_num_transforms(); i++) { int index = add_transform(transform_table, blend.get_transform(i), already_added); - nassertv(index <= 4); + nassertv(index < 4); weights[index] = blend.get_weight(i); } if (weight.has_column()) { diff --git a/panda/src/gobj/matrixLens.I b/panda/src/gobj/matrixLens.I index 74cc9296cf..b607106231 100644 --- a/panda/src/gobj/matrixLens.I +++ b/panda/src/gobj/matrixLens.I @@ -54,7 +54,7 @@ operator = (const MatrixLens ©) { * Explicitly specifies the projection matrix. This matrix should convert X * and Y to the range [-film_size/2, film_size/2], where (-fs/2,-fs/2) is the * lower left corner of the screen and (fs/2, fs/2) is the upper right. Z - * should go to the range [-1, 1], where -1 is the far plane and 1 is the near + * should go to the range [-1, 1], where -1 is the near plane and 1 is the far * plane. Note that this is a left-handed Y-up coordinate system. * * The default film_size for a MatrixLens is 2, so the default range is [-1, diff --git a/setup.cfg b/setup.cfg index 5ec78283ad..d10fc40455 100644 --- a/setup.cfg +++ b/setup.cfg @@ -17,6 +17,7 @@ classifiers = Programming Language :: Python :: 3.6 Programming Language :: Python :: 3.7 Programming Language :: Python :: 3.8 + Programming Language :: Python :: 3.9 Programming Language :: Python :: Implementation :: CPython Topic :: Games/Entertainment Topic :: Multimedia