Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
d40d7dc5f9
|
|
@ -49,9 +49,9 @@ class MotionTrailFrame:
|
|||
class MotionTrail(NodePath, DirectObject):
|
||||
"""Generates smooth geometry-based motion trails behind a moving object.
|
||||
|
||||
To use this class, first define the shape of the cross-section of the trail
|
||||
by repeatedly calling `add_vertex()` and `set_vertex_color()`.
|
||||
When this is done, `update_vertices()` must be called.
|
||||
To use this class, first define the shape of the cross-section polygon that
|
||||
is to be extruded along the motion trail by calling `add_vertex()` and
|
||||
`set_vertex_color()`. When this is done, call `update_vertices()`.
|
||||
|
||||
To generate the motion trail, either call `register_motion_trail()`
|
||||
to have Panda update it automatically, or periodically call the method
|
||||
|
|
@ -82,6 +82,10 @@ class MotionTrail(NodePath, DirectObject):
|
|||
|
||||
@classmethod
|
||||
def setGlobalEnable(cls, enable):
|
||||
"""Set this to False to have the task stop updating all motion trails.
|
||||
This does not prevent updating them manually using the
|
||||
`update_motion_trail()` method.
|
||||
"""
|
||||
cls.global_enable = enable
|
||||
|
||||
def __init__(self, name, parent_node_path):
|
||||
|
|
@ -119,14 +123,14 @@ class MotionTrail(NodePath, DirectObject):
|
|||
self.continuous_motion_trail = True
|
||||
self.color_scale = 1.0
|
||||
|
||||
## How long the time window is for which the trail is computed. Can be
|
||||
## increased to obtain a longer trail, decreased for a shorter trail.
|
||||
#: How long the time window is for which the trail is computed. Can be
|
||||
#: increased to obtain a longer trail, decreased for a shorter trail.
|
||||
self.time_window = 1.0
|
||||
|
||||
## How often the trail updates, in seconds. The default is 0.0, which
|
||||
## has the trail updated every frame for the smoothest result. Higher
|
||||
## values will generate a choppier trail. The `use_nurbs` option can
|
||||
## compensate partially for this choppiness, however.
|
||||
#: How often the trail updates, in seconds. The default is 0.0, which
|
||||
#: has the trail updated every frame for the smoothest result. Higher
|
||||
#: values will generate a choppier trail. The `use_nurbs` option can
|
||||
#: compensate partially for this choppiness, however.
|
||||
self.sampling_time = 0.0
|
||||
|
||||
self.square_t = True
|
||||
|
|
@ -137,9 +141,9 @@ class MotionTrail(NodePath, DirectObject):
|
|||
# node path states
|
||||
self.reparentTo(parent_node_path)
|
||||
|
||||
## A `.GeomNode` object containing the generated geometry. By default
|
||||
## parented to the MotionTrail itself, but can be reparented elsewhere
|
||||
## if necessary.
|
||||
#: A `.GeomNode` object containing the generated geometry. By default
|
||||
#: parented to the MotionTrail itself, but can be reparented elsewhere
|
||||
#: if necessary.
|
||||
self.geom_node = GeomNode("motion_trail")
|
||||
self.geom_node.setBoundsType(BoundingVolume.BT_box)
|
||||
self.geom_node_path = self.attachNewNode(self.geom_node)
|
||||
|
|
@ -170,9 +174,11 @@ class MotionTrail(NodePath, DirectObject):
|
|||
|
||||
self.relative_to_render = False
|
||||
|
||||
## Set this to True to use a NURBS curve to generate a smooth trail,
|
||||
## even if the underlying animation or movement is janky.
|
||||
#: Set this to True to use a NURBS curve to generate a smooth trail,
|
||||
#: even if the underlying animation or movement is janky.
|
||||
self.use_nurbs = False
|
||||
|
||||
#: This can be changed to fine-tune the resolution of the NURBS curve.
|
||||
self.resolution_distance = 0.5
|
||||
|
||||
self.cmotion_trail = CMotionTrail()
|
||||
|
|
@ -249,7 +255,7 @@ class MotionTrail(NodePath, DirectObject):
|
|||
|
||||
def add_vertex(self, vertex_id, vertex_function=None, context=None, *,
|
||||
start_color=(1.0, 1.0, 1.0, 1.0), end_color=(0.0, 0.0, 0.0, 1.0)):
|
||||
"""This must be called repeatedly to define the polygon that forms the
|
||||
"""This must be called initially to define the polygon that forms the
|
||||
cross-section of the generated motion trail geometry. The first
|
||||
argument is a user-defined vertex identifier, the second is a function
|
||||
that will be called with three parameters that should return the
|
||||
|
|
@ -390,21 +396,21 @@ class MotionTrail(NodePath, DirectObject):
|
|||
|
||||
def add_geometry_quad(self, v0, v1, v2, v3, c0, c1, c2, c3, t0, t1, t2, t3):
|
||||
|
||||
self.vertex_writer.addData3f(v0 [0], v0 [1], v0 [2])
|
||||
self.vertex_writer.addData3f(v1 [0], v1 [1], v1 [2])
|
||||
self.vertex_writer.addData3f(v2 [0], v2 [1], v2 [2])
|
||||
self.vertex_writer.addData3f(v3 [0], v3 [1], v3 [2])
|
||||
self.vertex_writer.addData3(v0[0], v0[1], v0[2])
|
||||
self.vertex_writer.addData3(v1[0], v1[1], v1[2])
|
||||
self.vertex_writer.addData3(v2[0], v2[1], v2[2])
|
||||
self.vertex_writer.addData3(v3[0], v3[1], v3[2])
|
||||
|
||||
self.color_writer.addData4f(c0)
|
||||
self.color_writer.addData4f(c1)
|
||||
self.color_writer.addData4f(c2)
|
||||
self.color_writer.addData4f(c3)
|
||||
self.color_writer.addData4(c0)
|
||||
self.color_writer.addData4(c1)
|
||||
self.color_writer.addData4(c2)
|
||||
self.color_writer.addData4(c3)
|
||||
|
||||
if self.texture is not None:
|
||||
self.texture_writer.addData2f(t0)
|
||||
self.texture_writer.addData2f(t1)
|
||||
self.texture_writer.addData2f(t2)
|
||||
self.texture_writer.addData2f(t3)
|
||||
self.texture_writer.addData2(t0)
|
||||
self.texture_writer.addData2(t1)
|
||||
self.texture_writer.addData2(t2)
|
||||
self.texture_writer.addData2(t3)
|
||||
|
||||
vertex_index = self.vertex_index
|
||||
|
||||
|
|
|
|||
|
|
@ -1151,7 +1151,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
Creates the render scene graph, the primary scene graph for
|
||||
rendering 3-d geometry.
|
||||
"""
|
||||
## This is the root of the 3-D scene graph.
|
||||
#: This is the root of the 3-D scene graph.
|
||||
self.render = NodePath('render')
|
||||
self.render.setAttrib(RescaleNormalAttrib.makeDefault())
|
||||
|
||||
|
|
@ -1170,7 +1170,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
# for the benefit of creating DirectGui elements before ShowBase.
|
||||
from . import ShowBaseGlobal
|
||||
|
||||
## This is the root of the 2-D scene graph.
|
||||
#: This is the root of the 2-D scene graph.
|
||||
self.render2d = ShowBaseGlobal.render2d
|
||||
|
||||
# Set up some overrides to turn off certain properties which
|
||||
|
|
@ -1191,12 +1191,12 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.render2d.setMaterialOff(1)
|
||||
self.render2d.setTwoSided(1)
|
||||
|
||||
## 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.
|
||||
## For things where that makes a difference, we set up
|
||||
## aspect2d, which scales things back to the right aspect
|
||||
## ratio along the X axis (Z is still from -1 to 1)
|
||||
#: 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.
|
||||
#: For things where that makes a difference, we set up
|
||||
#: aspect2d, which scales things back to the right aspect
|
||||
#: ratio along the X axis (Z is still from -1 to 1)
|
||||
self.aspect2d = ShowBaseGlobal.aspect2d
|
||||
|
||||
aspectRatio = self.getAspectRatio()
|
||||
|
|
@ -1204,13 +1204,13 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
self.a2dBackground = self.aspect2d.attachNewNode("a2dBackground")
|
||||
|
||||
## The Z position of the top border of the aspect2d screen.
|
||||
#: The Z position of the top border of the aspect2d screen.
|
||||
self.a2dTop = 1.0
|
||||
## The Z position of the bottom border of the aspect2d screen.
|
||||
#: The Z position of the bottom border of the aspect2d screen.
|
||||
self.a2dBottom = -1.0
|
||||
## The X position of the left border of the aspect2d screen.
|
||||
#: The X position of the left border of the aspect2d screen.
|
||||
self.a2dLeft = -aspectRatio
|
||||
## The X position of the right border of the aspect2d screen.
|
||||
#: The X position of the right border of the aspect2d screen.
|
||||
self.a2dRight = aspectRatio
|
||||
|
||||
self.a2dTopCenter = self.aspect2d.attachNewNode("a2dTopCenter")
|
||||
|
|
@ -1250,9 +1250,9 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.a2dBottomRight.setPos(self.a2dRight, 0, self.a2dBottom)
|
||||
self.a2dBottomRightNs.setPos(self.a2dRight, 0, self.a2dBottom)
|
||||
|
||||
## This special root, pixel2d, uses units in pixels that are relative
|
||||
## to the window. The upperleft corner of the window is (0, 0),
|
||||
## the lowerleft corner is (xsize, -ysize), in this coordinate system.
|
||||
#: This special root, pixel2d, uses units in pixels that are relative
|
||||
#: to the window. The upperleft corner of the window is (0, 0),
|
||||
#: the lowerleft corner is (xsize, -ysize), in this coordinate system.
|
||||
self.pixel2d = self.render2d.attachNewNode(PGTop("pixel2d"))
|
||||
self.pixel2d.setPos(-1, 0, 1)
|
||||
xsize, ysize = self.getSize()
|
||||
|
|
@ -1282,25 +1282,25 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.render2dp.setMaterialOff(1)
|
||||
self.render2dp.setTwoSided(1)
|
||||
|
||||
## 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 render2dp gets stretched.
|
||||
## For things where that makes a difference, we set up
|
||||
## aspect2dp, which scales things back to the right aspect
|
||||
## ratio along the X axis (Z is still from -1 to 1)
|
||||
#: 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 render2dp gets stretched.
|
||||
#: For things where that makes a difference, we set up
|
||||
#: aspect2dp, which scales things back to the right aspect
|
||||
#: ratio along the X axis (Z is still from -1 to 1)
|
||||
self.aspect2dp = self.render2dp.attachNewNode(PGTop("aspect2dp"))
|
||||
self.aspect2dp.node().setStartSort(16384)
|
||||
|
||||
aspectRatio = self.getAspectRatio()
|
||||
self.aspect2dp.setScale(1.0 / aspectRatio, 1.0, 1.0)
|
||||
|
||||
## The Z position of the top border of the aspect2dp screen.
|
||||
#: The Z position of the top border of the aspect2dp screen.
|
||||
self.a2dpTop = 1.0
|
||||
## The Z position of the bottom border of the aspect2dp screen.
|
||||
#: The Z position of the bottom border of the aspect2dp screen.
|
||||
self.a2dpBottom = -1.0
|
||||
## The X position of the left border of the aspect2dp screen.
|
||||
#: The X position of the left border of the aspect2dp screen.
|
||||
self.a2dpLeft = -aspectRatio
|
||||
## The X position of the right border of the aspect2dp screen.
|
||||
#: The X position of the right border of the aspect2dp screen.
|
||||
self.a2dpRight = aspectRatio
|
||||
|
||||
self.a2dpTopCenter = self.aspect2dp.attachNewNode("a2dpTopCenter")
|
||||
|
|
@ -1324,9 +1324,9 @@ class ShowBase(DirectObject.DirectObject):
|
|||
self.a2dpBottomLeft.setPos(self.a2dpLeft, 0, self.a2dpBottom)
|
||||
self.a2dpBottomRight.setPos(self.a2dpRight, 0, self.a2dpBottom)
|
||||
|
||||
## This special root, pixel2d, uses units in pixels that are relative
|
||||
## to the window. The upperleft corner of the window is (0, 0),
|
||||
## the lowerleft corner is (xsize, -ysize), in this coordinate system.
|
||||
#: This special root, pixel2dp, uses units in pixels that are relative
|
||||
#: to the window. The upperleft corner of the window is (0, 0),
|
||||
#: the lowerleft corner is (xsize, -ysize), in this coordinate system.
|
||||
self.pixel2dp = self.render2dp.attachNewNode(PGTop("pixel2dp"))
|
||||
self.pixel2dp.node().setStartSort(16384)
|
||||
self.pixel2dp.setPos(-1, 0, 1)
|
||||
|
|
@ -1647,11 +1647,11 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
mw = self.buttonThrowers[0].getParent()
|
||||
|
||||
## A special ButtonThrower to generate keyboard events and
|
||||
## include the time from the OS. This is separate only to
|
||||
## support legacy code that did not expect a time parameter; it
|
||||
## will eventually be folded into the normal ButtonThrower,
|
||||
## above.
|
||||
#: A special ButtonThrower to generate keyboard events and
|
||||
#: include the time from the OS. This is separate only to
|
||||
#: support legacy code that did not expect a time parameter; it
|
||||
#: will eventually be folded into the normal ButtonThrower,
|
||||
#: above.
|
||||
self.timeButtonThrower = mw.attachNewNode(ButtonThrower('timeButtons'))
|
||||
self.timeButtonThrower.node().setPrefix('time-')
|
||||
self.timeButtonThrower.node().setTimeFlag(1)
|
||||
|
|
@ -2713,7 +2713,7 @@ class ShowBase(DirectObject.DirectObject):
|
|||
|
||||
def screenshot(self, namePrefix = 'screenshot',
|
||||
defaultFilename = 1, source = None,
|
||||
imageComment=""):
|
||||
imageComment="", blocking=True):
|
||||
""" Captures a screenshot from the main window or from the
|
||||
specified window or Texture and writes it to a filename in the
|
||||
current directory (or to a specified directory).
|
||||
|
|
@ -2735,6 +2735,13 @@ class ShowBase(DirectObject.DirectObject):
|
|||
generated by makeCubeMap(), namePrefix should contain the hash
|
||||
mark ('#') character.
|
||||
|
||||
Normally, this call will block until the screenshot is fully
|
||||
written. To write the screenshot in a background thread
|
||||
instead, pass blocking = False. In this case, the return value
|
||||
is a future that can be awaited.
|
||||
|
||||
A "screenshot" event will be sent once the screenshot is saved.
|
||||
|
||||
:returns: The filename if successful, or None if there is a problem.
|
||||
"""
|
||||
|
||||
|
|
@ -2751,8 +2758,12 @@ class ShowBase(DirectObject.DirectObject):
|
|||
saved = source.write(filename, 0, 0, 1, 0)
|
||||
else:
|
||||
saved = source.write(filename)
|
||||
else:
|
||||
elif blocking:
|
||||
saved = source.saveScreenshot(filename, imageComment)
|
||||
else:
|
||||
request = source.saveAsyncScreenshot(filename, imageComment)
|
||||
request.addDoneCallback(lambda fut, filename=filename: messenger.send('screenshot', [filename]))
|
||||
return request
|
||||
|
||||
if saved:
|
||||
# Announce to anybody that a screenshot has been taken
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ Miscellaneous
|
|||
* Fix texture transforms sometimes not being flattened (#1392)
|
||||
* Fix support for `#pragma include <file.glsl>` in GLSL shaders
|
||||
* Fix `ShaderBuffer.prepare()` not doing anything
|
||||
* Implement deepcopy for PointerToArray
|
||||
* Fix Texture deepcopy keeping a reference to the original RAM image
|
||||
* Fix bf-cbc encryption no longer working when building with OpenSSL 3.0
|
||||
* PandaNode bounds_type property was erroneously marked read-only
|
||||
* Fix warnings when copying OdeTriMeshGeom objects
|
||||
|
|
@ -81,8 +83,10 @@ Miscellaneous
|
|||
* Add various useful functions to interrogatedb module
|
||||
* Fix Python 3 issues unpacking uint types in Python 3 (#1380)
|
||||
* Fix interrogate syntax error with C++11-style attributes in declarators
|
||||
* Fix double-precision color values not being clamped by GeomVertexWriter
|
||||
* Fix regression with BufferViewer in double-precision build (#1365)
|
||||
* Fix `PandaNode.nested_vertices` not updating properly
|
||||
* Prevent Panda calculating bounding volume of Geom with custom bounding volume
|
||||
* Add `do_events()` and `process_event()` snake_case aliases in eventMgr
|
||||
* Support second arg of None in `replace_texture()` / `replace_material()`
|
||||
* Support `os.fspath()` for ConfigVariableFilename objects (#1406)
|
||||
|
|
|
|||
|
|
@ -97,7 +97,9 @@ PUBLISHED:
|
|||
// its value, it might happen after the value had already been set
|
||||
// previously by another static initializer!
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(static TypeHandle make(PyTypeObject *classobj));
|
||||
#endif
|
||||
|
||||
INLINE bool operator == (const TypeHandle &other) const;
|
||||
INLINE bool operator != (const TypeHandle &other) const;
|
||||
|
|
@ -137,13 +139,15 @@ PUBLISHED:
|
|||
MAKE_SEQ_PROPERTY(parent_classes, get_num_parent_classes, get_parent_class);
|
||||
MAKE_SEQ_PROPERTY(child_classes, get_num_child_classes, get_child_class);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__reduce__() const);
|
||||
EXTENSION(void __setstate__(PyObject *));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
#ifdef HAVE_PYTHON
|
||||
PyObject *get_python_type() const;
|
||||
#endif
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void *allocate_array(size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
void *reallocate_array(void *ptr, size_t size) RETURNS_ALIGNED(MEMORY_HOOK_ALIGNMENT);
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ PUBLISHED:
|
|||
EXTENSION(Filename(PyObject *path));
|
||||
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
#endif
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
// Static constructors to explicitly create a filename that refers to a text
|
||||
// or binary file. This is in lieu of calling set_text() or set_binary() or
|
||||
|
|
@ -114,8 +114,10 @@ PUBLISHED:
|
|||
INLINE size_t length() const;
|
||||
INLINE char operator [] (size_t n) const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__repr__() const);
|
||||
EXTENSION(PyObject *__fspath__() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE std::string substr(size_t begin) const;
|
||||
INLINE std::string substr(size_t begin, size_t end) const;
|
||||
|
|
@ -202,7 +204,7 @@ PUBLISHED:
|
|||
bool scan_directory(vector_string &contents) const;
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *scan_directory() const);
|
||||
#endif
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
bool open_read(std::ifstream &stream) const;
|
||||
bool open_write(std::ofstream &stream, bool truncate = true) const;
|
||||
|
|
@ -274,7 +276,7 @@ protected:
|
|||
#ifdef ANDROID
|
||||
public:
|
||||
static std::string _internal_data_dir;
|
||||
#endif
|
||||
#endif // ANDROID
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -295,4 +297,4 @@ INLINE std::ostream &operator << (std::ostream &out, const Filename &n) {
|
|||
|
||||
#include "filename.I"
|
||||
|
||||
#endif
|
||||
#endif // !FILENAME_H
|
||||
|
|
|
|||
|
|
@ -54,28 +54,28 @@ PUBLISHED:
|
|||
INLINE static Encoding get_default_encoding();
|
||||
MAKE_PROPERTY(default_encoding, get_default_encoding, set_default_encoding);
|
||||
|
||||
#ifdef CPPPARSER
|
||||
#if defined(CPPPARSER) && defined(HAVE_PYTHON)
|
||||
EXTEND void set_text(PyObject *text);
|
||||
EXTEND void set_text(PyObject *text, Encoding encoding);
|
||||
#else
|
||||
#else // CPPPARSER && HAVE_PYTHON
|
||||
INLINE void set_text(const std::string &text);
|
||||
INLINE void set_text(const std::string &text, Encoding encoding);
|
||||
#endif
|
||||
#endif // CPPPARSER && HAVE_PYTHON
|
||||
INLINE void clear_text();
|
||||
INLINE bool has_text() const;
|
||||
|
||||
void make_upper();
|
||||
void make_lower();
|
||||
|
||||
#ifdef CPPPARSER
|
||||
#if defined(CPPPARSER) && defined(HAVE_PYTHON)
|
||||
EXTEND PyObject *get_text() const;
|
||||
EXTEND PyObject *get_text(Encoding encoding) const;
|
||||
EXTEND void append_text(PyObject *text);
|
||||
#else
|
||||
#else // CPPPARSER && HAVE_PYTHON
|
||||
INLINE std::string get_text() const;
|
||||
INLINE std::string get_text(Encoding encoding) const;
|
||||
INLINE void append_text(const std::string &text);
|
||||
#endif
|
||||
#endif // CPPPARSER && HAVE_PYTHON
|
||||
INLINE void append_unicode_char(char32_t character);
|
||||
INLINE size_t get_num_chars() const;
|
||||
INLINE int get_unicode_char(size_t index) const;
|
||||
|
|
@ -108,19 +108,19 @@ PUBLISHED:
|
|||
std::wstring get_wtext_as_ascii() const;
|
||||
bool is_wtext() const;
|
||||
|
||||
#ifdef CPPPARSER
|
||||
#if defined(CPPPARSER) && defined(HAVE_PYTHON)
|
||||
EXTEND static PyObject *encode_wchar(char32_t ch, Encoding encoding);
|
||||
EXTEND INLINE PyObject *encode_wtext(const std::wstring &wtext) const;
|
||||
EXTEND static PyObject *encode_wtext(const std::wstring &wtext, Encoding encoding);
|
||||
EXTEND INLINE PyObject *decode_text(PyObject *text) const;
|
||||
EXTEND static PyObject *decode_text(PyObject *text, Encoding encoding);
|
||||
#else
|
||||
#else // CPPPARSER && HAVE_PYTHON
|
||||
static std::string encode_wchar(char32_t ch, Encoding encoding);
|
||||
INLINE std::string encode_wtext(const std::wstring &wtext) const;
|
||||
static std::string encode_wtext(const std::wstring &wtext, Encoding encoding);
|
||||
INLINE std::wstring decode_text(const std::string &text) const;
|
||||
static std::wstring decode_text(const std::string &text, Encoding encoding);
|
||||
#endif
|
||||
#endif // CPPPARSER && HAVE_PYTHON
|
||||
|
||||
MAKE_PROPERTY(text, get_text, set_text);
|
||||
|
||||
|
|
@ -156,4 +156,4 @@ INLINE std::ostream & operator << (std::ostream &out, const std::wstring &str);
|
|||
|
||||
#include "textEncoder.I"
|
||||
|
||||
#endif
|
||||
#endif // !TEXTENCODER_H
|
||||
|
|
|
|||
|
|
@ -44,7 +44,9 @@ PUBLISHED:
|
|||
|
||||
INLINE size_t get_num_words() const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
protected:
|
||||
INLINE const ConfigDeclaration *get_default_value() const;
|
||||
|
|
@ -74,4 +76,4 @@ protected:
|
|||
|
||||
#include "configVariable.I"
|
||||
|
||||
#endif
|
||||
#endif // !CONFIGVARIABLE_H
|
||||
|
|
|
|||
|
|
@ -68,11 +68,12 @@ PUBLISHED:
|
|||
|
||||
BLOCKING void skip_bytes(size_t size);
|
||||
BLOCKING size_t extract_bytes(unsigned char *into, size_t size);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *extract_bytes(size_t size));
|
||||
|
||||
EXTENSION(PyObject *readline());
|
||||
EXTENSION(PyObject *readlines());
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
public:
|
||||
BLOCKING vector_uchar extract_bytes(size_t size);
|
||||
BLOCKING std::string readline();
|
||||
|
|
@ -84,4 +85,4 @@ private:
|
|||
|
||||
#include "streamReader.I"
|
||||
|
||||
#endif
|
||||
#endif // !STREAMREADER_H
|
||||
|
|
|
|||
|
|
@ -70,7 +70,9 @@ PUBLISHED:
|
|||
BLOCKING INLINE void add_fixed_string(const std::string &str, size_t size);
|
||||
|
||||
BLOCKING void pad_bytes(size_t size);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(void append_data(PyObject *data));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
BLOCKING INLINE void flush();
|
||||
|
||||
|
|
@ -87,4 +89,4 @@ private:
|
|||
|
||||
#include "streamWriter.I"
|
||||
|
||||
#endif
|
||||
#endif // !STREAMWRITER_H
|
||||
|
|
|
|||
|
|
@ -39,7 +39,8 @@
|
|||
// Ask all the windows whether they are OK to be closed.
|
||||
bool should_close = true;
|
||||
for (NSWindow *window in [app windows]) {
|
||||
if (![[window delegate] windowShouldClose:window]) {
|
||||
id<NSWindowDelegate> delegate = [window delegate];
|
||||
if (delegate != nil && ![delegate windowShouldClose:window]) {
|
||||
should_close = false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,14 +15,6 @@
|
|||
|
||||
TypeHandle CollisionHandler::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
CollisionHandler::
|
||||
CollisionHandler() {
|
||||
_wants_all_potential_collidees = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will be called by the CollisionTraverser before a new traversal is begun.
|
||||
* It instructs the handler to reset itself in preparation for a number of
|
||||
|
|
|
|||
|
|
@ -28,9 +28,10 @@ class CollisionEntry;
|
|||
* dispatch detected collisions.
|
||||
*/
|
||||
class EXPCL_PANDA_COLLIDE CollisionHandler : public TypedReferenceCount {
|
||||
public:
|
||||
CollisionHandler();
|
||||
PUBLISHED:
|
||||
CollisionHandler() = default;
|
||||
|
||||
public:
|
||||
virtual void begin_group();
|
||||
virtual void add_entry(CollisionEntry *entry);
|
||||
virtual bool end_group();
|
||||
|
|
@ -38,12 +39,10 @@ public:
|
|||
INLINE bool wants_all_potential_collidees() const;
|
||||
INLINE void set_root(const NodePath &root);
|
||||
|
||||
PUBLISHED:
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
|
||||
public:
|
||||
static void init_type() {
|
||||
TypedReferenceCount::init_type();
|
||||
register_type(_type_handle, "CollisionHandler",
|
||||
|
|
@ -55,7 +54,7 @@ public:
|
|||
virtual TypeHandle force_init_type() {init_type(); return get_class_type();}
|
||||
|
||||
protected:
|
||||
bool _wants_all_potential_collidees;
|
||||
bool _wants_all_potential_collidees = false;
|
||||
const NodePath *_root;
|
||||
|
||||
private:
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ set(P3DISPLAY_HEADERS
|
|||
windowHandle.I windowHandle.h
|
||||
windowProperties.I windowProperties.h
|
||||
renderBuffer.h
|
||||
screenshotRequest.I screenshotRequest.h
|
||||
stereoDisplayRegion.I stereoDisplayRegion.h
|
||||
displaySearchParameters.h
|
||||
displayInformation.h
|
||||
|
|
@ -61,6 +62,7 @@ set(P3DISPLAY_SOURCES
|
|||
parasiteBuffer.cxx
|
||||
windowHandle.cxx
|
||||
windowProperties.cxx
|
||||
screenshotRequest.cxx
|
||||
stereoDisplayRegion.cxx
|
||||
subprocessWindow.cxx
|
||||
touchInfo.cxx
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@
|
|||
#include "nativeWindowHandle.h"
|
||||
#include "parasiteBuffer.h"
|
||||
#include "pandaSystem.h"
|
||||
#include "screenshotRequest.h"
|
||||
#include "stereoDisplayRegion.h"
|
||||
#include "subprocessWindow.h"
|
||||
#include "windowHandle.h"
|
||||
|
|
@ -534,6 +535,7 @@ init_libdisplay() {
|
|||
MouseAndKeyboard::init_type();
|
||||
NativeWindowHandle::init_type();
|
||||
ParasiteBuffer::init_type();
|
||||
ScreenshotRequest::init_type();
|
||||
StandardMunger::init_type();
|
||||
StereoDisplayRegion::init_type();
|
||||
#ifdef SUPPORT_SUBPROCESS_WINDOW
|
||||
|
|
|
|||
|
|
@ -144,8 +144,10 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(float_color, get_float_color, set_float_color);
|
||||
MAKE_PROPERTY(float_depth, get_float_depth, set_float_depth);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__getstate__() const);
|
||||
EXTENSION(void __setstate__(PyObject *self, PyObject *state));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
// Other.
|
||||
|
||||
|
|
@ -181,4 +183,4 @@ INLINE std::ostream &operator << (std::ostream &out, const FrameBufferProperties
|
|||
|
||||
#include "frameBufferProperties.I"
|
||||
|
||||
#endif
|
||||
#endif // !FRAMEBUFFERPROPERTIES_H
|
||||
|
|
|
|||
|
|
@ -1419,6 +1419,8 @@ cull_and_draw_together(GraphicsEngine::Windows wlist,
|
|||
}
|
||||
|
||||
if (win->begin_frame(GraphicsOutput::FM_render, current_thread)) {
|
||||
win->copy_async_screenshot();
|
||||
|
||||
if (win->is_any_clear_active()) {
|
||||
GraphicsStateGuardian *gsg = win->get_gsg();
|
||||
PStatGPUTimer timer(gsg, win->get_clear_window_pcollector(), current_thread);
|
||||
|
|
@ -1720,6 +1722,9 @@ draw_bins(const GraphicsEngine::Windows &wlist, Thread *current_thread) {
|
|||
// a current context for PStatGPUTimer to work.
|
||||
{
|
||||
PStatGPUTimer timer(gsg, win->get_draw_window_pcollector(), current_thread);
|
||||
|
||||
win->copy_async_screenshot();
|
||||
|
||||
if (win->is_any_clear_active()) {
|
||||
PStatGPUTimer timer(gsg, win->get_clear_window_pcollector(), current_thread);
|
||||
win->get_gsg()->push_group_marker("Clear");
|
||||
|
|
|
|||
|
|
@ -976,6 +976,43 @@ make_cube_map(const string &name, int size, NodePath &camera_rig,
|
|||
return buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Like save_screenshot, but performs both the texture transfer and the saving
|
||||
* to disk in the background. Returns a future that can be awaited.
|
||||
*
|
||||
* This captures the frame that was last submitted by the App stage to the
|
||||
* render_frame() call. This may not be the latest frame shown on the screen
|
||||
* if the multi-threaded pipeline is used, in which case the request may take
|
||||
* several frames extra to complete.
|
||||
*/
|
||||
PT(ScreenshotRequest) GraphicsOutput::
|
||||
save_async_screenshot(const Filename &filename, const std::string &image_comment) {
|
||||
PT(ScreenshotRequest) request = get_async_screenshot();
|
||||
request->add_output_file(filename, image_comment);
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to obtain a new Texture object containing the previously rendered frame.
|
||||
* Unlike get_screenshot, this works asynchronously, meaning that the contents
|
||||
* are transferred in the background. Returns a future that can be awaited.
|
||||
*
|
||||
* This captures the frame that was last submitted by the App stage to the
|
||||
* render_frame() call. This may not be the latest frame shown on the screen
|
||||
* if the multi-threaded pipeline is used, in which case the request may take
|
||||
* several frames extra to complete.
|
||||
*/
|
||||
PT(ScreenshotRequest) GraphicsOutput::
|
||||
get_async_screenshot() {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
CDWriter cdata(_cycler, current_thread);
|
||||
if (cdata->_screenshot_request == nullptr) {
|
||||
PT(Texture) texture = new Texture("screenshot of " + get_name());
|
||||
cdata->_screenshot_request = new ScreenshotRequest(texture);
|
||||
}
|
||||
return cdata->_screenshot_request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a PandaNode containing a square polygon. The dimensions are
|
||||
* (-1,0,-1) to (1,0,1). The texture coordinates are such that the texture of
|
||||
|
|
@ -1468,6 +1505,56 @@ copy_to_textures() {
|
|||
return okflag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Do the necessary copies for the get_async_screenshot request.
|
||||
*/
|
||||
void GraphicsOutput::
|
||||
copy_async_screenshot() {
|
||||
Thread *current_thread = Thread::get_current_thread();
|
||||
PT(ScreenshotRequest) request;
|
||||
{
|
||||
CDWriter cdata(_cycler, current_thread);
|
||||
if (cdata->_screenshot_request == nullptr) {
|
||||
return;
|
||||
}
|
||||
request = std::move(cdata->_screenshot_request);
|
||||
cdata->_screenshot_request.clear();
|
||||
}
|
||||
|
||||
// Make sure it is cleared from upstream stages as well.
|
||||
OPEN_ITERATE_UPSTREAM_ONLY(_cycler, current_thread) {
|
||||
CDStageWriter cdata(_cycler, pipeline_stage, current_thread);
|
||||
if (cdata->_screenshot_request == request) {
|
||||
cdata->_screenshot_request.clear();
|
||||
}
|
||||
}
|
||||
CLOSE_ITERATE_UPSTREAM_ONLY(_cycler);
|
||||
|
||||
PStatTimer timer(_copy_texture_pcollector);
|
||||
|
||||
RenderBuffer buffer = _gsg->get_render_buffer(get_draw_buffer_type(),
|
||||
get_fb_properties());
|
||||
DisplayRegion *dr = _overlay_display_region;
|
||||
|
||||
Texture *texture = request->get_result();
|
||||
|
||||
if (_fb_properties.is_stereo()) {
|
||||
// We've got two texture views to copy.
|
||||
texture->set_num_views(2);
|
||||
|
||||
RenderBuffer left(_gsg, buffer._buffer_type & ~RenderBuffer::T_right);
|
||||
RenderBuffer right(_gsg, buffer._buffer_type & ~RenderBuffer::T_left);
|
||||
|
||||
_gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page,
|
||||
dr, left, request);
|
||||
_gsg->framebuffer_copy_to_ram(texture, 1, _target_tex_page,
|
||||
dr, right, request);
|
||||
} else {
|
||||
_gsg->framebuffer_copy_to_ram(texture, 0, _target_tex_page,
|
||||
dr, buffer, request);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a GeomVertexData for a texture card.
|
||||
*/
|
||||
|
|
@ -1653,7 +1740,8 @@ CData(const GraphicsOutput::CData ©) :
|
|||
_active(copy._active),
|
||||
_one_shot_frame(copy._one_shot_frame),
|
||||
_active_display_regions(copy._active_display_regions),
|
||||
_active_display_regions_stale(copy._active_display_regions_stale)
|
||||
_active_display_regions_stale(copy._active_display_regions_stale),
|
||||
_screenshot_request(copy._screenshot_request)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "pipelineCycler.h"
|
||||
#include "updateSeq.h"
|
||||
#include "asyncFuture.h"
|
||||
#include "screenshotRequest.h"
|
||||
|
||||
class PNMImage;
|
||||
class GraphicsEngine;
|
||||
|
|
@ -239,6 +240,9 @@ PUBLISHED:
|
|||
const Filename &filename, const std::string &image_comment = "");
|
||||
INLINE bool get_screenshot(PNMImage &image);
|
||||
INLINE PT(Texture) get_screenshot();
|
||||
PT(ScreenshotRequest) save_async_screenshot(const Filename &filename,
|
||||
const std::string &image_comment = "");
|
||||
PT(ScreenshotRequest) get_async_screenshot();
|
||||
|
||||
NodePath get_texture_card();
|
||||
|
||||
|
|
@ -298,6 +302,7 @@ protected:
|
|||
void prepare_for_deletion();
|
||||
void promote_to_copy_texture();
|
||||
bool copy_to_textures();
|
||||
void copy_async_screenshot();
|
||||
|
||||
INLINE void begin_frame_spam(FrameMode mode);
|
||||
INLINE void end_frame_spam(FrameMode mode);
|
||||
|
|
@ -392,6 +397,8 @@ protected:
|
|||
int _one_shot_frame;
|
||||
ActiveDisplayRegions _active_display_regions;
|
||||
bool _active_display_regions_stale;
|
||||
|
||||
PT(ScreenshotRequest) _screenshot_request;
|
||||
};
|
||||
PipelineCycler<CData> _cycler;
|
||||
typedef CycleDataLockedReader<CData> CDLockedReader;
|
||||
|
|
|
|||
|
|
@ -52,7 +52,9 @@ PUBLISHED:
|
|||
|
||||
INLINE static GraphicsPipeSelection *get_global_ptr();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__reduce__() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
typedef PT(GraphicsPipe) PipeConstructorFunc();
|
||||
|
|
@ -94,4 +96,4 @@ private:
|
|||
|
||||
#include "graphicsPipeSelection.I"
|
||||
|
||||
#endif
|
||||
#endif // !GRAPHICSPIPESELECTION_H
|
||||
|
|
|
|||
|
|
@ -3037,11 +3037,15 @@ framebuffer_copy_to_texture(Texture *, int, int, const DisplayRegion *,
|
|||
* into system memory, not texture memory. Returns true on success, false on
|
||||
* failure.
|
||||
*
|
||||
* If a future is given, the operation may be scheduled to occur in the
|
||||
* background, in which case the texture will be passed as the result of the
|
||||
* future when the operation is complete.
|
||||
*
|
||||
* This completely redefines the ram image of the indicated texture.
|
||||
*/
|
||||
bool GraphicsStateGuardian::
|
||||
framebuffer_copy_to_ram(Texture *, int, int, const DisplayRegion *,
|
||||
const RenderBuffer &) {
|
||||
const RenderBuffer &, ScreenshotRequest *) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -254,7 +254,9 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(texture_quality_override, get_texture_quality_override,
|
||||
set_texture_quality_override);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_prepared_textures() const);
|
||||
#endif // HAVE_PYTHON
|
||||
typedef bool TextureCallback(TextureContext *tc, void *callback_arg);
|
||||
void traverse_prepared_textures(TextureCallback *func, void *callback_arg);
|
||||
|
||||
|
|
@ -263,7 +265,7 @@ PUBLISHED:
|
|||
void clear_flash_texture();
|
||||
Texture *get_flash_texture() const;
|
||||
MAKE_PROPERTY(flash_texture, get_flash_texture, set_flash_texture);
|
||||
#endif
|
||||
#endif // !NDEBUG || !CPPPARSER
|
||||
|
||||
PUBLISHED:
|
||||
virtual bool has_extension(const std::string &extension) const;
|
||||
|
|
@ -424,7 +426,8 @@ public:
|
|||
virtual bool framebuffer_copy_to_texture
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
|
||||
virtual bool framebuffer_copy_to_ram
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb,
|
||||
ScreenshotRequest *request = nullptr);
|
||||
|
||||
virtual void bind_light(PointLight *light_obj, const NodePath &light,
|
||||
int light_id);
|
||||
|
|
@ -444,7 +447,7 @@ public:
|
|||
#ifdef DO_PSTATS
|
||||
static void init_frame_pstats();
|
||||
PStatThread get_pstats_thread();
|
||||
#endif
|
||||
#endif // DO_PSTATS
|
||||
|
||||
protected:
|
||||
virtual void reissue_transforms();
|
||||
|
|
@ -601,7 +604,7 @@ protected:
|
|||
#ifdef DO_PSTATS
|
||||
int _pstats_gpu_thread;
|
||||
bool _timer_queries_active;
|
||||
#endif
|
||||
#endif // DO_PSTATS
|
||||
|
||||
bool _copy_texture_inverted;
|
||||
bool _supports_multisample;
|
||||
|
|
@ -650,9 +653,9 @@ protected:
|
|||
|
||||
#ifndef NDEBUG
|
||||
PT(Texture) _flash_texture;
|
||||
#else
|
||||
#else // !NDEBUG
|
||||
PT(Texture) _flash_texture_unused;
|
||||
#endif
|
||||
#endif // !NDEBUG
|
||||
|
||||
public:
|
||||
// Statistics
|
||||
|
|
@ -763,4 +766,4 @@ EXPCL_PANDA_DISPLAY std::ostream &operator << (std::ostream &out, GraphicsStateG
|
|||
|
||||
#include "graphicsStateGuardian.I"
|
||||
|
||||
#endif
|
||||
#endif // !GRAPHICSSTATEGUARDIAN_H
|
||||
|
|
|
|||
|
|
@ -56,7 +56,9 @@ PUBLISHED:
|
|||
void clear_rejected_properties();
|
||||
WindowProperties get_rejected_properties() const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(void request_properties(PyObject *args, PyObject *kwds));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE bool is_closed() const;
|
||||
virtual bool is_active() const;
|
||||
|
|
@ -169,7 +171,7 @@ private:
|
|||
#ifdef HAVE_PYTHON
|
||||
typedef pset<GraphicsWindowProc*> PythonWinProcClasses;
|
||||
PythonWinProcClasses _python_window_proc_classes;
|
||||
#endif
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
|
|
@ -194,4 +196,4 @@ private:
|
|||
|
||||
#include "graphicsWindow.I"
|
||||
|
||||
#endif /* GRAPHICSWINDOW_H */
|
||||
#endif // !GRAPHICSWINDOW_H
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@
|
|||
#include "parasiteBuffer.cxx"
|
||||
#include "standardMunger.cxx"
|
||||
#include "touchInfo.cxx"
|
||||
#include "screenshotRequest.cxx"
|
||||
#include "stereoDisplayRegion.cxx"
|
||||
#include "subprocessWindow.cxx"
|
||||
#ifdef IS_OSX
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
/**
|
||||
* 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 screenshotRequest.I
|
||||
* @author rdb
|
||||
* @date 2022-12-26
|
||||
*/
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
INLINE ScreenshotRequest::
|
||||
ScreenshotRequest(Texture *tex) :
|
||||
_frame_number(ClockObject::get_global_clock()->get_frame_count()) {
|
||||
_result = tex;
|
||||
_result_ref = tex;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the frame number in which the request originated.
|
||||
*/
|
||||
INLINE int ScreenshotRequest::
|
||||
get_frame_number() const {
|
||||
return _frame_number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resulting texture. Can always be called.
|
||||
*/
|
||||
INLINE Texture *ScreenshotRequest::
|
||||
get_result() const {
|
||||
return (Texture *)_result;
|
||||
}
|
||||
|
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* 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 screenshotRequest.cxx
|
||||
* @author rdb
|
||||
* @date 2022-12-26
|
||||
*/
|
||||
|
||||
#include "screenshotRequest.h"
|
||||
#include "lightMutexHolder.h"
|
||||
#include "pnmImage.h"
|
||||
#include "texture.h"
|
||||
|
||||
TypeHandle ScreenshotRequest::_type_handle;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void ScreenshotRequest::
|
||||
set_view_data(int view, const void *ptr) {
|
||||
const int z = 0;
|
||||
|
||||
Texture *tex = get_result();
|
||||
PTA_uchar new_image = tex->modify_ram_image();
|
||||
unsigned char *image_ptr = new_image.p();
|
||||
size_t image_size = tex->get_ram_image_size();
|
||||
if (z >= 0 || view > 0) {
|
||||
image_size = tex->get_expected_ram_page_size();
|
||||
if (z >= 0) {
|
||||
image_ptr += z * image_size;
|
||||
}
|
||||
if (view > 0) {
|
||||
image_ptr += (view * tex->get_z_size()) * image_size;
|
||||
nassertd(view < tex->get_num_views()) {
|
||||
if (set_future_state(FS_cancelled)) {
|
||||
notify_done(false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
memcpy(image_ptr, ptr, image_size);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void ScreenshotRequest::
|
||||
finish() {
|
||||
Texture *tex = get_result();
|
||||
|
||||
++_got_num_views;
|
||||
if (_got_num_views < tex->get_num_views()) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
LightMutexHolder holder(_lock);
|
||||
if (!_output_files.empty()) {
|
||||
PNMImage image;
|
||||
tex->store(image);
|
||||
|
||||
for (const auto &item : _output_files) {
|
||||
image.set_comment(item.second);
|
||||
image.write(item.first);
|
||||
}
|
||||
}
|
||||
|
||||
AsyncFuture::set_result(tex);
|
||||
_output_files.clear();
|
||||
|
||||
if (!set_future_state(FS_finished)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
notify_done(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a filename to write the screenshot to when it is available. If the
|
||||
* request is already done, performs the write synchronously.
|
||||
*/
|
||||
void ScreenshotRequest::
|
||||
add_output_file(const Filename &filename, const std::string &image_comment) {
|
||||
if (!done()) {
|
||||
LightMutexHolder holder(_lock);
|
||||
if (!done()) {
|
||||
_output_files[filename] = image_comment;
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Was already done, write it right away.
|
||||
Texture *tex = get_result();
|
||||
PNMImage image;
|
||||
tex->store(image);
|
||||
image.set_comment(image_comment);
|
||||
image.write(filename);
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
/**
|
||||
* 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 screenshotRequest.h
|
||||
* @author rdb
|
||||
* @date 2022-12-26
|
||||
*/
|
||||
|
||||
#ifndef SCREENSHOTREQUEST_H
|
||||
#define SCREENSHOTREQUEST_H
|
||||
|
||||
#include "pandabase.h"
|
||||
|
||||
#include "asyncFuture.h"
|
||||
#include "clockObject.h"
|
||||
#include "filename.h"
|
||||
#include "lightMutex.h"
|
||||
#include "pmap.h"
|
||||
#include "texture.h"
|
||||
|
||||
/**
|
||||
* A class representing an asynchronous request to save a screenshot.
|
||||
*/
|
||||
class EXPCL_PANDA_PGRAPH ScreenshotRequest : public AsyncFuture {
|
||||
public:
|
||||
INLINE ScreenshotRequest(Texture *tex);
|
||||
|
||||
INLINE int get_frame_number() const;
|
||||
INLINE Texture *get_result() const;
|
||||
|
||||
void set_view_data(int view, const void *ptr);
|
||||
void finish();
|
||||
|
||||
PUBLISHED:
|
||||
void add_output_file(const Filename &filename,
|
||||
const std::string &image_comment = "");
|
||||
|
||||
private:
|
||||
// It's possible to call save_screenshot multiple times in the same frame, so
|
||||
// rather than have to store a vector of request objects, we just allow
|
||||
// storing multiple filenames to handle this corner case.
|
||||
LightMutex _lock;
|
||||
pmap<Filename, std::string> _output_files;
|
||||
int _got_num_views = 0;
|
||||
|
||||
int _frame_number = 0;
|
||||
|
||||
public:
|
||||
static TypeHandle get_class_type() {
|
||||
return _type_handle;
|
||||
}
|
||||
static void init_type() {
|
||||
AsyncFuture::init_type();
|
||||
register_type(_type_handle, "ScreenshotRequest",
|
||||
AsyncFuture::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 "screenshotRequest.I"
|
||||
|
||||
#endif
|
||||
|
|
@ -44,7 +44,9 @@ PUBLISHED:
|
|||
M_confined,
|
||||
};
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(WindowProperties(PyObject *self, PyObject *args, PyObject *kwds));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
PUBLISHED:
|
||||
void operator = (const WindowProperties ©);
|
||||
|
|
@ -70,9 +72,9 @@ PUBLISHED:
|
|||
INLINE void set_origin(int x_origin, int y_origin);
|
||||
#ifdef CPPPARSER
|
||||
INLINE LPoint2i get_origin() const;
|
||||
#else
|
||||
#else // CPPPARSER
|
||||
INLINE const LPoint2i &get_origin() const;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
INLINE int get_x_origin() const;
|
||||
INLINE int get_y_origin() const;
|
||||
INLINE bool has_origin() const;
|
||||
|
|
@ -83,9 +85,9 @@ PUBLISHED:
|
|||
INLINE void set_size(int x_size, int y_size);
|
||||
#ifdef CPPPARSER
|
||||
INLINE LVector2i get_size() const;
|
||||
#else
|
||||
#else // CPPPARSER
|
||||
INLINE const LVector2i &get_size() const;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
INLINE int get_x_size() const;
|
||||
INLINE int get_y_size() const;
|
||||
INLINE bool has_size() const;
|
||||
|
|
@ -102,9 +104,9 @@ PUBLISHED:
|
|||
INLINE void set_title(const std::string &title);
|
||||
#ifdef CPPPARSER
|
||||
INLINE std::string get_title() const;
|
||||
#else
|
||||
#else // CPPPARSER
|
||||
INLINE const std::string &get_title() const;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
INLINE bool has_title() const;
|
||||
INLINE void clear_title();
|
||||
MAKE_PROPERTY2(title, has_title, get_title, set_title, clear_title);
|
||||
|
|
@ -172,9 +174,9 @@ PUBLISHED:
|
|||
INLINE void set_icon_filename(const Filename &icon_filename);
|
||||
#ifdef CPPPARSER
|
||||
INLINE Filename get_icon_filename() const;
|
||||
#else
|
||||
#else // CPPPARSER
|
||||
INLINE const Filename &get_icon_filename() const;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
INLINE bool has_icon_filename() const;
|
||||
INLINE void clear_icon_filename();
|
||||
MAKE_PROPERTY2(icon_filename, has_icon_filename, get_icon_filename,
|
||||
|
|
@ -183,9 +185,9 @@ PUBLISHED:
|
|||
INLINE void set_cursor_filename(const Filename &cursor_filename);
|
||||
#ifdef CPPPARSER
|
||||
INLINE Filename get_cursor_filename() const;
|
||||
#else
|
||||
#else // CPPPARSER
|
||||
INLINE const Filename &get_cursor_filename() const;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
INLINE bool has_cursor_filename() const;
|
||||
INLINE void clear_cursor_filename();
|
||||
MAKE_PROPERTY2(cursor_filename, has_cursor_filename, get_cursor_filename,
|
||||
|
|
@ -205,8 +207,10 @@ PUBLISHED:
|
|||
MAKE_PROPERTY2(parent_window, has_parent_window, get_parent_window,
|
||||
set_parent_window, clear_parent_window);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__getstate__(PyObject *self) const);
|
||||
EXTENSION(void __setstate__(PyObject *self, PyObject *state));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void add_properties(const WindowProperties &other);
|
||||
|
||||
|
|
@ -278,4 +282,4 @@ INLINE std::ostream &operator << (std::ostream &out, const WindowProperties &pro
|
|||
|
||||
#include "windowProperties.I"
|
||||
|
||||
#endif
|
||||
#endif // !WINDOWPROPERTIES_H
|
||||
|
|
|
|||
|
|
@ -1988,8 +1988,17 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z,
|
|||
*/
|
||||
bool DXGraphicsStateGuardian9::
|
||||
framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
||||
const DisplayRegion *dr, const RenderBuffer &rb) {
|
||||
return do_framebuffer_copy_to_ram(tex, view, z, dr, rb, false);
|
||||
const DisplayRegion *dr, const RenderBuffer &rb,
|
||||
ScreenshotRequest *request) {
|
||||
bool success = do_framebuffer_copy_to_ram(tex, view, z, dr, rb, false);
|
||||
if (request != nullptr) {
|
||||
if (success) {
|
||||
request->finish();
|
||||
} else {
|
||||
request->cancel();
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -127,7 +127,8 @@ public:
|
|||
const RenderBuffer &rb);
|
||||
virtual bool framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
||||
const DisplayRegion *dr,
|
||||
const RenderBuffer &rb);
|
||||
const RenderBuffer &rb,
|
||||
ScreenshotRequest *request);
|
||||
bool do_framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
||||
const DisplayRegion *dr,
|
||||
const RenderBuffer &rb,
|
||||
|
|
|
|||
|
|
@ -62,12 +62,16 @@ PUBLISHED:
|
|||
INLINE AsyncFuture();
|
||||
virtual ~AsyncFuture();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(static PyObject *__await__(PyObject *self));
|
||||
EXTENSION(static PyObject *__iter__(PyObject *self));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE bool done() const;
|
||||
INLINE bool cancelled() const;
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *result(PyObject *self, PyObject *timeout = Py_None) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
virtual bool cancel();
|
||||
|
||||
|
|
@ -75,9 +79,11 @@ PUBLISHED:
|
|||
INLINE const std::string &get_done_event() const;
|
||||
MAKE_PROPERTY(done_event, get_done_event, set_done_event);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *add_done_callback(PyObject *self, PyObject *fn));
|
||||
|
||||
EXTENSION(static PyObject *gather(PyObject *args));
|
||||
#endif // HAVE_PYTHON
|
||||
INLINE static PT(AsyncFuture) shield(PT(AsyncFuture) future);
|
||||
|
||||
virtual void output(std::ostream &out) const;
|
||||
|
|
@ -85,8 +91,9 @@ PUBLISHED:
|
|||
BLOCKING void wait();
|
||||
BLOCKING void wait(double timeout);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(void set_result(PyObject *));
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
public:
|
||||
INLINE void set_result(std::nullptr_t);
|
||||
INLINE void set_result(TypedReferenceCount *result);
|
||||
|
|
@ -201,4 +208,4 @@ private:
|
|||
|
||||
#include "asyncFuture.I"
|
||||
|
||||
#endif
|
||||
#endif // !ASYNCFUTURE_H
|
||||
|
|
|
|||
|
|
@ -21,6 +21,46 @@ is_started() const {
|
|||
return (_state == S_started);
|
||||
}
|
||||
|
||||
#ifndef CPPPARSER
|
||||
/**
|
||||
* Adds a new task to the task chain which calls the indicated callable.
|
||||
* This method is defined as a more convenient alternative to subclassing
|
||||
* AsyncTask.
|
||||
*
|
||||
* This given callable allowed to be any object defining a call operator that
|
||||
* accepts an AsyncTask pointer and returns a DoneStatus.
|
||||
*
|
||||
* Returns the newly created AsyncTask object.
|
||||
*
|
||||
* @since 1.11.0
|
||||
*/
|
||||
template<class Callable>
|
||||
INLINE AsyncTask *AsyncTaskChain::
|
||||
add(Callable callable, const std::string &name, int sort, int priority) {
|
||||
class InlineTask final : public AsyncTask {
|
||||
public:
|
||||
InlineTask(Callable callable, const std::string &name, int sort, int priority) :
|
||||
AsyncTask(name),
|
||||
_callable(std::move(callable)) {
|
||||
_sort = sort;
|
||||
_priority = priority;
|
||||
}
|
||||
|
||||
ALLOC_DELETED_CHAIN(InlineTask);
|
||||
|
||||
private:
|
||||
virtual DoneStatus do_task() override final {
|
||||
return _callable(this);
|
||||
}
|
||||
|
||||
Callable _callable;
|
||||
};
|
||||
AsyncTask *task = new InlineTask(std::move(callable), name, sort, priority);
|
||||
add(task);
|
||||
return task;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the time at which the next sleeping thread will awaken, or -1 if
|
||||
* there are no sleeping threads. Assumes the lock is already held.
|
||||
|
|
|
|||
|
|
@ -37,14 +37,15 @@ PStatCollector AsyncTaskChain::_wait_pcollector("Wait");
|
|||
*
|
||||
*/
|
||||
AsyncTaskChain::
|
||||
AsyncTaskChain(AsyncTaskManager *manager, const string &name) :
|
||||
AsyncTaskChain(AsyncTaskManager *manager, const string &name, int num_threads,
|
||||
ThreadPriority thread_priority) :
|
||||
Namable(name),
|
||||
_manager(manager),
|
||||
_cvar(manager->_lock),
|
||||
_tick_clock(false),
|
||||
_timeslice_priority(false),
|
||||
_num_threads(0),
|
||||
_thread_priority(TP_normal),
|
||||
_num_threads(num_threads),
|
||||
_thread_priority(thread_priority),
|
||||
_frame_budget(-1.0),
|
||||
_frame_sync(false),
|
||||
_num_busy_threads(0),
|
||||
|
|
@ -288,6 +289,27 @@ start_threads() {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the indicated task to the active queue. The task must be inactive, and
|
||||
* may not have been added to any queue (including the current one).
|
||||
*/
|
||||
void AsyncTaskChain::
|
||||
add(AsyncTask *task) {
|
||||
nassertv(task->_manager == nullptr && task->_state == AsyncTask::S_inactive);
|
||||
nassertv(task->is_runnable());
|
||||
|
||||
task->_chain_name = get_name();
|
||||
task->upon_birth(_manager);
|
||||
|
||||
if (task_cat.is_debug()) {
|
||||
task_cat.debug()
|
||||
<< "Adding " << *task << "\n";
|
||||
}
|
||||
|
||||
MutexHolder holder(_manager->_lock);
|
||||
do_add(task);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the indicated task has been added to this AsyncTaskChain,
|
||||
* false otherwise.
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ class AsyncTaskManager;
|
|||
*/
|
||||
class EXPCL_PANDA_EVENT AsyncTaskChain : public TypedReferenceCount, public Namable {
|
||||
public:
|
||||
AsyncTaskChain(AsyncTaskManager *manager, const std::string &name);
|
||||
AsyncTaskChain(AsyncTaskManager *manager, const std::string &name,
|
||||
int num_threads=0, ThreadPriority thread_priority=TP_normal);
|
||||
~AsyncTaskChain();
|
||||
|
||||
PUBLISHED:
|
||||
|
|
@ -76,6 +77,12 @@ PUBLISHED:
|
|||
void start_threads();
|
||||
INLINE bool is_started() const;
|
||||
|
||||
void add(AsyncTask *task);
|
||||
#ifndef CPPPARSER
|
||||
template<class Callable>
|
||||
INLINE AsyncTask *add(Callable callable, const std::string &name,
|
||||
int sort = 0, int priority = 0);
|
||||
#endif
|
||||
bool has_task(AsyncTask *task) const;
|
||||
|
||||
BLOCKING void wait_for_tasks();
|
||||
|
|
|
|||
|
|
@ -47,23 +47,10 @@ get_clock() {
|
|||
*/
|
||||
template<class Callable>
|
||||
INLINE AsyncTask *AsyncTaskManager::
|
||||
add(const std::string &name, Callable callable) {
|
||||
class InlineTask final : public AsyncTask {
|
||||
public:
|
||||
InlineTask(Callable callable) : _callable(std::move(callable)) {}
|
||||
|
||||
ALLOC_DELETED_CHAIN(InlineTask);
|
||||
|
||||
private:
|
||||
virtual DoneStatus do_task() override final {
|
||||
return _callable(this);
|
||||
}
|
||||
|
||||
Callable _callable;
|
||||
};
|
||||
AsyncTask *task = new InlineTask(std::move(callable));
|
||||
add(task);
|
||||
return task;
|
||||
add(Callable callable, const std::string &name, int sort, int priority) {
|
||||
AsyncTaskChain *chain = make_task_chain("default");
|
||||
nassertr(chain != nullptr, nullptr);
|
||||
return chain->add(std::move(callable), name, sort, priority);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
|||
|
|
@ -131,6 +131,17 @@ make_task_chain(const string &name) {
|
|||
return do_make_task_chain(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new threaded AsyncTaskChain of the indicated name and stores it
|
||||
* within the AsyncTaskManager. If a task chain with this name already exists,
|
||||
* returns it instead.
|
||||
*/
|
||||
AsyncTaskChain *AsyncTaskManager::
|
||||
make_task_chain(const string &name, int num_threads, ThreadPriority thread_priority) {
|
||||
MutexHolder holder(_lock);
|
||||
return do_make_task_chain(name, num_threads, thread_priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches a new AsyncTaskChain of the indicated name and returns it if it
|
||||
* exists, or NULL otherwise.
|
||||
|
|
@ -562,8 +573,8 @@ write(std::ostream &out, int indent_level) const {
|
|||
* Assumes the lock is held.
|
||||
*/
|
||||
AsyncTaskChain *AsyncTaskManager::
|
||||
do_make_task_chain(const string &name) {
|
||||
PT(AsyncTaskChain) chain = new AsyncTaskChain(this, name);
|
||||
do_make_task_chain(const string &name, int num_threads, ThreadPriority thread_priority) {
|
||||
PT(AsyncTaskChain) chain = new AsyncTaskChain(this, name, num_threads, thread_priority);
|
||||
|
||||
TaskChains::const_iterator tci = _task_chains.insert(chain).first;
|
||||
return (*tci);
|
||||
|
|
|
|||
|
|
@ -60,13 +60,16 @@ PUBLISHED:
|
|||
AsyncTaskChain *get_task_chain(int n) const;
|
||||
MAKE_SEQ(get_task_chains, get_num_task_chains, get_task_chain);
|
||||
AsyncTaskChain *make_task_chain(const std::string &name);
|
||||
AsyncTaskChain *make_task_chain(const std::string &name, int num_threads,
|
||||
ThreadPriority thread_priority);
|
||||
AsyncTaskChain *find_task_chain(const std::string &name);
|
||||
BLOCKING bool remove_task_chain(const std::string &name);
|
||||
|
||||
void add(AsyncTask *task);
|
||||
#ifndef CPPPARSER
|
||||
template<class Callable>
|
||||
INLINE AsyncTask *add(const std::string &name, Callable callable);
|
||||
INLINE AsyncTask *add(Callable callable, const std::string &name,
|
||||
int sort = 0, int priority = 0);
|
||||
#endif
|
||||
bool has_task(AsyncTask *task) const;
|
||||
|
||||
|
|
@ -100,7 +103,8 @@ PUBLISHED:
|
|||
INLINE static AsyncTaskManager *get_global_ptr();
|
||||
|
||||
protected:
|
||||
AsyncTaskChain *do_make_task_chain(const std::string &name);
|
||||
AsyncTaskChain *do_make_task_chain(const std::string &name, int num_threads=0,
|
||||
ThreadPriority thread_priority=TP_normal);
|
||||
AsyncTaskChain *do_find_task_chain(const std::string &name);
|
||||
|
||||
INLINE void add_task_by_name(AsyncTask *task);
|
||||
|
|
|
|||
|
|
@ -95,9 +95,11 @@ public:
|
|||
INLINE const void *get_data() const;
|
||||
|
||||
PUBLISHED:
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE PyObject *get_message() const);
|
||||
EXTENSION(INLINE PyObject *__bytes__() const);
|
||||
EXTENSION(PyObject *__reduce__() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE size_t get_length() const;
|
||||
|
||||
|
|
@ -121,9 +123,9 @@ private:
|
|||
|
||||
#ifdef STDFLOAT_DOUBLE
|
||||
bool _stdfloat_double = true;
|
||||
#else
|
||||
#else // STDFLOAT_DOUBLE
|
||||
bool _stdfloat_double = false;
|
||||
#endif
|
||||
#endif // STDFLOAT_DOUBLE
|
||||
|
||||
public:
|
||||
|
||||
|
|
@ -168,4 +170,4 @@ generic_write_datagram(Datagram &dest, const vector_uchar &value);
|
|||
|
||||
#include "datagram.I"
|
||||
|
||||
#endif
|
||||
#endif // !DATAGRAM_H
|
||||
|
|
|
|||
|
|
@ -50,9 +50,9 @@ PUBLISHED:
|
|||
std::string get_type_name(size_t n) const;
|
||||
double get_age(size_t n) const;
|
||||
|
||||
#ifdef DO_MEMORY_USAGE
|
||||
#if defined(DO_MEMORY_USAGE) && defined(HAVE_PYTHON)
|
||||
EXTENSION(PyObject *get_python_pointer(size_t n) const);
|
||||
#endif
|
||||
#endif // DO_MEMORY_USAGE && HAVE_PYTHON
|
||||
|
||||
void clear();
|
||||
|
||||
|
|
@ -93,4 +93,4 @@ INLINE std::ostream &operator << (std::ostream &out, const MemoryUsagePointers &
|
|||
|
||||
#include "memoryUsagePointers.I"
|
||||
|
||||
#endif
|
||||
#endif // !MEMORYUSAGEPOINTERS_H
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
#ifdef HAVE_OPENSSL
|
||||
typedef struct x509_st X509;
|
||||
typedef struct evp_pkey_st EVP_PKEY;
|
||||
#endif
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
/**
|
||||
* A file that contains a set of files.
|
||||
|
|
@ -84,8 +84,10 @@ PUBLISHED:
|
|||
std::string update_subfile(const std::string &subfile_name, const Filename &filename,
|
||||
int compression_level);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE PyObject *set_encryption_password(PyObject *encryption_password) const);
|
||||
EXTENSION(INLINE PyObject *get_encryption_password() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#ifdef HAVE_OPENSSL
|
||||
bool add_signature(const Filename &certificate,
|
||||
|
|
@ -208,7 +210,7 @@ private:
|
|||
int _compression_level; // Not preserved on disk.
|
||||
#ifdef HAVE_OPENSSL
|
||||
EVP_PKEY *_pkey; // Not preserved on disk.
|
||||
#endif
|
||||
#endif // HAVE_OPENSSL
|
||||
};
|
||||
|
||||
INLINE std::streampos word_to_streampos(size_t word) const;
|
||||
|
|
@ -238,7 +240,7 @@ private:
|
|||
#ifdef HAVE_OPENSSL
|
||||
typedef pvector<CertChain> Certificates;
|
||||
Certificates _signatures;
|
||||
#endif
|
||||
#endif // HAVE_OPENSSL
|
||||
|
||||
std::streampos _offset;
|
||||
IStreamWrapper *_read;
|
||||
|
|
@ -285,4 +287,4 @@ private:
|
|||
|
||||
#include "multifile.I"
|
||||
|
||||
#endif
|
||||
#endif // !MULTIFILE_H
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@
|
|||
// disable mysterious MSVC warning for static inline PTA::empty_array method
|
||||
// need to chk if vc 7.0 still has this problem, would like to keep it enabled
|
||||
#pragma warning (disable : 4506)
|
||||
#endif
|
||||
#endif // _MSC_VER && !__INTEL_COMPILER
|
||||
|
||||
template <class Element>
|
||||
class ConstPointerToArray;
|
||||
|
|
@ -96,7 +96,9 @@ PUBLISHED:
|
|||
INLINE static PointerToArray<Element> empty_array(size_type n, TypeHandle type_handle = get_type_handle(Element));
|
||||
INLINE PointerToArray(const PointerToArray<Element> ©);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PointerToArray(PyObject *self, PyObject *source));
|
||||
#endif // HAVE_PYTHON */
|
||||
|
||||
INLINE void clear();
|
||||
|
||||
|
|
@ -107,9 +109,11 @@ PUBLISHED:
|
|||
INLINE void set_element(size_type n, const Element &value);
|
||||
EXTENSION(const Element &__getitem__(size_type n) const);
|
||||
EXTENSION(void __setitem__(size_type n, const Element &value));
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_data() const);
|
||||
EXTENSION(void set_data(PyObject *data));
|
||||
EXTENSION(PyObject *get_subdata(size_type n, size_type count) const);
|
||||
#endif // HAVE_PYTHON
|
||||
INLINE void set_subdata(size_type n, size_type count, const std::string &data);
|
||||
INLINE int get_ref_count() const;
|
||||
INLINE int get_node_ref_count() const;
|
||||
|
|
@ -121,7 +125,9 @@ PUBLISHED:
|
|||
|
||||
EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags));
|
||||
EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const);
|
||||
#endif
|
||||
|
||||
EXTENSION(PointerToArray<Element> __deepcopy__(PyObject *memo) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#else // CPPPARSER
|
||||
// This is the actual, complete interface.
|
||||
|
|
@ -184,7 +190,7 @@ public:
|
|||
#ifndef _WIN32
|
||||
INLINE reference operator [](size_type n) const;
|
||||
INLINE reference operator [](int n) const;
|
||||
#endif
|
||||
#endif // !_WIN32
|
||||
|
||||
INLINE void push_back(const Element &x);
|
||||
INLINE void pop_back();
|
||||
|
|
@ -267,8 +273,10 @@ PUBLISHED:
|
|||
INLINE size_type size() const;
|
||||
INLINE const Element &get_element(size_type n) const;
|
||||
EXTENSION(const Element &__getitem__(size_type n) const);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_data() const);
|
||||
EXTENSION(PyObject *get_subdata(size_type n, size_type count) const);
|
||||
#endif // HAVE_PYTHON
|
||||
INLINE int get_ref_count() const;
|
||||
INLINE int get_node_ref_count() const;
|
||||
|
||||
|
|
@ -279,7 +287,9 @@ PUBLISHED:
|
|||
|
||||
EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
|
||||
EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const);
|
||||
#endif
|
||||
|
||||
EXTENSION(ConstPointerToArray<Element> __deepcopy__(PyObject *memo) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
#else // CPPPARSER
|
||||
// This is the actual, complete interface.
|
||||
|
|
@ -292,9 +302,9 @@ PUBLISHED:
|
|||
#ifdef _MSC_VER
|
||||
// VC++ seems to break the const_reverse_iterator definition somehow.
|
||||
typedef typename pvector<Element>::reverse_iterator reverse_iterator;
|
||||
#else
|
||||
#else // _MSC_VER
|
||||
typedef typename pvector<Element>::const_reverse_iterator reverse_iterator;
|
||||
#endif
|
||||
#endif // _MSC_VER
|
||||
typedef typename pvector<Element>::const_reverse_iterator const_reverse_iterator;
|
||||
typedef typename pvector<Element>::difference_type difference_type;
|
||||
typedef typename pvector<Element>::size_type size_type;
|
||||
|
|
@ -330,7 +340,7 @@ PUBLISHED:
|
|||
#ifndef _WIN32
|
||||
INLINE reference operator [](size_type n) const;
|
||||
INLINE reference operator [](int n) const;
|
||||
#endif
|
||||
#endif // !_WIN32
|
||||
|
||||
INLINE operator const Element *() const;
|
||||
INLINE const Element *p() const;
|
||||
|
|
@ -386,4 +396,4 @@ private:
|
|||
|
||||
#include "pointerToArray.I"
|
||||
|
||||
#endif // HAVE_POINTERTOARRAY_H
|
||||
#endif // !POINTERTOARRAY_H
|
||||
|
|
|
|||
|
|
@ -440,6 +440,20 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A special Python method that is invoked by copy.deepcopy(pta). This makes
|
||||
* sure that there is truly a unique copy of the array.
|
||||
*/
|
||||
template<class Element>
|
||||
INLINE PointerToArray<Element> Extension<PointerToArray<Element> >::
|
||||
__deepcopy__(PyObject *memo) const {
|
||||
PointerToArray<Element> copy;
|
||||
if (!this->_this->is_null()) {
|
||||
copy.v() = this->_this->v();
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used to implement the buffer protocol, in order to allow efficient
|
||||
* access to the array data through a Python multiview object.
|
||||
|
|
@ -610,3 +624,17 @@ __releasebuffer__(PyObject *self, Py_buffer *view) const {
|
|||
view->internal = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A special Python method that is invoked by copy.deepcopy(pta). This makes
|
||||
* sure that there is truly a unique copy of the array.
|
||||
*/
|
||||
template<class Element>
|
||||
INLINE ConstPointerToArray<Element> Extension<ConstPointerToArray<Element> >::
|
||||
__deepcopy__(PyObject *memo) const {
|
||||
PointerToArray<Element> copy;
|
||||
if (!this->_this->is_null()) {
|
||||
copy.v() = this->_this->v();
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
#ifndef POINTERTOARRAY_EXT_H
|
||||
#define POINTERTOARRAY_EXT_H
|
||||
|
||||
#ifndef CPPPARSER
|
||||
#if !defined(CPPPARSER) && defined(HAVE_PYTHON)
|
||||
|
||||
#include "extension.h"
|
||||
#include "py_panda.h"
|
||||
|
|
@ -44,6 +44,8 @@ public:
|
|||
|
||||
INLINE int __getbuffer__(PyObject *self, Py_buffer *view, int flags);
|
||||
INLINE void __releasebuffer__(PyObject *self, Py_buffer *view) const;
|
||||
|
||||
INLINE PointerToArray<Element> __deepcopy__(PyObject *memo) const;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
@ -81,6 +83,8 @@ public:
|
|||
|
||||
INLINE int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const;
|
||||
INLINE void __releasebuffer__(PyObject *self, Py_buffer *view) const;
|
||||
|
||||
INLINE ConstPointerToArray<Element> __deepcopy__(PyObject *memo) const;
|
||||
};
|
||||
|
||||
template<>
|
||||
|
|
@ -162,6 +166,6 @@ define_format_code("4i", UnalignedLVecBase4i);
|
|||
|
||||
#include "pointerToArray_ext.I"
|
||||
|
||||
#endif // CPPPARSER
|
||||
#endif // !CPPPARSER && HAVE_PYTHON
|
||||
|
||||
#endif // HAVE_POINTERTOARRAY_EXT_H
|
||||
#endif // !HAVE_POINTERTOARRAY_EXT_H
|
||||
|
|
|
|||
|
|
@ -28,17 +28,20 @@ PUBLISHED:
|
|||
|
||||
INLINE void seek(size_t pos);
|
||||
INLINE size_t tell() const;
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *read(size_t length));
|
||||
EXTENSION(PyObject *readline());
|
||||
EXTENSION(PyObject *readlines());
|
||||
|
||||
EXTENSION(PyObject *get_data() const);
|
||||
#endif // HAVE_PYTHON
|
||||
INLINE size_t get_data_size() const;
|
||||
INLINE void clear();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__getstate__() const);
|
||||
EXTENSION(void __setstate__(PyObject *state));
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
public:
|
||||
std::string read(size_t length);
|
||||
std::string readline();
|
||||
|
|
@ -52,4 +55,4 @@ public:
|
|||
|
||||
#include "ramfile.I"
|
||||
|
||||
#endif
|
||||
#endif // !RAMFILE_H
|
||||
|
|
|
|||
|
|
@ -30,27 +30,31 @@ public:
|
|||
INLINE StringStream(vector_uchar source);
|
||||
|
||||
PUBLISHED:
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(StringStream(PyObject *source));
|
||||
#endif // HAVE_PYTHON
|
||||
INLINE StringStream();
|
||||
|
||||
#if _MSC_VER >= 1800
|
||||
INLINE StringStream(const StringStream ©) = delete;
|
||||
#endif
|
||||
#endif // _MSC_VER >= 1800
|
||||
|
||||
INLINE void clear_data();
|
||||
INLINE size_t get_data_size();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_data());
|
||||
EXTENSION(void set_data(PyObject *data));
|
||||
|
||||
MAKE_PROPERTY(data, get_data, set_data);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
#ifndef CPPPARSER
|
||||
INLINE std::string get_data();
|
||||
INLINE void set_data(const std::string &data);
|
||||
void set_data(const unsigned char *data, size_t size);
|
||||
#endif
|
||||
#endif // !CPPPARSER
|
||||
|
||||
INLINE void swap_data(vector_uchar &data);
|
||||
|
||||
|
|
@ -62,4 +66,4 @@ private:
|
|||
|
||||
#include "stringStream.I"
|
||||
|
||||
#endif
|
||||
#endif // !STRINGSTREAM_H
|
||||
|
|
|
|||
|
|
@ -56,12 +56,16 @@ PUBLISHED:
|
|||
BLOCKING void ls(std::ostream &out = std::cout) const;
|
||||
BLOCKING void ls_all(std::ostream &out = std::cout) const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *read_file(bool auto_unwrap) const);
|
||||
#endif // HAVE_PYTHON
|
||||
BLOCKING virtual std::istream *open_read_file(bool auto_unwrap) const;
|
||||
BLOCKING virtual void close_read_file(std::istream *stream) const;
|
||||
virtual bool was_read_successful() const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *write_file(PyObject *data, bool auto_wrap));
|
||||
#endif // HAVE_PYTHON
|
||||
BLOCKING virtual std::ostream *open_write_file(bool auto_wrap, bool truncate);
|
||||
BLOCKING virtual std::ostream *open_append_file();
|
||||
BLOCKING virtual void close_write_file(std::ostream *stream);
|
||||
|
|
@ -126,4 +130,4 @@ INLINE std::ostream &operator << (std::ostream &out, const VirtualFile &file);
|
|||
|
||||
#include "virtualFile.I"
|
||||
|
||||
#endif
|
||||
#endif // !VIRTUALFILE_H
|
||||
|
|
|
|||
|
|
@ -98,11 +98,15 @@ PUBLISHED:
|
|||
|
||||
static VirtualFileSystem *get_global_ptr();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *read_file(const Filename &filename, bool auto_unwrap) const);
|
||||
#endif // HAVE_PYTHON
|
||||
BLOCKING std::istream *open_read_file(const Filename &filename, bool auto_unwrap) const;
|
||||
BLOCKING static void close_read_file(std::istream *stream);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *write_file(const Filename &filename, PyObject *data, bool auto_wrap));
|
||||
#endif // HAVE_PYTHON
|
||||
BLOCKING std::ostream *open_write_file(const Filename &filename, bool auto_wrap, bool truncate);
|
||||
BLOCKING std::ostream *open_append_file(const Filename &filename);
|
||||
BLOCKING static void close_write_file(std::ostream *stream);
|
||||
|
|
@ -172,4 +176,4 @@ private:
|
|||
|
||||
#include "virtualFileSystem.I"
|
||||
|
||||
#endif
|
||||
#endif // !VIRTUALFILESYSTEM_H
|
||||
|
|
|
|||
|
|
@ -1437,10 +1437,10 @@ create_anim_controls() {
|
|||
setup_shuttle_button(":", 3, st_forward_button);
|
||||
|
||||
AsyncTaskManager &task_mgr = _panda_framework->get_task_mgr();
|
||||
_update_anim_controls_task = task_mgr.add("controls", [this](AsyncTask *task) {
|
||||
_update_anim_controls_task = task_mgr.add([this](AsyncTask *task) {
|
||||
update_anim_controls();
|
||||
return AsyncTask::DS_cont;
|
||||
});
|
||||
}, "controls");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -177,6 +177,7 @@ typedef char GLchar;
|
|||
#define GL_READ_ONLY 0x88B8
|
||||
#define GL_WRITE_ONLY 0x88B9
|
||||
#define GL_READ_WRITE 0x88BA
|
||||
#define GL_PIXEL_PACK_BUFFER 0x88EB
|
||||
#define GL_MAX_ARRAY_TEXTURE_LAYERS 0x88FF
|
||||
#define GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH 0x8A35
|
||||
#define GL_ACTIVE_UNIFORM_BLOCKS 0x8A36
|
||||
|
|
@ -253,6 +254,12 @@ typedef char GLchar;
|
|||
#define GL_UNSIGNED_INT_IMAGE_3D 0x9064
|
||||
#define GL_UNSIGNED_INT_IMAGE_CUBE 0x9066
|
||||
#define GL_UNSIGNED_INT_IMAGE_2D_ARRAY 0x9069
|
||||
#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
|
||||
#define GL_UNSIGNALED 0x9118
|
||||
#define GL_SIGNALED 0x9119
|
||||
#define GL_ALREADY_SIGNALED 0x911A
|
||||
#define GL_TIMEOUT_EXPIRED 0x911B
|
||||
#define GL_CONDITION_SATISFIED 0x911C
|
||||
#define GL_COMPUTE_SHADER 0x91B9
|
||||
#define GL_FRAMEBUFFER_DEFAULT_WIDTH 0x9310
|
||||
#define GL_FRAMEBUFFER_DEFAULT_HEIGHT 0x9311
|
||||
|
|
|
|||
|
|
@ -93,6 +93,8 @@ PStatCollector CLP(GraphicsStateGuardian)::_texture_update_pcollector("Draw:Upda
|
|||
PStatCollector CLP(GraphicsStateGuardian)::_fbo_bind_pcollector("Draw:Bind FBO");
|
||||
PStatCollector CLP(GraphicsStateGuardian)::_check_error_pcollector("Draw:Check errors");
|
||||
PStatCollector CLP(GraphicsStateGuardian)::_check_residency_pcollector("*:PStats:Check residency");
|
||||
PStatCollector CLP(GraphicsStateGuardian)::_wait_fence_pcollector("Wait:Fence");
|
||||
PStatCollector CLP(GraphicsStateGuardian)::_copy_texture_finish_pcollector("Draw:Copy texture:Finish");
|
||||
|
||||
#if defined(HAVE_CG) && !defined(OPENGLES)
|
||||
AtomicAdjust::Integer CLP(GraphicsStateGuardian)::_num_gsgs_with_cg_contexts = 0;
|
||||
|
|
@ -164,6 +166,10 @@ null_glPolygonOffsetClamp(GLfloat factor, GLfloat units, GLfloat clamp) {
|
|||
}
|
||||
#endif
|
||||
|
||||
static void APIENTRY
|
||||
null_glMemoryBarrier(GLbitfield barriers) {
|
||||
}
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
// We have a default shader that will be applied when there isn't any shader
|
||||
// applied (e.g. if it failed to compile). We need this because OpenGL ES
|
||||
|
|
@ -507,7 +513,9 @@ int CLP(GraphicsStateGuardian)::get_driver_shader_version_minor() { return _gl_s
|
|||
CLP(GraphicsStateGuardian)::
|
||||
CLP(GraphicsStateGuardian)(GraphicsEngine *engine, GraphicsPipe *pipe) :
|
||||
GraphicsStateGuardian(gl_coordinate_system, engine, pipe),
|
||||
_renderbuffer_residency(get_prepared_objects()->get_name(), "renderbuffer")
|
||||
_renderbuffer_residency(get_prepared_objects()->get_name(), "renderbuffer"),
|
||||
_active_ppbuffer_memory_pcollector("Graphics memory:" + get_prepared_objects()->get_name() + ":Active:ppbuffer"),
|
||||
_inactive_ppbuffer_memory_pcollector("Graphics memory:" + get_prepared_objects()->get_name() + ":Inactive:ppbuffer")
|
||||
{
|
||||
_error_count = 0;
|
||||
_last_error_check = -1.0;
|
||||
|
|
@ -1685,13 +1693,18 @@ reset() {
|
|||
if (is_at_least_gles_version(3, 0)) {
|
||||
_glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC)
|
||||
get_extension_func("glMapBufferRange");
|
||||
|
||||
} else if (has_extension("GL_EXT_map_buffer_range")) {
|
||||
_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)
|
||||
get_extension_func("glUnmapBuffer");
|
||||
}
|
||||
else if (has_extension("GL_EXT_map_buffer_range")) {
|
||||
_glMapBufferRange = (PFNGLMAPBUFFERRANGEEXTPROC)
|
||||
get_extension_func("glMapBufferRangeEXT");
|
||||
|
||||
} else {
|
||||
_glUnmapBuffer = (PFNGLUNMAPBUFFERPROC)
|
||||
get_extension_func("glUnmapBufferOES");
|
||||
}
|
||||
else {
|
||||
_glMapBufferRange = nullptr;
|
||||
_glUnmapBuffer = nullptr;
|
||||
}
|
||||
#else
|
||||
// Check for various advanced buffer management features.
|
||||
|
|
@ -2891,6 +2904,28 @@ reset() {
|
|||
is_at_least_gl_version(3, 3) || has_extension("GL_ARB_blend_func_extended");
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES
|
||||
if (is_at_least_gl_version(3, 2) || has_extension("GL_ARB_sync")) {
|
||||
_glFenceSync = (PFNGLFENCESYNCPROC)get_extension_func("glFenceSync");
|
||||
_glDeleteSync = (PFNGLDELETESYNCPROC)get_extension_func("glDeleteSync");
|
||||
_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)get_extension_func("glClientWaitSync");
|
||||
_glGetSynciv = (PFNGLGETSYNCIVPROC)get_extension_func("glGetSynciv");
|
||||
}
|
||||
#elif !defined(OPENGLES_1)
|
||||
if (is_at_least_gles_version(3, 0)) {
|
||||
_glFenceSync = (PFNGLFENCESYNCPROC)get_extension_func("glFenceSync");
|
||||
_glDeleteSync = (PFNGLDELETESYNCPROC)get_extension_func("glDeleteSync");
|
||||
_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)get_extension_func("glClientWaitSync");
|
||||
_glGetSynciv = (PFNGLGETSYNCIVPROC)get_extension_func("glGetSynciv");
|
||||
}
|
||||
else if (has_extension("GL_APPLE_sync")) {
|
||||
_glFenceSync = (PFNGLFENCESYNCPROC)get_extension_func("glFenceSyncAPPLE");
|
||||
_glDeleteSync = (PFNGLDELETESYNCPROC)get_extension_func("glDeleteSyncAPPLE");
|
||||
_glClientWaitSync = (PFNGLCLIENTWAITSYNCPROC)get_extension_func("glClientWaitSyncAPPLE");
|
||||
_glGetSynciv = (PFNGLGETSYNCIVPROC)get_extension_func("glGetSyncivAPPLE");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef OPENGLES
|
||||
_edge_clamp = GL_CLAMP_TO_EDGE;
|
||||
#else
|
||||
|
|
@ -3137,7 +3172,7 @@ reset() {
|
|||
|
||||
} else {
|
||||
_glBindImageTexture = nullptr;
|
||||
_glMemoryBarrier = nullptr;
|
||||
_glMemoryBarrier = null_glMemoryBarrier;
|
||||
}
|
||||
#endif // !OPENGLES_1
|
||||
|
||||
|
|
@ -4162,6 +4197,10 @@ begin_frame(Thread *current_thread) {
|
|||
_primitive_batches_display_list_pcollector.clear_level();
|
||||
#endif
|
||||
|
||||
if (!_async_ram_copies.empty()) {
|
||||
finish_async_framebuffer_ram_copies();
|
||||
}
|
||||
|
||||
#if defined(DO_PSTATS) && !defined(OPENGLES)
|
||||
int frame_number = ClockObject::get_global_clock()->get_frame_count(current_thread);
|
||||
if (_current_frame_timing == nullptr ||
|
||||
|
|
@ -4350,6 +4389,38 @@ end_frame(Thread *current_thread) {
|
|||
}
|
||||
#endif // OPENGLES
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
if (!_deleted_buffers.empty()) {
|
||||
GLuint *indices = (GLuint *)alloca(sizeof(GLuint *) * _deleted_buffers.size());
|
||||
size_t num_indices = 0;
|
||||
DeletedBuffers::iterator it = _deleted_buffers.begin();
|
||||
while (it != _deleted_buffers.end()) {
|
||||
DeletedBuffer &buffer = *it;
|
||||
if (!_supports_buffer_storage && buffer._mapped_pointer != nullptr) {
|
||||
_glBindBuffer(GL_PIXEL_PACK_BUFFER, buffer._index);
|
||||
_glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
buffer._mapped_pointer = nullptr;
|
||||
}
|
||||
if (++buffer._age > 2) {
|
||||
indices[num_indices++] = buffer._index;
|
||||
it = _deleted_buffers.erase(it);
|
||||
_inactive_ppbuffer_memory_pcollector.sub_level(buffer._size);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
if (!_supports_buffer_storage) {
|
||||
_glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
if (num_indices > 0) {
|
||||
_glDeleteBuffers(num_indices, indices);
|
||||
}
|
||||
}
|
||||
|
||||
_active_ppbuffer_memory_pcollector.flush_level();
|
||||
_inactive_ppbuffer_memory_pcollector.flush_level();
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
if (_check_errors || (_supports_debug && gl_debug)) {
|
||||
report_my_gl_errors();
|
||||
|
|
@ -6573,6 +6644,72 @@ record_deleted_display_list(GLuint index) {
|
|||
_deleted_display_lists.push_back(index);
|
||||
}
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
/**
|
||||
* Creates a new buffer for client access. It is bound when this returns.
|
||||
* If persistent mapping is possible, mapped_ptr will be filled in with a
|
||||
* pointer to the mapped data.
|
||||
*/
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
bind_new_client_buffer(GLuint &index, void *&mapped_ptr, GLenum target, size_t size) {
|
||||
_active_ppbuffer_memory_pcollector.add_level(size);
|
||||
|
||||
{
|
||||
// Start at the end, because removing near the end is cheaper.
|
||||
LightMutexHolder holder(_lock);
|
||||
size_t i = _deleted_buffers.size();
|
||||
while (i > 1) {
|
||||
--i;
|
||||
DeletedBuffer &buffer = _deleted_buffers[i];
|
||||
if (buffer._size == size) {
|
||||
index = buffer._index;
|
||||
mapped_ptr = buffer._mapped_pointer;
|
||||
_glBindBuffer(target, buffer._index);
|
||||
if (!_supports_buffer_storage && mapped_ptr != nullptr) {
|
||||
// Need to unmap it before we can use it.
|
||||
_glUnmapBuffer(target);
|
||||
mapped_ptr = nullptr;
|
||||
}
|
||||
_deleted_buffers.erase(_deleted_buffers.begin() + i);
|
||||
_inactive_ppbuffer_memory_pcollector.sub_level(size);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_glGenBuffers(1, &index);
|
||||
_glBindBuffer(target, index);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_buffer_storage) {
|
||||
// Map persistently, we already use fences to synchronize access anyway.
|
||||
_glBufferStorage(target, size, nullptr, GL_MAP_READ_BIT |
|
||||
GL_CLIENT_STORAGE_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
mapped_ptr = _glMapBufferRange(target, 0, size,
|
||||
GL_MAP_READ_BIT | GL_MAP_PERSISTENT_BIT);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
//XXX does it matter what usage hint we pass here? None seem to fit well.
|
||||
_glBufferData(target, size, nullptr, GL_DYNAMIC_DRAW);
|
||||
mapped_ptr = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the given buffer, as returned by bind_new_client_buffer, is no
|
||||
* longer needed.
|
||||
*/
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
release_client_buffer(GLuint index, void *mapped_ptr, size_t size) {
|
||||
// This may be called from any thread, so we can't make OpenGL calls here
|
||||
// (like unmapping the buffer).
|
||||
LightMutexHolder holder(_lock);
|
||||
_deleted_buffers.push_back({index, 0, mapped_ptr, size});
|
||||
_active_ppbuffer_memory_pcollector.sub_level(size);
|
||||
_inactive_ppbuffer_memory_pcollector.add_level(size);
|
||||
}
|
||||
#endif // !OPENGLES_1
|
||||
|
||||
/**
|
||||
* Creates a new retained-mode representation of the given data, and returns a
|
||||
* newly-allocated VertexBufferContext pointer to reference it. It is the
|
||||
|
|
@ -7567,7 +7704,6 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Copy the pixels within the indicated display region from the framebuffer
|
||||
* into system memory, not texture memory. Returns true on success, false on
|
||||
|
|
@ -7577,7 +7713,8 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z,
|
|||
*/
|
||||
bool CLP(GraphicsStateGuardian)::
|
||||
framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
||||
const DisplayRegion *dr, const RenderBuffer &rb) {
|
||||
const DisplayRegion *dr, const RenderBuffer &rb,
|
||||
ScreenshotRequest *request) {
|
||||
nassertr(tex != nullptr && dr != nullptr, false);
|
||||
set_read_buffer(rb._buffer_type);
|
||||
glPixelStorei(GL_PACK_ALIGNMENT, 1);
|
||||
|
|
@ -7868,12 +8005,23 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
|||
}
|
||||
#endif // NDEBUG
|
||||
|
||||
unsigned char *image_ptr = tex->modify_ram_image();
|
||||
size_t image_size = tex->get_ram_image_size();
|
||||
if (z >= 0 || view > 0) {
|
||||
image_size = tex->get_expected_ram_page_size();
|
||||
size_t image_size = tex->get_expected_ram_page_size();
|
||||
unsigned char *image_ptr = nullptr;
|
||||
#ifndef OPENGLES_1
|
||||
GLuint pbo = 0;
|
||||
void *mapped_ptr = nullptr;
|
||||
if (request != nullptr) {
|
||||
nassertr(z <= 0, false);
|
||||
image_size *= tex->get_z_size();
|
||||
bind_new_client_buffer(pbo, mapped_ptr, GL_PIXEL_PACK_BUFFER, image_size);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
image_ptr = tex->modify_ram_image();
|
||||
if (z >= 0) {
|
||||
image_ptr += z * image_size;
|
||||
} else {
|
||||
image_size = tex->get_ram_image_size();
|
||||
}
|
||||
if (view > 0) {
|
||||
image_ptr += (view * tex->get_z_size()) * image_size;
|
||||
|
|
@ -7884,9 +8032,22 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
|||
glReadPixels(xo, yo, w, h, external_format,
|
||||
get_component_type(component_type), image_ptr);
|
||||
|
||||
// We may have to reverse the byte ordering of the image if GL didn't do it
|
||||
// for us.
|
||||
#ifndef OPENGLES_1
|
||||
if (request != nullptr) {
|
||||
_glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
#ifndef OPENGLES
|
||||
if (_supports_buffer_storage) {
|
||||
_glMemoryBarrier(GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT);
|
||||
}
|
||||
#endif
|
||||
GLsync fence = _glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
_async_ram_copies.push_back({request, pbo, fence, external_format,
|
||||
view, mapped_ptr, image_size});
|
||||
} else
|
||||
#endif
|
||||
if (external_format == GL_RGBA || external_format == GL_RGB) {
|
||||
// We may have to reverse the byte ordering of the image if GL didn't do it
|
||||
// for us.
|
||||
PTA_uchar new_image;
|
||||
const unsigned char *result =
|
||||
fix_component_ordering(new_image, image_ptr, image_size,
|
||||
|
|
@ -7896,10 +8057,114 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef OPENGLES_1
|
||||
if (request != nullptr) {
|
||||
request->finish();
|
||||
}
|
||||
#endif
|
||||
|
||||
report_my_gl_errors();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes all asynchronous framebuffer-copy-to-ram operations.
|
||||
*/
|
||||
void CLP(GraphicsStateGuardian)::
|
||||
finish_async_framebuffer_ram_copies(bool force) {
|
||||
#ifndef OPENGLES_1
|
||||
if (_async_ram_copies.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//XXX having a fixed number of threads is not a great idea. We ought to have
|
||||
// a common thread pool that is sized based on the available number of CPUs.
|
||||
#ifdef HAVE_THREADS
|
||||
AsyncTaskManager *task_mgr = AsyncTaskManager::get_global_ptr();
|
||||
static AsyncTaskChain *chain = task_mgr->make_task_chain("texture_download", 2, TP_low);
|
||||
#endif
|
||||
|
||||
PStatTimer timer(_copy_texture_finish_pcollector);
|
||||
|
||||
if (force) {
|
||||
// Just wait for the last fence, the rest must be complete too then.
|
||||
PStatTimer timer(_wait_fence_pcollector);
|
||||
GLsync fence = _async_ram_copies.back()._fence;
|
||||
_glClientWaitSync(fence, 0, (GLuint64)-1);
|
||||
}
|
||||
|
||||
while (!_async_ram_copies.empty()) {
|
||||
AsyncRamCopy © = _async_ram_copies.front();
|
||||
if (!force) {
|
||||
GLenum result = _glClientWaitSync(copy._fence, 0, 0);
|
||||
if (result != GL_ALREADY_SIGNALED && result != GL_CONDITION_SATISFIED) {
|
||||
// Not yet done. The rest must not yet be done then, either.
|
||||
break;
|
||||
}
|
||||
}
|
||||
_glDeleteSync(copy._fence);
|
||||
|
||||
GLuint pbo = copy._pbo;
|
||||
int view = copy._view;
|
||||
PT(ScreenshotRequest) request = std::move(copy._request);
|
||||
GLuint external_format = copy._external_format;
|
||||
void *mapped_ptr = copy._mapped_pointer;
|
||||
size_t size = copy._size;
|
||||
|
||||
if (mapped_ptr == nullptr) {
|
||||
_glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo);
|
||||
#ifdef OPENGLES
|
||||
// There is neither glMapBuffer nor persistent mapping in OpenGL ES
|
||||
mapped_ptr = _glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, size, GL_MAP_READ_BIT);
|
||||
#else
|
||||
// If we get here in desktop GL, we must not have persistent mapping
|
||||
nassertv(!_supports_buffer_storage);
|
||||
mapped_ptr = _glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Do the memcpy in the background, since it can be slow.
|
||||
auto func = [=](AsyncTask *task) {
|
||||
const unsigned char *result = (unsigned char *)mapped_ptr;
|
||||
PTA_uchar new_image;
|
||||
if (external_format == GL_RGBA || external_format == GL_RGB) {
|
||||
// We may have to reverse the byte ordering of the image if GL didn't do
|
||||
// it for us.
|
||||
result = fix_component_ordering(new_image, result, size,
|
||||
external_format, request->get_result());
|
||||
}
|
||||
request->set_view_data(view, result);
|
||||
|
||||
// Finishing can take a long time, release the client buffer first so it
|
||||
// can be reused for the next screenshot.
|
||||
this->release_client_buffer(pbo, mapped_ptr, size);
|
||||
request->finish();
|
||||
return AsyncTask::DS_done;
|
||||
};
|
||||
#ifdef HAVE_THREADS
|
||||
// We assign a sort value based on the originating frame number, so that
|
||||
// earlier frames will be processed before subsequent frames, but we don't
|
||||
// make it unique for every frame, which would kill concurrency.
|
||||
int frame_number = request->get_frame_number();
|
||||
chain->add(std::move(func), "screenshot", frame_number >> 3, -(frame_number & ((1 << 3) - 1)));
|
||||
#else
|
||||
func(nullptr);
|
||||
#endif
|
||||
|
||||
_async_ram_copies.pop_front();
|
||||
|
||||
// If there is 1 remaining, save it for next frame. This helps prevent an
|
||||
// inconsistent frame rate when the number of fetched frames alternates
|
||||
// between 0 and 2, which can settle into a stable feedback loop.
|
||||
if (!force && _async_ram_copies.size() == 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
/**
|
||||
*
|
||||
|
|
|
|||
|
|
@ -142,6 +142,7 @@ typedef void (APIENTRYP PFNGLDELETEVERTEXARRAYSPROC) (GLsizei n, const GLuint *a
|
|||
typedef void (APIENTRYP PFNGLGENVERTEXARRAYSPROC) (GLsizei n, GLuint *arrays);
|
||||
typedef void (APIENTRYP PFNGLBLENDEQUATIONSEPARATEPROC) (GLenum modeRGB, GLenum modeAlpha);
|
||||
typedef void (APIENTRYP PFNGLBLENDFUNCSEPARATEPROC) (GLenum sfactorRGB, GLenum dfactorRGB, GLenum sfactorAlpha, GLenum dfactorAlpha);
|
||||
typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
// GLSL shader functions
|
||||
|
|
@ -231,6 +232,13 @@ typedef void (APIENTRYP PFNGLBUFFERSTORAGEPROC) (GLenum target, GLsizeiptr size,
|
|||
typedef void (APIENTRYP PFNGLBINDIMAGETEXTUREPROC) (GLuint unit, GLuint texture, GLint level, GLboolean layered, GLint layer, GLenum access, GLenum format);
|
||||
typedef void (APIENTRYP PFNGLCLEARTEXIMAGEPROC) (GLuint texture, GLint level, GLenum format, GLenum type, const void *data);
|
||||
typedef void (APIENTRYP PFNGLCLEARTEXSUBIMAGEPROC) (GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const void *data);
|
||||
typedef GLsync (APIENTRYP PFNGLFENCESYNCPROC) (GLenum condition, GLbitfield flags);
|
||||
typedef GLboolean (APIENTRYP PFNGLISSYNCPROC) (GLsync sync);
|
||||
typedef void (APIENTRYP PFNGLDELETESYNCPROC) (GLsync sync);
|
||||
typedef GLenum (APIENTRYP PFNGLCLIENTWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
typedef void (APIENTRYP PFNGLWAITSYNCPROC) (GLsync sync, GLbitfield flags, GLuint64 timeout);
|
||||
typedef void (APIENTRYP PFNGLGETINTEGER64VPROC) (GLenum pname, GLint64 *data);
|
||||
typedef void (APIENTRYP PFNGLGETSYNCIVPROC) (GLsync sync, GLenum pname, GLsizei bufSize, GLsizei *length, GLint *values);
|
||||
#endif // OPENGLES_1
|
||||
#ifndef OPENGLES
|
||||
typedef void (APIENTRYP PFNGLBINDTEXTURESPROC) (GLuint first, GLsizei count, const GLuint *textures);
|
||||
|
|
@ -253,7 +261,6 @@ typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64PROC) (GLuint index, GLuint64EXT
|
|||
typedef void (APIENTRYP PFNGLVERTEXATTRIBL1UI64VPROC) (GLuint index, const GLuint64EXT *v);
|
||||
typedef void (APIENTRYP PFNGLGETVERTEXATTRIBLUI64VPROC) (GLuint index, GLenum pname, GLuint64EXT *params);
|
||||
typedef void *(APIENTRYP PFNGLMAPBUFFERPROC) (GLenum target, GLenum access);
|
||||
typedef GLboolean (APIENTRYP PFNGLUNMAPBUFFERPROC) (GLenum target);
|
||||
typedef void (APIENTRYP PFNGLGETBUFFERSUBDATAPROC) (GLenum target, GLintptr offset, GLsizeiptr size, void *data);
|
||||
#endif // OPENGLES
|
||||
#endif // __EDG__
|
||||
|
|
@ -353,6 +360,11 @@ public:
|
|||
virtual ShaderContext *prepare_shader(Shader *shader);
|
||||
virtual void release_shader(ShaderContext *sc);
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
void bind_new_client_buffer(GLuint &index, void *&mapped_ptr, GLenum target, size_t size);
|
||||
void release_client_buffer(GLuint index, void *mapped_ptr, size_t size);
|
||||
#endif
|
||||
|
||||
void record_deleted_display_list(GLuint index);
|
||||
|
||||
virtual VertexBufferContext *prepare_vertex_buffer(GeomVertexArrayData *data);
|
||||
|
|
@ -403,7 +415,9 @@ public:
|
|||
virtual bool framebuffer_copy_to_texture
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
|
||||
virtual bool framebuffer_copy_to_ram
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb,
|
||||
ScreenshotRequest *request);
|
||||
void finish_async_framebuffer_ram_copies(bool force = false);
|
||||
|
||||
#ifdef SUPPORT_FIXED_FUNCTION
|
||||
void apply_fog(Fog *fog);
|
||||
|
|
@ -880,6 +894,7 @@ public:
|
|||
|
||||
#ifdef OPENGLES
|
||||
PFNGLMAPBUFFERRANGEEXTPROC _glMapBufferRange;
|
||||
PFNGLUNMAPBUFFEROESPROC _glUnmapBuffer;
|
||||
#else
|
||||
PFNGLMAPBUFFERRANGEPROC _glMapBufferRange;
|
||||
#endif
|
||||
|
|
@ -891,6 +906,8 @@ public:
|
|||
|
||||
bool _supports_buffer_storage;
|
||||
PFNGLBUFFERSTORAGEPROC _glBufferStorage;
|
||||
#else
|
||||
static const bool _supports_buffer_storage = false;
|
||||
#endif
|
||||
|
||||
bool _supports_blend_equation_separate;
|
||||
|
|
@ -1088,6 +1105,13 @@ public:
|
|||
PFNGLSHADERSTORAGEBLOCKBINDINGPROC _glShaderStorageBlockBinding;
|
||||
#endif // !OPENGLES
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
PFNGLFENCESYNCPROC _glFenceSync;
|
||||
PFNGLDELETESYNCPROC _glDeleteSync;
|
||||
PFNGLCLIENTWAITSYNCPROC _glClientWaitSync;
|
||||
PFNGLGETSYNCIVPROC _glGetSynciv;
|
||||
#endif
|
||||
|
||||
GLenum _edge_clamp;
|
||||
GLenum _border_clamp;
|
||||
GLenum _mirror_repeat;
|
||||
|
|
@ -1109,6 +1133,17 @@ public:
|
|||
DeletedNames _deleted_display_lists;
|
||||
DeletedNames _deleted_queries;
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
struct DeletedBuffer {
|
||||
GLuint _index;
|
||||
int _age;
|
||||
void *_mapped_pointer;
|
||||
size_t _size;
|
||||
};
|
||||
typedef pvector<DeletedBuffer> DeletedBuffers;
|
||||
DeletedBuffers _deleted_buffers;
|
||||
#endif
|
||||
|
||||
#ifndef OPENGLES_1
|
||||
// Stores textures for which memory bariers should be issued.
|
||||
typedef pset<TextureContext*> TextureSet;
|
||||
|
|
@ -1165,8 +1200,22 @@ public:
|
|||
FrameTiming *_current_frame_timing = nullptr;
|
||||
#endif
|
||||
|
||||
struct AsyncRamCopy {
|
||||
PT(ScreenshotRequest) _request;
|
||||
GLuint _pbo;
|
||||
GLsync _fence;
|
||||
GLuint _external_format;
|
||||
int _view;
|
||||
void *_mapped_pointer;
|
||||
size_t _size;
|
||||
};
|
||||
pdeque<AsyncRamCopy> _async_ram_copies;
|
||||
|
||||
BufferResidencyTracker _renderbuffer_residency;
|
||||
|
||||
PStatCollector _active_ppbuffer_memory_pcollector;
|
||||
PStatCollector _inactive_ppbuffer_memory_pcollector;
|
||||
|
||||
static PStatCollector _load_display_list_pcollector;
|
||||
static PStatCollector _primitive_batches_display_list_pcollector;
|
||||
static PStatCollector _vertices_display_list_pcollector;
|
||||
|
|
@ -1177,6 +1226,8 @@ public:
|
|||
static PStatCollector _fbo_bind_pcollector;
|
||||
static PStatCollector _check_error_pcollector;
|
||||
static PStatCollector _check_residency_pcollector;
|
||||
static PStatCollector _wait_fence_pcollector;
|
||||
static PStatCollector _copy_texture_finish_pcollector;
|
||||
|
||||
public:
|
||||
virtual TypeHandle get_type() const {
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ PUBLISHED:
|
|||
EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags));
|
||||
EXTENSION(int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
|
||||
EXTENSION(void __releasebuffer__(PyObject *self, Py_buffer *view) const);
|
||||
#endif
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
virtual void evict_lru();
|
||||
|
|
@ -310,12 +310,14 @@ PUBLISHED:
|
|||
const unsigned char *source,
|
||||
size_t from_start, size_t from_size);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(void copy_data_from(PyObject *buffer));
|
||||
EXTENSION(void copy_subdata_from(size_t to_start, size_t to_size,
|
||||
PyObject *buffer));
|
||||
EXTENSION(void copy_subdata_from(size_t to_start, size_t to_size,
|
||||
PyObject *buffer,
|
||||
size_t from_start, size_t from_size));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE vector_uchar get_data() const;
|
||||
void set_data(const vector_uchar &data);
|
||||
|
|
@ -355,4 +357,4 @@ INLINE std::ostream &operator << (std::ostream &out, const GeomVertexArrayData &
|
|||
|
||||
#include "geomVertexArrayData.I"
|
||||
|
||||
#endif
|
||||
#endif // !GEOMVERTEXARRAYDATA_H
|
||||
|
|
|
|||
|
|
@ -4472,6 +4472,20 @@ get_data4f(const unsigned char *pointer) {
|
|||
return _v4;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const LVecBase4d &GeomVertexColumn::Packer_argb_packed::
|
||||
get_data4d(const unsigned char *pointer) {
|
||||
uint32_t dword = *(const uint32_t *)pointer;
|
||||
_v4d.set(GeomVertexData::unpack_abcd_b(dword),
|
||||
GeomVertexData::unpack_abcd_c(dword),
|
||||
GeomVertexData::unpack_abcd_d(dword),
|
||||
GeomVertexData::unpack_abcd_a(dword));
|
||||
_v4d /= 255.0;
|
||||
return _v4d;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -4486,6 +4500,20 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
|
|||
(unsigned int)(min(max(data[2], 0.0f), 1.0f) * 255.0f));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void GeomVertexColumn::Packer_argb_packed::
|
||||
set_data4d(unsigned char *pointer, const LVecBase4d &data) {
|
||||
// when packing an argb, we want to make sure we cap the input values at 1
|
||||
// since going above one will cause the value to be truncated.
|
||||
*(uint32_t *)pointer = GeomVertexData::pack_abcd
|
||||
((unsigned int)(min(max(data[3], 0.0), 1.0) * 255.0),
|
||||
(unsigned int)(min(max(data[0], 0.0), 1.0) * 255.0),
|
||||
(unsigned int)(min(max(data[1], 0.0), 1.0) * 255.0),
|
||||
(unsigned int)(min(max(data[2], 0.0), 1.0) * 255.0));
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -4497,6 +4525,17 @@ get_data4f(const unsigned char *pointer) {
|
|||
return _v4;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
const LVecBase4d &GeomVertexColumn::Packer_rgba_uint8_4::
|
||||
get_data4d(const unsigned char *pointer) {
|
||||
_v4d.set((double)pointer[0], (double)pointer[1],
|
||||
(double)pointer[2], (double)pointer[3]);
|
||||
_v4d /= 255.0;
|
||||
return _v4d;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
@ -4508,6 +4547,17 @@ set_data4f(unsigned char *pointer, const LVecBase4f &data) {
|
|||
pointer[3] = (unsigned int)(min(max(data[3], 0.0f), 1.0f) * 255.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void GeomVertexColumn::Packer_rgba_uint8_4::
|
||||
set_data4d(unsigned char *pointer, const LVecBase4d &data) {
|
||||
pointer[0] = (unsigned int)(min(max(data[0], 0.0), 1.0) * 255.0);
|
||||
pointer[1] = (unsigned int)(min(max(data[1], 0.0), 1.0) * 255.0);
|
||||
pointer[2] = (unsigned int)(min(max(data[2], 0.0), 1.0) * 255.0);
|
||||
pointer[3] = (unsigned int)(min(max(data[3], 0.0), 1.0) * 255.0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -381,7 +381,9 @@ private:
|
|||
class Packer_argb_packed final : public Packer_color {
|
||||
public:
|
||||
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
|
||||
virtual const LVecBase4d &get_data4d(const unsigned char *pointer);
|
||||
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
|
||||
virtual void set_data4d(unsigned char *pointer, const LVecBase4d &value);
|
||||
|
||||
virtual const char *get_name() const {
|
||||
return "Packer_argb_packed";
|
||||
|
|
@ -391,7 +393,9 @@ private:
|
|||
class Packer_rgba_uint8_4 final : public Packer_color {
|
||||
public:
|
||||
virtual const LVecBase4f &get_data4f(const unsigned char *pointer);
|
||||
virtual const LVecBase4d &get_data4d(const unsigned char *pointer);
|
||||
virtual void set_data4f(unsigned char *pointer, const LVecBase4f &value);
|
||||
virtual void set_data4d(unsigned char *pointer, const LVecBase4d &value);
|
||||
|
||||
virtual const char *get_name() const {
|
||||
return "Packer_rgba_uint8_4";
|
||||
|
|
|
|||
|
|
@ -1064,7 +1064,7 @@ async_ensure_ram_image(bool allow_compression, int priority) {
|
|||
double delay = async_load_delay;
|
||||
|
||||
// This texture has not yet been queued to be reloaded. Queue it up now.
|
||||
task = task_mgr->add(task_name, [=](AsyncTask *task) {
|
||||
task = chain->add([=](AsyncTask *task) {
|
||||
if (delay != 0.0) {
|
||||
Thread::sleep(delay);
|
||||
}
|
||||
|
|
@ -1080,9 +1080,8 @@ async_ensure_ram_image(bool allow_compression, int priority) {
|
|||
do_get_uncompressed_ram_image(cdata);
|
||||
}
|
||||
return AsyncTask::DS_done;
|
||||
});
|
||||
task->set_priority(priority);
|
||||
task->set_task_chain("texture_reload");
|
||||
}, task_name, 0, priority);
|
||||
|
||||
cdataw->_reload_task = task;
|
||||
return (AsyncFuture *)task;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@
|
|||
#include "pnmImage.h"
|
||||
#include "pfmFile.h"
|
||||
#include "asyncTask.h"
|
||||
#include "extension.h"
|
||||
|
||||
class TextureContext;
|
||||
class FactoryParams;
|
||||
|
|
@ -455,15 +456,15 @@ PUBLISHED:
|
|||
CPTA_uchar get_ram_image_as(const std::string &requested_format);
|
||||
INLINE PTA_uchar modify_ram_image();
|
||||
INLINE PTA_uchar make_ram_image();
|
||||
#ifndef CPPPARSER
|
||||
#if !defined(CPPPARSER) || !defined(HAVE_PYTHON)
|
||||
INLINE void set_ram_image(CPTA_uchar image, CompressionMode compression = CM_off,
|
||||
size_t page_size = 0);
|
||||
void set_ram_image_as(CPTA_uchar image, const std::string &provided_format);
|
||||
#else
|
||||
#else // !CPPPARSER || !HAVE_PYTHON
|
||||
EXTEND void set_ram_image(PyObject *image, CompressionMode compression = CM_off,
|
||||
size_t page_size = 0);
|
||||
EXTEND void set_ram_image_as(PyObject *image, const std::string &provided_format);
|
||||
#endif
|
||||
#endif // !CPPPARSER || !HAVE_PYTHON
|
||||
INLINE void clear_ram_image();
|
||||
INLINE void set_keep_ram_image(bool keep_ram_image);
|
||||
virtual bool get_keep_ram_image() const;
|
||||
|
|
@ -473,6 +474,8 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(keep_ram_image, get_keep_ram_image, set_keep_ram_image);
|
||||
MAKE_PROPERTY(cacheable, is_cacheable);
|
||||
|
||||
EXTENSION(PT(Texture) __deepcopy__(PyObject *memo) const);
|
||||
|
||||
BLOCKING INLINE bool compress_ram_image(CompressionMode compression = CM_on,
|
||||
QualityLevel quality_level = QL_default,
|
||||
GraphicsStateGuardianBase *gsg = nullptr);
|
||||
|
|
@ -1122,6 +1125,7 @@ private:
|
|||
|
||||
static TypeHandle _type_handle;
|
||||
|
||||
friend class Extension<Texture>;
|
||||
friend class TextureContext;
|
||||
friend class PreparedGraphicsObjects;
|
||||
friend class TexturePool;
|
||||
|
|
@ -1140,4 +1144,4 @@ EXPCL_PANDA_GOBJ std::istream &operator >> (std::istream &in, Texture::QualityLe
|
|||
|
||||
#include "texture.I"
|
||||
|
||||
#endif
|
||||
#endif // !TEXTURE_H
|
||||
|
|
|
|||
|
|
@ -98,9 +98,11 @@ PUBLISHED:
|
|||
TexturePoolFilter *get_filter(size_t i) const;
|
||||
MAKE_SEQ_PROPERTY(filters, get_num_filters, get_filter);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(bool register_filter(PyObject *tex_filter));
|
||||
EXTENSION(bool unregister_filter(PyObject *tex_filter));
|
||||
EXTENSION(bool is_filter_registered(PyObject *tex_filter));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
static TexturePool *get_global_ptr();
|
||||
|
||||
|
|
@ -216,4 +218,4 @@ private:
|
|||
|
||||
#include "texturePool.I"
|
||||
|
||||
#endif
|
||||
#endif // !TEXTUREPOOL_H
|
||||
|
|
|
|||
|
|
@ -138,4 +138,32 @@ set_ram_image_as(PyObject *image, const std::string &provided_format) {
|
|||
Dtool_Raise_ArgTypeError(image, 0, "Texture.set_ram_image_as", "CPTA_uchar or buffer");
|
||||
}
|
||||
|
||||
/**
|
||||
* A special Python method that is invoked by copy.deepcopy(tex). This makes
|
||||
* sure that the copy has a unique copy of the RAM image.
|
||||
*/
|
||||
PT(Texture) Extension<Texture>::
|
||||
__deepcopy__(PyObject *memo) const {
|
||||
PT(Texture) copy = _this->make_copy();
|
||||
{
|
||||
Texture::CDWriter cdata(copy->_cycler, true);
|
||||
for (Texture::RamImage &image : cdata->_ram_images) {
|
||||
if (image._image.get_ref_count() > 1) {
|
||||
PTA_uchar new_image;
|
||||
new_image.v() = image._image.v();
|
||||
image._image = std::move(new_image);
|
||||
}
|
||||
}
|
||||
{
|
||||
Texture::RamImage &image = cdata->_simple_ram_image;
|
||||
if (image._image.get_ref_count() > 1) {
|
||||
PTA_uchar new_image;
|
||||
new_image.v() = image._image.v();
|
||||
image._image = std::move(new_image);
|
||||
}
|
||||
}
|
||||
}
|
||||
return copy;
|
||||
}
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -32,6 +32,8 @@ public:
|
|||
void set_ram_image(PyObject *image, Texture::CompressionMode compression = Texture::CM_off,
|
||||
size_t page_size = 0);
|
||||
void set_ram_image_as(PyObject *image, const std::string &provided_format);
|
||||
|
||||
PT(Texture) __deepcopy__(PyObject *memo) const;
|
||||
};
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ class RenderBuffer;
|
|||
class GraphicsWindow;
|
||||
class NodePath;
|
||||
class GraphicsOutputBase;
|
||||
class ScreenshotRequest;
|
||||
|
||||
class VertexBufferContext;
|
||||
class IndexBufferContext;
|
||||
|
|
@ -220,7 +221,8 @@ public:
|
|||
virtual bool framebuffer_copy_to_texture
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0;
|
||||
virtual bool framebuffer_copy_to_ram
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb)=0;
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb,
|
||||
ScreenshotRequest *request = nullptr)=0;
|
||||
|
||||
virtual CoordinateSystem get_internal_coordinate_system() const=0;
|
||||
|
||||
|
|
|
|||
|
|
@ -68,7 +68,9 @@ PUBLISHED:
|
|||
const FLOATNAME(LVecBase3) &);
|
||||
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix3));
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void fill(FLOATTYPE fill_value);
|
||||
INLINE_LINMATH void set(
|
||||
|
|
|
|||
|
|
@ -72,7 +72,9 @@ PUBLISHED:
|
|||
const FLOATNAME(LVecBase4) &);
|
||||
ALLOC_DELETED_CHAIN(FLOATNAME(LMatrix4));
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
// Construct a 4x4 matrix given a 3x3 rotation matrix and an optional
|
||||
// translation component.
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ PUBLISHED:
|
|||
INLINE_LINMATH FLOATNAME(LPoint2)(FLOATTYPE fill_value);
|
||||
INLINE_LINMATH FLOATNAME(LPoint2)(FLOATTYPE x, FLOATTYPE y);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LPoint2) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LPoint2) &unit_x();
|
||||
|
|
@ -51,7 +53,7 @@ PUBLISHED:
|
|||
#ifndef FLOATTYPE_IS_INT
|
||||
INLINE_LINMATH FLOATNAME(LPoint2) normalized() const;
|
||||
INLINE_LINMATH FLOATNAME(LPoint2) project(const FLOATNAME(LVecBase2) &onto) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
EXTENSION(INLINE_LINMATH std::string __repr__() const);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,10 @@ PUBLISHED:
|
|||
INLINE_LINMATH FLOATNAME(LPoint3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
|
||||
INLINE_LINMATH FLOATNAME(LPoint3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LPoint3) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LPoint3) &unit_x();
|
||||
|
|
@ -61,7 +63,7 @@ PUBLISHED:
|
|||
#ifndef FLOATTYPE_IS_INT
|
||||
INLINE_LINMATH FLOATNAME(LPoint3) normalized() const;
|
||||
INLINE_LINMATH FLOATNAME(LPoint3) project(const FLOATNAME(LVecBase3) &onto) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LPoint3) operator * (FLOATTYPE scalar) const;
|
||||
INLINE_LINMATH FLOATNAME(LPoint3) operator / (FLOATTYPE scalar) const;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ PUBLISHED:
|
|||
INLINE_LINMATH FLOATNAME(LPoint4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
|
||||
INLINE_LINMATH FLOATNAME(LPoint4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LPoint4) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LPoint4) &unit_x();
|
||||
|
|
@ -59,7 +61,7 @@ PUBLISHED:
|
|||
#ifndef FLOATTYPE_IS_INT
|
||||
INLINE_LINMATH FLOATNAME(LPoint4) normalized() const;
|
||||
INLINE_LINMATH FLOATNAME(LPoint4) project(const FLOATNAME(LVecBase4) &onto) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
EXTENSION(INLINE_LINMATH std::string __repr__() const);
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ PUBLISHED:
|
|||
|
||||
#ifdef FLOATTYPE_IS_INT
|
||||
is_int = 1
|
||||
#else
|
||||
#else // FLOATTYPE_IS_INT
|
||||
is_int = 0
|
||||
#endif
|
||||
#endif // FLOATTYPE_IS_INT
|
||||
};
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase2)() = default;
|
||||
|
|
@ -38,15 +38,17 @@ PUBLISHED:
|
|||
#ifdef CPPPARSER
|
||||
FLOATNAME(LVecBase2) &operator = (const FLOATNAME(LVecBase2) ©) = default;
|
||||
FLOATNAME(LVecBase2) &operator = (FLOATTYPE fill_value) = default;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase2) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase2) &unit_x();
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase2) &unit_y();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
||||
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
||||
|
|
@ -95,7 +97,7 @@ PUBLISHED:
|
|||
INLINE_LINMATH bool normalize();
|
||||
INLINE_LINMATH FLOATNAME(LVecBase2) normalized() const;
|
||||
INLINE_LINMATH FLOATNAME(LVecBase2) project(const FLOATNAME(LVecBase2) &onto) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase2) &other) const;
|
||||
INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase2) &other) const;
|
||||
|
|
@ -113,7 +115,7 @@ PUBLISHED:
|
|||
INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const;
|
||||
INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
|
||||
FLOATTYPE threshold) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase2) operator - () const;
|
||||
|
||||
|
|
@ -133,6 +135,7 @@ PUBLISHED:
|
|||
|
||||
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase2) &other);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const);
|
||||
|
||||
EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const);
|
||||
|
|
@ -144,6 +147,7 @@ PUBLISHED:
|
|||
EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self));
|
||||
EXTENSION(INLINE_LINMATH PyObject *__floor__(PyObject *self));
|
||||
EXTENSION(INLINE_LINMATH PyObject *__ceil__(PyObject *self));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase2) fmax(const FLOATNAME(LVecBase2) &other) const;
|
||||
INLINE_LINMATH FLOATNAME(LVecBase2) fmin(const FLOATNAME(LVecBase2) &other) const;
|
||||
|
|
@ -160,7 +164,9 @@ PUBLISHED:
|
|||
INLINE_LINMATH void write_datagram(Datagram &destination) const;
|
||||
INLINE_LINMATH void read_datagram(DatagramIterator &source);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
// The underlying implementation is via the Eigen library, if available.
|
||||
|
|
|
|||
|
|
@ -25,9 +25,9 @@ PUBLISHED:
|
|||
|
||||
#ifdef FLOATTYPE_IS_INT
|
||||
is_int = 1
|
||||
#else
|
||||
#else // FLOATTYPE_IS_INT
|
||||
is_int = 0
|
||||
#endif
|
||||
#endif // FLOATTYPE_IS_INT
|
||||
};
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3)() = default;
|
||||
|
|
@ -39,16 +39,18 @@ PUBLISHED:
|
|||
#ifdef CPPPARSER
|
||||
FLOATNAME(LVecBase3) &operator = (const FLOATNAME(LVecBase3) ©) = default;
|
||||
FLOATNAME(LVecBase3) &operator = (FLOATTYPE fill_value) = default;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase3) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase3) &unit_x();
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase3) &unit_y();
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase3) &unit_z();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
||||
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
||||
|
|
@ -108,7 +110,7 @@ PUBLISHED:
|
|||
INLINE_LINMATH bool normalize();
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3) normalized() const;
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3) project(const FLOATNAME(LVecBase3) &onto) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3) cross(const FLOATNAME(LVecBase3) &other) const;
|
||||
|
||||
|
|
@ -118,7 +120,7 @@ PUBLISHED:
|
|||
|
||||
#ifndef FLOATTYPE_IS_INT
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3) get_standardized_hpr() const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH int compare_to(const FLOATNAME(LVecBase3) &other) const;
|
||||
INLINE_LINMATH size_t get_hash() const;
|
||||
|
|
@ -132,7 +134,7 @@ PUBLISHED:
|
|||
INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const;
|
||||
INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
|
||||
FLOATTYPE threshold) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3) operator - () const;
|
||||
|
||||
|
|
@ -152,6 +154,7 @@ PUBLISHED:
|
|||
|
||||
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase3) &other);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const);
|
||||
|
||||
EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const);
|
||||
|
|
@ -163,6 +166,7 @@ PUBLISHED:
|
|||
EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self));
|
||||
EXTENSION(INLINE_LINMATH PyObject *__floor__(PyObject *self));
|
||||
EXTENSION(INLINE_LINMATH PyObject *__ceil__(PyObject *self));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3) fmax(const FLOATNAME(LVecBase3) &other) const;
|
||||
INLINE_LINMATH FLOATNAME(LVecBase3) fmin(const FLOATNAME(LVecBase3) &other) const;
|
||||
|
|
@ -181,7 +185,9 @@ PUBLISHED:
|
|||
INLINE_LINMATH void write_datagram(Datagram &destination) const;
|
||||
INLINE_LINMATH void read_datagram(DatagramIterator &source);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
// The underlying implementation is via the Eigen library, if available.
|
||||
|
|
|
|||
|
|
@ -31,9 +31,9 @@ PUBLISHED:
|
|||
|
||||
#ifdef FLOATTYPE_IS_INT
|
||||
is_int = 1
|
||||
#else
|
||||
#else // FLOATTYPE_IS_INT
|
||||
is_int = 0
|
||||
#endif
|
||||
#endif // FLOATTYPE_IS_INT
|
||||
};
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase4)() = default;
|
||||
|
|
@ -48,7 +48,7 @@ PUBLISHED:
|
|||
#ifdef CPPPARSER
|
||||
FLOATNAME(LVecBase4) &operator = (const FLOATNAME(LVecBase4) ©) = default;
|
||||
FLOATNAME(LVecBase4) &operator = (FLOATTYPE fill_value) = default;
|
||||
#endif
|
||||
#endif // CPPPARSER
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase4) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase4) &unit_x();
|
||||
|
|
@ -56,9 +56,11 @@ PUBLISHED:
|
|||
INLINE_LINMATH static const FLOATNAME(LVecBase4) &unit_z();
|
||||
INLINE_LINMATH static const FLOATNAME(LVecBase4) &unit_w();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__reduce__(PyObject *self) const);
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH FLOATTYPE operator [](int i) const;
|
||||
INLINE_LINMATH FLOATTYPE &operator [](int i);
|
||||
|
|
@ -122,7 +124,7 @@ PUBLISHED:
|
|||
INLINE_LINMATH bool normalize();
|
||||
INLINE_LINMATH FLOATNAME(LVecBase4) normalized() const;
|
||||
INLINE_LINMATH FLOATNAME(LVecBase4) project(const FLOATNAME(LVecBase4) &onto) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH bool operator < (const FLOATNAME(LVecBase4) &other) const;
|
||||
INLINE_LINMATH bool operator == (const FLOATNAME(LVecBase4) &other) const;
|
||||
|
|
@ -140,7 +142,7 @@ PUBLISHED:
|
|||
INLINE_LINMATH size_t add_hash(size_t hash, FLOATTYPE threshold) const;
|
||||
INLINE_LINMATH void generate_hash(ChecksumHashGenerator &hashgen,
|
||||
FLOATTYPE threshold) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase4) operator - () const;
|
||||
|
||||
|
|
@ -160,6 +162,7 @@ PUBLISHED:
|
|||
|
||||
INLINE_LINMATH void componentwise_mult(const FLOATNAME(LVecBase4) &other);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__rmul__(PyObject *self, FLOATTYPE scalar) const);
|
||||
|
||||
EXTENSION(INLINE_LINMATH PyObject *__floordiv__(PyObject *self, FLOATTYPE scalar) const);
|
||||
|
|
@ -171,6 +174,7 @@ PUBLISHED:
|
|||
EXTENSION(INLINE_LINMATH PyObject *__round__(PyObject *self));
|
||||
EXTENSION(INLINE_LINMATH PyObject *__floor__(PyObject *self));
|
||||
EXTENSION(INLINE_LINMATH PyObject *__ceil__(PyObject *self));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVecBase4) fmax(const FLOATNAME(LVecBase4) &other) const;
|
||||
INLINE_LINMATH FLOATNAME(LVecBase4) fmin(const FLOATNAME(LVecBase4) &other) const;
|
||||
|
|
@ -187,7 +191,9 @@ PUBLISHED:
|
|||
INLINE_LINMATH void write_datagram(Datagram &destination) const;
|
||||
INLINE_LINMATH void read_datagram(DatagramIterator &source);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH int __getbuffer__(PyObject *self, Py_buffer *view, int flags) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
// The underlying implementation is via the Eigen library, if available.
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ PUBLISHED:
|
|||
INLINE_LINMATH FLOATNAME(LVector2)(FLOATTYPE fill_value);
|
||||
INLINE_LINMATH FLOATNAME(LVector2)(FLOATTYPE x, FLOATTYPE y);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LVector2) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LVector2) &unit_x();
|
||||
|
|
@ -47,7 +49,7 @@ PUBLISHED:
|
|||
INLINE_LINMATH FLOATNAME(LVector2) project(const FLOATNAME(LVecBase2) &onto) const;
|
||||
INLINE_LINMATH FLOATTYPE signed_angle_rad(const FLOATNAME(LVector2) &other) const;
|
||||
INLINE_LINMATH FLOATTYPE signed_angle_deg(const FLOATNAME(LVector2) &other) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
EXTENSION(INLINE_LINMATH std::string __repr__() const);
|
||||
|
||||
|
|
|
|||
|
|
@ -26,8 +26,10 @@ PUBLISHED:
|
|||
INLINE_LINMATH FLOATNAME(LVector3)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z);
|
||||
INLINE_LINMATH FLOATNAME(LVector3)(const FLOATNAME(LVecBase2) ©, FLOATTYPE z);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LVector3) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LVector3) &unit_x();
|
||||
|
|
@ -66,7 +68,7 @@ PUBLISHED:
|
|||
|
||||
INLINE_LINMATH FLOATTYPE relative_angle_rad(const FLOATNAME(LVector3) &other) const;
|
||||
INLINE_LINMATH FLOATTYPE relative_angle_deg(const FLOATNAME(LVector3) &other) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
INLINE_LINMATH FLOATNAME(LVector3) operator * (FLOATTYPE scalar) const;
|
||||
INLINE_LINMATH FLOATNAME(LVector3) operator / (FLOATTYPE scalar) const;
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@ PUBLISHED:
|
|||
INLINE_LINMATH FLOATNAME(LVector4)(FLOATTYPE x, FLOATTYPE y, FLOATTYPE z, FLOATTYPE w);
|
||||
INLINE_LINMATH FLOATNAME(LVector4)(const FLOATNAME(LVecBase3) ©, FLOATTYPE w);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE_LINMATH PyObject *__getattr__(PyObject *self, const std::string &attr_name) const);
|
||||
EXTENSION(INLINE_LINMATH int __setattr__(PyObject *self, const std::string &attr_name, PyObject *assign));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE_LINMATH static const FLOATNAME(LVector4) &zero();
|
||||
INLINE_LINMATH static const FLOATNAME(LVector4) &unit_x();
|
||||
|
|
@ -53,7 +55,7 @@ PUBLISHED:
|
|||
#ifndef FLOATTYPE_IS_INT
|
||||
INLINE_LINMATH FLOATNAME(LVector4) normalized() const;
|
||||
INLINE_LINMATH FLOATNAME(LVector4) project(const FLOATNAME(LVecBase4) &onto) const;
|
||||
#endif
|
||||
#endif // !FLOATTYPE_IS_INT
|
||||
|
||||
EXTENSION(INLINE_LINMATH std::string __repr__() const);
|
||||
|
||||
|
|
|
|||
|
|
@ -38,10 +38,12 @@ public:
|
|||
void unregister_type(LoaderFileType *type);
|
||||
|
||||
PUBLISHED:
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(void register_type(PyObject *type));
|
||||
EXTENSION(void register_deferred_type(PyObject *entry_point));
|
||||
|
||||
EXTENSION(void unregister_type(PyObject *type));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
int get_num_types() const;
|
||||
LoaderFileType *get_type(int n) const;
|
||||
|
|
@ -53,7 +55,9 @@ PUBLISHED:
|
|||
|
||||
static LoaderFileTypeRegistry *get_global_ptr();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__reduce__() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
private:
|
||||
void record_extension(const std::string &extension, LoaderFileType *type);
|
||||
|
|
@ -71,4 +75,4 @@ private:
|
|||
static LoaderFileTypeRegistry *_global_ptr;
|
||||
};
|
||||
|
||||
#endif
|
||||
#endif // !LOADERFILETYPEREGISTRY_H
|
||||
|
|
|
|||
|
|
@ -183,9 +183,11 @@ PUBLISHED:
|
|||
INLINE void clear();
|
||||
|
||||
EXTENSION(NodePath __copy__() const);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
EXTENSION(PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE static NodePath not_found();
|
||||
INLINE static NodePath removed();
|
||||
|
|
@ -666,8 +668,10 @@ PUBLISHED:
|
|||
INLINE void set_shader_input(CPT_InternalName id, PN_stdfloat n1, PN_stdfloat n2,
|
||||
PN_stdfloat n3=0, PN_stdfloat n4=0, int priority=0);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(void set_shader_input(CPT_InternalName, PyObject *, int priority=0));
|
||||
EXTENSION(void set_shader_inputs(PyObject *args, PyObject *kwargs));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void clear_shader_input(CPT_InternalName id);
|
||||
void set_instance_count(int instance_count);
|
||||
|
|
@ -911,7 +915,9 @@ PUBLISHED:
|
|||
const NodePath &other = NodePath(),
|
||||
Thread *current_thread = Thread::get_current_thread()) const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_tight_bounds(const NodePath &other = NodePath()) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
// void analyze() const;
|
||||
|
||||
|
|
@ -932,6 +938,7 @@ PUBLISHED:
|
|||
|
||||
MAKE_MAP_PROPERTY(net_tags, has_net_tag, get_net_tag);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(INLINE PyObject *get_tags() const);
|
||||
EXTENSION(INLINE PyObject *get_tag_keys() const);
|
||||
MAKE_PROPERTY(tags, get_tags);
|
||||
|
|
@ -948,6 +955,7 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(python_tags, get_python_tags);
|
||||
|
||||
EXTENSION(int __traverse__(visitproc visit, void *arg));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE void list_tags() const;
|
||||
|
||||
|
|
@ -1071,4 +1079,4 @@ INLINE std::ostream &operator << (std::ostream &out, const NodePath &node_path);
|
|||
|
||||
#include "nodePath.I"
|
||||
|
||||
#endif
|
||||
#endif // !NODEPATH_H
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ PUBLISHED:
|
|||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(NodePathCollection(PyObject *self, PyObject *sequence));
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
#endif
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void add_path(const NodePath &node_path);
|
||||
bool remove_path(const NodePath &node_path);
|
||||
|
|
@ -74,7 +74,9 @@ PUBLISHED:
|
|||
|
||||
bool calc_tight_bounds(LPoint3 &min_point, LPoint3 &max_point) const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_tight_bounds() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void set_texture(Texture *tex, int priority = 0);
|
||||
void set_texture(TextureStage *stage, Texture *tex, int priority = 0);
|
||||
|
|
@ -113,4 +115,4 @@ INLINE std::ostream &operator << (std::ostream &out, const NodePathCollection &c
|
|||
|
||||
#include "nodePathCollection.I"
|
||||
|
||||
#endif
|
||||
#endif // !NODEPATHCOLLECTION_H
|
||||
|
|
|
|||
|
|
@ -106,8 +106,10 @@ PUBLISHED:
|
|||
virtual PandaNode *make_copy() const;
|
||||
PT(PandaNode) copy_subgraph(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PT(PandaNode) __copy__() const);
|
||||
EXTENSION(PyObject *__deepcopy__(PyObject *self, PyObject *memo) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE int get_num_parents(Thread *current_thread = Thread::get_current_thread()) const;
|
||||
INLINE PandaNode *get_parent(int n, Thread *current_thread = Thread::get_current_thread()) const;
|
||||
|
|
@ -204,6 +206,7 @@ PUBLISHED:
|
|||
MAKE_MAP_PROPERTY(tags, has_tag, get_tag, set_tag, clear_tag);
|
||||
MAKE_MAP_KEYS_SEQ(tags, get_num_tags, get_tag_key);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_tag_keys() const);
|
||||
|
||||
EXTENSION(PyObject *get_python_tags());
|
||||
|
|
@ -215,6 +218,7 @@ PUBLISHED:
|
|||
MAKE_PROPERTY(python_tags, get_python_tags);
|
||||
|
||||
EXTENSION(int __traverse__(visitproc visit, void *arg));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE bool has_tags() const;
|
||||
void copy_tags(PandaNode *other);
|
||||
|
|
@ -843,7 +847,7 @@ private:
|
|||
#ifndef DO_PIPELINING
|
||||
friend class PandaNode::Children;
|
||||
friend class PandaNode::Stashed;
|
||||
#endif
|
||||
#endif // !DO_PIPELINING
|
||||
friend class NodePath;
|
||||
friend class NodePathComponent;
|
||||
friend class WorkingNodePath;
|
||||
|
|
@ -943,4 +947,4 @@ INLINE std::ostream &operator << (std::ostream &out, const PandaNode &node) {
|
|||
|
||||
#include "pandaNode.I"
|
||||
|
||||
#endif
|
||||
#endif // !PANDANODE_H
|
||||
|
|
|
|||
|
|
@ -132,8 +132,10 @@ PUBLISHED:
|
|||
INLINE size_t get_invert_composition_cache_size() const;
|
||||
INLINE const RenderState *get_invert_composition_cache_source(size_t n) const;
|
||||
INLINE const RenderState *get_invert_composition_cache_result(size_t n) const;
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_composition_cache() const);
|
||||
EXTENSION(PyObject *get_invert_composition_cache() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void output(std::ostream &out) const;
|
||||
void write(std::ostream &out, int indent_level) const;
|
||||
|
|
@ -148,8 +150,10 @@ PUBLISHED:
|
|||
static void list_cycles(std::ostream &out);
|
||||
static void list_states(std::ostream &out);
|
||||
static bool validate_states();
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(static PyObject *get_states());
|
||||
EXTENSION(static PyObject *get_unused_states());
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
PUBLISHED:
|
||||
// These methods are intended for use by low-level code, but they're also
|
||||
|
|
@ -391,4 +395,4 @@ INLINE std::ostream &operator << (std::ostream &out, const RenderState &state) {
|
|||
|
||||
#include "renderState.I"
|
||||
|
||||
#endif
|
||||
#endif // !RENDERSTATE_H
|
||||
|
|
|
|||
|
|
@ -92,12 +92,14 @@ public:
|
|||
INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, const LMatrix3 &v, int priority=0) const;
|
||||
INLINE CPT(RenderAttrib) set_shader_input(CPT_InternalName id, double n1=0, double n2=0, double n3=0, double n4=1,
|
||||
int priority=0) const;
|
||||
|
||||
|
||||
CPT(RenderAttrib) set_shader_inputs(const pvector<ShaderInput> &inputs) const;
|
||||
|
||||
PUBLISHED:
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(CPT(RenderAttrib) set_shader_input(CPT_InternalName, PyObject *, int priority=0) const);
|
||||
EXTENSION(CPT(RenderAttrib) set_shader_inputs(PyObject *args, PyObject *kwargs) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
CPT(RenderAttrib) set_instance_count(int instance_count) const;
|
||||
|
||||
|
|
@ -194,4 +196,4 @@ private:
|
|||
|
||||
#include "shaderAttrib.I"
|
||||
|
||||
#endif // SHADERATTRIB_H
|
||||
#endif // !SHADERATTRIB_H
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ PUBLISHED:
|
|||
static const ShaderInput &get_blank();
|
||||
INLINE explicit ShaderInput(CPT_InternalName name, int priority=0);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(explicit ShaderInput(CPT_InternalName name, PyObject *value, int priority=0));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
INLINE ShaderInput(CPT_InternalName name, Texture *tex, int priority=0);
|
||||
|
|
@ -145,4 +147,4 @@ private:
|
|||
|
||||
#include "shaderInput.I"
|
||||
|
||||
#endif // SHADERINPUT_H
|
||||
#endif // !SHADERINPUT_H
|
||||
|
|
|
|||
|
|
@ -194,8 +194,10 @@ PUBLISHED:
|
|||
INLINE const TransformState *get_invert_composition_cache_source(size_t n) const;
|
||||
INLINE const TransformState *get_invert_composition_cache_result(size_t n) const;
|
||||
bool validate_composition_cache() const;
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_composition_cache() const);
|
||||
EXTENSION(PyObject *get_invert_composition_cache() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
void output(std::ostream &out) const;
|
||||
void write(std::ostream &out, int indent_level) const;
|
||||
|
|
@ -208,8 +210,10 @@ PUBLISHED:
|
|||
static void list_cycles(std::ostream &out);
|
||||
static void list_states(std::ostream &out);
|
||||
static bool validate_states();
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(static PyObject *get_states());
|
||||
EXTENSION(static PyObject *get_unused_states());
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
static void init_states();
|
||||
|
|
@ -423,4 +427,4 @@ INLINE std::ostream &operator << (std::ostream &out, const TransformState &state
|
|||
|
||||
#include "transformState.I"
|
||||
|
||||
#endif
|
||||
#endif // !TRANSFORMSTATE_H
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@
|
|||
*/
|
||||
#ifdef DEBUG_THREADS
|
||||
class EXPCL_PANDA_PIPELINE Mutex : public MutexDebug
|
||||
#else
|
||||
#else // DEBUG_THREADS
|
||||
class EXPCL_PANDA_PIPELINE Mutex : public MutexDirect
|
||||
#endif // DEBUG_THREADS
|
||||
{
|
||||
|
|
@ -49,10 +49,11 @@ PUBLISHED:
|
|||
|
||||
void operator = (const Mutex ©) = delete;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(bool acquire(bool blocking=true) const);
|
||||
EXTENSION(bool __enter__());
|
||||
EXTENSION(void __exit__(PyObject *, PyObject *, PyObject *));
|
||||
|
||||
#endif // HAVE_PYTHON
|
||||
public:
|
||||
// This is a global mutex set aside for the purpose of protecting Notify
|
||||
// messages from being interleaved between threads.
|
||||
|
|
@ -61,4 +62,4 @@ public:
|
|||
|
||||
#include "pmutex.I"
|
||||
|
||||
#endif
|
||||
#endif // !PMUTEX_H
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
*/
|
||||
#ifdef DEBUG_THREADS
|
||||
class EXPCL_PANDA_PIPELINE ReMutex : public MutexDebug
|
||||
#else
|
||||
#else // DEBUG_THREADS
|
||||
class EXPCL_PANDA_PIPELINE ReMutex : public ReMutexDirect
|
||||
#endif // DEBUG_THREADS
|
||||
{
|
||||
|
|
@ -43,11 +43,13 @@ PUBLISHED:
|
|||
|
||||
void operator = (const ReMutex ©) = delete;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(bool acquire(bool blocking=true) const);
|
||||
EXTENSION(bool __enter__());
|
||||
EXTENSION(void __exit__(PyObject *, PyObject *, PyObject *));
|
||||
#endif // HAVE_PYTHON
|
||||
};
|
||||
|
||||
#include "reMutex.I"
|
||||
|
||||
#endif
|
||||
#endif // !REMUTEX_H
|
||||
|
|
|
|||
|
|
@ -58,7 +58,7 @@ public:
|
|||
INLINE double get_level(size_t n) const;
|
||||
|
||||
bool write_datagram(Datagram &destination, PStatClient *client = nullptr) const;
|
||||
void read_datagram(DatagramIterator &source, PStatClientVersion *version = nullptr);
|
||||
void read_datagram(DatagramIterator &source, PStatClientVersion *version);
|
||||
|
||||
private:
|
||||
class DataPoint {
|
||||
|
|
|
|||
|
|
@ -148,14 +148,18 @@ PUBLISHED:
|
|||
INLINE int get_current_major_ver() const;
|
||||
INLINE int get_current_minor_ver() const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *get_file_version() const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
PUBLISHED:
|
||||
MAKE_PROPERTY(source, get_source, set_source);
|
||||
MAKE_PROPERTY(filename, get_filename);
|
||||
MAKE_PROPERTY(loader_options, get_loader_options, set_loader_options);
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
MAKE_PROPERTY(file_version, get_file_version);
|
||||
#endif // HAVE_PYTHON
|
||||
MAKE_PROPERTY(file_endian, get_file_endian);
|
||||
MAKE_PROPERTY(file_stdfloat_double, get_file_stdfloat_double);
|
||||
|
||||
|
|
@ -201,8 +205,10 @@ public:
|
|||
void *user_data = nullptr);
|
||||
INLINE static WritableFactory *get_factory();
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
PUBLISHED:
|
||||
EXTENSION(static void register_factory(TypeHandle handle, PyObject *func));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
private:
|
||||
INLINE static void create_factory();
|
||||
|
|
@ -350,4 +356,4 @@ parse_params(const FactoryParams ¶ms,
|
|||
|
||||
#include "bamReader.I"
|
||||
|
||||
#endif
|
||||
#endif // !__BAM_READER_
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ PUBLISHED:
|
|||
|
||||
INLINE BitArray();
|
||||
BitArray(const SparseArray &from);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(BitArray(PyObject *init_value));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE static BitArray all_on();
|
||||
INLINE static BitArray all_off();
|
||||
|
|
@ -129,8 +131,10 @@ PUBLISHED:
|
|||
void operator >>= (int shift);
|
||||
|
||||
EXTENSION(bool __bool__() const);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__getstate__() const);
|
||||
EXTENSION(void __setstate__(PyObject *state));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
void generate_hash(ChecksumHashGenerator &hashgen) const;
|
||||
|
|
@ -171,4 +175,4 @@ operator << (std::ostream &out, const BitArray &array) {
|
|||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // !BITARRAY_H
|
||||
|
|
|
|||
|
|
@ -126,8 +126,10 @@ PUBLISHED:
|
|||
INLINE int get_key() const;
|
||||
|
||||
EXTENSION(bool __bool__() const);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__int__() const);
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
INLINE void generate_hash(ChecksumHashGenerator &hashgen) const;
|
||||
|
|
@ -170,8 +172,8 @@ typedef BitMask<uint64_t, 64> BitMask64;
|
|||
typedef BitMask32 BitMaskNative;
|
||||
#elif NATIVE_WORDSIZE == 64
|
||||
typedef BitMask64 BitMaskNative;
|
||||
#else
|
||||
#else // NATIVE_WORDSIZE
|
||||
#error No definition for NATIVE_WORDSIZE--should be defined in dtoolbase.h.
|
||||
#endif // NATIVE_WORDSIZE
|
||||
|
||||
#endif
|
||||
#endif // !BITMASK_H
|
||||
|
|
|
|||
|
|
@ -34,7 +34,9 @@ public:
|
|||
PUBLISHED:
|
||||
virtual void output(std::ostream &out) const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(static PT(CallbackObject) make(PyObject *function));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
virtual void do_callback(CallbackData *cbdata);
|
||||
|
|
@ -64,4 +66,4 @@ inline std::ostream &operator << (std::ostream &out, const CallbackObject &cbo)
|
|||
|
||||
#include "callbackObject.I"
|
||||
|
||||
#endif
|
||||
#endif // !CALLBACKOBJECT_H
|
||||
|
|
|
|||
|
|
@ -39,7 +39,9 @@ PUBLISHED:
|
|||
};
|
||||
|
||||
constexpr DoubleBitMask() = default;
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(DoubleBitMask(PyObject *init_value));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE static DoubleBitMask<BMType> all_on();
|
||||
INLINE static DoubleBitMask<BMType> all_off();
|
||||
|
|
@ -113,8 +115,10 @@ PUBLISHED:
|
|||
INLINE void operator >>= (int shift);
|
||||
|
||||
EXTENSION(bool __bool__() const);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__int__() const);
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
public:
|
||||
INLINE void generate_hash(ChecksumHashGenerator &hashgen) const;
|
||||
|
|
@ -148,4 +152,4 @@ typedef DoubleBitMask<BitMaskNative> DoubleBitMaskNative;
|
|||
EXPORT_TEMPLATE_CLASS(EXPCL_PANDA_PUTIL, EXPTP_PANDA_PUTIL, DoubleBitMask<DoubleBitMaskNative>);
|
||||
typedef DoubleBitMask<DoubleBitMaskNative> QuadBitMaskNative;
|
||||
|
||||
#endif
|
||||
#endif // !DOUBLEBITMASK_H
|
||||
|
|
|
|||
|
|
@ -118,8 +118,10 @@ PUBLISHED:
|
|||
INLINE int get_subrange_end(size_t n) const;
|
||||
|
||||
EXTENSION(bool __bool__() const);
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__getstate__() const);
|
||||
EXTENSION(void __setstate__(PyObject *state));
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
private:
|
||||
void do_add_range(int begin, int end);
|
||||
|
|
@ -171,4 +173,4 @@ operator << (std::ostream &out, const SparseArray &array) {
|
|||
return out;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif // !SPARSEARRAY_H
|
||||
|
|
|
|||
|
|
@ -60,8 +60,10 @@ PUBLISHED:
|
|||
INLINE void mark_bam_modified();
|
||||
INLINE UpdateSeq get_bam_modified() const;
|
||||
|
||||
#ifdef HAVE_PYTHON
|
||||
EXTENSION(PyObject *__reduce__(PyObject *self) const);
|
||||
EXTENSION(PyObject *__reduce_persist__(PyObject *self, PyObject *pickler) const);
|
||||
#endif // HAVE_PYTHON
|
||||
|
||||
INLINE vector_uchar encode_to_bam_stream() const;
|
||||
bool encode_to_bam_stream(vector_uchar &data, BamWriter *writer = nullptr) const;
|
||||
|
|
@ -111,4 +113,4 @@ private:
|
|||
|
||||
#include "typedWritable.I"
|
||||
|
||||
#endif
|
||||
#endif // !TYPEDWRITABLE_H
|
||||
|
|
|
|||
|
|
@ -1393,8 +1393,8 @@ framebuffer_copy_to_texture(Texture *tex, int view, int z,
|
|||
*/
|
||||
bool TinyGraphicsStateGuardian::
|
||||
framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
||||
const DisplayRegion *dr,
|
||||
const RenderBuffer &rb) {
|
||||
const DisplayRegion *dr, const RenderBuffer &rb,
|
||||
ScreenshotRequest *request) {
|
||||
nassertr(tex != nullptr && dr != nullptr, false);
|
||||
|
||||
int xo, yo, w, h;
|
||||
|
|
@ -1465,6 +1465,9 @@ framebuffer_copy_to_ram(Texture *tex, int view, int z,
|
|||
fo += _c->zb->linesize / PSZB;
|
||||
}
|
||||
|
||||
if (request != nullptr) {
|
||||
request->finish();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -78,7 +78,8 @@ public:
|
|||
virtual bool framebuffer_copy_to_texture
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
|
||||
virtual bool framebuffer_copy_to_ram
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb);
|
||||
(Texture *tex, int view, int z, const DisplayRegion *dr, const RenderBuffer &rb,
|
||||
ScreenshotRequest *request);
|
||||
|
||||
virtual void set_state_and_transform(const RenderState *state,
|
||||
const TransformState *transform);
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ x11GraphicsWindow(GraphicsEngine *engine, GraphicsPipe *pipe,
|
|||
_override_redirect = False;
|
||||
_wm_delete_window = x11_pipe->_wm_delete_window;
|
||||
_net_wm_ping = x11_pipe->_net_wm_ping;
|
||||
_net_wm_state = x11_pipe->_net_wm_state;
|
||||
|
||||
PT(GraphicsWindowInputDevice) device = GraphicsWindowInputDevice::pointer_and_keyboard(this, "keyboard_mouse");
|
||||
add_input_device(device);
|
||||
|
|
@ -368,9 +369,7 @@ process_events() {
|
|||
|
||||
case PropertyNotify:
|
||||
//std::cout << "PropertyNotify event: atom = " << event.xproperty.atom << std::endl;
|
||||
x11GraphicsPipe *x11_pipe;
|
||||
DCAST_INTO_V(x11_pipe, _pipe);
|
||||
if (event.xproperty.atom == x11_pipe->_net_wm_state) {
|
||||
if (event.xproperty.atom == _net_wm_state) {
|
||||
// currently we're only interested in the net_wm_state type of
|
||||
// changes and only need to gather property informations once at
|
||||
// the end after the while loop
|
||||
|
|
@ -516,6 +515,7 @@ process_events() {
|
|||
}
|
||||
else if ((Atom)(event.xclient.data.l[0]) == _net_wm_ping &&
|
||||
event.xclient.window == _xwindow) {
|
||||
x11GraphicsPipe *x11_pipe;
|
||||
DCAST_INTO_V(x11_pipe, _pipe);
|
||||
event.xclient.window = x11_pipe->get_root();
|
||||
XSendEvent(_display, x11_pipe->get_root(), False, SubstructureRedirectMask | SubstructureNotifyMask, &event);
|
||||
|
|
|
|||
|
|
@ -109,6 +109,7 @@ protected:
|
|||
Bool _override_redirect;
|
||||
Atom _wm_delete_window;
|
||||
Atom _net_wm_ping;
|
||||
Atom _net_wm_state;
|
||||
|
||||
x11GraphicsPipe::pfn_XRRGetScreenInfo _XRRGetScreenInfo;
|
||||
x11GraphicsPipe::pfn_XRRSetScreenConfig _XRRSetScreenConfig;
|
||||
|
|
|
|||
|
|
@ -471,7 +471,7 @@ read_datagram(DatagramIterator &scan) {
|
|||
std::string name = scan.get_string();
|
||||
define_thread(thread_index, name);
|
||||
|
||||
_threads[thread_index]._data->read_datagram(scan);
|
||||
_threads[thread_index]._data->read_datagram(scan, this);
|
||||
}
|
||||
|
||||
update_toplevel_collectors();
|
||||
|
|
|
|||
|
|
@ -328,11 +328,11 @@ write_datagram(Datagram &dg) const {
|
|||
* Restores the thread data from a datagram.
|
||||
*/
|
||||
void PStatThreadData::
|
||||
read_datagram(DatagramIterator &scan) {
|
||||
read_datagram(DatagramIterator &scan, PStatClientVersion *version) {
|
||||
int frame_number;
|
||||
while ((frame_number = scan.get_int32()) != -1) {
|
||||
PStatFrameData *frame_data = new PStatFrameData;
|
||||
frame_data->read_datagram(scan);
|
||||
frame_data->read_datagram(scan, version);
|
||||
|
||||
record_new_frame(frame_number, frame_data);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
class PStatCollectorDef;
|
||||
class PStatFrameData;
|
||||
class PStatClientData;
|
||||
class PStatClientVersion;
|
||||
|
||||
/**
|
||||
* A collection of FrameData structures for recently-received frames within a
|
||||
|
|
@ -63,7 +64,7 @@ public:
|
|||
void record_new_frame(int frame_number, PStatFrameData *frame_data);
|
||||
|
||||
void write_datagram(Datagram &dg) const;
|
||||
void read_datagram(DatagramIterator &scan);
|
||||
void read_datagram(DatagramIterator &scan, PStatClientVersion *version);
|
||||
|
||||
private:
|
||||
void compute_elapsed_frames() const;
|
||||
|
|
|
|||
|
|
@ -69,3 +69,63 @@ def test_cpta_float_pickle():
|
|||
data_pta2 = loads(dumps(data_pta, proto))
|
||||
assert tuple(data_pta2) == (1.0, 2.0, 3.0)
|
||||
assert data_pta2.get_data() == data_pta.get_data()
|
||||
|
||||
|
||||
def test_pta_float_copy():
|
||||
from panda3d.core import PTA_float
|
||||
from copy import copy
|
||||
|
||||
null_pta = PTA_float()
|
||||
assert copy(null_pta).is_null()
|
||||
|
||||
empty_pta = PTA_float([])
|
||||
empty_pta_copy = copy(empty_pta)
|
||||
assert not empty_pta_copy.is_null()
|
||||
assert len(empty_pta_copy) == 0
|
||||
assert empty_pta_copy.get_ref_count() == 2
|
||||
|
||||
data_pta = PTA_float([1.0, 2.0, 3.0])
|
||||
data_pta_copy = copy(data_pta)
|
||||
assert not data_pta_copy.is_null()
|
||||
assert data_pta_copy.get_ref_count() == 2
|
||||
assert tuple(data_pta_copy) == (1.0, 2.0, 3.0)
|
||||
|
||||
|
||||
def test_pta_float_deepcopy():
|
||||
from panda3d.core import PTA_float
|
||||
from copy import deepcopy
|
||||
|
||||
null_pta = PTA_float()
|
||||
assert deepcopy(null_pta).is_null()
|
||||
|
||||
empty_pta = PTA_float([])
|
||||
empty_pta_copy = deepcopy(empty_pta)
|
||||
assert not empty_pta_copy.is_null()
|
||||
assert len(empty_pta_copy) == 0
|
||||
assert empty_pta_copy.get_ref_count() == 1
|
||||
|
||||
data_pta = PTA_float([1.0, 2.0, 3.0])
|
||||
data_pta_copy = deepcopy(data_pta)
|
||||
assert not data_pta_copy.is_null()
|
||||
assert data_pta_copy.get_ref_count() == 1
|
||||
assert tuple(data_pta_copy) == (1.0, 2.0, 3.0)
|
||||
|
||||
|
||||
def test_cpta_float_deepcopy():
|
||||
from panda3d.core import PTA_float, CPTA_float
|
||||
from copy import deepcopy
|
||||
|
||||
null_pta = CPTA_float(PTA_float())
|
||||
assert deepcopy(null_pta).is_null()
|
||||
|
||||
empty_pta = CPTA_float([])
|
||||
empty_pta_copy = deepcopy(empty_pta)
|
||||
assert not empty_pta_copy.is_null()
|
||||
assert len(empty_pta_copy) == 0
|
||||
assert empty_pta_copy.get_ref_count() == 1
|
||||
|
||||
data_pta = CPTA_float([1.0, 2.0, 3.0])
|
||||
data_pta_copy = deepcopy(data_pta)
|
||||
assert not data_pta_copy.is_null()
|
||||
assert data_pta_copy.get_ref_count() == 1
|
||||
assert tuple(data_pta_copy) == (1.0, 2.0, 3.0)
|
||||
|
|
|
|||
|
|
@ -134,3 +134,26 @@ def test_texture_clear_half():
|
|||
assert col.y == -inf
|
||||
assert col.z == -inf
|
||||
assert math.isnan(col.w)
|
||||
|
||||
|
||||
def test_texture_deepcopy():
|
||||
from copy import deepcopy
|
||||
|
||||
empty_tex = Texture("empty-texture")
|
||||
empty_tex.setup_2d_texture(16, 16, Texture.T_unsigned_byte, Texture.F_rgba)
|
||||
assert not empty_tex.has_ram_image()
|
||||
empty_tex2 = deepcopy(empty_tex)
|
||||
assert empty_tex2.name == empty_tex.name
|
||||
assert not empty_tex2.has_ram_image()
|
||||
|
||||
tex = Texture("texture")
|
||||
tex.setup_2d_texture(16, 16, Texture.T_unsigned_byte, Texture.F_rgba)
|
||||
img = tex.make_ram_image()
|
||||
assert tex.has_ram_image()
|
||||
assert img.get_ref_count() == 2
|
||||
|
||||
tex2 = deepcopy(tex)
|
||||
assert tex2.name == tex.name
|
||||
assert tex2.has_ram_image()
|
||||
img2 = tex2.get_ram_image()
|
||||
assert img2.get_ref_count() == 2
|
||||
|
|
|
|||
Loading…
Reference in New Issue